Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <msg.h>
     28 #include <_rtld.h>
     29 #include <conv.h>
     30 #include <sys/mdb_modapi.h>
     31 #include <sys/param.h>
     32 #include <stdlib.h>
     33 
     34 /*
     35  * Data structure for walkers.
     36  */
     37 typedef struct {
     38 	uint_t	w_flags;
     39 } W_desc;
     40 
     41 /*
     42  * Flags values for dcmds
     43  */
     44 
     45 #define	RTLD_FLG_VERBOSE	0x0001		/* verbose output */
     46 
     47 static const mdb_bitmask_t rtflags_bits[] = {
     48 	{ MSG_ORIG(MSG_FLG_ISMAIN), FLG_RT_ISMAIN, FLG_RT_ISMAIN},
     49 	{ MSG_ORIG(MSG_FLG_IMGALLOC), FLG_RT_IMGALLOC, FLG_RT_IMGALLOC},
     50 	{ MSG_ORIG(MSG_FLG_RELOCED), FLG_RT_RELOCED, FLG_RT_RELOCED},
     51 	{ MSG_ORIG(MSG_FLG_SETGROUP), FLG_RT_SETGROUP, FLG_RT_SETGROUP},
     52 	{ MSG_ORIG(MSG_FLG_HWCAP), FLG_RT_HWCAP, FLG_RT_HWCAP},
     53 	{ MSG_ORIG(MSG_FLG_OBJECT), FLG_RT_OBJECT, FLG_RT_OBJECT},
     54 	{ MSG_ORIG(MSG_FLG_NEWLOAD), FLG_RT_NEWLOAD, FLG_RT_NEWLOAD},
     55 	{ MSG_ORIG(MSG_FLG_NODUMP), FLG_RT_NODUMP, FLG_RT_NODUMP},
     56 	{ MSG_ORIG(MSG_FLG_DELETE), FLG_RT_DELETE, FLG_RT_DELETE},
     57 	{ MSG_ORIG(MSG_FLG_ANALYZED), FLG_RT_ANALYZED, FLG_RT_ANALYZED},
     58 	{ MSG_ORIG(MSG_FLG_INITDONE), FLG_RT_INITDONE, FLG_RT_INITDONE},
     59 	{ MSG_ORIG(MSG_FLG_TRANS), FLG_RT_TRANS, FLG_RT_TRANS},
     60 	{ MSG_ORIG(MSG_FLG_FIXED), FLG_RT_FIXED, FLG_RT_FIXED},
     61 	{ MSG_ORIG(MSG_FLG_PRELOAD), FLG_RT_PRELOAD, FLG_RT_PRELOAD},
     62 	{ MSG_ORIG(MSG_FLG_ALTER), FLG_RT_ALTER, FLG_RT_ALTER},
     63 	{ MSG_ORIG(MSG_FLG_LOADFLTR), FLG_RT_LOADFLTR, FLG_RT_LOADFLTR},
     64 	{ MSG_ORIG(MSG_FLG_AUDIT), FLG_RT_AUDIT, FLG_RT_AUDIT},
     65 	{ MSG_ORIG(MSG_FLG_MODESET), FLG_RT_MODESET, FLG_RT_MODESET},
     66 	{ MSG_ORIG(MSG_FLG_ANALZING), FLG_RT_ANALZING, FLG_RT_ANALZING},
     67 	{ MSG_ORIG(MSG_FLG_INITFRST), FLG_RT_INITFRST, FLG_RT_INITFRST},
     68 	{ MSG_ORIG(MSG_FLG_NOOPEN), FLG_RT_NOOPEN, FLG_RT_NOOPEN},
     69 	{ MSG_ORIG(MSG_FLG_FINICLCT), FLG_RT_FINICLCT, FLG_RT_FINICLCT},
     70 	{ MSG_ORIG(MSG_FLG_INITCALL), FLG_RT_INITCALL, FLG_RT_INITCALL},
     71 	{ MSG_ORIG(MSG_FLG_OBJINTPO), FLG_RT_OBJINTPO, FLG_RT_OBJINTPO},
     72 	{ MSG_ORIG(MSG_FLG_SYMINTPO), FLG_RT_SYMINTPO, FLG_RT_SYMINTPO},
     73 	{ MSG_ORIG(MSG_FLG_MOVE), FLG_RT_MOVE, FLG_RT_MOVE},
     74 	{ MSG_ORIG(MSG_FLG_RELOCING), FLG_RT_RELOCING, FLG_RT_RELOCING},
     75 	{ MSG_ORIG(MSG_FLG_REGSYMS), FLG_RT_REGSYMS, FLG_RT_REGSYMS},
     76 	{ MSG_ORIG(MSG_FLG_INITCLCT), FLG_RT_INITCLCT, FLG_RT_INITCLCT},
     77 	{ MSG_ORIG(MSG_FLG_PUBHDL), FLG_RT_PUBHDL, FLG_RT_PUBHDL},
     78 	{ MSG_ORIG(MSG_FLG_PRIHDL), FLG_RT_PRIHDL, FLG_RT_PRIHDL},
     79 	{ NULL, 0, 0}
     80 };
     81 
     82 static const mdb_bitmask_t rtflags1_bits[] = {
     83 	{ MSG_ORIG(MSG_FL1_COPYTOOK), FL1_RT_COPYTOOK, FL1_RT_COPYTOOK},
     84 	{ MSG_ORIG(MSG_FL1_CONFSET), FL1_RT_CONFSET, FL1_RT_CONFSET },
     85 	{ MSG_ORIG(MSG_FL1_NODEFLIB), FL1_RT_NODEFLIB, FL1_RT_NODEFLIB },
     86 	{ MSG_ORIG(MSG_FL1_ENDFILTE), FL1_RT_ENDFILTE, FL1_RT_ENDFILTE },
     87 	{ MSG_ORIG(MSG_FL1_DISPREL), FL1_RT_DISPREL, FL1_RT_DISPREL },
     88 	{ MSG_ORIG(MSG_FL1_DTFLAGS), FL1_RT_DTFLAGS, FL1_RT_DTFLAGS},
     89 	{ MSG_ORIG(MSG_FL1_LDDSTUB), FL1_RT_LDDSTUB, FL1_RT_LDDSTUB},
     90 	{ MSG_ORIG(MSG_FL1_NOINIFIN), FL1_RT_NOINIFIN, FL1_RT_NOINIFIN },
     91 	{ MSG_ORIG(MSG_FL1_USED), FL1_RT_USED, FL1_RT_USED },
     92 	{ MSG_ORIG(MSG_FL1_SYMBOLIC), FL1_RT_SYMBOLIC, FL1_RT_SYMBOLIC },
     93 	{ MSG_ORIG(MSG_FL1_OBJSFLTR), FL1_RT_OBJSFLTR, FL1_RT_OBJSFLTR },
     94 	{ MSG_ORIG(MSG_FL1_OBJAFLTR), FL1_RT_OBJAFLTR, FL1_RT_OBJAFLTR },
     95 	{ MSG_ORIG(MSG_FL1_SYMSFLTR), FL1_RT_SYMSFLTR, FL1_RT_SYMSFLTR },
     96 	{ MSG_ORIG(MSG_FL1_SYMAFLTR), FL1_RT_SYMAFLTR, FL1_RT_SYMAFLTR },
     97 	{ MSG_ORIG(MSG_FL1_TLSADD), FL1_RT_TLSADD, FL1_RT_TLSADD },
     98 	{ MSG_ORIG(MSG_FL1_TLSSTAT), FL1_RT_TLSSTAT, FL1_RT_TLSSTAT },
     99 	{ MSG_ORIG(MSG_FL1_DIRECT), FL1_RT_DIRECT, FL1_RT_DIRECT},
    100 	{ MSG_ORIG(MSG_FL1_GLOBAUD), FL1_RT_GLOBAUD, FL1_RT_GLOBAUD},
    101 	{ NULL, 0, 0}
    102 };
    103 
    104 static const mdb_bitmask_t rtaflags_bits[] = {
    105 	{ MSG_ORIG(MSG_LTFL_AUD_PREINIT), LML_TFLG_AUD_PREINIT,
    106 	    LML_TFLG_AUD_PREINIT },
    107 	{ MSG_ORIG(MSG_LTFL_AUD_OBJSEARCH), LML_TFLG_AUD_OBJSEARCH,
    108 	    LML_TFLG_AUD_OBJSEARCH },
    109 	{ MSG_ORIG(MSG_LTFL_AUD_OBJOPEN), LML_TFLG_AUD_OBJOPEN,
    110 	    LML_TFLG_AUD_OBJOPEN },
    111 	{ MSG_ORIG(MSG_LTFL_AUD_OBJFILTER), LML_TFLG_AUD_OBJFILTER,
    112 	    LML_TFLG_AUD_OBJFILTER },
    113 	{ MSG_ORIG(MSG_LTFL_AUD_OBJCLOSE), LML_TFLG_AUD_OBJCLOSE,
    114 	    LML_TFLG_AUD_OBJCLOSE },
    115 	{ MSG_ORIG(MSG_LTFL_AUD_SYMBIND), LML_TFLG_AUD_SYMBIND,
    116 	    LML_TFLG_AUD_SYMBIND },
    117 	{ MSG_ORIG(MSG_LTFL_AUD_PLTENTER), LML_TFLG_AUD_PLTENTER,
    118 	    LML_TFLG_AUD_PLTENTER },
    119 	{ MSG_ORIG(MSG_LTFL_AUD_PLTEXIT), LML_TFLG_AUD_PLTEXIT,
    120 	    LML_TFLG_AUD_PLTEXIT },
    121 	{ MSG_ORIG(MSG_LTFL_AUD_ACTIVITY), LML_TFLG_AUD_ACTIVITY,
    122 	    LML_TFLG_AUD_ACTIVITY },
    123 	{ NULL, 0, 0}
    124 };
    125 
    126 static const mdb_bitmask_t rtmode_bits[] = {
    127 	{ MSG_ORIG(MSG_MODE_LAZY), RTLD_LAZY, RTLD_LAZY },
    128 	{ MSG_ORIG(MSG_MODE_NOW), RTLD_NOW, RTLD_NOW },
    129 	{ MSG_ORIG(MSG_MODE_NOLOAD), RTLD_NOLOAD, RTLD_NOLOAD },
    130 	{ MSG_ORIG(MSG_MODE_GLOBAL), RTLD_GLOBAL, RTLD_GLOBAL },
    131 	{ MSG_ORIG(MSG_MODE_PARENT), RTLD_PARENT, RTLD_PARENT },
    132 	{ MSG_ORIG(MSG_MODE_GROUP), RTLD_GROUP, RTLD_GROUP },
    133 	{ MSG_ORIG(MSG_MODE_WORLD), RTLD_WORLD, RTLD_WORLD },
    134 	{ MSG_ORIG(MSG_MODE_NODELETE), RTLD_NODELETE, RTLD_NODELETE },
    135 	{ MSG_ORIG(MSG_MODE_FIRST), RTLD_FIRST, RTLD_FIRST },
    136 	{ MSG_ORIG(MSG_MODE_CONFGEN), RTLD_CONFGEN, RTLD_CONFGEN },
    137 	{ NULL, 0, 0}
    138 };
    139 
    140 static const mdb_bitmask_t bndflags_bits[] = {
    141 	{ MSG_ORIG(MSG_BFL_NEEDED), BND_NEEDED, BND_NEEDED },
    142 	{ MSG_ORIG(MSG_BFL_REFER), BND_REFER, BND_REFER },
    143 	{ MSG_ORIG(MSG_BFL_FILTER), BND_FILTER, BND_FILTER },
    144 	{ NULL, 0, 0}
    145 };
    146 
    147 static const mdb_bitmask_t grhflags_bits[] = {
    148 	{ MSG_ORIG(MSG_GPH_PUBLIC), GPH_PUBLIC, GPH_PUBLIC },
    149 	{ MSG_ORIG(MSG_GPH_PRIVATE), GPH_PRIVATE, GPH_PRIVATE },
    150 	{ MSG_ORIG(MSG_GPH_ZERO), GPH_ZERO, GPH_ZERO },
    151 	{ MSG_ORIG(MSG_GPH_LDSO), GPH_LDSO, GPH_LDSO },
    152 	{ MSG_ORIG(MSG_GPH_FIRST), GPH_FIRST, GPH_FIRST },
    153 	{ MSG_ORIG(MSG_GPH_FILTEE), GPH_FILTEE, GPH_FILTEE },
    154 	{ MSG_ORIG(MSG_GPH_INITIAL), GPH_INITIAL, GPH_INITIAL },
    155 	{ NULL, 0, 0}
    156 };
    157 
    158 static const mdb_bitmask_t grdflags_bits[] = {
    159 	{ MSG_ORIG(MSG_GPD_DLSYM), GPD_DLSYM, GPD_DLSYM },
    160 	{ MSG_ORIG(MSG_GPD_RELOC), GPD_RELOC, GPD_RELOC },
    161 	{ MSG_ORIG(MSG_GPD_ADDEPS), GPD_ADDEPS, GPD_ADDEPS },
    162 	{ MSG_ORIG(MSG_GPD_PARENT), GPD_PARENT, GPD_PARENT },
    163 	{ MSG_ORIG(MSG_GPD_FILTER), GPD_FILTER, GPD_FILTER },
    164 	{ MSG_ORIG(MSG_GPD_REMOVE), GPD_REMOVE, GPD_REMOVE },
    165 	{ NULL, 0, 0}
    166 };
    167 
    168 static const mdb_bitmask_t lmc_bits[] = {
    169 	{ MSG_ORIG(MSG_LMC_ANALYZING), LMC_FLG_ANALYZING, LMC_FLG_ANALYZING},
    170 	{ MSG_ORIG(MSG_LMC_RELOCATING), LMC_FLG_RELOCATING, LMC_FLG_RELOCATING},
    171 	{ MSG_ORIG(MSG_LMC_REANALYZE), LMC_FLG_REANALYZE, LMC_FLG_REANALYZE},
    172 	{ NULL, 0, 0}
    173 };
    174 
    175 /*
    176  * Obtain a string - typically a link-map name.
    177  */
    178 static char *
    179 String(uintptr_t addr, const char *name)
    180 {
    181 	static char	str[MAXPATHLEN];
    182 
    183 	if (addr) {
    184 		if (mdb_readstr(str, MAXPATHLEN, addr) == -1) {
    185 			mdb_warn(MSG_ORIG(MSG_ERR_READ), name, addr);
    186 			return (0);
    187 		}
    188 		return (str);
    189 	}
    190 	return ((char *)MSG_ORIG(MSG_STR_EMPTY));
    191 }
    192 
    193 /*
    194  * Obtain a link-map name.
    195  */
    196 static char *
    197 Rtmap_Name(uintptr_t addr)
    198 {
    199 	Rt_map	rtmap;
    200 
    201 	if (addr) {
    202 		if (mdb_vread(&rtmap, sizeof (Rt_map), addr) == -1) {
    203 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
    204 			    MSG_ORIG(MSG_RTMAP_STR), addr);
    205 			return (0);
    206 		}
    207 		return (String((uintptr_t)NAME(&rtmap),
    208 		    MSG_ORIG(MSG_STR_NAME)));
    209 	}
    210 	return ((char *)MSG_ORIG(MSG_STR_EMPTY));
    211 }
    212 
    213 void
    214 dcmd_Bind_help(void)
    215 {
    216 	mdb_printf(MSG_ORIG(MSG_BND_HELP));
    217 }
    218 
    219 static int
    220 /* ARGSUSED2 */
    221 dcmd_Bind(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    222 {
    223 	Bnd_desc	bnd;
    224 	char		*str;
    225 
    226 	/*
    227 	 * Insure we have a valid address.
    228 	 */
    229 	if ((flags & DCMD_ADDRSPEC) == 0) {
    230 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_BND_STR));
    231 		return (DCMD_USAGE);
    232 	}
    233 
    234 	/*
    235 	 * Obtain the binding descriptor.
    236 	 */
    237 	if (mdb_vread(&bnd, sizeof (Bnd_desc), addr) == -1) {
    238 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_BND_STR), addr);
    239 		return (DCMD_ERR);
    240 	}
    241 	mdb_printf(MSG_ORIG(MSG_BND_TITLE), addr);
    242 
    243 	/*
    244 	 * Establish the identity of the caller.
    245 	 */
    246 	if ((str = Rtmap_Name((uintptr_t)bnd.b_caller)) == 0)
    247 		return (DCMD_ERR);
    248 	mdb_printf(MSG_ORIG(MSG_BND_LINE1), bnd.b_caller, str);
    249 
    250 	/*
    251 	 * Establish the identity of the dependency.
    252 	 */
    253 	if ((str = Rtmap_Name((uintptr_t)bnd.b_depend)) == 0)
    254 		return (DCMD_ERR);
    255 	mdb_printf(MSG_ORIG(MSG_BND_LINE2), bnd.b_depend, str);
    256 
    257 	/*
    258 	 * Display any flags.
    259 	 */
    260 	mdb_printf(MSG_ORIG(MSG_BND_LINE3), bnd.b_flags, bnd.b_flags,
    261 	    bndflags_bits);
    262 
    263 	return (DCMD_OK);
    264 }
    265 
    266 static void
    267 dcmd_Depends_help(void)
    268 {
    269 	mdb_printf(MSG_ORIG(MSG_DEPENDS_HELP));
    270 }
    271 
    272 static int
    273 Depends(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
    274     uint_t flg, const char *msg)
    275 {
    276 	APlist		apl;
    277 	uintptr_t	datap, nitems;
    278 	Bnd_desc	*bdp;
    279 
    280 	/*
    281 	 * Obtain the APlist and determine its number of elements and those
    282 	 * that are in use.
    283 	 */
    284 	if (mdb_vread(&apl, sizeof (APlist), addr) == -1) {
    285 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_APLIST),
    286 		    addr);
    287 		return (DCMD_ERR);
    288 	}
    289 
    290 	mdb_printf(msg, addr, (size_t)apl.apl_nitems,
    291 	    (size_t)apl.apl_arritems);
    292 
    293 	if (((flg & RTLD_FLG_VERBOSE) == 0) || (apl.apl_nitems == 0))
    294 		return (DCMD_OK);
    295 
    296 	/*
    297 	 * Under verbose mode print the name of each dependency.  An APlist can
    298 	 * have a variable number of data items, so read each individual entry.
    299 	 */
    300 	datap = APLIST_OFF_DATA + (uintptr_t)addr;
    301 	if (mdb_vread(&bdp, sizeof (Bnd_desc *), datap) == -1) {
    302 		mdb_warn(MSG_ORIG(MSG_ERR_READ),
    303 		    MSG_ORIG(MSG_BNDDESC_STR), datap);
    304 		return (DCMD_ERR);
    305 	}
    306 
    307 	(void) mdb_inc_indent(4);
    308 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    309 
    310 	if (dcmd_Bind((uintptr_t)bdp, flags, argc, argv) == DCMD_ERR) {
    311 		(void) mdb_dec_indent(4);
    312 		return (DCMD_ERR);
    313 	}
    314 
    315 	for (nitems = 1; nitems < apl.apl_nitems; nitems++) {
    316 		datap += sizeof (void *);
    317 		if (mdb_vread(&bdp, sizeof (Bnd_desc *), datap) == -1) {
    318 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
    319 			    MSG_ORIG(MSG_BNDDESC_STR), datap);
    320 			return (DCMD_ERR);
    321 		}
    322 
    323 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    324 		if (dcmd_Bind((uintptr_t)bdp, flags, argc, argv) == DCMD_ERR) {
    325 			(void) mdb_dec_indent(4);
    326 			return (DCMD_ERR);
    327 		}
    328 	}
    329 	(void) mdb_dec_indent(4);
    330 	return (DCMD_OK);
    331 }
    332 
    333 static int
    334 dcmd_Depends(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    335 {
    336 	Rt_map		rtmap;
    337 	char		*str;
    338 	uint_t		flg = 0;
    339 
    340 	/*
    341 	 * Insure we have a valid address, and provide for a -v option.
    342 	 */
    343 	if ((flags & DCMD_ADDRSPEC) == 0) {
    344 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_DEPENDS_STR));
    345 		return (DCMD_USAGE);
    346 	}
    347 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, RTLD_FLG_VERBOSE,
    348 	    &flg, NULL) != argc)
    349 		return (DCMD_USAGE);
    350 
    351 	/*
    352 	 * Read the Rt_map contents.
    353 	 */
    354 	if (mdb_vread(&rtmap, sizeof (Rt_map), addr) == -1) {
    355 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_RTMAP_STR), addr);
    356 		return (DCMD_ERR);
    357 	}
    358 	if ((str = String((uintptr_t)NAME(&rtmap),
    359 	    MSG_ORIG(MSG_STR_NAME))) == 0)
    360 		return (DCMD_ERR);
    361 
    362 	mdb_printf(MSG_ORIG(MSG_DEPENDS_LINE1), str);
    363 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    364 
    365 	if (DEPENDS(&rtmap) == NULL)
    366 		return (DCMD_OK);
    367 
    368 	return (Depends((uintptr_t)DEPENDS(&rtmap), flags, argc, argv, flg,
    369 	    MSG_ORIG(MSG_DEPENDS_LINE2)));
    370 }
    371 
    372 static void
    373 dcmd_Callers_help(void)
    374 {
    375 	mdb_printf(MSG_ORIG(MSG_CALLERS_HELP));
    376 }
    377 
    378 static int
    379 dcmd_Callers(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    380 {
    381 	Rt_map		rtmap;
    382 	char		*str;
    383 	uint_t		flg = 0;
    384 
    385 	/*
    386 	 * Insure we have a valid address, and provide for a -v option.
    387 	 */
    388 	if ((flags & DCMD_ADDRSPEC) == 0) {
    389 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_DEPENDS_STR));
    390 		return (DCMD_USAGE);
    391 	}
    392 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, RTLD_FLG_VERBOSE,
    393 	    &flg, NULL) != argc)
    394 		return (DCMD_USAGE);
    395 
    396 	/*
    397 	 * Read the Rt_map contents.
    398 	 */
    399 	if (mdb_vread(&rtmap, sizeof (Rt_map), addr) == -1) {
    400 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_RTMAP_STR), addr);
    401 		return (DCMD_ERR);
    402 	}
    403 	if ((str = String((uintptr_t)NAME(&rtmap),
    404 	    MSG_ORIG(MSG_STR_NAME))) == 0)
    405 		return (DCMD_ERR);
    406 
    407 	mdb_printf(MSG_ORIG(MSG_CALLERS_LINE1), str);
    408 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    409 
    410 	if (CALLERS(&rtmap) == NULL)
    411 		return (DCMD_OK);
    412 
    413 	return (Depends((uintptr_t)CALLERS(&rtmap), flags, argc, argv, flg,
    414 	    MSG_ORIG(MSG_CALLERS_LINE2)));
    415 }
    416 
    417 void
    418 dcmd_rtmap_help(void)
    419 {
    420 	mdb_printf(MSG_ORIG(MSG_RTMAP_HELP));
    421 }
    422 
    423 static int
    424 /* ARGSUSED2 */
    425 dcmd_rtmap(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    426 {
    427 	Rt_map		rtmap;
    428 	char		*str;
    429 
    430 	if ((flags & DCMD_ADDRSPEC) == 0) {
    431 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_RTMAP_STR));
    432 		return (DCMD_USAGE);
    433 	}
    434 
    435 	if (mdb_vread(&rtmap, sizeof (Rt_map), addr) == -1) {
    436 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_RTMAP_STR), addr);
    437 		return (DCMD_ERR);
    438 	}
    439 
    440 	mdb_printf(MSG_ORIG(MSG_RTMAP_TITLE), addr);
    441 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    442 
    443 	/*
    444 	 * Determine the objects name.  NAME() is the name by which the object
    445 	 * has been opened, typically from adding a search path to a file name.
    446 	 * PATHNAME() is the fully resolve name, which is displayed by the proc
    447 	 * tools and debuggers.  If the two names differ, print the PATHNAME().
    448 	 */
    449 	if ((str = String((uintptr_t)NAME(&rtmap),
    450 	    MSG_ORIG(MSG_STR_NAME))) == 0)
    451 		return (DCMD_ERR);
    452 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE1), str);
    453 	if (NAME(&rtmap) != PATHNAME(&rtmap)) {
    454 		if ((str = String((uintptr_t)PATHNAME(&rtmap),
    455 		    MSG_ORIG(MSG_STR_PATHNAME))) == 0)
    456 			return (DCMD_ERR);
    457 		mdb_printf(MSG_ORIG(MSG_RTMAP_LINE2), str);
    458 	}
    459 
    460 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE3), ADDR(&rtmap), DYN(&rtmap));
    461 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE4), NEXT(&rtmap), PREV(&rtmap));
    462 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE5), rtmap.rt_fct, TLSMODID(&rtmap));
    463 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE6), INIT(&rtmap), FINI(&rtmap));
    464 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE7), GROUPS(&rtmap), HANDLES(&rtmap));
    465 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE8), DEPENDS(&rtmap), CALLERS(&rtmap));
    466 
    467 	if ((str = String((uintptr_t)REFNAME(&rtmap),
    468 	    MSG_ORIG(MSG_STR_REFNAME))) == 0)
    469 		return (DCMD_ERR);
    470 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE9), DYNINFO(&rtmap), str);
    471 
    472 	if ((str = String((uintptr_t)RPATH(&rtmap),
    473 	    MSG_ORIG(MSG_STR_RPATH))) == 0)
    474 		return (DCMD_ERR);
    475 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE10), RLIST(&rtmap), str);
    476 
    477 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE11), LIST(&rtmap), LIST(&rtmap));
    478 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE12), FLAGS(&rtmap));
    479 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), FLAGS(&rtmap), rtflags_bits);
    480 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE13), FLAGS1(&rtmap));
    481 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), FLAGS1(&rtmap), rtflags1_bits);
    482 	if (AFLAGS(&rtmap)) {
    483 		mdb_printf(MSG_ORIG(MSG_RTMAP_LINE14), AFLAGS(&rtmap));
    484 		mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), AFLAGS(&rtmap),
    485 		    rtaflags_bits);
    486 	}
    487 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE15), MODE(&rtmap));
    488 	mdb_printf(MSG_ORIG(MSG_RTMAP_LINE20), MODE(&rtmap), rtmode_bits);
    489 
    490 	return (DCMD_OK);
    491 }
    492 
    493 static int
    494 rtmap_format(uintptr_t addr, const void *data, void *private)
    495 {
    496 	const Rt_map	*lmp = (const Rt_map *)data;
    497 	W_desc		*wdp = (W_desc *)private;
    498 	char		*str;
    499 
    500 	if (wdp && (wdp->w_flags & RTLD_FLG_VERBOSE)) {
    501 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    502 		(void) mdb_call_dcmd(
    503 		    MSG_ORIG(MSG_RTMAP_STR), addr, DCMD_ADDRSPEC, NULL, NULL);
    504 		return (0);
    505 	}
    506 
    507 	if ((str = String((uintptr_t)NAME(lmp),
    508 	    MSG_ORIG(MSG_STR_NAME))) == 0)
    509 		return (DCMD_ERR);
    510 
    511 	mdb_printf(MSG_ORIG(MSG_FMT_RT), CNTL(lmp), addr, ADDR(lmp), str);
    512 	return (0);
    513 }
    514 
    515 void
    516 dcmd_Rtmaps_help(void)
    517 {
    518 	mdb_printf(MSG_ORIG(MSG_RTMAPS_HELP));
    519 }
    520 
    521 static int
    522 dcmd_Rtmaps(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    523 {
    524 	uint_t		flg = 0;
    525 	GElf_Sym	gsym;
    526 	APlist		*aplp, apl;
    527 	uintptr_t	datap, nitems;
    528 	const char	*str;
    529 	W_desc		wdesc;
    530 
    531 	/*
    532 	 * '-v' - Verbose output of rtmap
    533 	 */
    534 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, RTLD_FLG_VERBOSE,
    535 	    &flg, NULL) != argc)
    536 		return (DCMD_USAGE);
    537 
    538 	/*
    539 	 * If an address was provided use it.
    540 	 */
    541 	if (flags & DCMD_ADDRSPEC) {
    542 		if (((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) &&
    543 		    !(flg & RTLD_FLG_VERBOSE)) {
    544 			mdb_printf(MSG_ORIG(MSG_RTMAPS_TITLE0));
    545 			mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    546 		}
    547 
    548 		wdesc.w_flags = flg;
    549 		if (mdb_pwalk(MSG_ORIG(MSG_RTMAPS_STR), rtmap_format,
    550 		    (void *)&wdesc, addr) == -1)
    551 			return (DCMD_ERR);
    552 		return (DCMD_OK);
    553 	}
    554 
    555 	/*
    556 	 * Otherwise traverse the dynlm_list and display each link-map.
    557 	 */
    558 	if (mdb_lookup_by_obj(MSG_ORIG(MSG_STR_LDSO1),
    559 	    MSG_ORIG(MSG_STR_DYNLMLIST), &gsym) == -1) {
    560 		mdb_warn(MSG_ORIG(MSG_ERR_SYMFAILED), MSG_ORIG(MSG_STR_LDSO1),
    561 		    MSG_ORIG(MSG_STR_DYNLMLIST));
    562 		return (DCMD_ERR);
    563 	}
    564 	if (mdb_vread(&aplp, sizeof (APlist *),
    565 	    (uintptr_t)gsym.st_value) == -1) {
    566 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_APLIST),
    567 		    gsym.st_value);
    568 		return (DCMD_ERR);
    569 	}
    570 
    571 	if (aplp == NULL) {
    572 		mdb_printf(MSG_ORIG(MSG_LMLIST_TITLE0),
    573 		    MSG_ORIG(MSG_STR_DYNLMLIST));
    574 		return (DCMD_OK);
    575 	}
    576 
    577 	if (mdb_vread(&apl, sizeof (APlist), (uintptr_t)aplp) == -1) {
    578 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_APLIST),
    579 		    aplp);
    580 	}
    581 	mdb_printf(MSG_ORIG(MSG_LMLIST_TITLE1), MSG_ORIG(MSG_STR_DYNLMLIST),
    582 	    aplp, (size_t)apl.apl_nitems, (size_t)apl.apl_arritems);
    583 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    584 
    585 	flags |= (DCMD_LOOP | DCMD_LOOPFIRST);
    586 	for (datap = (uintptr_t)aplp + APLIST_OFF_DATA, nitems = 0;
    587 	    nitems < apl.apl_nitems; nitems++, datap += sizeof (void *)) {
    588 		Lm_list	*lml, lm;
    589 
    590 		if (mdb_vread(&lml, sizeof (Lm_list *), datap) == -1) {
    591 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
    592 			    MSG_ORIG(MSG_LMLIST_STR), datap);
    593 			return (DCMD_ERR);
    594 		}
    595 		if (mdb_vread(&lm, sizeof (Lm_list), (uintptr_t)lml) == -1) {
    596 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
    597 			    MSG_ORIG(MSG_LMLIST_STR), lml);
    598 			return (DCMD_ERR);
    599 		}
    600 
    601 		(void) mdb_inc_indent(2);
    602 		if (lm.lm_flags & LML_FLG_BASELM)
    603 			str = MSG_ORIG(MSG_LMLIST_BASE);
    604 		else if (lm.lm_flags & LML_FLG_RTLDLM)
    605 			str = MSG_ORIG(MSG_LMLIST_LDSO);
    606 		else
    607 			str = MSG_ORIG(MSG_LMLIST_NEWLM);
    608 
    609 		if ((flags & DCMD_LOOP) && ((flags & DCMD_LOOPFIRST) == 0))
    610 			mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    611 
    612 		mdb_printf(MSG_ORIG(MSG_LMLIST_TITLE2), datap, str);
    613 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    614 
    615 		(void) mdb_inc_indent(2);
    616 
    617 		if (((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) &&
    618 		    !(flg & RTLD_FLG_VERBOSE)) {
    619 			mdb_printf(MSG_ORIG(MSG_RTMAPS_TITLE0));
    620 			mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    621 		}
    622 
    623 		wdesc.w_flags = flg;
    624 		if (mdb_pwalk(MSG_ORIG(MSG_RTMAPS_STR), rtmap_format,
    625 		    (void *)&wdesc, (uintptr_t)lm.lm_head) == -1) {
    626 			(void) mdb_dec_indent(4);
    627 			return (DCMD_ERR);
    628 		}
    629 		(void) mdb_dec_indent(4);
    630 		flags &= ~DCMD_LOOPFIRST;
    631 	}
    632 	return (DCMD_OK);
    633 }
    634 
    635 void
    636 dcmd_Setenv_help(void)
    637 {
    638 	mdb_printf(MSG_ORIG(MSG_SETENV_HELP));
    639 }
    640 
    641 /*
    642  * As of s10, mdb provides its own setenv command.  This command allows the
    643  * environment of the process being controlled to be changed at any time.
    644  * Prior to this, ld.so.1 provided it's own, more primitive implementation.
    645  * This allowed for changing mdb's environment only, which if it was changed
    646  * before the application ws executed, would be copied to the applications
    647  * environment.  Thus, we could start mdb, set an LD_ variable within its
    648  * environment (which it's own ld.so.1 had already finished processing), and
    649  * have this setting be inherited by the application.
    650  */
    651 static int
    652 /* ARGSUSED */
    653 dcmd_Setenv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    654 {
    655 	char	*str;
    656 
    657 	if (mdb_call_dcmd(MSG_ORIG(MSG_STR_SETENV), addr, flags, argc,
    658 	    argv) == 0)
    659 		return (DCMD_OK);
    660 
    661 	if (((flags & DCMD_ADDRSPEC) != 0) || (argc == 0) || (argc > 1) ||
    662 	    (argv->a_type != MDB_TYPE_STRING))
    663 		return (DCMD_USAGE);
    664 
    665 	str = mdb_alloc((strlen(argv->a_un.a_str) + 1), UM_NOSLEEP);
    666 	if (str == NULL)
    667 		return (DCMD_ERR);
    668 
    669 	(void) strcpy(str, argv->a_un.a_str);
    670 	(void) putenv(str);
    671 	return (DCMD_OK);
    672 }
    673 
    674 /*
    675  * Walk Rt_map lists
    676  */
    677 static int
    678 walk_rtmap_init(mdb_walk_state_t *wsp)
    679 {
    680 	if (wsp->walk_addr == NULL) {
    681 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_RTMAP_STR));
    682 		return (WALK_ERR);
    683 	}
    684 	return (WALK_NEXT);
    685 }
    686 
    687 static int
    688 walk_rtmap_step(mdb_walk_state_t *wsp)
    689 {
    690 	int	status;
    691 	Rt_map	lmp;
    692 
    693 	if (wsp->walk_addr == NULL)
    694 		return (WALK_DONE);
    695 	if (mdb_vread(&lmp, sizeof (Rt_map), wsp->walk_addr) == -1) {
    696 		mdb_warn(MSG_ORIG(MSG_ERR_READ),
    697 		    MSG_ORIG(MSG_RTMAP_STR), wsp->walk_addr);
    698 		return (WALK_DONE);
    699 	}
    700 
    701 	status = wsp->walk_callback(wsp->walk_addr, &lmp, wsp->walk_cbdata);
    702 	wsp->walk_addr = (uintptr_t)(NEXT(&lmp));
    703 	return (status);
    704 }
    705 
    706 static const mdb_bitmask_t lml_flags_bit[] = {
    707 	{ MSG_ORIG(MSG_LFL_BASELM), LML_FLG_BASELM, LML_FLG_BASELM },
    708 	{ MSG_ORIG(MSG_LFL_RTLDLM), LML_FLG_RTLDLM, LML_FLG_RTLDLM },
    709 	{ MSG_ORIG(MSG_LFL_NOAUDIT), LML_FLG_NOAUDIT, LML_FLG_NOAUDIT },
    710 	{ MSG_ORIG(MSG_LFL_PLTREL), LML_FLG_PLTREL, LML_FLG_PLTREL },
    711 	{ MSG_ORIG(MSG_LFL_HOLDLOCK), LML_FLG_HOLDLOCK, LML_FLG_HOLDLOCK },
    712 	{ MSG_ORIG(MSG_LFL_ENVIRON), LML_FLG_ENVIRON, LML_FLG_ENVIRON },
    713 	{ MSG_ORIG(MSG_LFL_INTRPOSE), LML_FLG_INTRPOSE, LML_FLG_INTRPOSE },
    714 	{ MSG_ORIG(MSG_LFL_LOCAUDIT), LML_FLG_LOCAUDIT, LML_FLG_LOCAUDIT },
    715 	{ MSG_ORIG(MSG_LFL_LOADAVAIL), LML_FLG_LOADAVAIL, LML_FLG_LOADAVAIL },
    716 	{ MSG_ORIG(MSG_LFL_IGNRELERR), LML_FLG_IGNRELERR, LML_FLG_IGNRELERR },
    717 	{ MSG_ORIG(MSG_LFL_DBNOTIF), LML_FLG_DBNOTIF, LML_FLG_DBNOTIF },
    718 	{ MSG_ORIG(MSG_LFL_STARTREL), LML_FLG_STARTREL, LML_FLG_STARTREL },
    719 	{ MSG_ORIG(MSG_LFL_ATEXIT), LML_FLG_ATEXIT, LML_FLG_ATEXIT },
    720 	{ MSG_ORIG(MSG_LFL_OBJADDED), LML_FLG_OBJADDED, LML_FLG_OBJADDED },
    721 	{ MSG_ORIG(MSG_LFL_OBJDELETED), LML_FLG_OBJDELETED,
    722 	    LML_FLG_OBJDELETED },
    723 	{ MSG_ORIG(MSG_LFL_OBJREEVAL), LML_FLG_OBJREEVAL, LML_FLG_OBJREEVAL },
    724 	{ MSG_ORIG(MSG_LFL_INTRPOSETSORT), LML_FLG_INTRPOSETSORT,
    725 	    LML_FLG_INTRPOSETSORT },
    726 	{ MSG_ORIG(MSG_LFL_AUDITNOTIFY), LML_FLG_AUDITNOTIFY,
    727 	    LML_FLG_AUDITNOTIFY },
    728 	{ MSG_ORIG(MSG_LFL_GROUPSEXIST), LML_FLG_GROUPSEXIST,
    729 	    LML_FLG_GROUPSEXIST },
    730 
    731 	{ MSG_ORIG(MSG_LFL_TRC_LDDSTUB), LML_FLG_TRC_LDDSTUB,
    732 	    LML_FLG_TRC_LDDSTUB },
    733 	{ MSG_ORIG(MSG_LFL_TRC_ENABLE), LML_FLG_TRC_ENABLE,
    734 	    LML_FLG_TRC_ENABLE },
    735 	{ MSG_ORIG(MSG_LFL_TRC_WARN), LML_FLG_TRC_WARN, LML_FLG_TRC_WARN },
    736 	{ MSG_ORIG(MSG_LFL_TRC_VERBOSE), LML_FLG_TRC_VERBOSE,
    737 	    LML_FLG_TRC_VERBOSE },
    738 	{ MSG_ORIG(MSG_LFL_TRC_SEARCH), LML_FLG_TRC_SEARCH,
    739 	    LML_FLG_TRC_SEARCH },
    740 	{ MSG_ORIG(MSG_LFL_TRC_UNREF), LML_FLG_TRC_UNREF, LML_FLG_TRC_UNREF },
    741 	{ MSG_ORIG(MSG_LFL_TRC_UNUSED), LML_FLG_TRC_UNUSED,
    742 	    LML_FLG_TRC_UNUSED },
    743 	{ MSG_ORIG(MSG_LFL_TRC_INIT), LML_FLG_TRC_INIT, LML_FLG_TRC_INIT },
    744 	{ MSG_ORIG(MSG_LFL_TRC_NOUNRESWEAK), LML_FLG_TRC_NOUNRESWEAK,
    745 	    LML_FLG_TRC_NOUNRESWEAK },
    746 	{ MSG_ORIG(MSG_LFL_TRC_NOPAREXT), LML_FLG_TRC_NOPAREXT,
    747 	    LML_FLG_TRC_NOPAREXT },
    748 	{ NULL, 0, 0}
    749 };
    750 
    751 static const mdb_bitmask_t lml_tflags_bit[] = {
    752 	{ MSG_ORIG(MSG_LTFL_NOLAZYLD), LML_TFLG_NOLAZYLD, LML_TFLG_NOLAZYLD },
    753 	{ MSG_ORIG(MSG_LTFL_NODIRECT), LML_TFLG_NODIRECT, LML_TFLG_NODIRECT },
    754 	{ MSG_ORIG(MSG_LTFL_LOADFLTR), LML_TFLG_LOADFLTR, LML_TFLG_LOADFLTR },
    755 
    756 	{ MSG_ORIG(MSG_LTFL_AUD_PREINIT), LML_TFLG_AUD_PREINIT,
    757 	    LML_TFLG_AUD_PREINIT },
    758 	{ MSG_ORIG(MSG_LTFL_AUD_OBJSEARCH), LML_TFLG_AUD_OBJSEARCH,
    759 	    LML_TFLG_AUD_OBJSEARCH },
    760 	{ MSG_ORIG(MSG_LTFL_AUD_OBJOPEN), LML_TFLG_AUD_OBJOPEN,
    761 	    LML_TFLG_AUD_OBJOPEN },
    762 	{ MSG_ORIG(MSG_LTFL_AUD_OBJFILTER), LML_TFLG_AUD_OBJFILTER,
    763 	    LML_TFLG_AUD_OBJFILTER },
    764 	{ MSG_ORIG(MSG_LTFL_AUD_OBJCLOSE), LML_TFLG_AUD_OBJCLOSE,
    765 	    LML_TFLG_AUD_OBJCLOSE },
    766 	{ MSG_ORIG(MSG_LTFL_AUD_SYMBIND), LML_TFLG_AUD_SYMBIND,
    767 	    LML_TFLG_AUD_SYMBIND },
    768 	{ MSG_ORIG(MSG_LTFL_AUD_PLTENTER), LML_TFLG_AUD_PLTENTER,
    769 	    LML_TFLG_AUD_PLTENTER },
    770 	{ MSG_ORIG(MSG_LTFL_AUD_PLTEXIT), LML_TFLG_AUD_PLTEXIT,
    771 	    LML_TFLG_AUD_PLTEXIT },
    772 	{ MSG_ORIG(MSG_LTFL_AUD_ACTIVITY), LML_TFLG_AUD_ACTIVITY,
    773 	    LML_TFLG_AUD_ACTIVITY },
    774 	{ NULL, 0, 0}
    775 };
    776 
    777 void
    778 dcmd_Lm_list_help(void)
    779 {
    780 	mdb_printf(MSG_ORIG(MSG_LMLIST_HELP));
    781 }
    782 
    783 static int
    784 /* ARGSUSED1 */
    785 _dcmd_Lm_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    786 {
    787 	Lm_list		lml;
    788 	const char	*str;
    789 	uint_t		flg = 0;
    790 
    791 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, RTLD_FLG_VERBOSE,
    792 	    &flg, NULL) != argc)
    793 		return (DCMD_USAGE);
    794 
    795 	if (mdb_vread(&lml, sizeof (lml), addr) == -1) {
    796 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_LMLIST_STR),
    797 		    addr);
    798 		return (DCMD_ERR);
    799 	}
    800 
    801 	if (lml.lm_flags & LML_FLG_BASELM)
    802 		str = MSG_ORIG(MSG_LMLIST_BASE);
    803 	else if (lml.lm_flags & LML_FLG_RTLDLM)
    804 		str = MSG_ORIG(MSG_LMLIST_LDSO);
    805 	else
    806 		str = MSG_ORIG(MSG_LMLIST_NEWLM);
    807 
    808 	if ((flags & DCMD_LOOP) && ((flags & DCMD_LOOPFIRST) == 0))
    809 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    810 
    811 	mdb_printf(MSG_ORIG(MSG_LMLIST_TITLE2), addr, str);
    812 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    813 
    814 	if (lml.lm_lists) {
    815 		Alist		al;
    816 		Lm_cntl		lmc;
    817 		uintptr_t	datap;
    818 
    819 		addr = (uintptr_t)lml.lm_lists;
    820 		if (mdb_vread(&al, sizeof (Alist), addr) == -1) {
    821 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
    822 			    MSG_ORIG(MSG_STR_ALIST), addr);
    823 			return (DCMD_ERR);
    824 		}
    825 
    826 		/*
    827 		 * Determine whether the Alist has been populated.  Note, the
    828 		 * implementation first reserves an alist entry, and initializes
    829 		 * this element when the first link-map is processed.  Thus,
    830 		 * there's a window when nitems is updated, but before the next
    831 		 * element has been initialized.
    832 		 */
    833 		if (al.al_nitems && (flg & RTLD_FLG_VERBOSE)) {
    834 			datap = ALIST_OFF_DATA + (uintptr_t)addr;
    835 
    836 			if (mdb_vread(&lmc, sizeof (Lm_cntl),
    837 			    datap) == -1) {
    838 				mdb_warn(MSG_ORIG(MSG_ERR_READ),
    839 				    MSG_ORIG(MSG_LMLIST_STR), datap);
    840 				return (DCMD_ERR);
    841 			}
    842 		}
    843 
    844 		mdb_printf(MSG_ORIG(MSG_LMLIST_LINE0), addr,
    845 		    (size_t)al.al_nitems, (size_t)al.al_arritems);
    846 		(void) mdb_inc_indent(2);
    847 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    848 
    849 		if (al.al_nitems && (flg & RTLD_FLG_VERBOSE)) {
    850 			uintptr_t	nitems;
    851 
    852 			(void) mdb_inc_indent(2);
    853 			mdb_printf(MSG_ORIG(MSG_LMC_LINE1), datap);
    854 			mdb_printf(MSG_ORIG(MSG_LMC_LINE2), lmc.lc_head,
    855 			    lmc.lc_tail);
    856 			mdb_printf(MSG_ORIG(MSG_LMC_LINE3), lmc.lc_flags,
    857 			    lmc.lc_now);
    858 			mdb_printf(MSG_ORIG(MSG_LMC_LINE4), lmc.lc_flags,
    859 			    lmc_bits);
    860 			mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    861 			mdb_printf(MSG_ORIG(MSG_RTMAPS_TITLE0));
    862 			mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    863 
    864 			if (lmc.lc_head) {
    865 				if (mdb_pwalk(MSG_ORIG(MSG_RTMAPS_STR),
    866 				    rtmap_format, (void *)0,
    867 				    (uintptr_t)lmc.lc_head) == -1) {
    868 					(void) mdb_dec_indent(4);
    869 					return (DCMD_ERR);
    870 				}
    871 			} else
    872 				mdb_printf(MSG_ORIG(MSG_FMT_RT), 0, 0, 0,
    873 				    MSG_ORIG(MSG_STR_EMPTY));
    874 
    875 			mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    876 
    877 			for (nitems = 1; nitems < al.al_nitems; nitems++) {
    878 				datap += al.al_size;
    879 				if (mdb_vread(&lmc, sizeof (Lm_cntl),
    880 				    datap) == -1) {
    881 					mdb_warn(MSG_ORIG(MSG_ERR_READ),
    882 					    MSG_ORIG(MSG_LMLIST_STR), datap);
    883 					(void) mdb_dec_indent(4);
    884 					return (DCMD_ERR);
    885 				}
    886 
    887 				mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    888 				mdb_printf(MSG_ORIG(MSG_LMC_LINE1), datap);
    889 				mdb_printf(MSG_ORIG(MSG_LMC_LINE2),
    890 				    lmc.lc_head, lmc.lc_tail);
    891 				mdb_printf(MSG_ORIG(MSG_LMC_LINE3),
    892 				    lmc.lc_flags, lmc.lc_now);
    893 				mdb_printf(MSG_ORIG(MSG_LMC_LINE4),
    894 				    lmc.lc_flags, lmc_bits);
    895 				mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    896 				mdb_printf(MSG_ORIG(MSG_RTMAPS_TITLE0));
    897 				mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    898 
    899 				if (lmc.lc_head) {
    900 					if (mdb_pwalk(MSG_ORIG(MSG_RTMAPS_STR),
    901 					    rtmap_format, (void *)0,
    902 					    (uintptr_t)lmc.lc_head) == -1) {
    903 						(void) mdb_dec_indent(4);
    904 						return (DCMD_ERR);
    905 					}
    906 				} else
    907 					mdb_printf(MSG_ORIG(MSG_FMT_RT), 0, 0,
    908 					    0, MSG_ORIG(MSG_STR_EMPTY));
    909 
    910 				mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    911 			}
    912 			(void) mdb_dec_indent(2);
    913 		}
    914 		(void) mdb_dec_indent(2);
    915 	}
    916 
    917 	mdb_printf(MSG_ORIG(MSG_LMLIST_LINE1), lml.lm_head, lml.lm_tail);
    918 	mdb_printf(MSG_ORIG(MSG_LMLIST_LINE2), lml.lm_alp, lml.lm_rti);
    919 	mdb_printf(MSG_ORIG(MSG_LMLIST_LINE3), lml.lm_handle, lml.lm_obj,
    920 	    lml.lm_init, lml.lm_lazy);
    921 
    922 	mdb_printf(MSG_ORIG(MSG_LMLIST_LINE4), lml.lm_flags);
    923 	if (lml.lm_flags)
    924 		mdb_printf(MSG_ORIG(MSG_LMLIST_LINE6), lml.lm_flags,
    925 		    lml_flags_bit);
    926 
    927 	mdb_printf(MSG_ORIG(MSG_LMLIST_LINE5), lml.lm_tflags);
    928 	if (lml.lm_tflags)
    929 		mdb_printf(MSG_ORIG(MSG_LMLIST_LINE6), lml.lm_tflags,
    930 		    lml_tflags_bit);
    931 
    932 	return (DCMD_OK);
    933 }
    934 
    935 static int
    936 /* ARGSUSED2 */
    937 dcmd_Lm_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    938 {
    939 	GElf_Sym	gsym;
    940 	APlist		*aplp, apl;
    941 	uintptr_t	datap, nitems;
    942 
    943 	/*
    944 	 * If an address was provided us it.
    945 	 */
    946 	if (flags & DCMD_ADDRSPEC)
    947 		return (_dcmd_Lm_list(addr, flags, argc, argv));
    948 
    949 	/*
    950 	 * Otherwise traverse the dynlm_list and display each link-map list.
    951 	 */
    952 	if (mdb_lookup_by_obj(MSG_ORIG(MSG_STR_LDSO1),
    953 	    MSG_ORIG(MSG_STR_DYNLMLIST), &gsym) == -1) {
    954 		mdb_warn(MSG_ORIG(MSG_ERR_SYMFAILED), MSG_ORIG(MSG_STR_LDSO1),
    955 		    MSG_ORIG(MSG_STR_DYNLMLIST));
    956 		return (DCMD_ERR);
    957 	}
    958 	if (mdb_vread(&aplp, sizeof (APlist *),
    959 	    (uintptr_t)gsym.st_value) == -1) {
    960 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_APLIST),
    961 		    gsym.st_value);
    962 		return (DCMD_ERR);
    963 	}
    964 	if (aplp == NULL) {
    965 		mdb_printf(MSG_ORIG(MSG_LMLIST_TITLE0),
    966 		    MSG_ORIG(MSG_STR_DYNLMLIST));
    967 		return (DCMD_OK);
    968 	}
    969 
    970 	if (mdb_vread(&apl, sizeof (APlist), (uintptr_t)aplp) == -1) {
    971 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_APLIST),
    972 		    aplp);
    973 		return (DCMD_ERR);
    974 	}
    975 
    976 	mdb_printf(MSG_ORIG(MSG_LMLIST_TITLE1), MSG_ORIG(MSG_STR_DYNLMLIST),
    977 	    aplp, (size_t)apl.apl_nitems, (size_t)apl.apl_arritems);
    978 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
    979 
    980 	flags |= (DCMD_LOOP | DCMD_LOOPFIRST);
    981 	for (datap = (uintptr_t)aplp + APLIST_OFF_DATA, nitems = 0;
    982 	    nitems < apl.apl_nitems; nitems++, datap += sizeof (void *)) {
    983 		Lm_list	*lml;
    984 
    985 		if (mdb_vread(&lml, sizeof (Lm_list *), datap) == -1) {
    986 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
    987 			    MSG_ORIG(MSG_LMLIST_STR), datap);
    988 			return (DCMD_ERR);
    989 		}
    990 
    991 		(void) mdb_inc_indent(2);
    992 		if (_dcmd_Lm_list((uintptr_t)lml, flags, argc,
    993 		    argv) == DCMD_ERR) {
    994 			(void) mdb_dec_indent(2);
    995 			return (DCMD_ERR);
    996 		}
    997 		(void) mdb_dec_indent(2);
    998 		flags &= ~DCMD_LOOPFIRST;
    999 	}
   1000 	return (DCMD_OK);
   1001 }
   1002 
   1003 void
   1004 dcmd_GrpDesc_help(void)
   1005 {
   1006 	mdb_printf(MSG_ORIG(MSG_GRPDESC_HELP));
   1007 }
   1008 
   1009 static int
   1010 /* ARGSUSED2 */
   1011 dcmd_GrpDesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1012 {
   1013 	Grp_desc	gd;
   1014 	char		*str;
   1015 
   1016 	/*
   1017 	 * Insure we have a valid address.
   1018 	 */
   1019 	if ((flags & DCMD_ADDRSPEC) == 0) {
   1020 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_GRPDESC_STR));
   1021 		return (DCMD_USAGE);
   1022 	}
   1023 
   1024 	mdb_printf(MSG_ORIG(MSG_GRPDESC_LINE1), addr);
   1025 	if (mdb_vread(&gd, sizeof (Grp_desc), addr) == -1) {
   1026 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_GRPDESC_STR),
   1027 		    addr);
   1028 		return (DCMD_ERR);
   1029 	}
   1030 
   1031 	if ((str = Rtmap_Name((uintptr_t)gd.gd_depend)) == 0)
   1032 		return (DCMD_ERR);
   1033 
   1034 	mdb_printf(MSG_ORIG(MSG_GRPDESC_LINE2), gd.gd_depend, str);
   1035 	mdb_printf(MSG_ORIG(MSG_GRPDESC_LINE3), gd.gd_flags, gd.gd_flags,
   1036 	    grdflags_bits);
   1037 
   1038 	return (DCMD_OK);
   1039 }
   1040 
   1041 void
   1042 dcmd_GrpHdl_help(void)
   1043 {
   1044 	mdb_printf(MSG_ORIG(MSG_GRPHDL_HELP));
   1045 }
   1046 
   1047 static int
   1048 /* ARGSUSED2 */
   1049 dcmd_GrpHdl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1050 {
   1051 	Grp_hdl		gh;
   1052 	Alist		al;
   1053 	uintptr_t	datap, listidx;
   1054 	char		*str;
   1055 	uint_t		flg = 0;
   1056 
   1057 	/*
   1058 	 * Insure we have a valid address, and provide for a -v option.
   1059 	 */
   1060 	if ((flags & DCMD_ADDRSPEC) == 0) {
   1061 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_GRPHDL_STR));
   1062 		return (DCMD_USAGE);
   1063 	}
   1064 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, RTLD_FLG_VERBOSE,
   1065 	    &flg, NULL) != argc)
   1066 		return (DCMD_USAGE);
   1067 
   1068 	mdb_printf(MSG_ORIG(MSG_GRPHDL_LINE1), addr);
   1069 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1070 
   1071 	if (mdb_vread(&gh, sizeof (Grp_hdl), addr) == -1) {
   1072 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_GRPHDL_STR),
   1073 		    addr);
   1074 		return (DCMD_ERR);
   1075 	}
   1076 
   1077 	/*
   1078 	 * Determine the handles owner.  Note that an orphaned handle may no
   1079 	 * longer contain its originating owner.
   1080 	 */
   1081 	if (gh.gh_ownlmp) {
   1082 		if ((str = Rtmap_Name((uintptr_t)gh.gh_ownlmp)) == 0)
   1083 			return (DCMD_ERR);
   1084 	} else
   1085 		str = (char *)MSG_ORIG(MSG_STR_ORPHANED);
   1086 
   1087 	mdb_printf(MSG_ORIG(MSG_GRPHDL_LINE2), str);
   1088 	mdb_printf(MSG_ORIG(MSG_GRPHDL_LINE3), gh.gh_flags, gh.gh_flags,
   1089 	    grhflags_bits);
   1090 
   1091 	if (gh.gh_depends == 0) {
   1092 		mdb_printf(MSG_ORIG(MSG_GRPHDL_LINE4), gh.gh_refcnt);
   1093 		return (DCMD_OK);
   1094 	}
   1095 
   1096 	addr = (uintptr_t)gh.gh_depends;
   1097 	if (mdb_vread(&al, sizeof (Alist), addr) == -1) {
   1098 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_ALIST), addr);
   1099 		return (DCMD_ERR);
   1100 	}
   1101 
   1102 	mdb_printf(MSG_ORIG(MSG_GRPHDL_LINE5), gh.gh_refcnt, addr,
   1103 	    (size_t)al.al_nitems, (size_t)al.al_arritems);
   1104 
   1105 	if (((flg & RTLD_FLG_VERBOSE) == 0) || (al.al_nitems == 0))
   1106 		return (DCMD_OK);
   1107 
   1108 	(void) mdb_inc_indent(4);
   1109 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1110 
   1111 	/*
   1112 	 * Under verbose mode print the name of each dependency.  An Alist can
   1113 	 * have a variable number of data items, so read each individual entry.
   1114 	 */
   1115 	datap = ALIST_OFF_DATA + (uintptr_t)addr;
   1116 	if (dcmd_GrpDesc(datap, flags, argc, argv) == DCMD_ERR) {
   1117 		(void) mdb_dec_indent(4);
   1118 		return (DCMD_ERR);
   1119 	}
   1120 
   1121 	for (listidx = 1; listidx < al.al_nitems; listidx++) {
   1122 		datap += al.al_size;
   1123 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1124 		if (dcmd_GrpDesc(datap, flags, argc, argv) == DCMD_ERR) {
   1125 			(void) mdb_dec_indent(4);
   1126 			return (DCMD_ERR);
   1127 		}
   1128 	}
   1129 
   1130 	(void) mdb_dec_indent(4);
   1131 	return (DCMD_OK);
   1132 }
   1133 
   1134 static void
   1135 dcmd_Handles_help(void)
   1136 {
   1137 	mdb_printf(MSG_ORIG(MSG_HANDLES_HELP));
   1138 }
   1139 
   1140 static int
   1141 dcmd_Handles(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1142 {
   1143 	Rt_map		rtmap;
   1144 	char		*str;
   1145 	uint_t		flg = 0;
   1146 	APlist		apl;
   1147 	uintptr_t	datap, nitems;
   1148 	Grp_hdl		*ghp;
   1149 
   1150 	/*
   1151 	 * Insure we have a valid address, and provide for a -v option.
   1152 	 */
   1153 	if ((flags & DCMD_ADDRSPEC) == 0) {
   1154 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_HANDLES_STR));
   1155 		return (DCMD_USAGE);
   1156 	}
   1157 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, RTLD_FLG_VERBOSE,
   1158 	    &flg, NULL) != argc)
   1159 		return (DCMD_USAGE);
   1160 
   1161 	/*
   1162 	 * Read the Rt_map contents.
   1163 	 */
   1164 	if (mdb_vread(&rtmap, sizeof (Rt_map), addr) == -1) {
   1165 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_RTMAP_STR), addr);
   1166 		return (DCMD_ERR);
   1167 	}
   1168 	if ((str = String((uintptr_t)NAME(&rtmap),
   1169 	    MSG_ORIG(MSG_STR_NAME))) == 0)
   1170 		return (DCMD_ERR);
   1171 
   1172 	mdb_printf(MSG_ORIG(MSG_HANDLES_LINE1), str);
   1173 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1174 
   1175 	if (HANDLES(&rtmap) == 0)
   1176 		return (DCMD_OK);
   1177 
   1178 	addr = (uintptr_t)HANDLES(&rtmap);
   1179 	if (mdb_vread(&apl, sizeof (APlist), addr) == -1) {
   1180 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_APLIST),
   1181 		    addr);
   1182 		return (DCMD_ERR);
   1183 	}
   1184 
   1185 	mdb_printf(MSG_ORIG(MSG_HANDLES_LINE2), addr, (size_t)apl.apl_nitems,
   1186 	    (size_t)apl.apl_arritems);
   1187 
   1188 	if (((flg & RTLD_FLG_VERBOSE) == 0) || (apl.apl_nitems == 0))
   1189 		return (DCMD_OK);
   1190 
   1191 	/*
   1192 	 * Under verbose mode print the name of each dependency.  An APlist can
   1193 	 * have a variable number of data items, so read each individual entry.
   1194 	 */
   1195 	datap = addr + APLIST_OFF_DATA;
   1196 	if (mdb_vread(&ghp, sizeof (Grp_hdl *), datap) == -1) {
   1197 		mdb_warn(MSG_ORIG(MSG_ERR_READ),
   1198 		    MSG_ORIG(MSG_GRPHDL_STR), datap);
   1199 		return (DCMD_ERR);
   1200 	}
   1201 
   1202 	(void) mdb_inc_indent(4);
   1203 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1204 
   1205 	if (dcmd_GrpHdl((uintptr_t)ghp, flags, argc, argv) == DCMD_ERR) {
   1206 		(void) mdb_dec_indent(4);
   1207 		return (DCMD_ERR);
   1208 	}
   1209 
   1210 	nitems = 1;
   1211 	for (nitems = 1; nitems < apl.apl_nitems; nitems++) {
   1212 		datap += sizeof (void *);
   1213 		if (mdb_vread(&ghp, sizeof (Grp_hdl *), datap) == -1) {
   1214 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
   1215 			    MSG_ORIG(MSG_GRPHDL_STR), datap);
   1216 			return (DCMD_ERR);
   1217 		}
   1218 
   1219 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1220 		if (dcmd_GrpHdl((uintptr_t)ghp, flags, argc,
   1221 		    argv) == DCMD_ERR) {
   1222 			(void) mdb_dec_indent(4);
   1223 			return (DCMD_ERR);
   1224 		}
   1225 	}
   1226 	(void) mdb_dec_indent(4);
   1227 	return (DCMD_OK);
   1228 }
   1229 
   1230 static void
   1231 dcmd_Groups_help(void)
   1232 {
   1233 	mdb_printf(MSG_ORIG(MSG_GROUPS_HELP));
   1234 }
   1235 
   1236 
   1237 static int
   1238 dcmd_Groups(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1239 {
   1240 	Rt_map		rtmap;
   1241 	char		*str;
   1242 	APlist		apl;
   1243 	uint_t		flg = 0;
   1244 	uintptr_t	datap, nitems;
   1245 	Grp_hdl		*ghp;
   1246 
   1247 	/*
   1248 	 * Insure we have a valid address, and provide for a -v option.
   1249 	 */
   1250 	if ((flags & DCMD_ADDRSPEC) == 0) {
   1251 		mdb_warn(MSG_ORIG(MSG_ERR_NAS), MSG_ORIG(MSG_GROUPS_STR));
   1252 		return (DCMD_USAGE);
   1253 	}
   1254 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, RTLD_FLG_VERBOSE,
   1255 	    &flg, NULL) != argc)
   1256 		return (DCMD_USAGE);
   1257 
   1258 	/*
   1259 	 * Read the Rt_map contents.
   1260 	 */
   1261 	if (mdb_vread(&rtmap, sizeof (Rt_map), addr) == -1) {
   1262 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_RTMAP_STR), addr);
   1263 		return (DCMD_ERR);
   1264 	}
   1265 	if ((str = String((uintptr_t)NAME(&rtmap),
   1266 	    MSG_ORIG(MSG_STR_NAME))) == 0)
   1267 		return (DCMD_ERR);
   1268 
   1269 	mdb_printf(MSG_ORIG(MSG_GROUPS_LINE1), str);
   1270 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1271 
   1272 	if (GROUPS(&rtmap) == 0)
   1273 		return (DCMD_OK);
   1274 
   1275 	addr = (uintptr_t)GROUPS(&rtmap);
   1276 	if (mdb_vread(&apl, sizeof (APlist), addr) == -1) {
   1277 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_STR_APLIST),
   1278 		    addr);
   1279 		return (DCMD_ERR);
   1280 	}
   1281 
   1282 	mdb_printf(MSG_ORIG(MSG_GROUPS_LINE2), addr, (size_t)apl.apl_nitems,
   1283 	    (size_t)apl.apl_arritems);
   1284 
   1285 	if (((flg & RTLD_FLG_VERBOSE) == 0) || (apl.apl_nitems == 0))
   1286 		return (DCMD_OK);
   1287 
   1288 	/*
   1289 	 * Under verbose mode print the name of each dependency.  An APlist can
   1290 	 * have a variable number of data items, so read each individual entry.
   1291 	 */
   1292 	datap = addr + APLIST_OFF_DATA;
   1293 	if (mdb_vread(&ghp, sizeof (Grp_hdl *), datap) == -1) {
   1294 		mdb_warn(MSG_ORIG(MSG_ERR_READ),
   1295 		    MSG_ORIG(MSG_GRPHDL_STR), datap);
   1296 		return (DCMD_ERR);
   1297 	}
   1298 
   1299 	(void) mdb_inc_indent(4);
   1300 	mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1301 
   1302 	if (dcmd_GrpHdl((uintptr_t)ghp, flags, argc, argv) == DCMD_ERR) {
   1303 		(void) mdb_dec_indent(4);
   1304 		return (DCMD_ERR);
   1305 	}
   1306 
   1307 	for (nitems = 1; nitems < apl.apl_nitems; nitems++) {
   1308 		datap += sizeof (void *);
   1309 		if (mdb_vread(&ghp, sizeof (Grp_hdl *), datap) == -1) {
   1310 			mdb_warn(MSG_ORIG(MSG_ERR_READ),
   1311 			    MSG_ORIG(MSG_GRPHDL_STR), datap);
   1312 			return (DCMD_ERR);
   1313 		}
   1314 
   1315 		mdb_printf(MSG_ORIG(MSG_STR_DASHES));
   1316 		if (dcmd_GrpHdl((uintptr_t)ghp, flags, argc,
   1317 		    argv) == DCMD_ERR) {
   1318 			(void) mdb_dec_indent(4);
   1319 			return (DCMD_ERR);
   1320 		}
   1321 	}
   1322 	(void) mdb_dec_indent(4);
   1323 	return (DCMD_OK);
   1324 }
   1325 static void
   1326 dcmd_ElfDyn_help(void)
   1327 {
   1328 	mdb_printf(MSG_ORIG(MSG_ELFDYN_HELP));
   1329 }
   1330 
   1331 static int
   1332 /* ARGSUSED2 */
   1333 dcmd_ElfDyn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1334 {
   1335 	Dyn		dyn;
   1336 	const char	*dynstr;
   1337 	Conv_inv_buf_t	inv_buf;
   1338 
   1339 	if ((flags & DCMD_ADDRSPEC) == 0)
   1340 		return (DCMD_USAGE);
   1341 	if (mdb_vread(&dyn, sizeof (dyn), addr) == -1) {
   1342 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_ELFDYN_STR),
   1343 		    addr);
   1344 		return (DCMD_ERR);
   1345 	}
   1346 
   1347 	mdb_printf(MSG_ORIG(MSG_ELFDYN_TITLE), addr);
   1348 	dynstr = conv_dyn_tag(dyn.d_tag, ELFOSABI_SOLARIS, M_MACH, 0, &inv_buf);
   1349 	mdb_printf(MSG_ORIG(MSG_ELFDYN_LINE1), addr, dynstr, dyn.d_un.d_ptr);
   1350 
   1351 	mdb_set_dot(addr + sizeof (Dyn));
   1352 
   1353 	return (DCMD_OK);
   1354 }
   1355 
   1356 static void
   1357 dcmd_ElfEhdr_help(void)
   1358 {
   1359 	mdb_printf(MSG_ORIG(MSG_EHDR_HELP));
   1360 }
   1361 
   1362 static int
   1363 /* ARGSUSED2 */
   1364 dcmd_ElfEhdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1365 {
   1366 	Ehdr			ehdr;
   1367 	Byte			*byte;
   1368 	const char		*flgs;
   1369 	Conv_inv_buf_t		inv_buf1, inv_buf2;
   1370 	Conv_ehdr_flags_buf_t	ehdr_flags_buf;
   1371 
   1372 
   1373 	if ((flags & DCMD_ADDRSPEC) == 0)
   1374 		return (DCMD_USAGE);
   1375 
   1376 	if (mdb_vread(&ehdr, sizeof (ehdr), addr) == -1) {
   1377 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_EHDR_STR),
   1378 		    addr);
   1379 		return (DCMD_ERR);
   1380 	}
   1381 
   1382 	mdb_printf(MSG_ORIG(MSG_EHDR_TITLE), addr);
   1383 	byte = &ehdr.e_ident[0];
   1384 	mdb_printf(MSG_ORIG(MSG_EHDR_LINE1), byte[EI_MAG0],
   1385 	    (byte[EI_MAG1] ? byte[EI_MAG1] : '0'),
   1386 	    (byte[EI_MAG2] ? byte[EI_MAG2] : '0'),
   1387 	    (byte[EI_MAG3] ? byte[EI_MAG3] : '0'));
   1388 	mdb_printf(MSG_ORIG(MSG_EHDR_LINE2),
   1389 	    conv_ehdr_class(ehdr.e_ident[EI_CLASS], 0, &inv_buf1),
   1390 	    conv_ehdr_data(ehdr.e_ident[EI_DATA], 0, &inv_buf2));
   1391 
   1392 	mdb_printf(MSG_ORIG(MSG_EHDR_LINE3),
   1393 	    conv_ehdr_mach(ehdr.e_machine, 0, &inv_buf1),
   1394 	    conv_ehdr_vers(ehdr.e_version, 0, &inv_buf2));
   1395 	mdb_printf(MSG_ORIG(MSG_EHDR_LINE4),
   1396 	    conv_ehdr_type(ehdr.e_ident[EI_OSABI], ehdr.e_type, 0, &inv_buf1));
   1397 
   1398 	/*
   1399 	 * Line up the flags differently depending on whether we
   1400 	 * received a numeric (e.g. "0x200") or text representation
   1401 	 * (e.g. "[ EF_SPARC_SUN_US1 ]").
   1402 	 */
   1403 	flgs = conv_ehdr_flags(ehdr.e_machine, ehdr.e_flags,
   1404 	    0, &ehdr_flags_buf);
   1405 	if (flgs[0] == '[')
   1406 		mdb_printf(MSG_ORIG(MSG_EHDR_LINE5), flgs);
   1407 	else
   1408 		mdb_printf(MSG_ORIG(MSG_EHDR_LINE6), flgs);
   1409 
   1410 	mdb_printf(MSG_ORIG(MSG_EHDR_LINE7), ehdr.e_entry, ehdr.e_ehsize,
   1411 	    ehdr.e_shstrndx);
   1412 	mdb_printf(MSG_ORIG(MSG_EHDR_LINE8), ehdr.e_shoff, ehdr.e_shentsize,
   1413 	    ehdr.e_shnum);
   1414 	mdb_printf(MSG_ORIG(MSG_EHDR_LINE9), ehdr.e_phoff, ehdr.e_phentsize,
   1415 	    ehdr.e_phnum);
   1416 
   1417 	mdb_set_dot(addr + sizeof (Ehdr));
   1418 
   1419 	return (DCMD_OK);
   1420 }
   1421 
   1422 static void
   1423 dcmd_ElfPhdr_help(void)
   1424 {
   1425 	mdb_printf(MSG_ORIG(MSG_EPHDR_HELP));
   1426 }
   1427 
   1428 static int
   1429 /* ARGSUSED2 */
   1430 dcmd_ElfPhdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
   1431 {
   1432 	Phdr			phdr;
   1433 	Conv_inv_buf_t		inv_buf;
   1434 	Conv_phdr_flags_buf_t	phdr_flags_buf;
   1435 
   1436 	if ((flags & DCMD_ADDRSPEC) == 0)
   1437 		return (DCMD_USAGE);
   1438 
   1439 	if (mdb_vread(&phdr, sizeof (phdr), addr) == -1) {
   1440 		mdb_warn(MSG_ORIG(MSG_ERR_READ), MSG_ORIG(MSG_EPHDR_STR),
   1441 		    addr);
   1442 		return (DCMD_ERR);
   1443 	}
   1444 
   1445 	mdb_printf(MSG_ORIG(MSG_EPHDR_TITLE), addr);
   1446 	mdb_printf(MSG_ORIG(MSG_EPHDR_LINE1), phdr.p_vaddr,
   1447 	    conv_phdr_flags(ELFOSABI_SOLARIS, phdr.p_flags, 0,
   1448 	    &phdr_flags_buf));
   1449 	mdb_printf(MSG_ORIG(MSG_EPHDR_LINE2), phdr.p_paddr,
   1450 	    conv_phdr_type(ELFOSABI_SOLARIS, M_MACH, phdr.p_type, 0, &inv_buf));
   1451 	mdb_printf(MSG_ORIG(MSG_EPHDR_LINE3), phdr.p_filesz, phdr.p_memsz);
   1452 	mdb_printf(MSG_ORIG(MSG_EPHDR_LINE4), phdr.p_offset, phdr.p_align);
   1453 
   1454 	mdb_set_dot(addr + sizeof (Phdr));
   1455 
   1456 	return (DCMD_OK);
   1457 }
   1458 
   1459 
   1460 static const mdb_dcmd_t dcmds[] = {
   1461 	{ MSG_ORIG(MSG_BND_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1462 		MSG_ORIG(MSG_BND_DCD),
   1463 		dcmd_Bind, dcmd_Bind_help},
   1464 	{ MSG_ORIG(MSG_DEPENDS_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1465 		MSG_ORIG(MSG_DEPENDS_DCD),
   1466 		dcmd_Depends, dcmd_Depends_help},
   1467 	{ MSG_ORIG(MSG_CALLERS_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1468 		MSG_ORIG(MSG_CALLERS_DCD),
   1469 		dcmd_Callers, dcmd_Callers_help},
   1470 	{ MSG_ORIG(MSG_GRPHDL_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1471 		MSG_ORIG(MSG_GRPHDL_DCD),
   1472 		dcmd_GrpHdl, dcmd_GrpHdl_help},
   1473 	{ MSG_ORIG(MSG_GRPDESC_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1474 		MSG_ORIG(MSG_GRPDESC_DCD),
   1475 		dcmd_GrpDesc, dcmd_GrpDesc_help},
   1476 	{ MSG_ORIG(MSG_HANDLES_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1477 		MSG_ORIG(MSG_HANDLES_DCD),
   1478 		dcmd_Handles, dcmd_Handles_help},
   1479 	{ MSG_ORIG(MSG_GROUPS_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1480 		MSG_ORIG(MSG_GROUPS_DCD),
   1481 		dcmd_Groups, dcmd_Groups_help},
   1482 	{ MSG_ORIG(MSG_ELFDYN_STR), MSG_ORIG(MSG_USG_ADDREQ),
   1483 		MSG_ORIG(MSG_ELFDYN_DCD),
   1484 		dcmd_ElfDyn, dcmd_ElfDyn_help},
   1485 	{ MSG_ORIG(MSG_EHDR_STR), MSG_ORIG(MSG_USG_ADDREQ),
   1486 		MSG_ORIG(MSG_EHDR_DCD),
   1487 		dcmd_ElfEhdr, dcmd_ElfEhdr_help},
   1488 	{ MSG_ORIG(MSG_EPHDR_STR), MSG_ORIG(MSG_USG_ADDREQ),
   1489 		MSG_ORIG(MSG_EPHDR_DCD),
   1490 		dcmd_ElfPhdr, dcmd_ElfPhdr_help},
   1491 	{ MSG_ORIG(MSG_LMLIST_STR), MSG_ORIG(MSG_USG_ADDREQ_V),
   1492 		MSG_ORIG(MSG_LMLIST_DCD),
   1493 		dcmd_Lm_list, dcmd_Lm_list_help},
   1494 	{ MSG_ORIG(MSG_RTMAPS_STR), MSG_ORIG(MSG_USG_ADDOPT_V),
   1495 		MSG_ORIG(MSG_RTMAPS_DCD),
   1496 		dcmd_Rtmaps, dcmd_Rtmaps_help},
   1497 	{ MSG_ORIG(MSG_RTMAP_STR), MSG_ORIG(MSG_USG_ADDREQ),
   1498 		MSG_ORIG(MSG_RTMAP_DCD),
   1499 		dcmd_rtmap, dcmd_rtmap_help},
   1500 	{ MSG_ORIG(MSG_SETENV_STR), MSG_ORIG(MSG_USG_SETENV),
   1501 		MSG_ORIG(MSG_SETENV_DCD),
   1502 		dcmd_Setenv, dcmd_Setenv_help},
   1503 	{ NULL }
   1504 };
   1505 
   1506 static const mdb_walker_t walkers[] = {
   1507 	{ MSG_ORIG(MSG_RTMAPS_STR), MSG_ORIG(MSG_WWD_RTMAP),
   1508 		walk_rtmap_init, walk_rtmap_step, NULL, NULL },
   1509 	{ NULL }
   1510 };
   1511 
   1512 static const mdb_modinfo_t modinfo = {
   1513 	MDB_API_VERSION, dcmds, walkers
   1514 };
   1515 
   1516 const	mdb_modinfo_t *
   1517 _mdb_init(void)
   1518 {
   1519 	return (&modinfo);
   1520 }
   1521