Print this page
cleanup
Rich's feedback
Address Robert's feedback
6375 Add native name demangling support
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
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 + *
26 + * Copyright 2018 Jason King
25 27 */
26 28
27 -#pragma ident "%Z%%M% %I% %E% SMI"
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 -#include <demangle.h>
35 34 #include <strings.h>
36 35 #include <unistd.h>
37 36 #include <dlfcn.h>
38 37 #include <link.h>
39 38
40 -#ifdef _LP64
41 -static const char LIB_DEMANGLE[] = "/usr/lib/64/libdemangle.so.1";
42 -#else
43 -static const char LIB_DEMANGLE[] = "/usr/lib/libdemangle.so.1";
44 -#endif
39 +static void *
40 +mdb_dem_alloc(size_t len)
41 +{
42 + return (mdb_alloc(len, UM_SLEEP));
43 +}
45 44
45 +static void
46 +mdb_dem_free(void *p, size_t len)
47 +{
48 + mdb_free(p, len);
49 +}
50 +
51 +static sysdem_ops_t mdb_dem_demops = {
52 + .alloc = mdb_dem_alloc,
53 + .free = mdb_dem_free
54 +};
55 +
46 56 mdb_demangler_t *
47 -mdb_dem_load(const char *path)
57 +mdb_dem_load(void)
48 58 {
49 59 mdb_demangler_t *dmp;
50 - void *hdl, *func;
51 60
52 - if (access(path, F_OK) == -1)
53 - return (NULL);
54 -
55 - if ((hdl = dlmopen(LM_ID_BASE, path, RTLD_LAZY | RTLD_LOCAL)) == NULL) {
56 - (void) set_errno(EMDB_RTLD);
57 - return (NULL);
58 - }
59 -
60 - if ((func = dlsym(hdl, "cplus_demangle")) == NULL) {
61 - (void) dlclose(hdl);
62 - (void) set_errno(EMDB_NODEM);
63 - return (NULL);
64 - }
65 -
66 61 dmp = mdb_alloc(sizeof (mdb_demangler_t), UM_SLEEP);
67 - (void) strncpy(dmp->dm_pathname, path, MAXPATHLEN);
68 - dmp->dm_pathname[MAXPATHLEN - 1] = '\0';
69 - dmp->dm_handle = hdl;
70 - dmp->dm_convert = (int (*)())func;
71 - dmp->dm_len = MDB_SYM_NAMLEN * 2;
72 - dmp->dm_buf = mdb_alloc(dmp->dm_len, UM_SLEEP);
62 + dmp->dm_len = 0;
63 + dmp->dm_buf = NULL;
73 64 dmp->dm_flags = MDB_DM_SCOPE;
65 + /* stick with C++ for now to match old behavior */
66 + dmp->dm_lang = SYSDEM_LANG_CPP;
74 67
75 68 return (dmp);
76 69 }
77 70
78 71 void
79 72 mdb_dem_unload(mdb_demangler_t *dmp)
80 73 {
81 - (void) dlclose(dmp->dm_handle);
82 74 mdb_free(dmp->dm_buf, dmp->dm_len);
83 75 mdb_free(dmp, sizeof (mdb_demangler_t));
84 76 }
85 77
86 78 static const char *
87 79 mdb_dem_filter(mdb_demangler_t *dmp, const char *name)
88 80 {
89 81 static const char s_pref[] = "static ";
90 82 static const char c_suff[] = " const";
91 83 static const char v_suff[] = " volatile";
92 84
93 85 /*
94 86 * We process dm_dem, which skips the prefix in dm_buf (if any)
95 87 */
96 88 size_t len = strlen(dmp->dm_dem);
97 89 char *end = dmp->dm_dem + len;
98 90 size_t resid;
99 91
100 92 /*
101 93 * If static, const, and volatile qualifiers should not be displayed,
102 94 * rip all of them out of dmp->dm_dem.
103 95 */
104 96 if (!(dmp->dm_flags & MDB_DM_QUAL)) {
105 97 if (strncmp(dmp->dm_dem, s_pref, sizeof (s_pref) - 1) == 0) {
106 98 bcopy(dmp->dm_dem + sizeof (s_pref) - 1, dmp->dm_dem,
107 99 len - (sizeof (s_pref) - 1) + 1);
108 100 end -= sizeof (s_pref) - 1;
109 101 len -= sizeof (s_pref) - 1;
110 102 }
111 103
112 104 for (;;) {
113 105 if (len > sizeof (c_suff) - 1 &&
114 106 strcmp(end - (sizeof (c_suff) - 1), c_suff) == 0) {
115 107 end -= sizeof (c_suff) - 1;
116 108 len -= sizeof (c_suff) - 1;
117 109 *end = '\0';
118 110 continue;
119 111 }
120 112 if (len > sizeof (v_suff) - 1 &&
121 113 strcmp(end - (sizeof (v_suff) - 1), v_suff) == 0) {
122 114 end -= sizeof (v_suff) - 1;
123 115 len -= sizeof (v_suff) - 1;
124 116 *end = '\0';
125 117 continue;
126 118 }
127 119 break;
128 120 }
129 121 }
130 122
131 123 /*
132 124 * If function arguments should not be displayed, remove everything
133 125 * between the outermost set of parentheses in dmp->dm_dem.
134 126 */
135 127 if (!(dmp->dm_flags & MDB_DM_FUNCARG)) {
136 128 char *lp = strchr(dmp->dm_dem, '(');
137 129 char *rp = strrchr(dmp->dm_dem, ')');
138 130
139 131 if (lp != NULL && rp != NULL)
140 132 bcopy(rp + 1, lp, strlen(rp) + 1);
141 133 }
142 134
143 135 /*
144 136 * If function scope specifiers should not be displayed, remove text
145 137 * from the leftmost space to the rightmost colon prior to any paren.
146 138 */
147 139 if (!(dmp->dm_flags & MDB_DM_SCOPE)) {
148 140 char *c, *s, *lp = strchr(dmp->dm_dem, '(');
149 141
150 142 if (lp != NULL)
151 143 *lp = '\0';
152 144
153 145 c = strrchr(dmp->dm_dem, ':');
154 146 s = strchr(dmp->dm_dem, ' ');
155 147
156 148 if (lp != NULL)
157 149 *lp = '(';
158 150
159 151 if (c != NULL) {
160 152 if (s == NULL || s > c)
161 153 bcopy(c + 1, dmp->dm_dem, strlen(c + 1) + 1);
162 154 else
163 155 bcopy(c + 1, s + 1, strlen(c + 1) + 1);
164 156 }
165 157 }
166 158
167 159 len = strlen(dmp->dm_dem); /* recompute length of buffer */
168 160
169 161 /*
170 162 * Compute bytes remaining
171 163 */
172 164 resid = (dmp->dm_buf + dmp->dm_len) - (dmp->dm_dem + len);
173 165
174 166 /*
175 167 * If we want to append the mangled name as well and there is enough
176 168 * space for "[]\0" and at least one character, append "["+name+"]".
177 169 */
178 170 if ((dmp->dm_flags & MDB_DM_MANGLED) && resid > 3) {
179 171 char *p = dmp->dm_dem + len;
180 172
181 173 *p++ = '[';
182 174 (void) strncpy(p, name, resid - 3);
183 175 p[resid - 3] = '\0';
184 176 p += strlen(p);
185 177 (void) strcpy(p, "]");
186 178 }
187 179
188 180 /*
189 181 * We return the whole string
190 182 */
191 183 return (dmp->dm_buf);
192 184 }
193 185
194 186 /*
↓ open down ↓ |
103 lines elided |
↑ open up ↑ |
195 187 * Take a name: (the foo`bar` is optional)
196 188 * foo`bar`__mangled_
197 189 * and put:
198 190 * foo`bar`demangled
199 191 * into dmp->dm_buf. Point dmp->dm_dem to the beginning of the
200 192 * demangled section of the result.
201 193 */
202 194 static int
203 195 mdb_dem_process(mdb_demangler_t *dmp, const char *name)
204 196 {
205 - char *buf = dmp->dm_buf;
206 - size_t len = dmp->dm_len;
197 + char *res = NULL;
198 + size_t reslen = 0;
207 199
208 200 char *prefix = strrchr(name, '`');
209 - size_t prefixlen;
201 + size_t prefixlen = 0;
210 202
211 203 if (prefix) {
212 204 prefix++; /* the ` is part of the prefix */
213 205 prefixlen = prefix - name;
206 + }
214 207
215 - if (prefixlen >= len)
216 - return (DEMANGLE_ESPACE);
208 + res = sysdemangle(name + prefixlen, dmp->dm_lang, &mdb_dem_demops);
209 + if (res == NULL) {
210 + if (errno != EINVAL)
211 + mdb_warn("Error while demangling");
212 + return (-1);
213 + }
217 214
218 - (void) strncpy(buf, name, prefixlen);
215 + reslen = (res != NULL) ? strlen(res) : 0;
216 + reslen += prefixlen;
217 + reslen += 1;
219 218
220 - /*
221 - * Fix up the arguments to dmp->dm_convert()
222 - */
223 - name += prefixlen;
224 - buf += prefixlen;
225 - len -= prefixlen;
219 + if (reslen > dmp->dm_len) {
220 + mdb_free(dmp->dm_buf, dmp->dm_len);
221 +
222 + dmp->dm_buf = mdb_zalloc(reslen, UM_SLEEP);
223 + if (dmp->dm_buf == NULL) {
224 + dmp->dm_len = 0;
225 + mdb_warn("Unable to allocate memory for demangling");
226 + return (-1);
227 + }
228 + dmp->dm_len = reslen;
226 229 }
227 230
231 + if (prefixlen > 0)
232 + (void) strlcpy(dmp->dm_buf, name, prefixlen + 1);
233 + else
234 + *dmp->dm_buf = '\0';
235 +
236 + if (res != NULL) {
237 + (void) strlcat(dmp->dm_buf, res, dmp->dm_len);
238 + mdb_dem_free(res, strlen(res) + 1);
239 + }
240 +
228 241 /*
229 242 * Save the position of the demangled string for mdb_dem_filter()
230 243 */
231 - dmp->dm_dem = buf;
244 + dmp->dm_dem = dmp->dm_buf + prefixlen;
232 245
233 - return (dmp->dm_convert(name, buf, len));
246 + return (0);
234 247 }
235 248
249 +/* used by mdb_io.c:iob_addr2str */
236 250 const char *
237 251 mdb_dem_convert(mdb_demangler_t *dmp, const char *name)
238 252 {
239 - int err;
253 + if (mdb_dem_process(dmp, name) != 0 ||
254 + strcmp(dmp->dm_buf, name) == 0)
255 + return (name);
240 256
241 - while ((err = mdb_dem_process(dmp, name)) == DEMANGLE_ESPACE) {
242 - size_t len = dmp->dm_len * 2;
243 - char *buf = mdb_alloc(len, UM_NOSLEEP);
244 -
245 - if (buf == NULL) {
246 - mdb_warn("failed to allocate memory for demangling");
247 - return (name); /* just return original name */
248 - }
249 -
250 - mdb_free(dmp->dm_buf, dmp->dm_len);
251 - dmp->dm_buf = buf;
252 - dmp->dm_len = len;
253 - }
254 -
255 - if (err != 0 || strcmp(dmp->dm_buf, name) == 0)
256 - return (name); /* return original name if not mangled */
257 -
258 257 return (mdb_dem_filter(dmp, name));
259 258 }
260 259
261 260 /*ARGSUSED*/
262 261 int
263 262 cmd_demangle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
264 263 {
265 264 mdb_demangler_t *dmp = mdb.m_demangler;
266 - const char *path = LIB_DEMANGLE;
267 265
268 - if (argc > 1 || (argc > 0 && argv->a_type != MDB_TYPE_STRING))
266 + if (argc > 0)
269 267 return (DCMD_USAGE);
270 268
271 - if (argc > 0) {
272 - if (dmp != NULL)
273 - mdb_dem_unload(mdb.m_demangler);
274 - path = argv->a_un.a_str;
275 - }
276 -
277 - if (dmp != NULL && argc == 0 && !(mdb.m_flags & MDB_FL_DEMANGLE)) {
269 + if (dmp != NULL && !(mdb.m_flags & MDB_FL_DEMANGLE)) {
278 270 mdb_printf("C++ symbol demangling enabled\n");
279 271 mdb.m_flags |= MDB_FL_DEMANGLE;
280 272
281 - } else if (dmp == NULL || argc > 0) {
282 - if ((mdb.m_demangler = mdb_dem_load(path)) != NULL) {
273 + } else if (dmp == NULL) {
274 + if ((mdb.m_demangler = mdb_dem_load()) != NULL) {
283 275 mdb_printf("C++ symbol demangling enabled\n");
284 276 mdb.m_flags |= MDB_FL_DEMANGLE;
285 277 } else {
286 - mdb_warn("failed to load C++ demangler %s", path);
278 + mdb_warn("no memory to load C++ demangler");
287 279 mdb.m_flags &= ~MDB_FL_DEMANGLE;
288 280 }
289 281
290 282 } else {
291 283 mdb_dem_unload(mdb.m_demangler);
292 284 mdb.m_flags &= ~MDB_FL_DEMANGLE;
293 285 mdb.m_demangler = NULL;
294 286 mdb_printf("C++ symbol demangling disabled\n");
295 287 }
296 288
297 289 return (DCMD_OK);
298 290 }
299 291
300 292 /*ARGSUSED*/
301 293 int
302 294 cmd_demflags(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
303 295 {
304 296 static const char *const dm_desc[] = {
305 297 "static/const/volatile member func qualifiers displayed",
306 298 "scope resolution specifiers displayed",
307 299 "function arguments displayed",
308 300 "mangled name displayed"
309 301 };
310 302
311 303 mdb_demangler_t *dmp = mdb.m_demangler;
312 304 int i;
313 305
314 306 if (argc > 0)
315 307 return (DCMD_USAGE);
316 308
317 309 if (dmp == NULL || !(mdb.m_flags & MDB_FL_DEMANGLE)) {
318 310 mdb_warn("C++ demangling facility is currently disabled\n");
319 311 return (DCMD_ERR);
320 312 }
321 313
322 314 if (flags & DCMD_ADDRSPEC)
323 315 dmp->dm_flags = ((uint_t)addr & MDB_DM_ALL);
324 316
325 317 for (i = 0; i < sizeof (dm_desc) / sizeof (dm_desc[0]); i++) {
326 318 mdb_printf("0x%x\t%s\t%s\n", 1 << i,
327 319 (dmp->dm_flags & (1 << i)) ? "on" : "off", dm_desc[i]);
328 320 }
329 321
330 322 return (DCMD_OK);
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
331 323 }
332 324
333 325 /*ARGSUSED*/
334 326 int
335 327 cmd_demstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
336 328 {
337 329 if ((flags & DCMD_ADDRSPEC) || argc == 0)
338 330 return (DCMD_USAGE);
339 331
340 332 if (mdb.m_demangler == NULL && (mdb.m_demangler =
341 - mdb_dem_load(LIB_DEMANGLE)) == NULL) {
342 - mdb_warn("failed to load C++ demangler %s", LIB_DEMANGLE);
333 + mdb_dem_load()) == NULL) {
334 + mdb_warn("failed to load demangler");
343 335 return (DCMD_ERR);
344 336 }
345 337
346 338 for (; argc != 0; argc--, argv++) {
347 339 mdb_printf("%s == %s\n", argv->a_un.a_str,
348 340 mdb_dem_convert(mdb.m_demangler, argv->a_un.a_str));
349 341 }
350 342
351 343 return (DCMD_OK);
352 344 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX