dtrace.c revision 7994dfdd2a48fab1a1e1dc23109801c2f4cac5b3
/*
* 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 (c) 2013 by Delphix. All rights reserved.
*/
/*
* 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>
#include <stdio.h>
#include <unistd.h>
/*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);
}
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 -- with the
* notable exception that we automatically set DTRACEOPT_GRABANON if this
* state is an anonymous enabling.
*/
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;
}
if (isanon)
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;
int dtmd_isanon;
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;
/*
* Helper to grab all the content from a file, spit it into a string, and erase
* and reset the file.
*/
static void
{
long len;
char *out;
/* flush, find length of file, seek to beginning, initialize buffer */
return;
}
/* read file into buffer, truncate file, and seek to beginning */
return;
}
}
/*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);
}
return (DCMD_ERR);
}
}
mdb_warn("failed to initialize dtrace: %s\n",
return (DCMD_ERR);
}
/*
* If this is the anonymous enabling, we need to set a bit indicating
* that DTRACEOPT_GRABANON should be set.
*/
mdb_warn("failed to read 'dtrace_anon'");
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;
}
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;
int f = help.dtht_fault;
f == DTRACEFLT_BADADDR ? "BADADDR" :
f == DTRACEFLT_BADALIGN ? "BADALIGN" :
f == DTRACEFLT_ILLOP ? "ILLOP" :
f == DTRACEFLT_DIVZERO ? "DIVZERO" :
f == DTRACEFLT_NOSCRATCH ? "NOSCRATCH" :
f == DTRACEFLT_KPRIV ? "KPRIV" :
f == DTRACEFLT_UPRIV ? "UPRIV" :
f == DTRACEFLT_TUPOFLOW ? "TUPOFLOW" :
f == DTRACEFLT_BADSTACK ? "BADSTACK" :
"DTRACEFLT_UNKNOWN");
}
"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("couldn't find 'dtrace_dynhash_sink'");
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);
}
typedef struct dtrace_ecb_walk {
int dtew_necbs;
int dtew_curecb;
static int
{
mdb_warn("dtrace_ecb walk needs dtrace_state_t\n");
return (WALK_ERR);
}
return (WALK_ERR);
}
ecbwp->dtew_curecb = 0;
return (WALK_NEXT);
}
static int
{
return (WALK_DONE);
mdb_warn("failed to read ecb at entry %d\n",
ecbwp->dtew_curecb);
return (WALK_ERR);
}
return (WALK_NEXT);
}
static void
{
int index = 0;
char u;
while (n >= 1024) {
n = (n + (1024 / 2)) / 1024; /* Round up or down */
index++;
}
u = " KMGTPE"[index];
if (index == 0) {
} else {
}
}
static void
{
}
static void
{
char *policy = "unknown";
switch (num) {
case DTRACEOPT_BUFPOLICY_RING:
policy = "ring";
break;
case DTRACEOPT_BUFPOLICY_FILL:
policy = "fill";
break;
policy = "switch";
break;
}
}
static void
{
if (cpu == DTRACE_CPUALL)
else
}
static struct dtrace_options {
char *dtop_optstr;
} _dtrace_options[] = {
{ "bufsize", dtrace_options_numtostr },
{ "bufpolicy", dtrace_options_numtobufpolicy },
{ "dynvarsize", dtrace_options_numtostr },
{ "aggsize", dtrace_options_numtostr },
{ "specsize", dtrace_options_numtostr },
{ "nspec", dtrace_options_numtostr },
{ "strsize", dtrace_options_numtostr },
{ "cleanrate", dtrace_options_numtohz },
{ "cpu", dtrace_options_numtocpu },
{ "bufresize", dtrace_options_numtostr },
{ "grabanon", dtrace_options_numtostr },
{ "flowindent", dtrace_options_numtostr },
{ "quiet", dtrace_options_numtostr },
{ "stackframes", dtrace_options_numtostr },
{ "ustackframes", dtrace_options_numtostr },
{ "aggrate", dtrace_options_numtohz },
{ "switchrate", dtrace_options_numtohz },
{ "statusrate", dtrace_options_numtohz },
{ "destructive", dtrace_options_numtostr },
{ "stackindent", dtrace_options_numtostr },
{ "rawbytes", dtrace_options_numtostr },
{ "jstackframes", dtrace_options_numtostr },
{ "jstackstrsize", dtrace_options_numtostr },
{ "aggsortkey", dtrace_options_numtostr },
{ "aggsortrev", dtrace_options_numtostr },
{ "aggsortpos", dtrace_options_numtostr },
{ "aggsortkeypos", dtrace_options_numtostr }
};
static void
dtrace_options_help(void)
{
mdb_printf("Given a dtrace_state_t structure, displays the "
"current tunable option\nsettings.\n");
}
/*ARGSUSED*/
static int
{
int i = 0;
char val[32];
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
for (i = 0; i < DTRACEOPT_MAX; i++) {
if (options[i] == DTRACEOPT_UNSET) {
mdb_printf("%-25s %s\n",
} else {
val, 32);
mdb_printf("%-25s %s\n",
}
}
return (DCMD_OK);
}
static int
{
mdb_warn("pid2state walk requires PID\n");
return (WALK_ERR);
}
mdb_warn("failed to read 'dtrace_softstate'");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
mdb_warn("failed to read 'dtrace_devi'");
return (DCMD_ERR);
}
mdb_warn("failed to read 'dev_info'");
return (DCMD_ERR);
}
return (WALK_NEXT);
}
/*ARGSUSED*/
static int
{
/* Get the vnode for this file */
return (WALK_NEXT);
}
/* Is this the dtrace device? */
return (WALK_NEXT);
/* Get the minor number for this device entry */
return (WALK_NEXT);
}
return (WALK_NEXT);
}
static int
{
if (mdb_pwalk("file",
return (WALK_ERR);
}
return (WALK_DONE);
}
/*ARGSUSED*/
static int
{
return (WALK_ERR);
return (WALK_ERR);
}
return (WALK_ERR);
return (WALK_ERR);
}
return (WALK_NEXT);
}
static void
dtrace_probes_help(void)
{
mdb_printf("Given a dtrace_state_t structure, displays all "
"its active enablings. If no\nstate structure is provided, "
"all available probes are listed.\n");
}
/*ARGSUSED*/
static int
{
int nprobes, i;
mdb_printf("%5s %10s %17s %33s %s\n",
"ID", "PROVIDER", "MODULE", "FUNCTION", "NAME");
if (!(flags & DCMD_ADDRSPEC)) {
/*
* If no argument is provided just display all available
* probes.
*/
mdb_warn("failed to read 'dtrace_probes'");
return (-1);
}
mdb_warn("failed to read 'dtrace_nprobes'");
return (-1);
}
for (i = 0; i < nprobes; i++) {
mdb_warn("couldn't read probe pointer at %p",
caddr);
continue;
}
continue;
mdb_printf("%5d %10s %17s %33s %s\n",
}
}
} else {
mdb_warn("couldn't walk 'dtrace_ecb'");
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
const mdb_dcmd_t kernel_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 },
{ "dtrace_options", ":",
"print a DTrace consumer's current tuneable options",
{ "dtrace_probes", "?", "print a DTrace consumer's enabled probes",
{ NULL }
};
const mdb_walker_t kernel_walkers[] = {
{ "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",
{ "dtrace_ecb", "walk a DTrace consumer's enabling control blocks",
{ "pid2state", "walk a processes dtrace_state structures",
{ NULL }
};