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