dtrace.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* explicitly define DTRACE_ERRDEBUG to pull in definition of dtrace_errhash_t
*/
#define DTRACE_ERRDEBUG
#define _STDARG_H
#include <mdb/mdb_param.h>
#include <mdb/mdb_modapi.h>
#include <sys/dtrace_impl.h>
#include <sys/vmem_impl.h>
#include <sys/ddi_impldefs.h>
#include <sys/sysmacros.h>
#include <dtrace.h>
#include <alloca.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
#ifdef _LP64
#define DIFO_ADDRWIDTH 11
#else
#define DIFO_ADDRWIDTH 8
#endif
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
static const char *
{
uint_t i;
return (NULL);
return ("<unreadable>");
}
for (i = 0; i < dp->dtdo_varlen; i++) {
break;
}
}
return (NULL);
return ("<unreadable>");
}
return (str);
}
static uint_t
{
switch (name[2]) {
case 'l': return (DIFV_SCOPE_LOCAL);
case 't': return (DIFV_SCOPE_THREAD);
case 'g': return (DIFV_SCOPE_GLOBAL);
default: return (-1u);
}
}
static void
{
const char *vname;
}
static void
{
const char *vname;
}
static void
{
const char *vname;
}
static void
{
else
}
}
static void
{
else
}
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
static struct {
const char *name;
int subr;
} snames[] = {
{ "rand", DIF_SUBR_RAND },
{ "mutex_owned", DIF_SUBR_MUTEX_OWNED },
{ "mutex_owner", DIF_SUBR_MUTEX_OWNER },
{ "mutex_type_adaptive", DIF_SUBR_MUTEX_TYPE_ADAPTIVE },
{ "mutex_type_spin", DIF_SUBR_MUTEX_TYPE_SPIN },
{ "rw_read_held", DIF_SUBR_RW_READ_HELD },
{ "rw_write_held", DIF_SUBR_RW_WRITE_HELD },
{ "rw_iswriter", DIF_SUBR_RW_ISWRITER },
{ "copyin", DIF_SUBR_COPYIN },
{ "copyinstr", DIF_SUBR_COPYINSTR },
{ "speculation", DIF_SUBR_SPECULATION },
{ "progenyof", DIF_SUBR_PROGENYOF },
{ "strlen", DIF_SUBR_STRLEN },
{ "copyout", DIF_SUBR_COPYOUT },
{ "copyoutstr", DIF_SUBR_COPYOUTSTR },
{ "alloca", DIF_SUBR_ALLOCA },
{ "bcopy", DIF_SUBR_BCOPY },
{ "copyinto", DIF_SUBR_COPYINTO },
{ "msgdsize", DIF_SUBR_MSGDSIZE },
{ "msgsize", DIF_SUBR_MSGSIZE },
{ "getmajor", DIF_SUBR_GETMAJOR },
{ "getminor", DIF_SUBR_GETMINOR },
{ "ddi_pathname", DIF_SUBR_DDI_PATHNAME },
{ "strjoin", DIF_SUBR_STRJOIN },
{ "lltostr", DIF_SUBR_LLTOSTR },
{ "basename", DIF_SUBR_BASENAME },
{ "dirname", DIF_SUBR_DIRNAME },
{ "cleanpath", DIF_SUBR_CLEANPATH },
{ "strchr", DIF_SUBR_STRCHR },
{ "strrchr", DIF_SUBR_STRRCHR },
{ "strstr", DIF_SUBR_STRSTR },
{ "strtok", DIF_SUBR_STRTOK },
{ "substr", DIF_SUBR_SUBSTR },
{ "index", DIF_SUBR_INDEX },
{ "rindex", DIF_SUBR_RINDEX },
{ NULL, 0 }
};
return;
}
}
}
/*ARGSUSED*/
static void
{
mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u",
}
static char *
{
char kind[8];
switch (t->dtdt_kind) {
case DIF_TYPE_CTF:
break;
case DIF_TYPE_STRING:
break;
default:
}
if (t->dtdt_flags & DIF_TF_BYREF) {
"%s by ref (size %lu)",
} else {
}
return (buf);
}
static int
{
static const struct opent {
const char *op_name;
void (*op_func)(const dtrace_difo_t *,
const char *, dif_instr_t);
} optab[] = {
{ "(illegal opcode)", dis_str },
};
return (DCMD_ERR);
}
opcode = 0; /* force invalid opcode message */
mdb_printf("\n");
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
ulong_t i;
char type[64];
char *str;
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n",
"OPCODE", "INSTRUCTION");
if (dp->dtdo_varlen != 0) {
mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n",
"NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
}
mdb_warn("couldn't read dtdo_vartab");
return (DCMD_ERR);
}
mdb_warn("couldn't read dtdo_strtab");
return (DCMD_ERR);
}
for (i = 0; i < dp->dtdo_varlen; i++) {
dtrace_difv_t *v = &dvp[i];
switch (v->dtdv_kind) {
case DIFV_KIND_ARRAY:
break;
case DIFV_KIND_SCALAR:
break;
default:
"%u", v->dtdv_kind);
}
switch (v->dtdv_scope) {
case DIFV_SCOPE_GLOBAL:
break;
case DIFV_SCOPE_THREAD:
break;
case DIFV_SCOPE_LOCAL:
break;
default:
"%u", v->dtdv_scope);
}
}
if (v->dtdv_flags & DIFV_F_REF)
if (v->dtdv_flags & DIFV_F_MOD)
mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n",
}
mdb_printf("\n%<b>RETURN%</b>\n%s\n\n",
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
}
/*ARGSUSED*/
int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
goto out;
mdb_warn("failed to read 'dtrace_probes'");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
out:
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
dof_hdr_t h;
if (argc != 0)
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC))
addr = 0; /* assume base of file in file target */
return (DCMD_ERR);
}
mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n",
switch (h.dofh_ident[DOF_ID_MODEL]) {
case DOF_MODEL_ILP32:
mdb_printf("dofh_ident.id_model = ILP32\n");
break;
case DOF_MODEL_LP64:
mdb_printf("dofh_ident.id_model = LP64\n");
break;
default:
mdb_printf("dofh_ident.id_model = 0x%x\n",
h.dofh_ident[DOF_ID_MODEL]);
}
switch (h.dofh_ident[DOF_ID_ENCODING]) {
case DOF_ENCODE_LSB:
mdb_printf("dofh_ident.id_encoding = LSB\n");
break;
case DOF_ENCODE_MSB:
mdb_printf("dofh_ident.id_encoding = MSB\n");
break;
default:
mdb_printf("dofh_ident.id_encoding = 0x%x\n",
}
mdb_printf("dofh_ident.id_version = %u\n",
h.dofh_ident[DOF_ID_VERSION]);
mdb_printf("dofh_ident.id_difvers = %u\n",
h.dofh_ident[DOF_ID_DIFVERS]);
mdb_printf("dofh_ident.id_difireg = %u\n",
h.dofh_ident[DOF_ID_DIFIREG]);
mdb_printf("dofh_ident.id_diftreg = %u\n",
h.dofh_ident[DOF_ID_DIFTREG]);
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
return (WALK_NEXT);
}
static const char *
{
static const char *const types[] = {
"none", "comments", "source", "ecbdesc", "probedesc", "actdesc",
"difohdr", "dif", "strtab", "vartab", "reltab", "typtab",
"urelhdr", "krelhdr", "optdesc", "provider", "probes",
"prargs", "proffs", "inttab", "utsname"
};
static char buf[32];
return (buf);
}
/*ARGSUSED*/
int
{
dof_sec_t s;
if (!(flags & DCMD_ADDRSPEC))
mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n",
"ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET",
"SIZE");
}
if (!(flags & DCMD_ADDRSPEC)) {
int sec = 0;
if (mdb_walk("dof_sec",
mdb_warn("failed to walk dof_sec");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
int
{
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
if (i >= hp->dofh_secnum)
return (WALK_DONE);
}
void
{
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
void
dtrace_help(void)
{
mdb_printf("Given a dtrace_state_t structure that represents a "
"DTrace consumer, prints\n"
"dtrace(1M)-like output for in-kernel DTrace data. (The "
"dtrace_state_t\n"
"structures for all DTrace consumers may be obtained by running "
"the \n"
"::dtrace_state dcmd.) When data is present on multiple CPUs, "
"data are\n"
"presented in CPU order, with records within each CPU ordered "
"oldest to \n"
"youngest. Options:\n\n"
"-c cpu Only provide output for specified CPU.\n");
}
static int
{
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
/*
* This is a little painful: in order to find the number of actions,
* we need to first walk through them.
*/
mdb_warn("failed to read action %p on ecb %p",
return (-1);
}
nactions++;
}
mdb_warn("failed to read action %p on ecb %p",
return (-1);
}
if (nrecs-- == 0)
break;
}
}
return (0);
}
/*ARGSUSED*/
static int
{
int nprobes, i;
mdb_warn("failed to read 'dtrace_probes'");
return (-1);
}
mdb_warn("failed to read 'dtrace_nprobes'");
return (-1);
}
return (-1);
}
break;
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (0);
}
/*ARGSUSED*/
static int
{
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
/*
* This is a little painful: in order to find the number of actions,
* we need to first walk through them.
*/
nactions = 0;
for (;;) {
mdb_warn("failed to read action %p on aggregation %p",
return (-1);
}
nactions++;
break;
}
nactions = 0;
for (;;) {
mdb_warn("failed to read action %p on aggregation %p",
return (-1);
}
if (nrecs-- == 0)
break;
break;
}
return (0);
}
static int
{
mdb_warn("failed to read 'max_cpuid'");
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
} else {
}
return (-1);
}
return (-1);
}
mdb_warn("ringbuffer for CPU %d has corrupt "
"wrapped offset\n", cpu);
return (-1);
}
/*
* If the ring buffer has wrapped, it needs to be polished.
* See the comment in dtrace_buffer_polish() for details.
*/
}
}
} else {
desc->dtbd_oldest = 0;
}
return (0);
}
/*
* This is essentially identical to its cousin in the kernel.
*/
static dof_hdr_t *
{
sizeof (dof_optdesc_t) * DTRACEOPT_MAX;
dof->dofh_flags = 0;
/*
* Fill in the option section header...
*/
for (i = 0; i < DTRACEOPT_MAX; i++) {
opt[i].dofo_option = i;
}
return (dof);
}
static int
{
char c;
int len = 0;
return (-1);
}
return (-1);
}
do {
return (-1);
}
} while (c != '\0');
return (0);
}
return (-1);
}
return (0);
}
static int
{
int i, j;
int ncpu;
mdb_warn("failed to read '_ncpu'");
return (DCMD_ERR);
}
return (-1);
}
/*
* For the MDB backend, we never set dtst_exiting or dtst_filled. This
* is by design: we don't want the library to try to stop tracing,
* because it doesn't particularly mean anything.
*/
for (i = 0; i < ncpu; i++) {
return (-1);
}
return (-1);
}
for (j = 0; j < state->dts_nspeculations; j++) {
mdb_warn("failed to read "
"speculation at %p", addr);
return (-1);
}
mdb_warn("failed to read "
"speculative buffer at %p", addr);
return (-1);
}
}
}
return (0);
}
typedef struct dtracemdb_data {
char *dtmd_symstr;
char *dtmd_modstr;
static int
{
switch (cmd) {
case DTRACEIOC_CONF: {
return (0);
}
case DTRACEIOC_DOFGET: {
return (0);
}
case DTRACEIOC_BUFSNAP:
case DTRACEIOC_AGGSNAP:
case DTRACEIOC_AGGDESC:
case DTRACEIOC_EPROBE:
case DTRACEIOC_PROBES:
case DTRACEIOC_FORMAT:
case DTRACEIOC_STATUS:
case DTRACEIOC_GO:
return (0);
case DTRACEIOC_ENABLE:
return (-1);
case DTRACEIOC_PROVIDER:
case DTRACEIOC_PROBEMATCH:
return (-1);
default:
"???");
return (-1);
}
}
static int
{
return (WALK_NEXT);
return (WALK_NEXT);
}
return (WALK_NEXT);
return (WALK_NEXT);
return (WALK_ERR);
return (WALK_DONE);
}
static int
{
}
}
return (-1);
}
if (mdb_walk("modctl",
mdb_warn("couldn't walk 'modctl'");
return (-1);
}
}
return (0);
}
/*ARGSUSED*/
static int
{
cpu_t c;
mdb_warn("failed to find symbol for 'cpu'");
return (-1);
}
return (-1);
return (-1);
}
return (-1);
return (-1);
}
if (c.cpu_flags & CPU_POWEROFF) {
return (P_POWEROFF);
return (P_SPARE);
} else if (c.cpu_flags & CPU_FAULTED) {
return (P_FAULTED);
return (P_OFFLINE);
} else if (c.cpu_flags & CPU_ENABLE) {
return (P_ONLINE);
} else {
return (P_NOINTR);
}
}
/*ARGSUSED*/
static long
{
int max_ncpus;
switch (name) {
case _SC_CPUID_MAX:
mdb_warn("failed to read 'max_cpuid'");
return (-1);
}
return (max_cpuid);
case _SC_NPROCESSORS_MAX:
mdb_warn("failed to read 'max_ncpus'");
return (-1);
}
return (max_ncpus);
default:
return (-1);
}
}
const dtrace_vector_t dtrace_mdbops = {
};
typedef struct dtrace_dcmddata {
int dtdd_cpu;
int dtdd_quiet;
int dtdd_flowindent;
int dtdd_heading;
/*ARGSUSED*/
static int
{
/*
* We have processed the final record; output the newline if
* we're not in quiet mode.
*/
if (!dd->dtdd_quiet)
mdb_printf("\n");
return (DTRACE_CONSUME_NEXT);
}
return (DTRACE_CONSUME_THIS);
}
/*ARGSUSED*/
static int
{
return (DTRACE_CONSUME_NEXT);
if (dd->dtdd_heading == 0) {
if (!dd->dtdd_flowindent) {
if (!dd->dtdd_quiet) {
mdb_printf("%3s %6s %32s\n",
"CPU", "ID", "FUNCTION:NAME");
}
} else {
}
}
if (!dd->dtdd_flowindent) {
if (!dd->dtdd_quiet) {
}
} else {
} else {
}
}
return (DTRACE_CONSUME_THIS);
}
/*ARGSUSED*/
static int
{
return (DTRACE_HANDLE_OK);
}
/*ARGSUSED*/
static int
{
return (DTRACE_HANDLE_OK);
}
/*ARGSUSED*/
static int
{
return (DTRACE_HANDLE_OK);
}
/*ARGSUSED*/
int
{
uintptr_t c = -1UL;
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_USAGE);
mdb_warn("failed to read '_ncpu'");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
mdb_warn("failed to initialize dtrace: %s\n",
return (DCMD_ERR);
}
mdb_warn("failed to initialize dtrace: %s\n",
goto err;
}
mdb_warn("couldn't get 'flowindent' option: %s\n",
goto err;
}
mdb_warn("couldn't get 'quiet' option: %s\n",
goto err;
}
mdb_warn("couldn't add err handler: %s\n",
goto err;
}
mdb_warn("couldn't add drop handler: %s\n",
goto err;
}
mdb_warn("couldn't add buffered handler: %s\n",
goto err;
}
mdb_warn("couldn't get status: %s\n",
goto err;
}
mdb_warn("couldn't snapshot aggregation: %s\n",
goto err;
}
mdb_warn("couldn't consume DTrace buffers: %s\n",
}
mdb_warn("couldn't print aggregation: %s\n",
goto err;
}
err:
return (rval);
}
static int
dtrace_errhash_cmp(const void *l, const void *r)
{
return (-1);
return (1);
}
int
{
int i;
mdb_warn("dtrace_errhash walk only supports global walks\n");
return (WALK_ERR);
}
mdb_warn("couldn't find 'dtrace_errhash' (non-DEBUG kernel?)");
return (WALK_ERR);
}
for (i = 0; i < DTRACE_ERRHASHSZ; i++)
return (WALK_NEXT);
}
int
{
if (ndx >= DTRACE_ERRHASHSZ)
return (WALK_DONE);
return (WALK_DONE);
}
return (WALK_NEXT);
}
/*ARGSUSED*/
int
{
char msg[256];
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("can't walk 'dtrace_errhash'");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (DCMD_HDRSPEC(flags))
return (DCMD_ERR);
}
return (DCMD_ERR);
}
/*
* Some error messages include a newline -- only print the newline
* if the message doesn't have one.
*/
mdb_printf("\n");
return (DCMD_OK);
}
int
{
int enabled;
mdb_warn("dtrace_helptrace only supports global walks\n");
return (WALK_ERR);
}
mdb_warn("couldn't read 'dtrace_helptrace_enabled'");
return (WALK_ERR);
}
if (!enabled) {
mdb_warn("helper tracing is not enabled\n");
return (WALK_ERR);
}
mdb_warn("couldn't read 'dtrace_helptrace_next'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int rval;
mdb_warn("couldn't read 'dtrace_helptrace_next'");
return (WALK_ERR);
}
mdb_warn("couldn't read 'dtrace_helptrace_bufsize'");
return (WALK_ERR);
}
mdb_warn("couldn't read 'dtrace_helptrace_buffer'");
return (WALK_ERR);
}
mdb_warn("couldn't read 'dtrace_helptrace_nlocals'");
return (WALK_ERR);
}
size = sizeof (dtrace_helptrace_t) +
if (next == 0)
return (WALK_DONE);
}
return (WALK_ERR);
}
return (rval);
}
return (WALK_DONE);
return (WALK_NEXT);
}
int
{
char where[30];
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("can't walk 'dtrace_helptrace'");
return (DCMD_ERR);
}
return (DCMD_OK);
}
return (DCMD_USAGE);
if (DCMD_HDRSPEC(flags)) {
mdb_printf(" %?s %?s %12s %s\n",
"ADDR", "HELPER", "WHERE", "DIFO");
}
return (DCMD_ERR);
}
switch (help.dtht_where) {
case 0:
break;
case DTRACE_HELPTRACE_NEXT:
break;
case DTRACE_HELPTRACE_DONE:
break;
case DTRACE_HELPTRACE_ERR:
break;
default:
break;
}
/*
* We're not going to warn in this case -- we're just not going
* to print anything exciting.
*/
mdb_printf("???\n");
} else {
switch (help.dtht_where) {
case 0:
break;
case DTRACE_HELPTRACE_NEXT:
case DTRACE_HELPTRACE_DONE:
case DTRACE_HELPTRACE_ERR:
mdb_printf("-\n");
break;
default:
mdb_printf("???\n");
} else {
}
}
}
if (opt_v) {
int i;
"ADDR", "NDX", "VALUE");
for (i = 0; i < help.dtht_nlocals; i++) {
continue;
}
}
mdb_printf("\n");
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
return (WALK_NEXT);
}
typedef struct dtrace_state_walk {
int
{
mdb_warn("dtrace_state only supports global walks\n");
return (WALK_ERR);
}
/*
* Find the dtrace_minor vmem arena and walk it to get the maximum
* minor number.
*/
mdb_warn("failed to read 'dtrace_minor'");
return (WALK_ERR);
}
mdb_warn("couldn't walk 'vmem_alloc'");
return (WALK_ERR);
}
dw->dtsw_current = 0;
mdb_warn("failed to read 'dtrace_softstate'");
return (DCMD_ERR);
}
return (WALK_NEXT);
}
int
{
int rval;
return (WALK_DONE);
dw->dtsw_current++;
}
return (WALK_NEXT);
}
dw->dtsw_current++;
return (rval);
}
typedef struct dtrace_state_data {
int dtsd_major;
static int
{
return (WALK_NEXT);
}
return (WALK_NEXT);
return (WALK_NEXT);
}
return (WALK_NEXT);
}
return (WALK_NEXT);
return (WALK_NEXT);
}
/*ARGSUSED*/
static int
{
if (mdb_pwalk("file",
return (WALK_ERR);
}
return (WALK_NEXT);
}
void
dtrace_state_help(void)
{
mdb_printf("Given a dtrace_state_t structure, displays all "
/*CSTYLED*/
"consumers, or \"<anonymous>\"\nif the consumer is anonymous. If "
"no state structure is provided, iterates\nover all state "
"structures.\n\n"
"Addresses in ADDR column may be provided to ::dtrace to obtain\n"
"dtrace(1M)-like output for in-kernel DTrace data.\n");
}
int
{
if (!(flags & DCMD_ADDRSPEC)) {
if (mdb_walk_dcmd("dtrace_state",
mdb_warn("can't walk dtrace_state");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (DCMD_HDRSPEC(flags)) {
}
/*
* First determine if this is anonymous state.
*/
mdb_warn("failed to read 'dtrace_anon'");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
"<anonymous>", "-");
return (DCMD_OK);
}
mdb_warn("failed to read 'dtrace_devi'");
return (DCMD_ERR);
}
mdb_warn("failed to read 'dev_info'");
return (DCMD_ERR);
}
mdb_warn("failed to read 'dtrace_softstate'");
return (DCMD_ERR);
}
/*
* Walk through all processes and all open files looking for this
* state. It must be open somewhere...
*/
mdb_warn("couldn't walk 'proc'");
return (DCMD_ERR);
}
return (DCMD_OK);
}
typedef struct dtrace_aggkey_data {
int
{
mdb_warn("dtrace_aggkey walk needs aggregation buffer\n");
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_ERR);
}
mdb_warn("failed to read hash at %p",
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
return (WALK_DONE);
}
return (WALK_ERR);
}
}
void
{
}
typedef struct dtrace_dynvar_data {
int
{
mdb_warn("dtrace_dynvar walk needs dtrace_dstate_t\n");
return (WALK_ERR);
}
return (WALK_ERR);
}
mdb_warn("failed to read hash at %p",
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int nkeys;
return (WALK_DONE);
data->dtdvd_next =
}
return (WALK_ERR);
}
/*
* Now we need to allocate the correct size.
*/
return (WALK_ERR);
}
}
void
{
}
typedef struct dtrace_hashstat_data {
char *dthsd_data;
int dthsd_header;
typedef void (*dtrace_hashstat_func_t)(dtrace_hashstat_data_t *);
static void
{
int i;
int hval = 0;
for (i = 0; i < data->dthsd_size; i++)
}
static void
{
int i;
return;
}
/* LINTED - alignment */
}
}
static void
{
int i;
for (i = 0; i < data->dthsd_size; i++)
}
static void
{
int i;
for (i = 0; i < data->dthsd_size; i++) {
}
}
static void
{
int i;
for (i = 0; i < data->dthsd_size; i++) {
}
}
static void
{
int longest = 0;
double sum = 0.0;
double avg;
if (!data->dthsd_header) {
"HASHSIZE", "%UTIL", "LONGEST", "AVERAGE", "STDDEV");
}
for (i = 0; i < data->dthsd_hashsize; i++) {
if (data->dthsd_counts[i] != 0) {
nz++;
}
}
if (nz == 0) {
return;
}
for (i = 0; i < data->dthsd_hashsize; i++) {
if (data->dthsd_counts[i] == 0)
continue;
}
}
static struct dtrace_hashstat {
char *dths_name;
} _dtrace_hashstat[] = {
{ "<actual>", NULL },
{ "additive", dtrace_hashstat_additive },
{ "shifty", dtrace_hashstat_shifty },
{ "knuth", dtrace_hashstat_knuth },
{ "one-at-a-time", dtrace_hashstat_oneatatime },
{ "fnv", dtrace_hashstat_fnv },
{ NULL, 0 }
};
typedef struct dtrace_aggstat_data {
static int
{
return (WALK_NEXT);
}
/*
* We need to read the data.
*/
return (WALK_ERR);
}
return (WALK_NEXT);
}
/*ARGSUSED*/
int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_ERR);
}
/*
* Now pick the largest prime smaller than the hash size. (If the
* existing size is prime, we'll pick a smaller prime just for the
* hell of it.)
*/
for (i = 2; i < limit; i++) {
if ((prime % i) == 0)
break;
}
if (i == limit)
break;
}
/*
* And now we want to pick the largest power of two smaller than the
* hashsize.
*/
continue;
if (mdb_pwalk("dtrace_aggkey",
return (DCMD_ERR);
}
/*
* If we were just printing the actual value, we won't try
* any of the sizing experiments.
*/
continue;
if (mdb_pwalk("dtrace_aggkey",
return (DCMD_ERR);
}
if (mdb_pwalk("dtrace_aggkey",
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
char *buf;
return (WALK_NEXT);
}
/*
* We want to hand the hashing algorithm a contiguous buffer. First
* run through the tuple and determine the size.
*/
for (i = 0; i < nkeys; i++) {
} else {
}
}
/*
* Now go back through the tuple and copy the data into the buffer.
*/
for (i = 0; i < nkeys; i++) {
sizeof (uint64_t));
} else {
mdb_warn("couldn't read tuple data at %p",
key[i].dttk_value);
return (WALK_ERR);
}
}
}
return (WALK_NEXT);
}
/*ARGSUSED*/
int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
/*
* Now pick the largest prime smaller than the hash size. (If the
* existing size is prime, we'll pick a smaller prime just for the
* hell of it.)
*/
for (i = 2; i < limit; i++) {
if ((prime % i) == 0)
break;
}
if (i == limit)
break;
}
if (mdb_pwalk("dtrace_dynvar",
return (DCMD_ERR);
}
/*
* If we were just printing the actual value, we won't try
* any of the sizing experiments.
*/
continue;
if (mdb_pwalk("dtrace_dynvar",
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
static int
{
char *strtab;
mdb_warn("failed to read string table");
return (1);
}
for (i = 0; i < sz; i++) {
if (strtab[i] == '\0')
mdb_printf("\\0");
else
}
mdb_printf("\n");
return (0);
}
static int
{
char *strtab;
int i, j;
mdb_warn("failed to read DOF provider");
return (-1);
}
mdb_warn("failed to read string table");
return (-1);
}
if (sz != 0) {
mdb_warn("failed to read args");
return (-1);
}
}
!= sz) {
mdb_warn("failed to read offs");
return (-1);
}
mdb_warn("failed to read probes");
return (-1);
}
(void) mdb_inc_indent(2);
(void) mdb_inc_indent(2);
mdb_printf("offs: ");
for (j = 0; j < pb[i].dofpr_noffs; j++) {
}
mdb_printf("\n");
mdb_printf("nargs:");
for (j = 0; j < pb[i].dofpr_nargc; j++) {
}
mdb_printf("\n");
mdb_printf("xargs:");
for (j = 0; j < pb[i].dofpr_xargc; j++) {
}
mdb_printf("\n");
mdb_printf("map: ");
for (j = 0; j < pb[i].dofpr_xargc; j++) {
}
(void) mdb_dec_indent(2);
mdb_printf("\n}\n");
}
(void) mdb_dec_indent(2);
mdb_printf("}\n");
return (0);
}
static int
{
int i;
mdb_warn("failed to read argument");
return (1);
}
if (i % 20 == 19)
mdb_printf("\n");
}
mdb_printf("\n");
return (0);
}
/*ARGSUSED*/
static int
{
int i;
mdb_warn("failed to read DOF header");
return (DCMD_ERR);
}
for (i = 0; i < dofh.dofh_secnum; i++) {
mdb_warn("failed to read DOF sections");
return (DCMD_ERR);
}
}
for (i = 0; i < dofh.dofh_secnum; i++) {
(void) mdb_inc_indent(2);
case DOF_SECT_PROVIDER:
break;
case DOF_SECT_STRTAB:
break;
case DOF_SECT_PRARGS:
break;
}
(void) mdb_dec_indent(2);
mdb_printf("\n");
}
return (DCMD_OK);
}
static const mdb_dcmd_t dcmds[] = {
{ "id2probe", ":", "translate a dtrace_id_t to a dtrace_probe_t",
id2probe },
{ "dtrace", ":[-c cpu]", "print dtrace(1M)-like output",
dtrace, dtrace_help },
{ "dtrace_helptrace", ":", "print DTrace helper trace",
{ "dtrace_aggstat", ":",
"print DTrace aggregation hash statistics", dtrace_aggstat },
{ "dtrace_dynstat", ":",
"print DTrace dynamic variable hash statistics", dtrace_dynstat },
{ NULL }
};
static const mdb_walker_t walkers[] = {
{ "dof_sec", "walk DOF section header table given header address",
{ "dtrace_errhash", "walk hash of DTrace error messasges",
{ "dtrace_helptrace", "walk DTrace helper trace entries",
{ "dtrace_state", "walk DTrace per-consumer softstate",
{ "dtrace_aggkey", "walk DTrace aggregation keys",
{ "dtrace_dynvar", "walk DTrace dynamic variables",
{ NULL }
};
static const mdb_modinfo_t modinfo = {
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}