Print this page
cleanup
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/mdb/mdb_demangle.c
+++ new/usr/src/cmd/mdb/common/mdb/mdb_demangle.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 *
26 26 * Copyright 2018 Jason King
27 27 */
28 28
29 29 #include <mdb/mdb_modapi.h>
30 30 #include <mdb/mdb_demangle.h>
31 31 #include <mdb/mdb_err.h>
32 32 #include <mdb/mdb.h>
33 33
34 34 #include <strings.h>
35 35 #include <unistd.h>
36 36 #include <dlfcn.h>
37 37 #include <link.h>
38 38
39 39 static void *
40 40 mdb_dem_alloc(size_t len)
41 41 {
42 42 return (mdb_alloc(len, UM_SLEEP));
43 43 }
44 44
45 45 static void
46 46 mdb_dem_free(void *p, size_t len)
47 47 {
48 48 mdb_free(p, len);
49 49 }
50 50
51 51 static sysdem_ops_t mdb_dem_demops = {
52 52 .alloc = mdb_dem_alloc,
53 53 .free = mdb_dem_free
54 54 };
55 55
56 56 mdb_demangler_t *
57 57 mdb_dem_load(void)
58 58 {
59 59 mdb_demangler_t *dmp;
60 60
61 61 dmp = mdb_alloc(sizeof (mdb_demangler_t), UM_SLEEP);
62 62 dmp->dm_len = 0;
63 63 dmp->dm_buf = NULL;
64 64 dmp->dm_flags = MDB_DM_SCOPE;
65 65 /* stick with C++ for now to match old behavior */
66 66 dmp->dm_lang = SYSDEM_LANG_CPP;
67 67
68 68 return (dmp);
69 69 }
70 70
71 71 void
72 72 mdb_dem_unload(mdb_demangler_t *dmp)
73 73 {
74 74 mdb_free(dmp->dm_buf, dmp->dm_len);
75 75 mdb_free(dmp, sizeof (mdb_demangler_t));
76 76 }
77 77
78 78 static const char *
79 79 mdb_dem_filter(mdb_demangler_t *dmp, const char *name)
80 80 {
81 81 static const char s_pref[] = "static ";
82 82 static const char c_suff[] = " const";
83 83 static const char v_suff[] = " volatile";
84 84
85 85 /*
86 86 * We process dm_dem, which skips the prefix in dm_buf (if any)
87 87 */
88 88 size_t len = strlen(dmp->dm_dem);
89 89 char *end = dmp->dm_dem + len;
90 90 size_t resid;
91 91
92 92 /*
93 93 * If static, const, and volatile qualifiers should not be displayed,
94 94 * rip all of them out of dmp->dm_dem.
95 95 */
96 96 if (!(dmp->dm_flags & MDB_DM_QUAL)) {
97 97 if (strncmp(dmp->dm_dem, s_pref, sizeof (s_pref) - 1) == 0) {
98 98 bcopy(dmp->dm_dem + sizeof (s_pref) - 1, dmp->dm_dem,
99 99 len - (sizeof (s_pref) - 1) + 1);
100 100 end -= sizeof (s_pref) - 1;
101 101 len -= sizeof (s_pref) - 1;
102 102 }
103 103
104 104 for (;;) {
105 105 if (len > sizeof (c_suff) - 1 &&
106 106 strcmp(end - (sizeof (c_suff) - 1), c_suff) == 0) {
107 107 end -= sizeof (c_suff) - 1;
108 108 len -= sizeof (c_suff) - 1;
109 109 *end = '\0';
110 110 continue;
111 111 }
112 112 if (len > sizeof (v_suff) - 1 &&
113 113 strcmp(end - (sizeof (v_suff) - 1), v_suff) == 0) {
114 114 end -= sizeof (v_suff) - 1;
115 115 len -= sizeof (v_suff) - 1;
116 116 *end = '\0';
117 117 continue;
118 118 }
119 119 break;
120 120 }
121 121 }
122 122
123 123 /*
124 124 * If function arguments should not be displayed, remove everything
125 125 * between the outermost set of parentheses in dmp->dm_dem.
126 126 */
127 127 if (!(dmp->dm_flags & MDB_DM_FUNCARG)) {
128 128 char *lp = strchr(dmp->dm_dem, '(');
129 129 char *rp = strrchr(dmp->dm_dem, ')');
130 130
131 131 if (lp != NULL && rp != NULL)
132 132 bcopy(rp + 1, lp, strlen(rp) + 1);
133 133 }
134 134
135 135 /*
136 136 * If function scope specifiers should not be displayed, remove text
137 137 * from the leftmost space to the rightmost colon prior to any paren.
138 138 */
139 139 if (!(dmp->dm_flags & MDB_DM_SCOPE)) {
140 140 char *c, *s, *lp = strchr(dmp->dm_dem, '(');
141 141
142 142 if (lp != NULL)
143 143 *lp = '\0';
144 144
145 145 c = strrchr(dmp->dm_dem, ':');
146 146 s = strchr(dmp->dm_dem, ' ');
147 147
148 148 if (lp != NULL)
149 149 *lp = '(';
150 150
151 151 if (c != NULL) {
152 152 if (s == NULL || s > c)
153 153 bcopy(c + 1, dmp->dm_dem, strlen(c + 1) + 1);
154 154 else
155 155 bcopy(c + 1, s + 1, strlen(c + 1) + 1);
156 156 }
157 157 }
158 158
159 159 len = strlen(dmp->dm_dem); /* recompute length of buffer */
160 160
161 161 /*
162 162 * Compute bytes remaining
163 163 */
164 164 resid = (dmp->dm_buf + dmp->dm_len) - (dmp->dm_dem + len);
165 165
166 166 /*
167 167 * If we want to append the mangled name as well and there is enough
168 168 * space for "[]\0" and at least one character, append "["+name+"]".
169 169 */
170 170 if ((dmp->dm_flags & MDB_DM_MANGLED) && resid > 3) {
171 171 char *p = dmp->dm_dem + len;
172 172
173 173 *p++ = '[';
174 174 (void) strncpy(p, name, resid - 3);
175 175 p[resid - 3] = '\0';
176 176 p += strlen(p);
177 177 (void) strcpy(p, "]");
178 178 }
179 179
180 180 /*
181 181 * We return the whole string
182 182 */
183 183 return (dmp->dm_buf);
184 184 }
185 185
186 186 /*
187 187 * Take a name: (the foo`bar` is optional)
188 188 * foo`bar`__mangled_
189 189 * and put:
190 190 * foo`bar`demangled
191 191 * into dmp->dm_buf. Point dmp->dm_dem to the beginning of the
192 192 * demangled section of the result.
193 193 */
194 194 static int
195 195 mdb_dem_process(mdb_demangler_t *dmp, const char *name)
196 196 {
197 197 char *res = NULL;
198 198 size_t reslen = 0;
199 199
200 200 char *prefix = strrchr(name, '`');
201 201 size_t prefixlen = 0;
202 202
203 203 if (prefix) {
204 204 prefix++; /* the ` is part of the prefix */
205 205 prefixlen = prefix - name;
206 206 }
207 207
208 208 res = sysdemangle(name + prefixlen, dmp->dm_lang, &mdb_dem_demops);
209 209 if (res == NULL) {
210 210 if (errno != EINVAL)
211 211 mdb_warn("Error while demangling");
212 212 return (-1);
213 213 }
214 214
215 215 reslen = (res != NULL) ? strlen(res) : 0;
216 216 reslen += prefixlen;
217 217 reslen += 1;
218 218
219 219 if (reslen > dmp->dm_len) {
220 220 mdb_free(dmp->dm_buf, dmp->dm_len);
221 221
↓ open down ↓ |
221 lines elided |
↑ open up ↑ |
222 222 dmp->dm_buf = mdb_zalloc(reslen, UM_SLEEP);
223 223 if (dmp->dm_buf == NULL) {
224 224 dmp->dm_len = 0;
225 225 mdb_warn("Unable to allocate memory for demangling");
226 226 return (-1);
227 227 }
228 228 dmp->dm_len = reslen;
229 229 }
230 230
231 231 if (prefixlen > 0)
232 - (void) strlcpy(dmp->dm_buf, name, prefixlen);
232 + (void) strlcpy(dmp->dm_buf, name, prefixlen + 1);
233 + else
234 + *dmp->dm_buf = '\0';
233 235
234 236 if (res != NULL) {
235 237 (void) strlcat(dmp->dm_buf, res, dmp->dm_len);
236 238 mdb_dem_free(res, strlen(res) + 1);
237 239 }
238 240
239 241 /*
240 242 * Save the position of the demangled string for mdb_dem_filter()
241 243 */
242 244 dmp->dm_dem = dmp->dm_buf + prefixlen;
243 245
244 246 return (0);
245 247 }
246 248
247 249 /* used by mdb_io.c:iob_addr2str */
248 250 const char *
249 251 mdb_dem_convert(mdb_demangler_t *dmp, const char *name)
250 252 {
251 253 if (mdb_dem_process(dmp, name) != 0 ||
252 254 strcmp(dmp->dm_buf, name) == 0)
253 255 return (name);
254 256
255 257 return (mdb_dem_filter(dmp, name));
256 258 }
257 259
258 260 /*ARGSUSED*/
259 261 int
260 262 cmd_demangle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
261 263 {
262 264 mdb_demangler_t *dmp = mdb.m_demangler;
263 265
264 266 if (argc > 0)
265 267 return (DCMD_USAGE);
266 268
267 269 if (dmp != NULL && !(mdb.m_flags & MDB_FL_DEMANGLE)) {
268 270 mdb_printf("C++ symbol demangling enabled\n");
269 271 mdb.m_flags |= MDB_FL_DEMANGLE;
270 272
271 273 } else if (dmp == NULL) {
272 274 if ((mdb.m_demangler = mdb_dem_load()) != NULL) {
273 275 mdb_printf("C++ symbol demangling enabled\n");
274 276 mdb.m_flags |= MDB_FL_DEMANGLE;
275 277 } else {
276 278 mdb_warn("no memory to load C++ demangler");
277 279 mdb.m_flags &= ~MDB_FL_DEMANGLE;
278 280 }
279 281
280 282 } else {
281 283 mdb_dem_unload(mdb.m_demangler);
282 284 mdb.m_flags &= ~MDB_FL_DEMANGLE;
283 285 mdb.m_demangler = NULL;
284 286 mdb_printf("C++ symbol demangling disabled\n");
285 287 }
286 288
287 289 return (DCMD_OK);
288 290 }
289 291
290 292 /*ARGSUSED*/
291 293 int
292 294 cmd_demflags(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
293 295 {
294 296 static const char *const dm_desc[] = {
295 297 "static/const/volatile member func qualifiers displayed",
296 298 "scope resolution specifiers displayed",
297 299 "function arguments displayed",
298 300 "mangled name displayed"
299 301 };
300 302
301 303 mdb_demangler_t *dmp = mdb.m_demangler;
302 304 int i;
303 305
304 306 if (argc > 0)
305 307 return (DCMD_USAGE);
306 308
307 309 if (dmp == NULL || !(mdb.m_flags & MDB_FL_DEMANGLE)) {
308 310 mdb_warn("C++ demangling facility is currently disabled\n");
309 311 return (DCMD_ERR);
310 312 }
311 313
312 314 if (flags & DCMD_ADDRSPEC)
313 315 dmp->dm_flags = ((uint_t)addr & MDB_DM_ALL);
314 316
315 317 for (i = 0; i < sizeof (dm_desc) / sizeof (dm_desc[0]); i++) {
316 318 mdb_printf("0x%x\t%s\t%s\n", 1 << i,
317 319 (dmp->dm_flags & (1 << i)) ? "on" : "off", dm_desc[i]);
318 320 }
319 321
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
320 322 return (DCMD_OK);
321 323 }
322 324
323 325 /*ARGSUSED*/
324 326 int
325 327 cmd_demstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
326 328 {
327 329 if ((flags & DCMD_ADDRSPEC) || argc == 0)
328 330 return (DCMD_USAGE);
329 331
332 + if (mdb.m_demangler == NULL && (mdb.m_demangler =
333 + mdb_dem_load()) == NULL) {
334 + mdb_warn("failed to load demangler");
335 + return (DCMD_ERR);
336 + }
337 +
330 338 for (; argc != 0; argc--, argv++) {
331 339 mdb_printf("%s == %s\n", argv->a_un.a_str,
332 340 mdb_dem_convert(mdb.m_demangler, argv->a_un.a_str));
333 341 }
334 342
335 343 return (DCMD_OK);
336 344 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX