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