4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <mdb/mdb_modapi.h>
28 #include <mdb/mdb_demangle.h>
29 #include <mdb/mdb_err.h>
38 #define LIB_DEMANGLE "libstdc++.so.6"
41 mdb_dem_load(const char *path
)
46 if ((hdl
= dlmopen(LM_ID_BASE
, path
, RTLD_LAZY
| RTLD_LOCAL
)) == NULL
) {
47 (void) set_errno(EMDB_RTLD
);
51 if ((func
= dlsym(hdl
, "__cxa_demangle")) == NULL
) {
53 (void) set_errno(EMDB_NODEM
);
57 dmp
= (mdb_demangler_t
*)mdb_alloc(sizeof (mdb_demangler_t
), UM_SLEEP
);
58 (void) strncpy(dmp
->dm_pathname
, path
, MAXPATHLEN
);
59 dmp
->dm_pathname
[MAXPATHLEN
- 1] = '\0';
61 dmp
->dm_convert
= (char *(*)(const char *, char *, size_t *, int *))
63 dmp
->dm_len
= MDB_SYM_NAMLEN
* 2;
64 dmp
->dm_buf
= (char *)mdb_alloc(dmp
->dm_len
, UM_SLEEP
);
65 dmp
->dm_flags
= MDB_DM_SCOPE
;
71 mdb_dem_unload(mdb_demangler_t
*dmp
)
73 (void) dlclose(dmp
->dm_handle
);
74 mdb_free(dmp
->dm_buf
, dmp
->dm_len
);
75 mdb_free(dmp
, sizeof (mdb_demangler_t
));
79 mdb_dem_filter(mdb_demangler_t
*dmp
, const char *name
)
81 static const char s_pref
[] = "static ";
82 static const char c_suff
[] = " const";
83 static const char v_suff
[] = " volatile";
86 * We process dm_dem, which skips the prefix in dm_buf (if any)
88 size_t len
= strlen(dmp
->dm_dem
);
89 char *end
= dmp
->dm_dem
+ len
;
93 * If static, const, and volatile qualifiers should not be displayed,
94 * rip all of them out of dmp->dm_dem.
96 if (!(dmp
->dm_flags
& MDB_DM_QUAL
)) {
97 if (strncmp(dmp
->dm_dem
, s_pref
, sizeof (s_pref
) - 1) == 0) {
98 bcopy(dmp
->dm_dem
+ sizeof (s_pref
) - 1, dmp
->dm_dem
,
99 len
- (sizeof (s_pref
) - 1) + 1);
100 end
-= sizeof (s_pref
) - 1;
101 len
-= sizeof (s_pref
) - 1;
105 if (len
> sizeof (c_suff
) - 1 &&
106 strcmp(end
- (sizeof (c_suff
) - 1), c_suff
) == 0) {
107 end
-= sizeof (c_suff
) - 1;
108 len
-= sizeof (c_suff
) - 1;
112 if (len
> sizeof (v_suff
) - 1 &&
113 strcmp(end
- (sizeof (v_suff
) - 1), v_suff
) == 0) {
114 end
-= sizeof (v_suff
) - 1;
115 len
-= sizeof (v_suff
) - 1;
124 * If function arguments should not be displayed, remove everything
125 * between the outermost set of parentheses in dmp->dm_dem.
127 if (!(dmp
->dm_flags
& MDB_DM_FUNCARG
)) {
128 char *lp
= strchr(dmp
->dm_dem
, '(');
129 char *rp
= strrchr(dmp
->dm_dem
, ')');
131 if (lp
!= NULL
&& rp
!= NULL
)
132 bcopy(rp
+ 1, lp
, strlen(rp
) + 1);
136 * If function scope specifiers should not be displayed, remove text
137 * from the leftmost space to the rightmost colon prior to any paren.
139 if (!(dmp
->dm_flags
& MDB_DM_SCOPE
)) {
140 char *c
, *s
, *lp
= strchr(dmp
->dm_dem
, '(');
145 c
= strrchr(dmp
->dm_dem
, ':');
146 s
= strchr(dmp
->dm_dem
, ' ');
152 if (s
== NULL
|| s
> c
)
153 bcopy(c
+ 1, dmp
->dm_dem
, strlen(c
+ 1) + 1);
155 bcopy(c
+ 1, s
+ 1, strlen(c
+ 1) + 1);
159 len
= strlen(dmp
->dm_dem
); /* recompute length of buffer */
162 * Compute bytes remaining
164 resid
= (dmp
->dm_buf
+ dmp
->dm_len
) - (dmp
->dm_dem
+ len
);
167 * If we want to append the mangled name as well and there is enough
168 * space for "[]\0" and at least one character, append "["+name+"]".
170 if ((dmp
->dm_flags
& MDB_DM_MANGLED
) && resid
> 3) {
171 char *p
= dmp
->dm_dem
+ len
;
174 (void) strncpy(p
, name
, resid
- 3);
177 (void) strcpy(p
, "]");
181 * We return the whole string
183 return (dmp
->dm_buf
);
187 * Take a name: (the foo`bar` is optional)
191 * into dmp->dm_buf. Point dmp->dm_dem to the beginning of the
192 * demangled section of the result.
195 mdb_dem_process(mdb_demangler_t
*dmp
, const char *name
)
197 char *buf
= dmp
->dm_buf
;
198 size_t len
= dmp
->dm_len
;
200 const char *prefix
= strrchr(name
, '`');
205 prefix
++; /* the ` is part of the prefix */
206 prefixlen
= prefix
- name
;
208 if (prefixlen
>= len
)
211 (void) strncpy(buf
, name
, prefixlen
);
214 * Fix up the arguments to dmp->dm_convert()
222 * Save the position of the demangled string for mdb_dem_filter()
226 dmp
->dm_convert(name
, buf
, &len
, &ret
);
231 mdb_dem_convert(mdb_demangler_t
*dmp
, const char *name
)
235 while ((err
= mdb_dem_process(dmp
, name
)) == -1) {
236 size_t len
= dmp
->dm_len
* 2;
237 char *buf
= (char *)mdb_alloc(len
, UM_NOSLEEP
);
240 mdb_warn("failed to allocate memory for demangling");
241 return (name
); /* just return original name */
244 mdb_free(dmp
->dm_buf
, dmp
->dm_len
);
249 if (err
!= 0 || strcmp(dmp
->dm_buf
, name
) == 0)
250 return (name
); /* return original name if not mangled */
252 return (mdb_dem_filter(dmp
, name
));
257 cmd_demangle(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
259 mdb_demangler_t
*dmp
= mdb
.m_demangler
;
260 const char *path
= LIB_DEMANGLE
;
262 if (argc
> 1 || (argc
> 0 && argv
->a_type
!= MDB_TYPE_STRING
))
267 mdb_dem_unload(mdb
.m_demangler
);
268 path
= argv
->a_un
.a_str
;
271 if (dmp
!= NULL
&& argc
== 0 && !(mdb
.m_flags
& MDB_FL_DEMANGLE
)) {
272 mdb_printf("C++ symbol demangling enabled\n");
273 mdb
.m_flags
|= MDB_FL_DEMANGLE
;
275 } else if (dmp
== NULL
|| argc
> 0) {
276 if ((mdb
.m_demangler
= mdb_dem_load(path
)) != NULL
) {
277 mdb_printf("C++ symbol demangling enabled\n");
278 mdb
.m_flags
|= MDB_FL_DEMANGLE
;
280 mdb_warn("failed to load C++ demangler %s", path
);
281 mdb
.m_flags
&= ~MDB_FL_DEMANGLE
;
285 mdb_dem_unload(mdb
.m_demangler
);
286 mdb
.m_flags
&= ~MDB_FL_DEMANGLE
;
287 mdb
.m_demangler
= NULL
;
288 mdb_printf("C++ symbol demangling disabled\n");
296 cmd_demflags(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
298 static const char *const dm_desc
[] = {
299 "static/const/volatile member func qualifiers displayed",
300 "scope resolution specifiers displayed",
301 "function arguments displayed",
302 "mangled name displayed"
305 mdb_demangler_t
*dmp
= mdb
.m_demangler
;
311 if (dmp
== NULL
|| !(mdb
.m_flags
& MDB_FL_DEMANGLE
)) {
312 mdb_warn("C++ demangling facility is currently disabled\n");
316 if (flags
& DCMD_ADDRSPEC
)
317 dmp
->dm_flags
= ((uint_t
)addr
& MDB_DM_ALL
);
319 for (i
= 0; i
< sizeof (dm_desc
) / sizeof (dm_desc
[0]); i
++) {
320 mdb_printf("0x%x\t%s\t%s\n", 1 << i
,
321 (dmp
->dm_flags
& (1 << i
)) ? "on" : "off", dm_desc
[i
]);
329 cmd_demstr(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
331 if ((flags
& DCMD_ADDRSPEC
) || argc
== 0)
334 if (mdb
.m_demangler
== NULL
&& (mdb
.m_demangler
=
335 mdb_dem_load(LIB_DEMANGLE
)) == NULL
) {
336 mdb_warn("failed to load C++ demangler " LIB_DEMANGLE
);
340 for (; argc
!= 0; argc
--, argv
++) {
341 mdb_printf("%s == %s\n", argv
->a_un
.a_str
,
342 mdb_dem_convert(mdb
.m_demangler
, argv
->a_un
.a_str
));