libc.c revision 883492d5a933deb34cd27521e7f2756773cd27af
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/mdb_modapi.h>
#include <procfs.h>
#include <ucontext.h>
#include <siginfo.h>
#include <signal.h>
#include <setjmp.h>
#include <string.h>
#include <thr_uberdata.h>
static const char *
{
static char buf[32];
else {
buf[0] = '\0';
}
return (buf + 1);
}
/*ARGSUSED*/
static int
{
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
#if defined(__sparc)
mdb_printf(" %%rbx = 0x%lx\n", b[0]);
mdb_printf(" %%ebx = 0x%lx\n", b[0]);
#endif
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
mdb_printf(" sigmask = 0x%08x 0x%08x 0x%08x 0x%08x\n",
mdb_printf(" stack = sp 0x%p size 0x%lx flags %s\n",
mdb_printf(" mcontext = 0x%p\n",
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
#if defined(__sparc)
struct {
int sjs_flags;
#if defined(_LP64)
#endif
} s;
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
mdb_printf(" sigset = 0x%08x 0x%08x 0x%08x 0x%08x\n",
mdb_printf(" stack = sp 0x%p size 0x%lx flags %s\n",
return (DCMD_OK);
#endif
}
/*ARGSUSED*/
static int
{
static const char *const msname[] = {
"USER", "SYSTEM", "TRAP", "TFAULT", "DFAULT", "KFAULT",
"USER_LOCK", "SLEEP", "WAIT_CPU", "STOPPED"
};
char signame[SIG2STR_MAX];
int i;
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
case SI_NOINFO:
mdb_printf("no info");
break;
case SI_DTRACE:
mdb_printf("from DTrace raise() action");
break;
case SI_RCTL:
mdb_printf("from rctl action");
break;
case SI_USER:
mdb_printf("user generated via kill");
break;
case SI_LWP:
mdb_printf("user generated via lwp_kill");
break;
case SI_QUEUE:
mdb_printf("user generated via sigqueue");
break;
case SI_TIMER:
mdb_printf("from timer expiration");
break;
case SI_ASYNCIO:
mdb_printf("from async i/o completion");
break;
case SI_MESGQ:
mdb_printf("from message arrival");
break;
default:
if (SI_FROMUSER(&si))
mdb_printf("from user process");
else
mdb_printf("from kernel");
}
mdb_printf(")\n errno %5d (%s)\n",
mdb_printf(" signal sent from PID %d (uid %d)\n",
}
mdb_printf(" signal value = 0t%d / %p\n",
}
case SIGCLD:
mdb_printf(" signal sent from child PID %d (uid %d)\n",
mdb_printf(" usr time = 0t%ld ticks, sys time = 0t%ld ticks\n",
break;
case SIGSEGV:
case SIGBUS:
case SIGILL:
case SIGTRAP:
case SIGFPE:
mdb_printf(" fault address = 0x%p\n trapno = %d\n",
mdb_printf(" instruction address = 0x%p %lA\n",
break;
case SIGPOLL:
case SIGXFSZ:
mdb_printf(" fd = %d band = 0x%lx\n",
break;
case SIGPROF:
mdb_printf(" last fault address = 0x%p fault type = %d\n",
mdb_printf(" timestamp = 0t%ld sec 0t%ld nsec\n",
if (si.si_nsysarg > 0) {
}
mdb_printf(" )\n");
}
mdb_printf(" mstate[\"%s\"] = %d\n",
}
break;
}
return (DCMD_OK);
}
static int
{
return (WALK_DONE);
return (WALK_ERR);
}
}
static int
{
if (nbytes <= 0) {
mdb_warn("lwpstatus information not available");
return (WALK_ERR);
}
mdb_warn("walker only supports global walk\n");
return (WALK_ERR);
}
mdb_warn("failed to read lwpstatus information");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
return (WALK_NEXT);
return (WALK_NEXT);
}
}
return (WALK_DONE);
}
static void
{
}
/*
* ==================== threads ==========================
* These are the interfaces that used to require libthread.
* Now, libthread has been folded into libc.
* =======================================================
*/
/*
* prt_addr() is called up to three times to generate arguments for
* one call to mdb_printf(). We must return at least three different
* pointers to static storage for consecutive calls to prt_addr().
*/
static const char *
{
static int ix = 0;
char *buf;
ix = 0;
else {
#ifdef _LP64
if (pad)
#else
if (pad)
#endif /* _LP64 */
return (buf);
}
}
#define OFFSTR "+0x%-7lx "
/*ARGSUSED*/
static int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
HD("self uberdata");
HD("tlsent ntlsent");
HD("forw back next");
HD("hash rval stk");
HD("mapsiz guardsize stktop stksiz");
HD("ix lwpid pri mappedpri policy pri_mapped");
HD("cursig pleasestop stop signalled dead unwind");
mdb_printf("%-10d %-10d %d\n",
HD("detached writer stopping can'prolog preempt savpreempt");
HD("sigsuspend main fork primarymap m'spinners d'noreserv");
HD("queue_fifo c'w'defer e'detect' async_safe pad1[0] pad1[1]");
HD("adapt'spin rele'spin queue_spin critical sigdefer vfork");
HD("cancelable c'pending c'disabled c'async save_async mutator");
HD("created replace nocancel errno errnop");
HD("clnup_hdr schedctl_called schedctl");
HD("bindflags pad2 stsd &ftsd");
mdb_printf("%s %s\n",
HD("eventmask[0..1] eventnum eventdata");
HD("td'enable sync'reg qtype cv_wake usropts");
HD("startpc startarg wchan");
HD("link sleepq cvmutex");
HD("mxchain epri emappedpri");
HD("rdlockcnt rd_rwlock rd_count");
HD("heldlockcnt heldlocks tpdp");
HD("siglink s'l'spin s'l'spin2 s'l'sleep s'l'wakeup");
/*
* The remainder of the ulwp_t structure
* is invalid if this is a replacement.
*/
if (ulwp.ul_replace)
return (DCMD_OK);
HD("sigmask[0..3]");
HD("tmpmask[0..3]");
HD("&siginfo &spinlock &fpuenv");
return (DCMD_OK);
}
/*
* Get the address of the unique uberdata_t structure.
*/
static uintptr_t
uberdata_addr(void)
{
return (NULL);
}
return (uaddr);
}
return (NULL);
}
}
/*ARGSUSED*/
static int
{
int i;
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
sizeof (uberdata)) {
return (DCMD_ERR);
}
HD("&link_lock &fork_lock fork_owner");
HD("&tdb_hash_lock &tdb_hash_lock_stats &siguaction[0]");
HD("&bucket free_list chunks");
for (i = 0; i < NBUCKETS; i++) {
}
HD("&atexit_root head exit_frame_monitor");
HD("&tsd_metadata tsdm_nkeys tsdm_nused tsdm_destro");
HD("&tls_metadata tls_modinfo.data tls_modinfo.size");
HD(" static_tls.data static_tls.size");
" ",
HD("queue_head thr_hash_table hash_size hash_mask");
HD("ulwp_one all_lwps all_zombies");
HD("nthreads nzombies ndaemons pid sigacthandler");
HD("lwp_stacks lwp_laststack nfreestack stk_cache");
HD("ulwp_freelist ulwp_lastfree");
HD("ulwp_replace_free ulwp_replace_last");
HD("atforklist robustlocks");
HD("tdb_bootstrap tdb_sync_addr_hash tdb_'count tdb_'fail");
HD("tdb_sync_addr_free tdb_sync_addr_last tdb_sync_alloc");
HD("tdb_ev_global_mask tdb_events");
return (DCMD_OK);
}
static int
{
!= sizeof (addr))) {
mdb_warn("cannot find 'uberdata.all_lwps'");
return (WALK_ERR);
}
return (WALK_DONE);
return (WALK_NEXT);
}
static int
{
return (WALK_DONE);
return (WALK_ERR);
}
/*
* If we have looped around to the beginning
* of the circular linked list, we are done.
*/
}
/*
* =======================================================
* End of thread (previously libthread) interfaces.
* ==================== threads ==========================
*/
static const mdb_dcmd_t dcmds[] = {
{ NULL }
};
static const mdb_walker_t walkers[] = {
{ "ucontext", "walk ucontext_t uc_link list",
{ "oldcontext", "walk per-lwp oldcontext pointers",
{ "ulwps", "walk list of ulwp_t pointers",
{ NULL }
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}