17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
254226f635SJason King *
264226f635SJason King * Copyright 2018 Jason King
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
29*6a6cfa5dSJason King /*
30*6a6cfa5dSJason King * Copyright (c) 2019, Joyent, Inc. All rights reserved.
31*6a6cfa5dSJason King */
32*6a6cfa5dSJason King
337c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
347c478bd9Sstevel@tonic-gate #include <mdb/mdb_demangle.h>
357c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
367c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include <strings.h>
397c478bd9Sstevel@tonic-gate #include <unistd.h>
407c478bd9Sstevel@tonic-gate #include <dlfcn.h>
417c478bd9Sstevel@tonic-gate #include <link.h>
427c478bd9Sstevel@tonic-gate
434226f635SJason King static void *
mdb_dem_alloc(size_t len)444226f635SJason King mdb_dem_alloc(size_t len)
457c478bd9Sstevel@tonic-gate {
464226f635SJason King return (mdb_alloc(len, UM_SLEEP));
474226f635SJason King }
487c478bd9Sstevel@tonic-gate
494226f635SJason King static void
mdb_dem_free(void * p,size_t len)504226f635SJason King mdb_dem_free(void *p, size_t len)
514226f635SJason King {
524226f635SJason King mdb_free(p, len);
534226f635SJason King }
547c478bd9Sstevel@tonic-gate
554226f635SJason King static sysdem_ops_t mdb_dem_demops = {
564226f635SJason King .alloc = mdb_dem_alloc,
574226f635SJason King .free = mdb_dem_free
584226f635SJason King };
597c478bd9Sstevel@tonic-gate
604226f635SJason King mdb_demangler_t *
mdb_dem_load(void)614226f635SJason King mdb_dem_load(void)
624226f635SJason King {
634226f635SJason King mdb_demangler_t *dmp;
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate dmp = mdb_alloc(sizeof (mdb_demangler_t), UM_SLEEP);
664226f635SJason King dmp->dm_len = 0;
674226f635SJason King dmp->dm_buf = NULL;
687c478bd9Sstevel@tonic-gate dmp->dm_flags = MDB_DM_SCOPE;
69*6a6cfa5dSJason King dmp->dm_lang = SYSDEM_LANG_AUTO;
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate return (dmp);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate void
mdb_dem_unload(mdb_demangler_t * dmp)757c478bd9Sstevel@tonic-gate mdb_dem_unload(mdb_demangler_t *dmp)
767c478bd9Sstevel@tonic-gate {
777c478bd9Sstevel@tonic-gate mdb_free(dmp->dm_buf, dmp->dm_len);
787c478bd9Sstevel@tonic-gate mdb_free(dmp, sizeof (mdb_demangler_t));
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate static const char *
mdb_dem_filter(mdb_demangler_t * dmp,const char * name)827c478bd9Sstevel@tonic-gate mdb_dem_filter(mdb_demangler_t *dmp, const char *name)
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate static const char s_pref[] = "static ";
857c478bd9Sstevel@tonic-gate static const char c_suff[] = " const";
867c478bd9Sstevel@tonic-gate static const char v_suff[] = " volatile";
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate * We process dm_dem, which skips the prefix in dm_buf (if any)
907c478bd9Sstevel@tonic-gate */
917c478bd9Sstevel@tonic-gate size_t len = strlen(dmp->dm_dem);
927c478bd9Sstevel@tonic-gate char *end = dmp->dm_dem + len;
937c478bd9Sstevel@tonic-gate size_t resid;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate * If static, const, and volatile qualifiers should not be displayed,
977c478bd9Sstevel@tonic-gate * rip all of them out of dmp->dm_dem.
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate if (!(dmp->dm_flags & MDB_DM_QUAL)) {
1007c478bd9Sstevel@tonic-gate if (strncmp(dmp->dm_dem, s_pref, sizeof (s_pref) - 1) == 0) {
1017c478bd9Sstevel@tonic-gate bcopy(dmp->dm_dem + sizeof (s_pref) - 1, dmp->dm_dem,
1027c478bd9Sstevel@tonic-gate len - (sizeof (s_pref) - 1) + 1);
1037c478bd9Sstevel@tonic-gate end -= sizeof (s_pref) - 1;
1047c478bd9Sstevel@tonic-gate len -= sizeof (s_pref) - 1;
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate for (;;) {
1087c478bd9Sstevel@tonic-gate if (len > sizeof (c_suff) - 1 &&
1097c478bd9Sstevel@tonic-gate strcmp(end - (sizeof (c_suff) - 1), c_suff) == 0) {
1107c478bd9Sstevel@tonic-gate end -= sizeof (c_suff) - 1;
1117c478bd9Sstevel@tonic-gate len -= sizeof (c_suff) - 1;
1127c478bd9Sstevel@tonic-gate *end = '\0';
1137c478bd9Sstevel@tonic-gate continue;
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate if (len > sizeof (v_suff) - 1 &&
1167c478bd9Sstevel@tonic-gate strcmp(end - (sizeof (v_suff) - 1), v_suff) == 0) {
1177c478bd9Sstevel@tonic-gate end -= sizeof (v_suff) - 1;
1187c478bd9Sstevel@tonic-gate len -= sizeof (v_suff) - 1;
1197c478bd9Sstevel@tonic-gate *end = '\0';
1207c478bd9Sstevel@tonic-gate continue;
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate break;
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate * If function arguments should not be displayed, remove everything
1287c478bd9Sstevel@tonic-gate * between the outermost set of parentheses in dmp->dm_dem.
1297c478bd9Sstevel@tonic-gate */
1307c478bd9Sstevel@tonic-gate if (!(dmp->dm_flags & MDB_DM_FUNCARG)) {
1317c478bd9Sstevel@tonic-gate char *lp = strchr(dmp->dm_dem, '(');
1327c478bd9Sstevel@tonic-gate char *rp = strrchr(dmp->dm_dem, ')');
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate if (lp != NULL && rp != NULL)
1357c478bd9Sstevel@tonic-gate bcopy(rp + 1, lp, strlen(rp) + 1);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate * If function scope specifiers should not be displayed, remove text
1407c478bd9Sstevel@tonic-gate * from the leftmost space to the rightmost colon prior to any paren.
1417c478bd9Sstevel@tonic-gate */
1427c478bd9Sstevel@tonic-gate if (!(dmp->dm_flags & MDB_DM_SCOPE)) {
1437c478bd9Sstevel@tonic-gate char *c, *s, *lp = strchr(dmp->dm_dem, '(');
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate if (lp != NULL)
1467c478bd9Sstevel@tonic-gate *lp = '\0';
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate c = strrchr(dmp->dm_dem, ':');
1497c478bd9Sstevel@tonic-gate s = strchr(dmp->dm_dem, ' ');
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate if (lp != NULL)
1527c478bd9Sstevel@tonic-gate *lp = '(';
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate if (c != NULL) {
1557c478bd9Sstevel@tonic-gate if (s == NULL || s > c)
1567c478bd9Sstevel@tonic-gate bcopy(c + 1, dmp->dm_dem, strlen(c + 1) + 1);
1577c478bd9Sstevel@tonic-gate else
1587c478bd9Sstevel@tonic-gate bcopy(c + 1, s + 1, strlen(c + 1) + 1);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate len = strlen(dmp->dm_dem); /* recompute length of buffer */
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate * Compute bytes remaining
1667c478bd9Sstevel@tonic-gate */
1677c478bd9Sstevel@tonic-gate resid = (dmp->dm_buf + dmp->dm_len) - (dmp->dm_dem + len);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate * If we want to append the mangled name as well and there is enough
1717c478bd9Sstevel@tonic-gate * space for "[]\0" and at least one character, append "["+name+"]".
1727c478bd9Sstevel@tonic-gate */
1737c478bd9Sstevel@tonic-gate if ((dmp->dm_flags & MDB_DM_MANGLED) && resid > 3) {
1747c478bd9Sstevel@tonic-gate char *p = dmp->dm_dem + len;
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate *p++ = '[';
1777c478bd9Sstevel@tonic-gate (void) strncpy(p, name, resid - 3);
1787c478bd9Sstevel@tonic-gate p[resid - 3] = '\0';
1797c478bd9Sstevel@tonic-gate p += strlen(p);
1807c478bd9Sstevel@tonic-gate (void) strcpy(p, "]");
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate * We return the whole string
1857c478bd9Sstevel@tonic-gate */
1867c478bd9Sstevel@tonic-gate return (dmp->dm_buf);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate * Take a name: (the foo`bar` is optional)
1917c478bd9Sstevel@tonic-gate * foo`bar`__mangled_
1927c478bd9Sstevel@tonic-gate * and put:
1937c478bd9Sstevel@tonic-gate * foo`bar`demangled
1947c478bd9Sstevel@tonic-gate * into dmp->dm_buf. Point dmp->dm_dem to the beginning of the
1957c478bd9Sstevel@tonic-gate * demangled section of the result.
1967c478bd9Sstevel@tonic-gate */
1977c478bd9Sstevel@tonic-gate static int
mdb_dem_process(mdb_demangler_t * dmp,const char * name)1987c478bd9Sstevel@tonic-gate mdb_dem_process(mdb_demangler_t *dmp, const char *name)
1997c478bd9Sstevel@tonic-gate {
2004226f635SJason King char *res = NULL;
2014226f635SJason King size_t reslen = 0;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate char *prefix = strrchr(name, '`');
2044226f635SJason King size_t prefixlen = 0;
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate if (prefix) {
2077c478bd9Sstevel@tonic-gate prefix++; /* the ` is part of the prefix */
2087c478bd9Sstevel@tonic-gate prefixlen = prefix - name;
2094226f635SJason King }
2107c478bd9Sstevel@tonic-gate
2114226f635SJason King res = sysdemangle(name + prefixlen, dmp->dm_lang, &mdb_dem_demops);
2124226f635SJason King if (res == NULL) {
213*6a6cfa5dSJason King /*
214*6a6cfa5dSJason King * EINVAL indicates the name is not a properly mangled name
215*6a6cfa5dSJason King * (or perhaps is truncated so it cannot be correctly
216*6a6cfa5dSJason King * demangled) while ENOTSUP means sysdemangle could not
217*6a6cfa5dSJason King * determine which language was used to mangle the name when
218*6a6cfa5dSJason King * SYSDEM_LANG_AUTO is used (the name might not be mangled,
219*6a6cfa5dSJason King * the name could be truncated enough to prevent determination
220*6a6cfa5dSJason King * of the name, etc).
221*6a6cfa5dSJason King *
222*6a6cfa5dSJason King * Both are allowed/expected failure modes, so in both cases
223*6a6cfa5dSJason King * do not emit a warning -- let the caller display the
224*6a6cfa5dSJason King * original name.
225*6a6cfa5dSJason King */
226*6a6cfa5dSJason King if (errno != EINVAL && errno != ENOTSUP)
2274226f635SJason King mdb_warn("Error while demangling");
2284226f635SJason King return (-1);
2294226f635SJason King }
2307c478bd9Sstevel@tonic-gate
2314226f635SJason King reslen = (res != NULL) ? strlen(res) : 0;
2324226f635SJason King reslen += prefixlen;
2334226f635SJason King reslen += 1;
2347c478bd9Sstevel@tonic-gate
2354226f635SJason King if (reslen > dmp->dm_len) {
2364226f635SJason King mdb_free(dmp->dm_buf, dmp->dm_len);
2374226f635SJason King
2384226f635SJason King dmp->dm_buf = mdb_zalloc(reslen, UM_SLEEP);
2394226f635SJason King if (dmp->dm_buf == NULL) {
2404226f635SJason King dmp->dm_len = 0;
2414226f635SJason King mdb_warn("Unable to allocate memory for demangling");
2424226f635SJason King return (-1);
2434226f635SJason King }
2444226f635SJason King dmp->dm_len = reslen;
2454226f635SJason King }
2464226f635SJason King
2474226f635SJason King if (prefixlen > 0)
2484226f635SJason King (void) strlcpy(dmp->dm_buf, name, prefixlen + 1);
2494226f635SJason King else
2504226f635SJason King *dmp->dm_buf = '\0';
2514226f635SJason King
2524226f635SJason King if (res != NULL) {
2534226f635SJason King (void) strlcat(dmp->dm_buf, res, dmp->dm_len);
2544226f635SJason King mdb_dem_free(res, strlen(res) + 1);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate * Save the position of the demangled string for mdb_dem_filter()
2597c478bd9Sstevel@tonic-gate */
2604226f635SJason King dmp->dm_dem = dmp->dm_buf + prefixlen;
2617c478bd9Sstevel@tonic-gate
2624226f635SJason King return (0);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate
2654226f635SJason King /* used by mdb_io.c:iob_addr2str */
2667c478bd9Sstevel@tonic-gate const char *
mdb_dem_convert(mdb_demangler_t * dmp,const char * name)2677c478bd9Sstevel@tonic-gate mdb_dem_convert(mdb_demangler_t *dmp, const char *name)
2687c478bd9Sstevel@tonic-gate {
2694226f635SJason King if (mdb_dem_process(dmp, name) != 0 ||
2704226f635SJason King strcmp(dmp->dm_buf, name) == 0)
2714226f635SJason King return (name);
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate return (mdb_dem_filter(dmp, name));
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2777c478bd9Sstevel@tonic-gate int
cmd_demangle(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2787c478bd9Sstevel@tonic-gate cmd_demangle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate mdb_demangler_t *dmp = mdb.m_demangler;
2817c478bd9Sstevel@tonic-gate
2824226f635SJason King if (argc > 0)
2837c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
2847c478bd9Sstevel@tonic-gate
2854226f635SJason King if (dmp != NULL && !(mdb.m_flags & MDB_FL_DEMANGLE)) {
2867c478bd9Sstevel@tonic-gate mdb_printf("C++ symbol demangling enabled\n");
2877c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_DEMANGLE;
2887c478bd9Sstevel@tonic-gate
2894226f635SJason King } else if (dmp == NULL) {
2904226f635SJason King if ((mdb.m_demangler = mdb_dem_load()) != NULL) {
2917c478bd9Sstevel@tonic-gate mdb_printf("C++ symbol demangling enabled\n");
2927c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_DEMANGLE;
2937c478bd9Sstevel@tonic-gate } else {
2944226f635SJason King mdb_warn("no memory to load C++ demangler");
2957c478bd9Sstevel@tonic-gate mdb.m_flags &= ~MDB_FL_DEMANGLE;
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate } else {
2997c478bd9Sstevel@tonic-gate mdb_dem_unload(mdb.m_demangler);
3007c478bd9Sstevel@tonic-gate mdb.m_flags &= ~MDB_FL_DEMANGLE;
3017c478bd9Sstevel@tonic-gate mdb.m_demangler = NULL;
3027c478bd9Sstevel@tonic-gate mdb_printf("C++ symbol demangling disabled\n");
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate return (DCMD_OK);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3097c478bd9Sstevel@tonic-gate int
cmd_demflags(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3107c478bd9Sstevel@tonic-gate cmd_demflags(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3117c478bd9Sstevel@tonic-gate {
3127c478bd9Sstevel@tonic-gate static const char *const dm_desc[] = {
3137c478bd9Sstevel@tonic-gate "static/const/volatile member func qualifiers displayed",
3147c478bd9Sstevel@tonic-gate "scope resolution specifiers displayed",
3157c478bd9Sstevel@tonic-gate "function arguments displayed",
3167c478bd9Sstevel@tonic-gate "mangled name displayed"
3177c478bd9Sstevel@tonic-gate };
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate mdb_demangler_t *dmp = mdb.m_demangler;
3207c478bd9Sstevel@tonic-gate int i;
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate if (argc > 0)
3237c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate if (dmp == NULL || !(mdb.m_flags & MDB_FL_DEMANGLE)) {
3267c478bd9Sstevel@tonic-gate mdb_warn("C++ demangling facility is currently disabled\n");
3277c478bd9Sstevel@tonic-gate return (DCMD_ERR);
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC)
3317c478bd9Sstevel@tonic-gate dmp->dm_flags = ((uint_t)addr & MDB_DM_ALL);
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (dm_desc) / sizeof (dm_desc[0]); i++) {
3347c478bd9Sstevel@tonic-gate mdb_printf("0x%x\t%s\t%s\n", 1 << i,
3357c478bd9Sstevel@tonic-gate (dmp->dm_flags & (1 << i)) ? "on" : "off", dm_desc[i]);
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate return (DCMD_OK);
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3427c478bd9Sstevel@tonic-gate int
cmd_demstr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3437c478bd9Sstevel@tonic-gate cmd_demstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) || argc == 0)
3467c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate if (mdb.m_demangler == NULL && (mdb.m_demangler =
3494226f635SJason King mdb_dem_load()) == NULL) {
3504226f635SJason King mdb_warn("failed to load demangler");
3517c478bd9Sstevel@tonic-gate return (DCMD_ERR);
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate for (; argc != 0; argc--, argv++) {
3557c478bd9Sstevel@tonic-gate mdb_printf("%s == %s\n", argv->a_un.a_str,
3567c478bd9Sstevel@tonic-gate mdb_dem_convert(mdb.m_demangler, argv->a_un.a_str));
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate return (DCMD_OK);
3607c478bd9Sstevel@tonic-gate }
361