Home | History | Annotate | Download | only in libc
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   1885       raf  * Common Development and Distribution License (the "License").
      6   1885       raf  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21   1885       raf 
     22      0    stevel /*
     23   9170     Roger  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0    stevel  * Use is subject to license terms.
     25      0    stevel  */
     26      0    stevel 
     27      0    stevel #include <sys/mdb_modapi.h>
     28  10610  Jonathan #include <mdb/mdb_whatis.h>
     29      0    stevel #include <procfs.h>
     30      0    stevel #include <ucontext.h>
     31      0    stevel #include <siginfo.h>
     32      0    stevel #include <signal.h>
     33      0    stevel #include <setjmp.h>
     34      0    stevel #include <string.h>
     35      0    stevel #include <thr_uberdata.h>
     36      0    stevel 
     37      0    stevel static const char *
     38      0    stevel stack_flags(const stack_t *sp)
     39      0    stevel {
     40      0    stevel 	static char buf[32];
     41      0    stevel 
     42      0    stevel 	if (sp->ss_flags == 0)
     43      0    stevel 		(void) strcpy(buf, " 0");
     44      0    stevel 	else if (sp->ss_flags & ~(SS_ONSTACK | SS_DISABLE))
     45      0    stevel 		(void) mdb_snprintf(buf, sizeof (buf), " 0x%x", sp->ss_flags);
     46      0    stevel 	else {
     47      0    stevel 		buf[0] = '\0';
     48      0    stevel 		if (sp->ss_flags & SS_ONSTACK)
     49      0    stevel 			(void) strcat(buf, "|ONSTACK");
     50      0    stevel 		if (sp->ss_flags & SS_DISABLE)
     51      0    stevel 			(void) strcat(buf, "|DISABLE");
     52      0    stevel 	}
     53      0    stevel 
     54      0    stevel 	return (buf + 1);
     55      0    stevel }
     56      0    stevel 
     57      0    stevel /*ARGSUSED*/
     58      0    stevel static int
     59      0    stevel d_jmp_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
     60      0    stevel {
     61      0    stevel 	jmp_buf jb;
     62      0    stevel 	const ulong_t *b = (const ulong_t *)jb;
     63      0    stevel 
     64      0    stevel 	if (argc != 0)
     65      0    stevel 		return (DCMD_USAGE);
     66      0    stevel 
     67      0    stevel 	if (mdb_vread(&jb, sizeof (jb), addr) != sizeof (jb)) {
     68      0    stevel 		mdb_warn("failed to read jmp_buf at %p", addr);
     69      0    stevel 		return (DCMD_ERR);
     70      0    stevel 	}
     71      0    stevel 
     72      0    stevel #if defined(__sparc)
     73      0    stevel 	mdb_printf("  %%sp = 0x%lx\n", b[1]);
     74      0    stevel 	mdb_printf("  %%pc = 0x%lx %lA\n", b[2], b[2]);
     75      0    stevel 	mdb_printf("  %%fp = 0x%lx\n", b[3]);
     76      0    stevel 	mdb_printf("  %%i7 = 0x%lx %lA\n", b[4], b[4]);
     77      0    stevel #elif defined(__amd64)
     78      0    stevel 	mdb_printf("  %%rbx = 0x%lx\n", b[0]);
     79      0    stevel 	mdb_printf("  %%r12 = 0x%lx\n", b[1]);
     80      0    stevel 	mdb_printf("  %%r13 = 0x%lx\n", b[2]);
     81      0    stevel 	mdb_printf("  %%r14 = 0x%lx\n", b[3]);
     82      0    stevel 	mdb_printf("  %%r15 = 0x%lx\n", b[4]);
     83      0    stevel 	mdb_printf("  %%rbp = 0x%lx\n", b[5]);
     84      0    stevel 	mdb_printf("  %%rsp = 0x%lx\n", b[6]);
     85      0    stevel 	mdb_printf("  %%rip = 0x%lx %lA\n", b[7], b[7]);
     86      0    stevel #elif defined(__i386)
     87      0    stevel 	mdb_printf("  %%ebx = 0x%lx\n", b[0]);
     88      0    stevel 	mdb_printf("  %%esi = 0x%lx\n", b[1]);
     89      0    stevel 	mdb_printf("  %%edi = 0x%lx\n", b[2]);
     90      0    stevel 	mdb_printf("  %%ebp = 0x%lx\n", b[3]);
     91      0    stevel 	mdb_printf("  %%esp = 0x%lx\n", b[4]);
     92      0    stevel 	mdb_printf("  %%eip = 0x%lx %lA\n", b[5], b[5]);
     93      0    stevel #endif
     94      0    stevel 	return (DCMD_OK);
     95      0    stevel }
     96      0    stevel 
     97      0    stevel /*ARGSUSED*/
     98      0    stevel static int
     99      0    stevel d_ucontext(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    100      0    stevel {
    101      0    stevel 	ucontext_t uc;
    102      0    stevel 
    103      0    stevel 	if (argc != 0)
    104      0    stevel 		return (DCMD_USAGE);
    105      0    stevel 
    106      0    stevel 	if (mdb_vread(&uc, sizeof (uc), addr) != sizeof (uc)) {
    107      0    stevel 		mdb_warn("failed to read ucontext at %p", addr);
    108      0    stevel 		return (DCMD_ERR);
    109      0    stevel 	}
    110      0    stevel 
    111      0    stevel 	mdb_printf("  flags    = 0x%lx\n", uc.uc_flags);
    112      0    stevel 	mdb_printf("  link     = 0x%p\n", uc.uc_link);
    113      0    stevel 	mdb_printf("  sigmask  = 0x%08x 0x%08x 0x%08x 0x%08x\n",
    114      0    stevel 	    uc.uc_sigmask.__sigbits[0], uc.uc_sigmask.__sigbits[1],
    115      0    stevel 	    uc.uc_sigmask.__sigbits[2], uc.uc_sigmask.__sigbits[3]);
    116      0    stevel 	mdb_printf("  stack    = sp 0x%p size 0x%lx flags %s\n",
    117      0    stevel 	    uc.uc_stack.ss_sp, uc.uc_stack.ss_size, stack_flags(&uc.uc_stack));
    118      0    stevel 	mdb_printf("  mcontext = 0x%p\n",
    119      0    stevel 	    addr + OFFSETOF(ucontext_t, uc_mcontext));
    120      0    stevel 
    121      0    stevel 	return (DCMD_OK);
    122      0    stevel }
    123      0    stevel 
    124      0    stevel /*ARGSUSED*/
    125      0    stevel static int
    126      0    stevel d_sigjmp_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    127      0    stevel {
    128      0    stevel #if defined(__sparc)
    129      0    stevel 	struct {
    130      0    stevel 		int sjs_flags;
    131      0    stevel 		greg_t sjs_sp;
    132      0    stevel 		greg_t sjs_pc;
    133      0    stevel 		greg_t sjs_fp;
    134      0    stevel 		greg_t sjs_i7;
    135      0    stevel 		ucontext_t *sjs_uclink;
    136      0    stevel 		ulong_t sjs_pad[_JBLEN - 6];
    137      0    stevel 		sigset_t sjs_sigmask;
    138      0    stevel #if defined(_LP64)
    139      0    stevel 		ulong_t sjs_pad1[2];
    140      0    stevel #endif
    141      0    stevel 		stack_t sjs_stack;
    142      0    stevel 	} s;
    143      0    stevel 
    144      0    stevel 	if (argc != 0)
    145      0    stevel 		return (DCMD_USAGE);
    146      0    stevel 
    147      0    stevel 	if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
    148      0    stevel 		mdb_warn("failed to read sigjmp_buf at %p", addr);
    149      0    stevel 		return (DCMD_ERR);
    150      0    stevel 	}
    151      0    stevel 
    152      0    stevel 	mdb_printf("  flags  = 0x%x\n", s.sjs_flags);
    153      0    stevel 	mdb_printf("  %%sp    = 0x%lx %lA\n", s.sjs_sp, s.sjs_sp);
    154      0    stevel 	mdb_printf("  %%pc    = 0x%lx %lA\n", s.sjs_pc, s.sjs_pc);
    155      0    stevel 	mdb_printf("  %%fp    = 0x%lx %lA\n", s.sjs_fp, s.sjs_fp);
    156      0    stevel 	mdb_printf("  %%i7    = 0x%lx %lA\n", s.sjs_i7, s.sjs_i7);
    157      0    stevel 	mdb_printf("  uclink = %p\n", s.sjs_uclink);
    158      0    stevel 	mdb_printf("  sigset = 0x%08x 0x%08x 0x%08x 0x%08x\n",
    159      0    stevel 	    s.sjs_sigmask.__sigbits[0], s.sjs_sigmask.__sigbits[1],
    160      0    stevel 	    s.sjs_sigmask.__sigbits[2], s.sjs_sigmask.__sigbits[3]);
    161      0    stevel 	mdb_printf("  stack  = sp 0x%p size 0x%lx flags %s\n",
    162      0    stevel 	    s.sjs_stack.ss_sp, s.sjs_stack.ss_size, stack_flags(&s.sjs_stack));
    163      0    stevel 
    164      0    stevel 	return (DCMD_OK);
    165      0    stevel 
    166      0    stevel #elif defined(__i386) || defined(__amd64)
    167      0    stevel 	return (d_ucontext(addr, flags, argc, argv));
    168      0    stevel #endif
    169      0    stevel }
    170      0    stevel 
    171      0    stevel /*ARGSUSED*/
    172      0    stevel static int
    173      0    stevel d_siginfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    174      0    stevel {
    175      0    stevel 	static const char *const msname[] = {
    176      0    stevel 		"USER", "SYSTEM", "TRAP", "TFAULT", "DFAULT", "KFAULT",
    177      0    stevel 		"USER_LOCK", "SLEEP", "WAIT_CPU", "STOPPED"
    178      0    stevel 	};
    179      0    stevel 
    180      0    stevel 	char signame[SIG2STR_MAX];
    181      0    stevel 	siginfo_t si;
    182      0    stevel 	int i;
    183      0    stevel 
    184      0    stevel 	if (argc != 0)
    185      0    stevel 		return (DCMD_USAGE);
    186      0    stevel 
    187      0    stevel 	if (mdb_vread(&si, sizeof (si), addr) != sizeof (si)) {
    188      0    stevel 		mdb_warn("failed to read siginfo at %p", addr);
    189      0    stevel 		return (DCMD_ERR);
    190      0    stevel 	}
    191      0    stevel 
    192      0    stevel 	if (sig2str(si.si_signo, signame) == -1)
    193      0    stevel 		(void) strcpy(signame, "unknown");
    194      0    stevel 
    195      0    stevel 	mdb_printf("  signal %5d (%s)\n", si.si_signo, signame);
    196      0    stevel 	mdb_printf("  code   %5d (", si.si_code);
    197      0    stevel 
    198      0    stevel 	switch (si.si_code) {
    199      0    stevel 	case SI_NOINFO:
    200      0    stevel 		mdb_printf("no info");
    201      0    stevel 		break;
    202      0    stevel 	case SI_DTRACE:
    203      0    stevel 		mdb_printf("from DTrace raise() action");
    204      0    stevel 		break;
    205      0    stevel 	case SI_RCTL:
    206      0    stevel 		mdb_printf("from rctl action");
    207      0    stevel 		break;
    208      0    stevel 	case SI_USER:
    209      0    stevel 		mdb_printf("user generated via kill");
    210      0    stevel 		break;
    211      0    stevel 	case SI_LWP:
    212      0    stevel 		mdb_printf("user generated via lwp_kill");
    213      0    stevel 		break;
    214      0    stevel 	case SI_QUEUE:
    215      0    stevel 		mdb_printf("user generated via sigqueue");
    216      0    stevel 		break;
    217      0    stevel 	case SI_TIMER:
    218      0    stevel 		mdb_printf("from timer expiration");
    219      0    stevel 		break;
    220      0    stevel 	case SI_ASYNCIO:
    221      0    stevel 		mdb_printf("from async i/o completion");
    222      0    stevel 		break;
    223      0    stevel 	case SI_MESGQ:
    224      0    stevel 		mdb_printf("from message arrival");
    225      0    stevel 		break;
    226      0    stevel 	default:
    227      0    stevel 		if (SI_FROMUSER(&si))
    228      0    stevel 			mdb_printf("from user process");
    229      0    stevel 		else
    230      0    stevel 			mdb_printf("from kernel");
    231      0    stevel 	}
    232      0    stevel 
    233      0    stevel 	mdb_printf(")\n  errno  %5d (%s)\n",
    234      0    stevel 	    si.si_errno, strerror(si.si_errno));
    235      0    stevel 
    236      0    stevel 	if (si.si_code == SI_USER || si.si_code == SI_QUEUE) {
    237      0    stevel 		mdb_printf("  signal sent from PID %d (uid %d)\n",
    238      0    stevel 		    si.si_pid, si.si_uid);
    239      0    stevel 	}
    240      0    stevel 
    241      0    stevel 	if (si.si_code == SI_QUEUE) {
    242      0    stevel 		mdb_printf("  signal value = 0t%d / %p\n",
    243      0    stevel 		    si.si_value.sival_int, si.si_value.sival_ptr);
    244      0    stevel 	}
    245      0    stevel 
    246      0    stevel 	switch (si.si_signo) {
    247      0    stevel 	case SIGCLD:
    248      0    stevel 		mdb_printf("  signal sent from child PID %d (uid %d)\n",
    249      0    stevel 		    si.si_pid, si.si_uid);
    250      0    stevel 		mdb_printf("  usr time = 0t%ld ticks, sys time = 0t%ld ticks\n",
    251      0    stevel 		    si.si_utime, si.si_stime);
    252      0    stevel 		mdb_printf("  wait status = 0x%x\n", si.si_status);
    253      0    stevel 		break;
    254      0    stevel 
    255      0    stevel 	case SIGSEGV:
    256      0    stevel 	case SIGBUS:
    257      0    stevel 	case SIGILL:
    258      0    stevel 	case SIGTRAP:
    259      0    stevel 	case SIGFPE:
    260      0    stevel 		mdb_printf("  fault address = 0x%p\n  trapno = %d\n",
    261      0    stevel 		    si.si_addr, si.si_trapno);
    262      0    stevel 		mdb_printf("  instruction address = 0x%p %lA\n",
    263      0    stevel 		    si.si_pc, si.si_pc);
    264      0    stevel 		break;
    265      0    stevel 
    266      0    stevel 	case SIGPOLL:
    267      0    stevel 	case SIGXFSZ:
    268      0    stevel 		mdb_printf("  fd = %d  band = 0x%lx\n",
    269      0    stevel 		    si.si_fd, si.si_band);
    270      0    stevel 		break;
    271      0    stevel 
    272      0    stevel 	case SIGPROF:
    273      0    stevel 		mdb_printf("  last fault address = 0x%p fault type = %d\n",
    274      0    stevel 		    si.si_faddr, si.si_fault);
    275      0    stevel 		mdb_printf("  timestamp = 0t%ld sec 0t%ld nsec\n",
    276      0    stevel 		    si.si_tstamp.tv_sec, si.si_tstamp.tv_nsec);
    277      0    stevel 
    278      0    stevel 		if (si.__data.__prof.__syscall != 0) {
    279      0    stevel 			mdb_printf("  system call %d (", si.si_syscall);
    280      0    stevel 			if (si.si_nsysarg > 0) {
    281      0    stevel 				mdb_printf("%lx", si.si_sysarg[0]);
    282      0    stevel 				for (i = 1; i < si.si_nsysarg; i++)
    283      0    stevel 					mdb_printf(", %lx", si.si_sysarg[i]);
    284      0    stevel 			}
    285      0    stevel 			mdb_printf("  )\n");
    286      0    stevel 		}
    287      0    stevel 
    288      0    stevel 		for (i = 0; i < sizeof (msname) / sizeof (msname[0]); i++) {
    289      0    stevel 			mdb_printf("  mstate[\"%s\"] = %d\n",
    290      0    stevel 			    msname[i], si.si_mstate[i]);
    291      0    stevel 		}
    292      0    stevel 		break;
    293      0    stevel 	}
    294      0    stevel 
    295      0    stevel 	return (DCMD_OK);
    296      0    stevel }
    297      0    stevel 
    298      0    stevel static int
    299      0    stevel uc_walk_step(mdb_walk_state_t *wsp)
    300      0    stevel {
    301      0    stevel 	uintptr_t addr = wsp->walk_addr;
    302      0    stevel 	ucontext_t uc;
    303      0    stevel 
    304      0    stevel 	if (addr == NULL)
    305      0    stevel 		return (WALK_DONE);
    306      0    stevel 
    307      0    stevel 	if (mdb_vread(&uc, sizeof (uc), addr) != sizeof (uc)) {
    308      0    stevel 		mdb_warn("failed to read ucontext at %p", addr);
    309      0    stevel 		return (WALK_ERR);
    310      0    stevel 	}
    311      0    stevel 
    312      0    stevel 	wsp->walk_addr = (uintptr_t)uc.uc_link;
    313      0    stevel 	return (wsp->walk_callback(addr, &uc, wsp->walk_cbdata));
    314      0    stevel }
    315      0    stevel 
    316      0    stevel static int
    317      0    stevel oldc_walk_init(mdb_walk_state_t *wsp)
    318      0    stevel {
    319      0    stevel 	ssize_t nbytes = mdb_get_xdata("lwpstatus", NULL, 0);
    320      0    stevel 
    321      0    stevel 	if (nbytes <= 0) {
    322      0    stevel 		mdb_warn("lwpstatus information not available");
    323      0    stevel 		return (WALK_ERR);
    324      0    stevel 	}
    325      0    stevel 
    326      0    stevel 	if (wsp->walk_addr != NULL) {
    327      0    stevel 		mdb_warn("walker only supports global walk\n");
    328      0    stevel 		return (WALK_ERR);
    329      0    stevel 	}
    330      0    stevel 
    331      0    stevel 	wsp->walk_addr = nbytes; /* Use walk_addr to track size */
    332      0    stevel 	wsp->walk_data = mdb_alloc(nbytes, UM_SLEEP);
    333      0    stevel 
    334      0    stevel 	if (mdb_get_xdata("lwpstatus", wsp->walk_data, nbytes) != nbytes) {
    335      0    stevel 		mdb_warn("failed to read lwpstatus information");
    336      0    stevel 		mdb_free(wsp->walk_data, nbytes);
    337      0    stevel 		return (WALK_ERR);
    338      0    stevel 	}
    339      0    stevel 
    340      0    stevel 	wsp->walk_arg = wsp->walk_data; /* Use walk_arg to track pointer */
    341      0    stevel 	return (WALK_NEXT);
    342      0    stevel }
    343      0    stevel 
    344      0    stevel static int
    345      0    stevel oldc_walk_step(mdb_walk_state_t *wsp)
    346      0    stevel {
    347      0    stevel 	const lwpstatus_t *lsp, *end;
    348      0    stevel 
    349      0    stevel 	end = (const lwpstatus_t *)((uintptr_t)wsp->walk_data + wsp->walk_addr);
    350      0    stevel 	lsp = wsp->walk_arg;
    351      0    stevel 
    352      0    stevel 	wsp->walk_arg = (void *)(lsp + 1);
    353      0    stevel 
    354      0    stevel 	if (lsp < end) {
    355      0    stevel 		uintptr_t addr = lsp->pr_oldcontext;
    356      0    stevel 		ucontext_t uc;
    357      0    stevel 
    358      0    stevel 		if (addr == NULL)
    359      0    stevel 			return (WALK_NEXT);
    360      0    stevel 
    361      0    stevel 		if (mdb_vread(&uc, sizeof (uc), addr) != sizeof (uc)) {
    362      0    stevel 			mdb_warn("failed to read ucontext at %p", addr);
    363      0    stevel 			return (WALK_NEXT);
    364      0    stevel 		}
    365      0    stevel 
    366      0    stevel 		return (wsp->walk_callback(addr, &uc, wsp->walk_cbdata));
    367      0    stevel 	}
    368      0    stevel 
    369      0    stevel 	return (WALK_DONE);
    370      0    stevel }
    371      0    stevel 
    372      0    stevel static void
    373      0    stevel oldc_walk_fini(mdb_walk_state_t *wsp)
    374      0    stevel {
    375      0    stevel 	mdb_free(wsp->walk_data, wsp->walk_addr); /* walk_addr has size */
    376      0    stevel }
    377      0    stevel 
    378      0    stevel /*
    379      0    stevel  * ==================== threads ==========================
    380      0    stevel  * These are the interfaces that used to require libthread.
    381      0    stevel  * Now, libthread has been folded into libc.
    382      0    stevel  * =======================================================
    383      0    stevel  */
    384      0    stevel 
    385      0    stevel /*
    386      0    stevel  * prt_addr() is called up to three times to generate arguments for
    387      0    stevel  * one call to mdb_printf().  We must return at least three different
    388      0    stevel  * pointers to static storage for consecutive calls to prt_addr().
    389      0    stevel  */
    390      0    stevel static const char *
    391      0    stevel prt_addr(void *addr, int pad)
    392      0    stevel {
    393      0    stevel 	static char buffer[4][24];
    394      0    stevel 	static int ix = 0;
    395      0    stevel 	char *buf;
    396      0    stevel 
    397      0    stevel 	if (ix == 4)	/* use buffers in sequence: 0, 1, 2, 3 */
    398      0    stevel 		ix = 0;
    399      0    stevel 	buf = buffer[ix++];
    400      0    stevel 	if (addr == NULL)
    401      0    stevel 		return (pad? "<NULL>               " : "<NULL>");
    402      0    stevel 	else {
    403      0    stevel #ifdef _LP64
    404      0    stevel 		(void) mdb_snprintf(buf, sizeof (buffer[0]), "0x%016lx", addr);
    405      0    stevel 		if (pad)
    406      0    stevel 			(void) strcpy(buf + 18, "   ");
    407      0    stevel #else
    408      0    stevel 		(void) mdb_snprintf(buf, sizeof (buffer[0]), "0x%08lx", addr);
    409      0    stevel 		if (pad)
    410      0    stevel 			(void) strcpy(buf + 10, "           ");
    411      0    stevel #endif	/* _LP64 */
    412      0    stevel 		return (buf);
    413      0    stevel 	}
    414      0    stevel }
    415      0    stevel 
    416      0    stevel #define	HD(str)		mdb_printf("           " str "\n")
    417      0    stevel #define	OFFSTR		"+0x%-7lx "
    418      0    stevel #define	OFFSET(member)	((size_t)OFFSETOF(ulwp_t, member))
    419      0    stevel 
    420      0    stevel /*ARGSUSED*/
    421      0    stevel static int
    422      0    stevel d_ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    423      0    stevel {
    424      0    stevel 	ulwp_t ulwp;
    425      0    stevel 
    426      0    stevel 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
    427      0    stevel 		return (DCMD_USAGE);
    428      0    stevel 
    429      0    stevel 	if (mdb_vread(&ulwp, sizeof (ulwp), addr) != sizeof (ulwp) &&
    430      0    stevel 	    (bzero(&ulwp, sizeof (ulwp)),
    431      0    stevel 	    mdb_vread(&ulwp, REPLACEMENT_SIZE, addr)) != REPLACEMENT_SIZE) {
    432      0    stevel 		mdb_warn("failed to read ulwp at 0x%p", addr);
    433      0    stevel 		return (DCMD_ERR);
    434      0    stevel 	}
    435      0    stevel 
    436      0    stevel 	mdb_printf("%#a\n", addr);
    437      0    stevel 
    438      0    stevel 	HD("self                  uberdata");
    439      0    stevel 	mdb_printf(OFFSTR "%s %s\n",
    440   6515       raf 	    OFFSET(ul_self),
    441   6515       raf 	    prt_addr(ulwp.ul_self, 1),
    442   6515       raf 	    prt_addr(ulwp.ul_uberdata, 0));
    443      0    stevel 
    444      0    stevel 	HD("tlsent                ntlsent");
    445      0    stevel 	mdb_printf(OFFSTR "%s %ld\n",
    446   6515       raf 	    OFFSET(ul_tlsent),
    447   6515       raf 	    prt_addr(ulwp.ul_tlsent, 1),
    448   6515       raf 	    ulwp.ul_ntlsent);
    449      0    stevel 
    450      0    stevel 	HD("forw                  back                  next");
    451      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    452   6515       raf 	    OFFSET(ul_forw),
    453   6515       raf 	    prt_addr(ulwp.ul_forw, 1),
    454   6515       raf 	    prt_addr(ulwp.ul_back, 1),
    455   6515       raf 	    prt_addr(ulwp.ul_next, 0));
    456      0    stevel 
    457      0    stevel 	HD("hash                  rval                  stk");
    458      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    459   6515       raf 	    OFFSET(ul_hash),
    460   6515       raf 	    prt_addr(ulwp.ul_hash, 1),
    461   6515       raf 	    prt_addr(ulwp.ul_rval, 1),
    462   6515       raf 	    prt_addr(ulwp.ul_stk, 0));
    463      0    stevel 
    464      0    stevel 	HD("mapsiz     guardsize  stktop                stksiz");
    465      0    stevel 	mdb_printf(OFFSTR "%-10ld %-10ld %s %ld\n",
    466   6515       raf 	    OFFSET(ul_mapsiz),
    467   6515       raf 	    ulwp.ul_mapsiz,
    468   6515       raf 	    ulwp.ul_guardsize,
    469   6515       raf 	    prt_addr((void *)ulwp.ul_stktop, 1),
    470   6515       raf 	    ulwp.ul_stksiz);
    471      0    stevel 
    472      0    stevel 	HD("ustack.ss_sp          ustack.ss_size        ustack.ss_flags");
    473      0    stevel 	mdb_printf(OFFSTR "%s %-21ld %s\n",
    474   6515       raf 	    OFFSET(ul_ustack.ss_sp),
    475   6515       raf 	    prt_addr(ulwp.ul_ustack.ss_sp, 1),
    476   6515       raf 	    ulwp.ul_ustack.ss_size,
    477   6515       raf 	    stack_flags(&ulwp.ul_ustack));
    478      0    stevel 
    479   6247       raf 	HD("ix         lwpid      pri        epri       policy     cid");
    480      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
    481   6515       raf 	    OFFSET(ul_ix),
    482   6515       raf 	    ulwp.ul_ix,
    483   6515       raf 	    ulwp.ul_lwpid,
    484   6515       raf 	    ulwp.ul_pri,
    485   6515       raf 	    ulwp.ul_epri,
    486   6515       raf 	    ulwp.ul_policy,
    487   6515       raf 	    ulwp.ul_cid);
    488      0    stevel 
    489      0    stevel 	HD("cursig     pleasestop stop       signalled  dead       unwind");
    490      0    stevel 	mdb_printf(OFFSTR "%-10d ",
    491   6515       raf 	    OFFSET(ul_cursig),
    492   6515       raf 	    ulwp.ul_cursig);
    493      0    stevel 	mdb_printf(ulwp.ul_pleasestop? "0x%-8x " : "%-10d ",
    494   6515       raf 	    ulwp.ul_pleasestop);
    495      0    stevel 	mdb_printf(ulwp.ul_stop? "0x%-8x " : "%-10d ",
    496   6515       raf 	    ulwp.ul_stop);
    497      0    stevel 	mdb_printf("%-10d %-10d %d\n",
    498   6515       raf 	    ulwp.ul_signalled,
    499   6515       raf 	    ulwp.ul_dead,
    500   6515       raf 	    ulwp.ul_unwind);
    501      0    stevel 
    502   1885       raf 	HD("detached   writer     stopping   can'prolog preempt    savpreempt");
    503      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
    504   6515       raf 	    OFFSET(ul_detached),
    505   6515       raf 	    ulwp.ul_detached,
    506   6515       raf 	    ulwp.ul_writer,
    507   6515       raf 	    ulwp.ul_stopping,
    508   6515       raf 	    ulwp.ul_cancel_prologue,
    509   6515       raf 	    ulwp.ul_preempt,
    510   6515       raf 	    ulwp.ul_savpreempt);
    511      0    stevel 
    512      0    stevel 	HD("sigsuspend main       fork       primarymap m'spinners d'noreserv");
    513      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
    514   6515       raf 	    OFFSET(ul_sigsuspend),
    515   6515       raf 	    ulwp.ul_sigsuspend,
    516   6515       raf 	    ulwp.ul_main,
    517   6515       raf 	    ulwp.ul_fork,
    518   6515       raf 	    ulwp.ul_primarymap,
    519   6515       raf 	    ulwp.ul_max_spinners,
    520   6515       raf 	    ulwp.ul_door_noreserve);
    521      0    stevel 
    522   6247       raf 	HD("queue_fifo c'w'defer  e'detect'  async_safe rt         rtqueued");
    523      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
    524   6515       raf 	    OFFSET(ul_queue_fifo),
    525   6515       raf 	    ulwp.ul_queue_fifo,
    526   6515       raf 	    ulwp.ul_cond_wait_defer,
    527   6515       raf 	    ulwp.ul_error_detection,
    528   6515       raf 	    ulwp.ul_async_safe,
    529   6515       raf 	    ulwp.ul_rt,
    530   6515       raf 	    ulwp.ul_rtqueued);
    531      0    stevel 
    532   7255       raf 	HD("misaligned adapt'spin queue_spin critical   sigdefer   vfork");
    533   7255       raf 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
    534   7255       raf 	    OFFSET(ul_misaligned),
    535   7255       raf 	    ulwp.ul_misaligned,
    536   6515       raf 	    ulwp.ul_adaptive_spin,
    537   6515       raf 	    ulwp.ul_queue_spin,
    538   6515       raf 	    ulwp.ul_critical,
    539   6515       raf 	    ulwp.ul_sigdefer,
    540   6515       raf 	    ulwp.ul_vfork);
    541      0    stevel 
    542      0    stevel 	HD("cancelable c'pending  c'disabled c'async    save_async mutator");
    543      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
    544   6515       raf 	    OFFSET(ul_cancelable),
    545   6515       raf 	    ulwp.ul_cancelable,
    546   6515       raf 	    ulwp.ul_cancel_pending,
    547   6515       raf 	    ulwp.ul_cancel_disabled,
    548   6515       raf 	    ulwp.ul_cancel_async,
    549   6515       raf 	    ulwp.ul_save_async,
    550   6515       raf 	    ulwp.ul_mutator);
    551      0    stevel 
    552      0    stevel 	HD("created    replace    nocancel   errno      errnop");
    553      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %s\n",
    554   6515       raf 	    OFFSET(ul_created),
    555   6515       raf 	    ulwp.ul_created,
    556   6515       raf 	    ulwp.ul_replace,
    557   6515       raf 	    ulwp.ul_nocancel,
    558   6515       raf 	    ulwp.ul_errno,
    559   6515       raf 	    prt_addr(ulwp.ul_errnop, 0));
    560      0    stevel 
    561      0    stevel 	HD("clnup_hdr             schedctl_called       schedctl");
    562      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    563   6515       raf 	    OFFSET(ul_clnup_hdr),
    564   6515       raf 	    prt_addr(ulwp.ul_clnup_hdr, 1),
    565   6515       raf 	    prt_addr(ulwp.ul_schedctl_called, 1),
    566   6515       raf 	    prt_addr((void *)ulwp.ul_schedctl, 0));
    567      0    stevel 
    568   5891       raf 	HD("bindflags  libc_locks stsd                  &ftsd");
    569      0    stevel 	mdb_printf(OFFSTR,
    570   6515       raf 	    OFFSET(ul_bindflags));
    571      0    stevel 	mdb_printf(ulwp.ul_bindflags? "0x%-8x " : "%-10d ",
    572   6515       raf 	    ulwp.ul_bindflags);
    573   5891       raf 	mdb_printf("%-10d ", ulwp.ul_libc_locks);
    574      0    stevel 	mdb_printf("%s %s\n",
    575   6515       raf 	    prt_addr(ulwp.ul_stsd, 1),
    576   6515       raf 	    prt_addr((void *)(addr + OFFSET(ul_ftsd[0])), 0));
    577      0    stevel 
    578      0    stevel 	HD("eventmask[0..1]       eventnum              eventdata");
    579      0    stevel 	mdb_printf(OFFSTR "0x%08x 0x%08x %-21d %s\n",
    580   6515       raf 	    OFFSET(ul_td_evbuf.eventmask.event_bits[0]),
    581   6515       raf 	    ulwp.ul_td_evbuf.eventmask.event_bits[0],
    582   6515       raf 	    ulwp.ul_td_evbuf.eventmask.event_bits[1],
    583   6515       raf 	    ulwp.ul_td_evbuf.eventnum,
    584   6515       raf 	    prt_addr(ulwp.ul_td_evbuf.eventdata, 0));
    585      0    stevel 
    586  10637     Roger 	HD("td'enable  sync'reg   qtype      cv_wake    rtld       usropts");
    587  10637     Roger 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d ",
    588   6515       raf 	    OFFSET(ul_td_events_enable),
    589   6515       raf 	    ulwp.ul_td_events_enable,
    590   6515       raf 	    ulwp.ul_sync_obj_reg,
    591   6515       raf 	    ulwp.ul_qtype,
    592  10637     Roger 	    ulwp.ul_cv_wake,
    593  10637     Roger 	    ulwp.ul_rtld);
    594      0    stevel 	mdb_printf(ulwp.ul_usropts? "0x%x\n" : "%d\n",
    595   6515       raf 	    ulwp.ul_usropts);
    596      0    stevel 
    597      0    stevel 	HD("startpc               startarg              wchan");
    598      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    599   6515       raf 	    OFFSET(ul_startpc),
    600   6515       raf 	    prt_addr((void *)ulwp.ul_startpc, 1),
    601   6515       raf 	    prt_addr(ulwp.ul_startarg, 1),
    602   6515       raf 	    prt_addr(ulwp.ul_wchan, 0));
    603      0    stevel 
    604      0    stevel 	HD("link                  sleepq                cvmutex");
    605      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    606   6515       raf 	    OFFSET(ul_link),
    607   6515       raf 	    prt_addr(ulwp.ul_link, 1),
    608   6515       raf 	    prt_addr(ulwp.ul_sleepq, 1),
    609   6515       raf 	    prt_addr(ulwp.ul_cvmutex, 0));
    610      0    stevel 
    611   6247       raf 	HD("mxchain               save_state");
    612   6247       raf 	mdb_printf(OFFSTR "%s %d\n",
    613   6515       raf 	    OFFSET(ul_mxchain),
    614   6515       raf 	    prt_addr(ulwp.ul_mxchain, 1),
    615   6515       raf 	    ulwp.ul_save_state);
    616      0    stevel 
    617   4574       raf 	HD("rdlockcnt             rd_rwlock             rd_count");
    618   4574       raf 	mdb_printf(OFFSTR "%-21d %s %d\n",
    619   6515       raf 	    OFFSET(ul_rdlockcnt),
    620   6515       raf 	    ulwp.ul_rdlockcnt,
    621   6515       raf 	    prt_addr(ulwp.ul_readlock.single.rd_rwlock, 1),
    622   6515       raf 	    ulwp.ul_readlock.single.rd_count);
    623   4574       raf 
    624   4574       raf 	HD("heldlockcnt           heldlocks             tpdp");
    625   4574       raf 	mdb_printf(OFFSTR "%-21d %s %s\n",
    626   6515       raf 	    OFFSET(ul_heldlockcnt),
    627   6515       raf 	    ulwp.ul_heldlockcnt,
    628   6515       raf 	    prt_addr(ulwp.ul_heldlocks.single, 1),
    629   6515       raf 	    prt_addr(ulwp.ul_tpdp, 0));
    630      0    stevel 
    631      0    stevel 	HD("siglink               s'l'spin   s'l'spin2  s'l'sleep  s'l'wakeup");
    632   6247       raf 	mdb_printf(OFFSTR "%s %-10d %-10d %-10d %d\n",
    633   6515       raf 	    OFFSET(ul_siglink),
    634   6515       raf 	    prt_addr(ulwp.ul_siglink, 1),
    635   6515       raf 	    ulwp.ul_spin_lock_spin,
    636   6515       raf 	    ulwp.ul_spin_lock_spin2,
    637   6515       raf 	    ulwp.ul_spin_lock_sleep,
    638   6515       raf 	    ulwp.ul_spin_lock_wakeup);
    639   6247       raf 
    640   6247       raf 	HD("&queue_root           rtclassid  pilocks");
    641   6247       raf 	mdb_printf(OFFSTR "%s %-10d %d\n",
    642   6515       raf 	    OFFSET(ul_queue_root),
    643   6515       raf 	    prt_addr((void *)(addr + OFFSET(ul_queue_root)), 1),
    644   6515       raf 	    ulwp.ul_rtclassid,
    645   6515       raf 	    ulwp.ul_pilocks);
    646      0    stevel 
    647      0    stevel 	/*
    648      0    stevel 	 * The remainder of the ulwp_t structure
    649      0    stevel 	 * is invalid if this is a replacement.
    650      0    stevel 	 */
    651      0    stevel 	if (ulwp.ul_replace)
    652      0    stevel 		return (DCMD_OK);
    653      0    stevel 
    654      0    stevel 	HD("sigmask[0..3]");
    655      0    stevel 	mdb_printf(OFFSTR "0x%08x 0x%08x 0x%08x 0x%08x\n",
    656   6515       raf 	    OFFSET(ul_sigmask.__sigbits[0]),
    657   6515       raf 	    ulwp.ul_sigmask.__sigbits[0],
    658   6515       raf 	    ulwp.ul_sigmask.__sigbits[1],
    659   6515       raf 	    ulwp.ul_sigmask.__sigbits[2],
    660   6515       raf 	    ulwp.ul_sigmask.__sigbits[3]);
    661      0    stevel 
    662      0    stevel 	HD("tmpmask[0..3]");
    663      0    stevel 	mdb_printf(OFFSTR "0x%08x 0x%08x 0x%08x 0x%08x\n",
    664   6515       raf 	    OFFSET(ul_tmpmask.__sigbits[0]),
    665   6515       raf 	    ulwp.ul_tmpmask.__sigbits[0],
    666   6515       raf 	    ulwp.ul_tmpmask.__sigbits[1],
    667   6515       raf 	    ulwp.ul_tmpmask.__sigbits[2],
    668   6515       raf 	    ulwp.ul_tmpmask.__sigbits[3]);
    669      0    stevel 
    670      0    stevel 	HD("&siginfo              &spinlock             &fpuenv");
    671      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    672   6515       raf 	    OFFSET(ul_siginfo),
    673   6515       raf 	    prt_addr((void *)(addr + OFFSET(ul_siginfo)), 1),
    674   6515       raf 	    prt_addr((void *)(addr + OFFSET(ul_spinlock)), 1),
    675   6515       raf 	    prt_addr((void *)(addr + OFFSET(ul_fpuenv)), 0));
    676      0    stevel 
    677      0    stevel 	return (DCMD_OK);
    678      0    stevel }
    679      0    stevel 
    680      0    stevel /*
    681      0    stevel  * Get the address of the unique uberdata_t structure.
    682      0    stevel  */
    683      0    stevel static uintptr_t
    684      0    stevel uberdata_addr(void)
    685      0    stevel {
    686      0    stevel 	uintptr_t uaddr;
    687      0    stevel 	uintptr_t addr;
    688      0    stevel 	GElf_Sym sym;
    689      0    stevel 
    690      0    stevel 	if (mdb_lookup_by_obj("libc.so.1", "_tdb_bootstrap", &sym) != 0) {
    691      0    stevel 		mdb_warn("cannot find libc.so.1`_tdb_bootstrap");
    692      0    stevel 		return (NULL);
    693      0    stevel 	}
    694      0    stevel 	if (mdb_vread(&addr, sizeof (addr), sym.st_value) == sizeof (addr) &&
    695      0    stevel 	    addr != NULL &&
    696      0    stevel 	    mdb_vread(&uaddr, sizeof (uaddr), addr) == sizeof (uaddr) &&
    697      0    stevel 	    uaddr != NULL) {
    698      0    stevel 		return (uaddr);
    699      0    stevel 	}
    700      0    stevel 	if (mdb_lookup_by_obj("libc.so.1", "_uberdata", &sym) != 0) {
    701      0    stevel 		mdb_warn("cannot find libc.so.1`_uberdata");
    702      0    stevel 		return (NULL);
    703      0    stevel 	}
    704      0    stevel 	return ((uintptr_t)sym.st_value);
    705      0    stevel }
    706      0    stevel 
    707      0    stevel #undef OFFSET
    708      0    stevel #define	OFFSET(member)	((size_t)OFFSETOF(uberdata_t, member))
    709      0    stevel 
    710      0    stevel /*ARGSUSED*/
    711      0    stevel static int
    712      0    stevel d_uberdata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    713      0    stevel {
    714      0    stevel 	uberdata_t uberdata;
    715      0    stevel 	int i;
    716      0    stevel 
    717      0    stevel 	if (argc != 0)
    718      0    stevel 		return (DCMD_USAGE);
    719      0    stevel 	if (!(flags & DCMD_ADDRSPEC) && (addr = uberdata_addr()) == NULL)
    720      0    stevel 		return (DCMD_ERR);
    721      0    stevel 
    722      0    stevel 	if (mdb_vread(&uberdata, sizeof (uberdata), addr) !=
    723      0    stevel 	    sizeof (uberdata)) {
    724      0    stevel 		mdb_warn("failed to read uberdata at 0x%p", addr);
    725      0    stevel 		return (DCMD_ERR);
    726      0    stevel 	}
    727      0    stevel 
    728      0    stevel 	mdb_printf("%#a\n", addr);
    729      0    stevel 
    730   6515       raf 	HD("&link_lock            &ld_lock              &fork_lock");
    731      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    732   6515       raf 	    OFFSET(link_lock),
    733   6515       raf 	    prt_addr((void *)(addr + OFFSET(link_lock)), 1),
    734   6515       raf 	    prt_addr((void *)(addr + OFFSET(ld_lock)), 1),
    735   6515       raf 	    prt_addr((void *)(addr + OFFSET(fork_lock)), 0));
    736      0    stevel 
    737   6515       raf 	HD("&atfork_lock          &callout_lock         &tdb_hash_lock");
    738      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    739   6515       raf 	    OFFSET(atfork_lock),
    740   6515       raf 	    prt_addr((void *)(addr + OFFSET(atfork_lock)), 1),
    741   6515       raf 	    prt_addr((void *)(addr + OFFSET(callout_lock)), 1),
    742   6515       raf 	    prt_addr((void *)(addr + OFFSET(tdb_hash_lock)), 0));
    743   6515       raf 
    744   6515       raf 	HD("&tdb_hash_lock_stats  &siguaction[0]");
    745   6515       raf 	mdb_printf(OFFSTR "%s %s\n",
    746   6515       raf 	    OFFSET(tdb_hash_lock_stats),
    747   6515       raf 	    prt_addr((void *)(addr + OFFSET(tdb_hash_lock_stats)), 1),
    748   6515       raf 	    prt_addr((void *)(addr + OFFSET(siguaction)), 0));
    749      0    stevel 
    750      0    stevel 	HD("&bucket               free_list             chunks");
    751      0    stevel 	for (i = 0; i < NBUCKETS; i++) {
    752      0    stevel 		mdb_printf(OFFSTR "%s %s %ld\n",
    753   6515       raf 		    OFFSET(bucket[i]),
    754   6515       raf 		    prt_addr((void *)(addr + OFFSET(bucket[i])), 1),
    755   6515       raf 		    prt_addr(uberdata.bucket[i].free_list, 1),
    756   6515       raf 		    uberdata.bucket[i].chunks);
    757      0    stevel 	}
    758      0    stevel 
    759      0    stevel 	HD("&atexit_root          head                  exit_frame_monitor");
    760      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    761   6515       raf 	    OFFSET(atexit_root),
    762   6515       raf 	    prt_addr((void *)(addr + OFFSET(atexit_root.exitfns_lock)), 1),
    763   6515       raf 	    prt_addr(uberdata.atexit_root.head, 1),
    764   6515       raf 	    prt_addr(uberdata.atexit_root.exit_frame_monitor, 0));
    765      0    stevel 
    766      0    stevel 	HD("&tsd_metadata         tsdm_nkeys tsdm_nused tsdm_destro");
    767      0    stevel 	mdb_printf(OFFSTR "%s %-10d %-10d %s\n",
    768   6515       raf 	    OFFSET(tsd_metadata),
    769   6515       raf 	    prt_addr((void *)(addr + OFFSET(tsd_metadata.tsdm_lock)), 1),
    770   6515       raf 	    uberdata.tsd_metadata.tsdm_nkeys,
    771   6515       raf 	    uberdata.tsd_metadata.tsdm_nused,
    772   6515       raf 	    prt_addr((void *)uberdata.tsd_metadata.tsdm_destro, 0));
    773      0    stevel 
    774      0    stevel 	HD("&tls_metadata         tls_modinfo.data      tls_modinfo.size");
    775      0    stevel 	mdb_printf(OFFSTR "%s %s %ld\n",
    776   6515       raf 	    OFFSET(tls_metadata),
    777   6515       raf 	    prt_addr((void *)(addr + OFFSET(tls_metadata.tls_lock)), 1),
    778   6515       raf 	    prt_addr(uberdata.tls_metadata.tls_modinfo.tls_data, 1),
    779   6515       raf 	    uberdata.tls_metadata.tls_modinfo.tls_size);
    780      0    stevel 
    781      0    stevel 	HD("                      static_tls.data       static_tls.size");
    782      0    stevel 	mdb_printf(OFFSTR "%s %s %ld\n",
    783   6515       raf 	    OFFSET(tls_metadata.static_tls),
    784   6515       raf 	    "                     ",
    785   6515       raf 	    prt_addr(uberdata.tls_metadata.static_tls.tls_data, 1),
    786   6515       raf 	    uberdata.tls_metadata.static_tls.tls_size);
    787      0    stevel 
    788      0    stevel 	HD("primary_ma bucket_ini uflags.mt  uflags.pad uflags.trs uflags.ted");
    789      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %-10d %d\n",
    790   6515       raf 	    OFFSET(primary_map),
    791   6515       raf 	    uberdata.primary_map,
    792   6515       raf 	    uberdata.bucket_init,
    793   6515       raf 	    uberdata.uberflags.uf_x.x_mt,
    794   6515       raf 	    uberdata.uberflags.uf_x.x_pad,
    795   6515       raf 	    uberdata.uberflags.uf_x.x_tdb_register_sync,
    796   6515       raf 	    uberdata.uberflags.uf_x.x_thread_error_detection);
    797      0    stevel 
    798      0    stevel 	HD("queue_head            thr_hash_table        hash_size  hash_mask");
    799      0    stevel 	mdb_printf(OFFSTR "%s %s %-10d 0x%x\n",
    800   6515       raf 	    OFFSET(queue_head),
    801   6515       raf 	    prt_addr(uberdata.queue_head, 1),
    802   6515       raf 	    prt_addr(uberdata.thr_hash_table, 1),
    803   6515       raf 	    uberdata.hash_size,
    804   6515       raf 	    uberdata.hash_mask);
    805      0    stevel 
    806      0    stevel 	HD("ulwp_one              all_lwps              all_zombies");
    807      0    stevel 	mdb_printf(OFFSTR "%s %s %s\n",
    808   6515       raf 	    OFFSET(ulwp_one),
    809   6515       raf 	    prt_addr(uberdata.ulwp_one, 1),
    810   6515       raf 	    prt_addr(uberdata.all_lwps, 1),
    811   6515       raf 	    prt_addr(uberdata.all_zombies, 0));
    812      0    stevel 
    813      0    stevel 	HD("nthreads   nzombies   ndaemons   pid        sigacthandler");
    814      0    stevel 	mdb_printf(OFFSTR "%-10d %-10d %-10d %-10d %s\n",
    815   6515       raf 	    OFFSET(nthreads),
    816   6515       raf 	    uberdata.nthreads,
    817   6515       raf 	    uberdata.nzombies,
    818   6515       raf 	    uberdata.ndaemons,
    819   6515       raf 	    (int)uberdata.pid,
    820   6515       raf 	    prt_addr((void *)uberdata.sigacthandler, 0));
    821      0    stevel 
    822      0    stevel 	HD("lwp_stacks            lwp_laststack         nfreestack stk_cache");
    823      0    stevel 	mdb_printf(OFFSTR "%s %s %-10d %d\n",
    824   6515       raf 	    OFFSET(lwp_stacks),
    825   6515       raf 	    prt_addr(uberdata.lwp_stacks, 1),
    826   6515       raf 	    prt_addr(uberdata.lwp_laststack, 1),
    827   6515       raf 	    uberdata.nfreestack,
    828   6515       raf 	    uberdata.thread_stack_cache);
    829      0    stevel 
    830   6515       raf 	HD("ulwp_freelist         ulwp_lastfree         ulwp_replace_free");
    831   6515       raf 	mdb_printf(OFFSTR "%s %s %s\n",
    832   6515       raf 	    OFFSET(ulwp_freelist),
    833   6515       raf 	    prt_addr(uberdata.ulwp_freelist, 1),
    834   6515       raf 	    prt_addr(uberdata.ulwp_lastfree, 1),
    835   6515       raf 	    prt_addr(uberdata.ulwp_replace_free, 0));
    836      0    stevel 
    837   9170     Roger 	HD("ulwp_replace_last     atforklist");
    838   9170     Roger 	mdb_printf(OFFSTR "%s %s\n",
    839   6515       raf 	    OFFSET(ulwp_replace_last),
    840   6515       raf 	    prt_addr(uberdata.ulwp_replace_last, 1),
    841   9170     Roger 	    prt_addr(uberdata.atforklist, 0));
    842   9170     Roger 
    843   9170     Roger 	HD("robustlocks           robustlist");
    844   9170     Roger 	mdb_printf(OFFSTR "%s %s\n",
    845   9170     Roger 	    OFFSET(robustlocks),
    846   9170     Roger 	    prt_addr(uberdata.robustlocks, 1),
    847   9170     Roger 	    prt_addr(uberdata.robustlist, 0));
    848      0    stevel 
    849      0    stevel 	HD("tdb_bootstrap         tdb_sync_addr_hash    tdb_'count tdb_'fail");
    850      0    stevel 	mdb_printf(OFFSTR "%s %s %-10d %d\n",
    851   6515       raf 	    OFFSET(tdb_bootstrap),
    852   6515       raf 	    prt_addr(uberdata.tdb_bootstrap, 1),
    853   6515       raf 	    prt_addr(uberdata.tdb.tdb_sync_addr_hash, 1),
    854   6515       raf 	    uberdata.tdb.tdb_register_count,
    855   6515       raf 	    uberdata.tdb.tdb_hash_alloc_failed);
    856      0    stevel 
    857      0    stevel 	HD("tdb_sync_addr_free    tdb_sync_addr_last    tdb_sync_alloc");
    858      0    stevel 	mdb_printf(OFFSTR "%s %s %ld\n",
    859   6515       raf 	    OFFSET(tdb.tdb_sync_addr_free),
    860   6515       raf 	    prt_addr(uberdata.tdb.tdb_sync_addr_free, 1),
    861   6515       raf 	    prt_addr(uberdata.tdb.tdb_sync_addr_last, 1),
    862   6515       raf 	    uberdata.tdb.tdb_sync_alloc);
    863      0    stevel 
    864      0    stevel 	HD("tdb_ev_global_mask    tdb_events");
    865      0    stevel 	mdb_printf(OFFSTR "0x%08x 0x%08x %s\n",
    866   6515       raf 	    OFFSET(tdb.tdb_ev_global_mask),
    867   6515       raf 	    uberdata.tdb.tdb_ev_global_mask.event_bits[0],
    868   6515       raf 	    uberdata.tdb.tdb_ev_global_mask.event_bits[1],
    869   6515       raf 	    prt_addr((void *)uberdata.tdb.tdb_events, 0));
    870      0    stevel 
    871      0    stevel 	return (DCMD_OK);
    872      0    stevel }
    873      0    stevel 
    874      0    stevel static int
    875      0    stevel ulwp_walk_init(mdb_walk_state_t *wsp)
    876      0    stevel {
    877      0    stevel 	uintptr_t addr = wsp->walk_addr;
    878      0    stevel 	uintptr_t uber_addr;
    879      0    stevel 
    880      0    stevel 	if (addr == NULL &&
    881      0    stevel 	    ((uber_addr = uberdata_addr()) == NULL ||
    882      0    stevel 	    mdb_vread(&addr, sizeof (addr),
    883      0    stevel 	    uber_addr + OFFSETOF(uberdata_t, all_lwps))
    884      0    stevel 	    != sizeof (addr))) {
    885      0    stevel 		mdb_warn("cannot find 'uberdata.all_lwps'");
    886      0    stevel 		return (WALK_ERR);
    887      0    stevel 	}
    888      0    stevel 	if (addr == NULL)
    889      0    stevel 		return (WALK_DONE);
    890      0    stevel 	wsp->walk_addr = addr;
    891      0    stevel 	wsp->walk_data = (void *)addr;
    892      0    stevel 	return (WALK_NEXT);
    893      0    stevel }
    894      0    stevel 
    895      0    stevel static int
    896      0    stevel ulwp_walk_step(mdb_walk_state_t *wsp)
    897      0    stevel {
    898      0    stevel 	uintptr_t addr = wsp->walk_addr;
    899      0    stevel 	ulwp_t ulwp;
    900      0    stevel 
    901      0    stevel 	if (addr == NULL)
    902      0    stevel 		return (WALK_DONE);
    903      0    stevel 	if (mdb_vread(&ulwp, sizeof (ulwp), addr) != sizeof (ulwp) &&
    904      0    stevel 	    (bzero(&ulwp, sizeof (ulwp)),
    905      0    stevel 	    mdb_vread(&ulwp, REPLACEMENT_SIZE, addr)) != REPLACEMENT_SIZE) {
    906      0    stevel 		mdb_warn("failed to read ulwp at 0x%p", addr);
    907      0    stevel 		return (WALK_ERR);
    908      0    stevel 	}
    909      0    stevel 	/*
    910      0    stevel 	 * If we have looped around to the beginning
    911      0    stevel 	 * of the circular linked list, we are done.
    912      0    stevel 	 */
    913      0    stevel 	if ((wsp->walk_addr = (uintptr_t)ulwp.ul_forw)
    914      0    stevel 	    == (uintptr_t)wsp->walk_data)
    915      0    stevel 		wsp->walk_addr = NULL;
    916      0    stevel 	return (wsp->walk_callback(addr, &ulwp, wsp->walk_cbdata));
    917      0    stevel }
    918      0    stevel 
    919  10610  Jonathan /* Avoid classifying NULL pointers as part of the main stack on x86 */
    920  10610  Jonathan #define	MIN_STACK_ADDR		(0x10000ul)
    921  10610  Jonathan 
    922  10610  Jonathan static int
    923  10610  Jonathan whatis_walk_ulwp(uintptr_t addr, const ulwp_t *ulwp, mdb_whatis_t *w)
    924  10610  Jonathan {
    925  10610  Jonathan 	uintptr_t cur;
    926  10610  Jonathan 	lwpid_t id = ulwp->ul_lwpid;
    927  10610  Jonathan 	uintptr_t top, base, size;
    928  10610  Jonathan 
    929  10610  Jonathan 	while (mdb_whatis_match(w, addr, sizeof (ulwp_t), &cur))
    930  10610  Jonathan 		mdb_whatis_report_object(w, cur, addr,
    931  10610  Jonathan 		    "allocated as thread %#r's ulwp_t\n", id);
    932  10610  Jonathan 
    933  10610  Jonathan 	top = (uintptr_t)ulwp->ul_stktop;
    934  10610  Jonathan 	size = ulwp->ul_stksiz;
    935  10610  Jonathan 
    936  10610  Jonathan 	/*
    937  10610  Jonathan 	 * The main stack ends up being a little weird, especially if
    938  10610  Jonathan 	 * the stack ulimit is unlimited.  This tries to take that into
    939  10610  Jonathan 	 * account.
    940  10610  Jonathan 	 */
    941  10610  Jonathan 	if (size > top)
    942  10610  Jonathan 		size = top;
    943  10610  Jonathan 	if (top > MIN_STACK_ADDR && top - size < MIN_STACK_ADDR)
    944  10610  Jonathan 		size = top - MIN_STACK_ADDR;
    945  10610  Jonathan 
    946  10610  Jonathan 	base = top - size;
    947  10610  Jonathan 
    948  10610  Jonathan 	while (mdb_whatis_match(w, base, size, &cur))
    949  10610  Jonathan 		mdb_whatis_report_address(w, cur, "in [ stack tid=%#r ]\n", id);
    950  10610  Jonathan 
    951  10610  Jonathan 	if (ulwp->ul_ustack.ss_flags & SS_ONSTACK) {
    952  10610  Jonathan 		base = (uintptr_t)ulwp->ul_ustack.ss_sp;
    953  10610  Jonathan 		size = ulwp->ul_ustack.ss_size;
    954  10610  Jonathan 
    955  10610  Jonathan 		while (mdb_whatis_match(w, base, size, &cur))
    956  10610  Jonathan 			mdb_whatis_report_address(w, cur,
    957  10610  Jonathan 			    "in [ altstack tid=%#r ]\n", id);
    958  10610  Jonathan 	}
    959  10610  Jonathan 
    960  10610  Jonathan 	return (WHATIS_WALKRET(w));
    961  10610  Jonathan }
    962  10610  Jonathan 
    963  10610  Jonathan /*ARGSUSED*/
    964  10610  Jonathan static int
    965  10610  Jonathan whatis_run_ulwps(mdb_whatis_t *w, void *arg)
    966  10610  Jonathan {
    967  10610  Jonathan 	if (mdb_walk("ulwps", (mdb_walk_cb_t)whatis_walk_ulwp, w) == -1) {
    968  10610  Jonathan 		mdb_warn("couldn't find ulwps walker");
    969  10610  Jonathan 		return (1);
    970  10610  Jonathan 	}
    971  10610  Jonathan 	return (0);
    972  10610  Jonathan }
    973  10610  Jonathan 
    974      0    stevel /*
    975      0    stevel  * =======================================================
    976      0    stevel  * End of thread (previously libthread) interfaces.
    977      0    stevel  * ==================== threads ==========================
    978      0    stevel  */
    979      0    stevel 
    980      0    stevel static const mdb_dcmd_t dcmds[] = {
    981      0    stevel 	{ "jmp_buf", ":", "print jmp_buf contents", d_jmp_buf, NULL },
    982      0    stevel 	{ "sigjmp_buf", ":", "print sigjmp_buf contents", d_sigjmp_buf, NULL },
    983      0    stevel 	{ "siginfo", ":", "print siginfo_t structure", d_siginfo, NULL },
    984      0    stevel 	{ "ucontext", ":", "print ucontext_t structure", d_ucontext, NULL },
    985      0    stevel 	{ "ulwp", ":", "print ulwp_t structure", d_ulwp, NULL },
    986      0    stevel 	{ "uberdata", ":", "print uberdata_t structure", d_uberdata, NULL },
    987      0    stevel 	{ NULL }
    988      0    stevel };
    989      0    stevel 
    990      0    stevel static const mdb_walker_t walkers[] = {
    991      0    stevel 	{ "ucontext", "walk ucontext_t uc_link list",
    992      0    stevel 		NULL, uc_walk_step, NULL, NULL },
    993      0    stevel 	{ "oldcontext", "walk per-lwp oldcontext pointers",
    994      0    stevel 		oldc_walk_init, oldc_walk_step, oldc_walk_fini, NULL },
    995      0    stevel 	{ "ulwps", "walk list of ulwp_t pointers",
    996      0    stevel 		ulwp_walk_init, ulwp_walk_step, NULL, NULL },
    997      0    stevel 	{ NULL }
    998      0    stevel };
    999      0    stevel 
   1000      0    stevel static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
   1001      0    stevel 
   1002      0    stevel const mdb_modinfo_t *
   1003      0    stevel _mdb_init(void)
   1004      0    stevel {
   1005  10610  Jonathan 	mdb_whatis_register("threads", whatis_run_ulwps, NULL,
   1006  10610  Jonathan 	    WHATIS_PRIO_EARLY, WHATIS_REG_NO_ID);
   1007  10610  Jonathan 
   1008      0    stevel 	return (&modinfo);
   1009      0    stevel }
   1010