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