summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2012-06-30 07:46:38 +0000
committerMartin Matuska <mm@FreeBSD.org>2012-06-30 07:46:38 +0000
commit4a37bb98c980176bf8002f7ccd8807092ff8f9cf (patch)
treefb4e00bd775ffa753a3b8466008fa3dbca70d12d /lib
parente0ea83ebb1a4b194c927cb114766e8781676380b (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/libctf/common/ctf_lib.c6
-rw-r--r--lib/libdtrace/common/dt_aggregate.c89
-rw-r--r--lib/libdtrace/common/dt_cc.c302
-rw-r--r--lib/libdtrace/common/dt_consume.c186
-rw-r--r--lib/libdtrace/common/dt_decl.c14
-rw-r--r--lib/libdtrace/common/dt_dof.c14
-rw-r--r--lib/libdtrace/common/dt_errtags.h30
-rw-r--r--lib/libdtrace/common/dt_ident.c8
-rw-r--r--lib/libdtrace/common/dt_impl.h13
-rw-r--r--lib/libdtrace/common/dt_map.c172
-rw-r--r--lib/libdtrace/common/dt_open.c32
-rw-r--r--lib/libdtrace/common/dt_options.c27
-rw-r--r--lib/libdtrace/common/dt_parser.c31
-rw-r--r--lib/libdtrace/common/dt_pragma.c49
-rw-r--r--lib/libdtrace/common/dt_print.c648
-rw-r--r--lib/libdtrace/common/dt_printf.c12
-rw-r--r--lib/libdtrace/common/dt_program.c2
-rw-r--r--lib/libdtrace/common/dt_string.c17
-rw-r--r--lib/libdtrace/common/dt_string.h12
-rw-r--r--lib/libdtrace/common/dt_subr.c6
-rw-r--r--lib/libdtrace/common/dtrace.h19
-rw-r--r--lib/libdtrace/i386/regs.d.in151
22 files changed, 1640 insertions, 200 deletions
diff --git a/lib/libctf/common/ctf_lib.c b/lib/libctf/common/ctf_lib.c
index 6e599540a4f6..1c5c3f1d5f7e 100644
--- a/lib/libctf/common/ctf_lib.c
+++ b/lib/libctf/common/ctf_lib.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
@@ -37,9 +35,9 @@
#include <gelf.h>
#ifdef _LP64
-static const char *_libctf_zlib = "/usr/lib/64/libz.so";
+static const char *_libctf_zlib = "/usr/lib/64/libz.so.1";
#else
-static const char *_libctf_zlib = "/usr/lib/libz.so";
+static const char *_libctf_zlib = "/usr/lib/libz.so.1";
#endif
static struct {
diff --git a/lib/libdtrace/common/dt_aggregate.c b/lib/libdtrace/common/dt_aggregate.c
index 2e66250b88d7..bb766f71c466 100644
--- a/lib/libdtrace/common/dt_aggregate.c
+++ b/lib/libdtrace/common/dt_aggregate.c
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ */
#include <stdlib.h>
#include <strings.h>
@@ -204,6 +206,83 @@ dt_aggregate_lquantizedcmp(int64_t *lhs, int64_t *rhs)
return (0);
}
+static void
+dt_aggregate_llquantize(int64_t *existing, int64_t *new, size_t size)
+{
+ int i;
+
+ for (i = 1; i < size / sizeof (int64_t); i++)
+ existing[i] = existing[i] + new[i];
+}
+
+static long double
+dt_aggregate_llquantizedsum(int64_t *llquanta)
+{
+ int64_t arg = *llquanta++;
+ uint16_t factor = DTRACE_LLQUANTIZE_FACTOR(arg);
+ uint16_t low = DTRACE_LLQUANTIZE_LOW(arg);
+ uint16_t high = DTRACE_LLQUANTIZE_HIGH(arg);
+ uint16_t nsteps = DTRACE_LLQUANTIZE_NSTEP(arg);
+ int bin = 0, order;
+ int64_t value = 1, next, step;
+ long double total;
+
+ assert(nsteps >= factor);
+ assert(nsteps % factor == 0);
+
+ for (order = 0; order < low; order++)
+ value *= factor;
+
+ total = (long double)llquanta[bin++] * (long double)(value - 1);
+
+ next = value * factor;
+ step = next > nsteps ? next / nsteps : 1;
+
+ while (order <= high) {
+ assert(value < next);
+ total += (long double)llquanta[bin++] * (long double)(value);
+
+ if ((value += step) != next)
+ continue;
+
+ next = value * factor;
+ step = next > nsteps ? next / nsteps : 1;
+ order++;
+ }
+
+ return (total + (long double)llquanta[bin] * (long double)value);
+}
+
+static int
+dt_aggregate_llquantizedcmp(int64_t *lhs, int64_t *rhs)
+{
+ long double lsum = dt_aggregate_llquantizedsum(lhs);
+ long double rsum = dt_aggregate_llquantizedsum(rhs);
+ int64_t lzero, rzero;
+
+ if (lsum < rsum)
+ return (DT_LESSTHAN);
+
+ if (lsum > rsum)
+ return (DT_GREATERTHAN);
+
+ /*
+ * If they're both equal, then we will compare based on the weights at
+ * zero. If the weights at zero are equal, then this will be judged a
+ * tie and will be resolved based on the key comparison.
+ */
+ lzero = lhs[1];
+ rzero = rhs[1];
+
+ if (lzero < rzero)
+ return (DT_LESSTHAN);
+
+ if (lzero > rzero)
+ return (DT_GREATERTHAN);
+
+ return (0);
+}
+
static int
dt_aggregate_quantizedcmp(int64_t *lhs, int64_t *rhs)
{
@@ -582,6 +661,10 @@ hashnext:
h->dtahe_aggregate = dt_aggregate_lquantize;
break;
+ case DTRACEAGG_LLQUANTIZE:
+ h->dtahe_aggregate = dt_aggregate_llquantize;
+ break;
+
case DTRACEAGG_COUNT:
case DTRACEAGG_SUM:
case DTRACEAGG_AVG:
@@ -849,6 +932,10 @@ dt_aggregate_valcmp(const void *lhs, const void *rhs)
rval = dt_aggregate_lquantizedcmp(laddr, raddr);
break;
+ case DTRACEAGG_LLQUANTIZE:
+ rval = dt_aggregate_llquantizedcmp(laddr, raddr);
+ break;
+
case DTRACEAGG_COUNT:
case DTRACEAGG_SUM:
case DTRACEAGG_MIN:
diff --git a/lib/libdtrace/common/dt_cc.c b/lib/libdtrace/common/dt_cc.c
index 24a386bbde95..8b8bcf475cba 100644
--- a/lib/libdtrace/common/dt_cc.c
+++ b/lib/libdtrace/common/dt_cc.c
@@ -21,6 +21,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
@@ -82,6 +84,7 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/sysmacros.h>
#include <assert.h>
#include <strings.h>
@@ -676,13 +679,59 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
ap->dtad_kind = DTRACEACT_DIFEXPR;
}
+/*
+ * The print() action behaves identically to trace(), except that it stores the
+ * CTF type of the argument (if present) within the DOF for the DIFEXPR action.
+ * To do this, we set the 'dtsd_strdata' to point to the fully-qualified CTF
+ * type ID for the result of the DIF action. We use the ID instead of the name
+ * to handles complex types like arrays and function pointers that can't be
+ * resolved by ctf_type_lookup(). This is later processed by
+ * dtrace_dof_create() and turned into a reference into the string table so
+ * that we can get the type information when we process the data after the
+ * fact.
+ */
+static void
+dt_action_print(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
+{
+ dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
+ dt_node_t *dret;
+ size_t len;
+ dt_module_t *dmp;
+
+ if (dt_node_is_void(dnp->dn_args)) {
+ dnerror(dnp->dn_args, D_PRINT_VOID,
+ "print( ) may not be applied to a void expression\n");
+ }
+
+ if (dt_node_is_dynamic(dnp->dn_args)) {
+ dnerror(dnp->dn_args, D_PRINT_DYN,
+ "print( ) may not be applied to a dynamic expression\n");
+ }
+
+ dt_cg(yypcb, dnp->dn_args);
+
+ dret = yypcb->pcb_dret;
+ dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
+
+ len = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
+ sdp->dtsd_strdata = dt_alloc(dtp, len);
+ if (sdp->dtsd_strdata == NULL)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
+ (void) snprintf(sdp->dtsd_strdata, len, "%s`%d", dmp->dm_name,
+ dret->dn_type);
+
+ ap->dtad_difo = dt_as(yypcb);
+ ap->dtad_kind = DTRACEACT_DIFEXPR;
+}
+
static void
dt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
{
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
dt_node_t *addr = dnp->dn_args;
- dt_node_t *size = dnp->dn_args->dn_list;
+ dt_node_t *max = dnp->dn_args->dn_list;
+ dt_node_t *size;
char n[DT_TYPE_NAMELEN];
@@ -694,17 +743,37 @@ dt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
dt_node_type_name(addr, n, sizeof (n)));
}
- if (dt_node_is_posconst(size) == 0) {
- dnerror(size, D_TRACEMEM_SIZE, "tracemem( ) argument #2 must "
+ if (dt_node_is_posconst(max) == 0) {
+ dnerror(max, D_TRACEMEM_SIZE, "tracemem( ) argument #2 must "
"be a non-zero positive integral constant expression\n");
}
+ if ((size = max->dn_list) != NULL) {
+ if (size->dn_list != NULL) {
+ dnerror(size, D_TRACEMEM_ARGS, "tracemem ( ) prototype "
+ "mismatch: expected at most 3 args\n");
+ }
+
+ if (!dt_node_is_scalar(size)) {
+ dnerror(size, D_TRACEMEM_DYNSIZE, "tracemem ( ) "
+ "dynamic size (argument #3) must be of "
+ "scalar type\n");
+ }
+
+ dt_cg(yypcb, size);
+ ap->dtad_difo = dt_as(yypcb);
+ ap->dtad_difo->dtdo_rtype = dt_int_rtype;
+ ap->dtad_kind = DTRACEACT_TRACEMEM_DYNSIZE;
+
+ ap = dt_stmt_action(dtp, sdp);
+ }
+
dt_cg(yypcb, addr);
ap->dtad_difo = dt_as(yypcb);
- ap->dtad_kind = DTRACEACT_DIFEXPR;
+ ap->dtad_kind = DTRACEACT_TRACEMEM;
ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF;
- ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value;
+ ap->dtad_difo->dtdo_rtype.dtdt_size = max->dn_value;
}
static void
@@ -1034,6 +1103,9 @@ dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
case DT_ACT_TRACE:
dt_action_trace(dtp, dnp->dn_expr, sdp);
break;
+ case DT_ACT_PRINT:
+ dt_action_print(dtp, dnp->dn_expr, sdp);
+ break;
case DT_ACT_TRACEMEM:
dt_action_tracemem(dtp, dnp->dn_expr, sdp);
break;
@@ -1291,6 +1363,145 @@ dt_compile_agg(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
argmax = 5;
}
+ if (fid->di_id == DTRACEAGG_LLQUANTIZE) {
+ /*
+ * For log/linear quantizations, we have between one and five
+ * arguments in addition to the expression:
+ *
+ * arg1 => Factor
+ * arg2 => Low magnitude
+ * arg3 => High magnitude
+ * arg4 => Number of steps per magnitude
+ * arg5 => Quantization increment value (defaults to 1)
+ */
+ dt_node_t *llarg = dnp->dn_aggfun->dn_args->dn_list;
+ uint64_t oarg, order, v;
+ dt_idsig_t *isp;
+ int i;
+
+ struct {
+ char *str; /* string identifier */
+ int badtype; /* error on bad type */
+ int badval; /* error on bad value */
+ int mismatch; /* error on bad match */
+ int shift; /* shift value */
+ uint16_t value; /* value itself */
+ } args[] = {
+ { "factor", D_LLQUANT_FACTORTYPE,
+ D_LLQUANT_FACTORVAL, D_LLQUANT_FACTORMATCH,
+ DTRACE_LLQUANTIZE_FACTORSHIFT },
+ { "low magnitude", D_LLQUANT_LOWTYPE,
+ D_LLQUANT_LOWVAL, D_LLQUANT_LOWMATCH,
+ DTRACE_LLQUANTIZE_LOWSHIFT },
+ { "high magnitude", D_LLQUANT_HIGHTYPE,
+ D_LLQUANT_HIGHVAL, D_LLQUANT_HIGHMATCH,
+ DTRACE_LLQUANTIZE_HIGHSHIFT },
+ { "linear steps per magnitude", D_LLQUANT_NSTEPTYPE,
+ D_LLQUANT_NSTEPVAL, D_LLQUANT_NSTEPMATCH,
+ DTRACE_LLQUANTIZE_NSTEPSHIFT },
+ { NULL }
+ };
+
+ assert(arg == 0);
+
+ for (i = 0; args[i].str != NULL; i++) {
+ if (llarg->dn_kind != DT_NODE_INT) {
+ dnerror(llarg, args[i].badtype, "llquantize( ) "
+ "argument #%d (%s) must be an "
+ "integer constant\n", i + 1, args[i].str);
+ }
+
+ if ((uint64_t)llarg->dn_value > UINT16_MAX) {
+ dnerror(llarg, args[i].badval, "llquantize( ) "
+ "argument #%d (%s) must be an unsigned "
+ "16-bit quantity\n", i + 1, args[i].str);
+ }
+
+ args[i].value = (uint16_t)llarg->dn_value;
+
+ assert(!(arg & (UINT16_MAX << args[i].shift)));
+ arg |= ((uint64_t)args[i].value << args[i].shift);
+ llarg = llarg->dn_list;
+ }
+
+ assert(arg != 0);
+
+ if (args[0].value < 2) {
+ dnerror(dnp, D_LLQUANT_FACTORSMALL, "llquantize( ) "
+ "factor (argument #1) must be two or more\n");
+ }
+
+ if (args[1].value >= args[2].value) {
+ dnerror(dnp, D_LLQUANT_MAGRANGE, "llquantize( ) "
+ "high magnitude (argument #3) must be greater "
+ "than low magnitude (argument #2)\n");
+ }
+
+ if (args[3].value < args[0].value) {
+ dnerror(dnp, D_LLQUANT_FACTORNSTEPS, "llquantize( ) "
+ "factor (argument #1) must be less than or "
+ "equal to the number of linear steps per "
+ "magnitude (argument #4)\n");
+ }
+
+ for (v = args[0].value; v < args[3].value; v *= args[0].value)
+ continue;
+
+ if ((args[3].value % args[0].value) || (v % args[3].value)) {
+ dnerror(dnp, D_LLQUANT_FACTOREVEN, "llquantize( ) "
+ "factor (argument #1) must evenly divide the "
+ "number of steps per magnitude (argument #4), "
+ "and the number of steps per magnitude must evenly "
+ "divide a power of the factor\n");
+ }
+
+ for (i = 0, order = 1; i < args[2].value; i++) {
+ if (order * args[0].value > order) {
+ order *= args[0].value;
+ continue;
+ }
+
+ dnerror(dnp, D_LLQUANT_MAGTOOBIG, "llquantize( ) "
+ "factor (%d) raised to power of high magnitude "
+ "(%d) overflows 64-bits\n", args[0].value,
+ args[2].value);
+ }
+
+ isp = (dt_idsig_t *)aid->di_data;
+
+ if (isp->dis_auxinfo == 0) {
+ /*
+ * This is the first time we've seen an llquantize()
+ * for this aggregation; we'll store our argument
+ * as the auxiliary signature information.
+ */
+ isp->dis_auxinfo = arg;
+ } else if ((oarg = isp->dis_auxinfo) != arg) {
+ /*
+ * If we have seen this llquantize() before and the
+ * argument doesn't match the original argument, pick
+ * the original argument apart to concisely report the
+ * mismatch.
+ */
+ int expected = 0, found = 0;
+
+ for (i = 0; expected == found; i++) {
+ assert(args[i].str != NULL);
+
+ expected = (oarg >> args[i].shift) & UINT16_MAX;
+ found = (arg >> args[i].shift) & UINT16_MAX;
+ }
+
+ dnerror(dnp, args[i - 1].mismatch, "llquantize( ) "
+ "%s (argument #%d) doesn't match previous "
+ "declaration: expected %d, found %d\n",
+ args[i - 1].str, i, expected, found);
+ }
+
+ incr = llarg;
+ argmax = 6;
+ }
+
if (fid->di_id == DTRACEAGG_QUANTIZE) {
incr = dnp->dn_aggfun->dn_args->dn_list;
argmax = 2;
@@ -1913,25 +2124,23 @@ dt_lib_depend_free(dtrace_hdl_t *dtp)
}
}
-
/*
- * Open all of the .d library files found in the specified directory and
- * compile each one in topological order to cache its inlines and translators,
- * etc. We silently ignore any missing directories and other files found
- * therein. We only fail (and thereby fail dt_load_libs()) if we fail to
- * compile a library and the error is something other than #pragma D depends_on.
- * Dependency errors are silently ignored to permit a library directory to
- * contain libraries which may not be accessible depending on our privileges.
+ * Open all the .d library files found in the specified directory and
+ * compile each one of them. We silently ignore any missing directories and
+ * other files found therein. We only fail (and thereby fail dt_load_libs()) if
+ * we fail to compile a library and the error is something other than #pragma D
+ * depends_on. Dependency errors are silently ignored to permit a library
+ * directory to contain libraries which may not be accessible depending on our
+ * privileges.
*/
static int
dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
{
struct dirent *dp;
- const char *p;
+ const char *p, *end;
DIR *dirp;
char fname[PATH_MAX];
- dtrace_prog_t *pgp;
FILE *fp;
void *rv;
dt_lib_depend_t *dld;
@@ -1955,9 +2164,28 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
continue;
}
+ /*
+ * Skip files whose name match an already processed library
+ */
+ for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
+ dld = dt_list_next(dld)) {
+ end = strrchr(dld->dtld_library, '/');
+ /* dt_lib_depend_add ensures this */
+ assert(end != NULL);
+ if (strcmp(end + 1, dp->d_name) == 0)
+ break;
+ }
+
+ if (dld != NULL) {
+ dt_dprintf("skipping library %s, already processed "
+ "library with the same name: %s", dp->d_name,
+ dld->dtld_library);
+ continue;
+ }
+
dtp->dt_filetag = fname;
if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0)
- goto err;
+ return (-1); /* preserve dt_errno */
rv = dt_compile(dtp, DT_CTX_DPROG,
DTRACE_PROBESPEC_NAME, NULL,
@@ -1966,7 +2194,7 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
if (rv != NULL && dtp->dt_errno &&
(dtp->dt_errno != EDT_COMPILER ||
dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
- goto err;
+ return (-1); /* preserve dt_errno */
if (dtp->dt_errno)
dt_dprintf("error parsing library %s: %s\n",
@@ -1977,6 +2205,27 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
}
(void) closedir(dirp);
+
+ return (0);
+}
+
+/*
+ * Perform a topological sorting of all the libraries found across the entire
+ * dt_lib_path. Once sorted, compile each one in topological order to cache its
+ * inlines and translators, etc. We silently ignore any missing directories and
+ * other files found therein. We only fail (and thereby fail dt_load_libs()) if
+ * we fail to compile a library and the error is something other than #pragma D
+ * depends_on. Dependency errors are silently ignored to permit a library
+ * directory to contain libraries which may not be accessible depending on our
+ * privileges.
+ */
+static int
+dt_load_libs_sort(dtrace_hdl_t *dtp)
+{
+ dtrace_prog_t *pgp;
+ FILE *fp;
+ dt_lib_depend_t *dld;
+
/*
* Finish building the graph containing the library dependencies
* and perform a topological sort to generate an ordered list
@@ -2037,7 +2286,14 @@ dt_load_libs(dtrace_hdl_t *dtp)
dtp->dt_cflags |= DTRACE_C_NOLIBS;
- for (dirp = dt_list_next(&dtp->dt_lib_path);
+ /*
+ * /usr/lib/dtrace is always at the head of the list. The rest of the
+ * list is specified in the precedence order the user requested. Process
+ * everything other than the head first. DTRACE_C_NOLIBS has already
+ * been spcified so dt_vopen will ensure that there is always one entry
+ * in dt_lib_path.
+ */
+ for (dirp = dt_list_next(dt_list_next(&dtp->dt_lib_path));
dirp != NULL; dirp = dt_list_next(dirp)) {
if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
@@ -2045,6 +2301,16 @@ dt_load_libs(dtrace_hdl_t *dtp)
}
}
+ /* Handle /usr/lib/dtrace */
+ dirp = dt_list_next(&dtp->dt_lib_path);
+ if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
+ dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
+ return (-1); /* errno is set for us */
+ }
+
+ if (dt_load_libs_sort(dtp) < 0)
+ return (-1); /* errno is set for us */
+
return (0);
}
diff --git a/lib/libdtrace/common/dt_consume.c b/lib/libdtrace/common/dt_consume.c
index 564189a000ad..d3a554c1c6b7 100644
--- a/lib/libdtrace/common/dt_consume.c
+++ b/lib/libdtrace/common/dt_consume.c
@@ -23,6 +23,11 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ */
+
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
@@ -681,6 +686,121 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
return (0);
}
+int
+dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+ size_t size, uint64_t normal)
+{
+ int i, first_bin, last_bin, bin = 1, order, levels;
+ uint16_t factor, low, high, nsteps;
+ const int64_t *data = addr;
+ int64_t value = 1, next, step;
+ char positives = 0, negatives = 0;
+ long double total = 0;
+ uint64_t arg;
+ char c[32];
+
+ if (size < sizeof (uint64_t))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ arg = *data++;
+ size -= sizeof (uint64_t);
+
+ factor = DTRACE_LLQUANTIZE_FACTOR(arg);
+ low = DTRACE_LLQUANTIZE_LOW(arg);
+ high = DTRACE_LLQUANTIZE_HIGH(arg);
+ nsteps = DTRACE_LLQUANTIZE_NSTEP(arg);
+
+ /*
+ * We don't expect to be handed invalid llquantize() parameters here,
+ * but sanity check them (to a degree) nonetheless.
+ */
+ if (size > INT32_MAX || factor < 2 || low >= high ||
+ nsteps == 0 || factor > nsteps)
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ levels = (int)size / sizeof (uint64_t);
+
+ first_bin = 0;
+ last_bin = levels - 1;
+
+ while (first_bin < levels && data[first_bin] == 0)
+ first_bin++;
+
+ if (first_bin == levels) {
+ first_bin = 0;
+ last_bin = 1;
+ } else {
+ if (first_bin > 0)
+ first_bin--;
+
+ while (last_bin > 0 && data[last_bin] == 0)
+ last_bin--;
+
+ if (last_bin < levels - 1)
+ last_bin++;
+ }
+
+ for (i = first_bin; i <= last_bin; i++) {
+ positives |= (data[i] > 0);
+ negatives |= (data[i] < 0);
+ total += dt_fabsl((long double)data[i]);
+ }
+
+ if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
+ "------------- Distribution -------------", "count") < 0)
+ return (-1);
+
+ for (order = 0; order < low; order++)
+ value *= factor;
+
+ next = value * factor;
+ step = next > nsteps ? next / nsteps : 1;
+
+ if (first_bin == 0) {
+ (void) snprintf(c, sizeof (c), "< %lld", value);
+
+ if (dt_printf(dtp, fp, "%16s ", c) < 0)
+ return (-1);
+
+ if (dt_print_quantline(dtp, fp, data[0], normal,
+ total, positives, negatives) < 0)
+ return (-1);
+ }
+
+ while (order <= high) {
+ if (bin >= first_bin && bin <= last_bin) {
+ if (dt_printf(dtp, fp, "%16lld ", (long long)value) < 0)
+ return (-1);
+
+ if (dt_print_quantline(dtp, fp, data[bin],
+ normal, total, positives, negatives) < 0)
+ return (-1);
+ }
+
+ assert(value < next);
+ bin++;
+
+ if ((value += step) != next)
+ continue;
+
+ next = value * factor;
+ step = next > nsteps ? next / nsteps : 1;
+ order++;
+ }
+
+ if (last_bin < bin)
+ return (0);
+
+ assert(last_bin == bin);
+ (void) snprintf(c, sizeof (c), ">= %lld", value);
+
+ if (dt_printf(dtp, fp, "%16s ", c) < 0)
+ return (-1);
+
+ return (dt_print_quantline(dtp, fp, data[bin], normal,
+ total, positives, negatives));
+}
+
/*ARGSUSED*/
static int
dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
@@ -708,7 +828,7 @@ dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
/*ARGSUSED*/
int
dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
- size_t nbytes, int width, int quiet)
+ size_t nbytes, int width, int quiet, int forceraw)
{
/*
* If the byte stream is a series of printable characters, followed by
@@ -721,6 +841,9 @@ dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
if (nbytes == 0)
return (0);
+ if (forceraw)
+ goto raw;
+
if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)
goto raw;
@@ -1397,6 +1520,9 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
case DTRACEAGG_LQUANTIZE:
return (dt_print_lquantize(dtp, fp, addr, size, normal));
+ case DTRACEAGG_LLQUANTIZE:
+ return (dt_print_llquantize(dtp, fp, addr, size, normal));
+
case DTRACEAGG_AVG:
return (dt_print_average(dtp, fp, addr, size, normal));
@@ -1428,7 +1554,7 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
(uint32_t)normal);
break;
default:
- err = dt_print_bytes(dtp, fp, addr, size, 50, 0);
+ err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
break;
}
@@ -1583,6 +1709,7 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
int rval, i, n;
dtrace_epid_t last = DTRACE_EPIDNONE;
+ uint64_t tracememsize = 0;
dtrace_probedata_t data;
uint64_t drops;
caddr_t addr;
@@ -1751,6 +1878,13 @@ again:
}
}
+ if (act == DTRACEACT_TRACEMEM_DYNSIZE &&
+ rec->dtrd_size == sizeof (uint64_t)) {
+ /* LINTED - alignment */
+ tracememsize = *((unsigned long long *)addr);
+ continue;
+ }
+
rval = (*rfunc)(&data, rec, arg);
if (rval == DTRACE_CONSUME_NEXT)
@@ -1842,6 +1976,35 @@ again:
goto nextrec;
}
+ /*
+ * If this is a DIF expression, and the record has a
+ * format set, this indicates we have a CTF type name
+ * associated with the data and we should try to print
+ * it out by type.
+ */
+ if (act == DTRACEACT_DIFEXPR) {
+ const char *strdata = dt_strdata_lookup(dtp,
+ rec->dtrd_format);
+ if (strdata != NULL) {
+ n = dtrace_print(dtp, fp, strdata,
+ addr, rec->dtrd_size);
+
+ /*
+ * dtrace_print() will return -1 on
+ * error, or return the number of bytes
+ * consumed. It will return 0 if the
+ * type couldn't be determined, and we
+ * should fall through to the normal
+ * trace method.
+ */
+ if (n < 0)
+ return (-1);
+
+ if (n > 0)
+ goto nextrec;
+ }
+ }
+
nofmt:
if (act == DTRACEACT_PRINTA) {
dt_print_aggdata_t pd;
@@ -1910,6 +2073,23 @@ nofmt:
goto nextrec;
}
+ if (act == DTRACEACT_TRACEMEM) {
+ if (tracememsize == 0 ||
+ tracememsize > rec->dtrd_size) {
+ tracememsize = rec->dtrd_size;
+ }
+
+ n = dt_print_bytes(dtp, fp, addr,
+ tracememsize, 33, quiet, 1);
+
+ tracememsize = 0;
+
+ if (n < 0)
+ return (-1);
+
+ goto nextrec;
+ }
+
switch (rec->dtrd_size) {
case sizeof (uint64_t):
n = dt_printf(dtp, fp,
@@ -1933,7 +2113,7 @@ nofmt:
break;
default:
n = dt_print_bytes(dtp, fp, addr,
- rec->dtrd_size, 33, quiet);
+ rec->dtrd_size, 33, quiet, 0);
break;
}
diff --git a/lib/libdtrace/common/dt_decl.c b/lib/libdtrace/common/dt_decl.c
index bb779840406c..d2a0b29ca8e7 100644
--- a/lib/libdtrace/common/dt_decl.c
+++ b/lib/libdtrace/common/dt_decl.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -19,13 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <strings.h>
#include <stdlib.h>
#include <limits.h>
@@ -703,8 +700,7 @@ dt_decl_enumerator(char *s, dt_node_t *dnp)
char *name;
int value;
- name = alloca(strlen(s) + 1);
- (void) strcpy(name, s);
+ name = strdupa(s);
free(s);
if (dsp == NULL)
diff --git a/lib/libdtrace/common/dt_dof.c b/lib/libdtrace/common/dt_dof.c
index a7eb8e4d239f..04c4c89cdbdb 100644
--- a/lib/libdtrace/common/dt_dof.c
+++ b/lib/libdtrace/common/dt_dof.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@@ -754,16 +755,23 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
dofa[i].dofa_difo = DOF_SECIDX_NONE;
/*
- * If the first action in a statement has format data,
- * add the format string to the global string table.
+ * If the first action in a statement has string data,
+ * add the string to the global string table. This can
+ * be due either to a printf() format string
+ * (dtsd_fmtdata) or a print() type string
+ * (dtsd_strdata).
*/
if (sdp != NULL && ap == sdp->dtsd_action) {
if (sdp->dtsd_fmtdata != NULL) {
(void) dtrace_printf_format(dtp,
sdp->dtsd_fmtdata, fmt, maxfmt + 1);
strndx = dof_add_string(ddo, fmt);
- } else
+ } else if (sdp->dtsd_strdata != NULL) {
+ strndx = dof_add_string(ddo,
+ sdp->dtsd_strdata);
+ } else {
strndx = 0; /* use dtad_arg instead */
+ }
if ((next = dt_list_next(next)) != NULL)
sdp = next->ds_desc;
diff --git a/lib/libdtrace/common/dt_errtags.h b/lib/libdtrace/common/dt_errtags.h
index 9e32dfdf2492..473e2addc789 100644
--- a/lib/libdtrace/common/dt_errtags.h
+++ b/lib/libdtrace/common/dt_errtags.h
@@ -24,11 +24,14 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ */
+
#ifndef _DT_ERRTAGS_H
#define _DT_ERRTAGS_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -187,8 +190,12 @@ typedef enum {
D_PRINTA_AGGPROTO, /* printa() aggregation mismatch */
D_TRACE_VOID, /* trace() argument has void type */
D_TRACE_DYN, /* trace() argument has dynamic type */
+ D_PRINT_VOID, /* print() argument has void type */
+ D_PRINT_DYN, /* print() argument has dynamic type */
D_TRACEMEM_ADDR, /* tracemem() address bad type */
D_TRACEMEM_SIZE, /* tracemem() size bad type */
+ D_TRACEMEM_ARGS, /* tracemem() illegal number of args */
+ D_TRACEMEM_DYNSIZE, /* tracemem() dynamic size bad type */
D_STACK_PROTO, /* stack() prototype mismatch */
D_STACK_SIZE, /* stack() size argument bad type */
D_USTACK_FRAMES, /* ustack() frames arg bad type */
@@ -235,7 +242,24 @@ typedef enum {
D_FREOPEN_INVALID, /* frename() filename is invalid */
D_LQUANT_MATCHBASE, /* lquantize() mismatch on base */
D_LQUANT_MATCHLIM, /* lquantize() mismatch on limit */
- D_LQUANT_MATCHSTEP /* lquantize() mismatch on step */
+ D_LQUANT_MATCHSTEP, /* lquantize() mismatch on step */
+ D_LLQUANT_FACTORTYPE, /* llquantize() bad magnitude type */
+ D_LLQUANT_FACTORVAL, /* llquantize() bad magnitude value */
+ D_LLQUANT_FACTORMATCH, /* llquantize() mismatch on magnitude */
+ D_LLQUANT_LOWTYPE, /* llquantize() bad low mag type */
+ D_LLQUANT_LOWVAL, /* llquantize() bad low mag value */
+ D_LLQUANT_LOWMATCH, /* llquantize() mismatch on low mag */
+ D_LLQUANT_HIGHTYPE, /* llquantize() bad high mag type */
+ D_LLQUANT_HIGHVAL, /* llquantize() bad high mag value */
+ D_LLQUANT_HIGHMATCH, /* llquantize() mismatch on high mag */
+ D_LLQUANT_NSTEPTYPE, /* llquantize() bad # steps type */
+ D_LLQUANT_NSTEPVAL, /* llquantize() bad # steps value */
+ D_LLQUANT_NSTEPMATCH, /* llquantize() mismatch on # steps */
+ D_LLQUANT_MAGRANGE, /* llquantize() bad magnitude range */
+ D_LLQUANT_FACTORNSTEPS, /* llquantize() # steps < factor */
+ D_LLQUANT_FACTOREVEN, /* llquantize() bad # steps/factor */
+ D_LLQUANT_FACTORSMALL, /* llquantize() magnitude too small */
+ D_LLQUANT_MAGTOOBIG /* llquantize() high mag too large */
} dt_errtag_t;
extern const char *dt_errtag(dt_errtag_t);
diff --git a/lib/libdtrace/common/dt_ident.c b/lib/libdtrace/common/dt_ident.c
index c437e0ab031a..3dfa058b1698 100644
--- a/lib/libdtrace/common/dt_ident.c
+++ b/lib/libdtrace/common/dt_ident.c
@@ -20,12 +20,9 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/sysmacros.h>
#include <strings.h>
#include <stdlib.h>
@@ -181,8 +178,7 @@ dt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
int i = 0;
assert(idp->di_iarg != NULL);
- s = alloca(strlen(idp->di_iarg) + 1);
- (void) strcpy(s, idp->di_iarg);
+ s = strdupa(idp->di_iarg);
if ((p2 = strrchr(s, ')')) != NULL)
*p2 = '\0'; /* mark end of parameter list string */
diff --git a/lib/libdtrace/common/dt_impl.h b/lib/libdtrace/common/dt_impl.h
index 1937ce06474d..b06fd6477d7a 100644
--- a/lib/libdtrace/common/dt_impl.h
+++ b/lib/libdtrace/common/dt_impl.h
@@ -24,6 +24,11 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ */
+
#ifndef _DT_IMPL_H
#define _DT_IMPL_H
@@ -236,6 +241,8 @@ struct dtrace_hdl {
dtrace_aggdesc_t **dt_aggdesc; /* aggregation descriptions */
int dt_maxformat; /* max format ID */
void **dt_formats; /* pointer to format array */
+ int dt_maxstrdata; /* max strdata ID */
+ char **dt_strdata; /* pointer to strdata array */
dt_aggregate_t dt_aggregate; /* aggregate */
dtrace_bufdesc_t dt_buf; /* staging buffer */
struct dt_pfdict *dt_pfdict; /* dictionary of printf conversions */
@@ -413,6 +420,7 @@ struct dtrace_hdl {
#define DT_ACT_UMOD DT_ACT(26) /* umod() action */
#define DT_ACT_UADDR DT_ACT(27) /* uaddr() action */
#define DT_ACT_SETOPT DT_ACT(28) /* setopt() action */
+#define DT_ACT_PRINT DT_ACT(29) /* print() action */
/*
* Sentinel to tell freopen() to restore the saved stdout. This must not
@@ -596,10 +604,15 @@ extern void dt_aggid_destroy(dtrace_hdl_t *);
extern void *dt_format_lookup(dtrace_hdl_t *, int);
extern void dt_format_destroy(dtrace_hdl_t *);
+extern const char *dt_strdata_lookup(dtrace_hdl_t *, int);
+extern void dt_strdata_destroy(dtrace_hdl_t *);
+
extern int dt_print_quantize(dtrace_hdl_t *, FILE *,
const void *, size_t, uint64_t);
extern int dt_print_lquantize(dtrace_hdl_t *, FILE *,
const void *, size_t, uint64_t);
+extern int dt_print_llquantize(dtrace_hdl_t *, FILE *,
+ const void *, size_t, uint64_t);
extern int dt_print_agg(const dtrace_aggdata_t *, void *);
extern int dt_handle(dtrace_hdl_t *, dtrace_probedata_t *);
diff --git a/lib/libdtrace/common/dt_map.c b/lib/libdtrace/common/dt_map.c
index 15361862de8f..8a3ce817e4d7 100644
--- a/lib/libdtrace/common/dt_map.c
+++ b/lib/libdtrace/common/dt_map.c
@@ -23,7 +23,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ */
#include <stdlib.h>
#include <strings.h>
@@ -35,10 +37,81 @@
#include <dt_printf.h>
static int
+dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
+{
+ int maxformat;
+ dtrace_fmtdesc_t fmt;
+ void *result;
+
+ if (rec->dtrd_format == 0)
+ return (0);
+
+ if (rec->dtrd_format <= *max &&
+ (*data)[rec->dtrd_format - 1] != NULL) {
+ return (0);
+ }
+
+ bzero(&fmt, sizeof (fmt));
+ fmt.dtfd_format = rec->dtrd_format;
+ fmt.dtfd_string = NULL;
+ fmt.dtfd_length = 0;
+
+ if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1)
+ return (dt_set_errno(dtp, errno));
+
+ if ((fmt.dtfd_string = dt_alloc(dtp, fmt.dtfd_length)) == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+
+ if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
+ free(fmt.dtfd_string);
+ return (dt_set_errno(dtp, errno));
+ }
+
+ while (rec->dtrd_format > (maxformat = *max)) {
+ int new_max = maxformat ? (maxformat << 1) : 1;
+ size_t nsize = new_max * sizeof (void *);
+ size_t osize = maxformat * sizeof (void *);
+ void **new_data = dt_zalloc(dtp, nsize);
+
+ if (new_data == NULL) {
+ dt_free(dtp, fmt.dtfd_string);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+
+ bcopy(*data, new_data, osize);
+ free(*data);
+
+ *data = new_data;
+ *max = new_max;
+ }
+
+ switch (rec->dtrd_action) {
+ case DTRACEACT_DIFEXPR:
+ result = fmt.dtfd_string;
+ break;
+ case DTRACEACT_PRINTA:
+ result = dtrace_printa_create(dtp, fmt.dtfd_string);
+ dt_free(dtp, fmt.dtfd_string);
+ break;
+ default:
+ result = dtrace_printf_create(dtp, fmt.dtfd_string);
+ dt_free(dtp, fmt.dtfd_string);
+ break;
+ }
+
+ if (result == NULL)
+ return (-1);
+
+ (*data)[rec->dtrd_format - 1] = result;
+
+ return (0);
+}
+
+static int
dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
{
dtrace_id_t max;
- int rval, i, maxformat;
+ int rval, i;
dtrace_eprobedesc_t *enabled, *nenabled;
dtrace_probedesc_t *probe;
@@ -124,71 +197,23 @@ dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
}
for (i = 0; i < enabled->dtepd_nrecs; i++) {
- dtrace_fmtdesc_t fmt;
dtrace_recdesc_t *rec = &enabled->dtepd_rec[i];
- if (!DTRACEACT_ISPRINTFLIKE(rec->dtrd_action))
- continue;
-
- if (rec->dtrd_format == 0)
- continue;
-
- if (rec->dtrd_format <= dtp->dt_maxformat &&
- dtp->dt_formats[rec->dtrd_format - 1] != NULL)
- continue;
-
- bzero(&fmt, sizeof (fmt));
- fmt.dtfd_format = rec->dtrd_format;
- fmt.dtfd_string = NULL;
- fmt.dtfd_length = 0;
-
- if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
- rval = dt_set_errno(dtp, errno);
- goto err;
- }
-
- if ((fmt.dtfd_string = malloc(fmt.dtfd_length)) == NULL) {
- rval = dt_set_errno(dtp, EDT_NOMEM);
- goto err;
- }
-
- if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
- rval = dt_set_errno(dtp, errno);
- free(fmt.dtfd_string);
- goto err;
- }
-
- while (rec->dtrd_format > (maxformat = dtp->dt_maxformat)) {
- int new_max = maxformat ? (maxformat << 1) : 1;
- size_t nsize = new_max * sizeof (void *);
- size_t osize = maxformat * sizeof (void *);
- void **new_formats = malloc(nsize);
-
- if (new_formats == NULL) {
- rval = dt_set_errno(dtp, EDT_NOMEM);
- free(fmt.dtfd_string);
+ if (DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) {
+ if (dt_strdata_add(dtp, rec, &dtp->dt_formats,
+ &dtp->dt_maxformat) != 0) {
+ rval = -1;
+ goto err;
+ }
+ } else if (rec->dtrd_action == DTRACEACT_DIFEXPR) {
+ if (dt_strdata_add(dtp, rec,
+ (void ***)&dtp->dt_strdata,
+ &dtp->dt_maxstrdata) != 0) {
+ rval = -1;
goto err;
}
-
- bzero(new_formats, nsize);
- bcopy(dtp->dt_formats, new_formats, osize);
- free(dtp->dt_formats);
-
- dtp->dt_formats = new_formats;
- dtp->dt_maxformat = new_max;
}
- dtp->dt_formats[rec->dtrd_format - 1] =
- rec->dtrd_action == DTRACEACT_PRINTA ?
- dtrace_printa_create(dtp, fmt.dtfd_string) :
- dtrace_printf_create(dtp, fmt.dtfd_string);
-
- free(fmt.dtfd_string);
-
- if (dtp->dt_formats[rec->dtrd_format - 1] == NULL) {
- rval = -1; /* dt_errno is set for us */
- goto err;
- }
}
dtp->dt_pdesc[id] = probe;
@@ -424,3 +449,28 @@ dt_aggid_destroy(dtrace_hdl_t *dtp)
dtp->dt_aggdesc = NULL;
dtp->dt_maxagg = 0;
}
+
+const char *
+dt_strdata_lookup(dtrace_hdl_t *dtp, int idx)
+{
+ if (idx == 0 || idx > dtp->dt_maxstrdata)
+ return (NULL);
+
+ if (dtp->dt_strdata == NULL)
+ return (NULL);
+
+ return (dtp->dt_strdata[idx - 1]);
+}
+
+void
+dt_strdata_destroy(dtrace_hdl_t *dtp)
+{
+ int i;
+
+ for (i = 0; i < dtp->dt_maxstrdata; i++) {
+ free(dtp->dt_strdata[i]);
+ }
+
+ free(dtp->dt_strdata);
+ dtp->dt_strdata = NULL;
+}
diff --git a/lib/libdtrace/common/dt_open.c b/lib/libdtrace/common/dt_open.c
index 2b9cd7c414da..502a9d42ad73 100644
--- a/lib/libdtrace/common/dt_open.c
+++ b/lib/libdtrace/common/dt_open.c
@@ -21,6 +21,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@@ -103,8 +105,13 @@
#define DT_VERS_1_6_1 DT_VERSION_NUMBER(1, 6, 1)
#define DT_VERS_1_6_2 DT_VERSION_NUMBER(1, 6, 2)
#define DT_VERS_1_6_3 DT_VERSION_NUMBER(1, 6, 3)
-#define DT_VERS_LATEST DT_VERS_1_6_3
-#define DT_VERS_STRING "Sun D 1.6.3"
+#define DT_VERS_1_7 DT_VERSION_NUMBER(1, 7, 0)
+#define DT_VERS_1_7_1 DT_VERSION_NUMBER(1, 7, 1)
+#define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0)
+#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
+#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
+#define DT_VERS_LATEST DT_VERS_1_9
+#define DT_VERS_STRING "Sun D 1.9"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -120,6 +127,11 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_6_1, /* D API 1.6.1 */
DT_VERS_1_6_2, /* D API 1.6.2 */
DT_VERS_1_6_3, /* D API 1.6.3 */
+ DT_VERS_1_7, /* D API 1.7 */
+ DT_VERS_1_7_1, /* D API 1.7.1 */
+ DT_VERS_1_8, /* D API 1.8 */
+ DT_VERS_1_8_1, /* D API 1.8.1 */
+ DT_VERS_1_9, /* D API 1.9 */
0
};
@@ -250,7 +262,10 @@ static const dt_ident_t _dtrace_globals[] = {
{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "stack(...)" },
{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
- &dt_idops_func, "string(int64_t)" },
+ &dt_idops_func, "string(int64_t, [int])" },
+{ "llquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LLQUANTIZE, DT_ATTR_STABCMN,
+ DT_VERS_1_7, &dt_idops_func,
+ "void(@, int32_t, int32_t, int32_t, int32_t, ...)" },
{ "lquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LQUANTIZE,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@, int32_t, int32_t, ...)" },
@@ -292,6 +307,8 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_type, "pid_t" },
{ "ppid", DT_IDENT_SCALAR, 0, DIF_VAR_PPID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "pid_t" },
+{ "print", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINT, DT_ATTR_STABCMN, DT_VERS_1_9,
+ &dt_idops_func, "void(@)" },
{ "printa", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTA, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@, ...)" },
{ "printf", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTF, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -371,11 +388,15 @@ static const dt_ident_t _dtrace_globals[] = {
{ "timestamp", DT_IDENT_SCALAR, 0, DIF_VAR_TIMESTAMP,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint64_t" },
+{ "tolower", DT_IDENT_FUNC, 0, DIF_SUBR_TOLOWER, DT_ATTR_STABCMN, DT_VERS_1_8,
+ &dt_idops_func, "string(const char *)" },
+{ "toupper", DT_IDENT_FUNC, 0, DIF_SUBR_TOUPPER, DT_ATTR_STABCMN, DT_VERS_1_8,
+ &dt_idops_func, "string(const char *)" },
{ "trace", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACE, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@)" },
{ "tracemem", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACEMEM,
DT_ATTR_STABCMN, DT_VERS_1_0,
- &dt_idops_func, "void(@, size_t)" },
+ &dt_idops_func, "void(@, size_t, ...)" },
{ "trunc", DT_IDENT_ACTFUNC, 0, DT_ACT_TRUNC, DT_ATTR_STABCMN,
DT_VERS_1_0, &dt_idops_func, "void(...)" },
{ "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN,
@@ -397,6 +418,8 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_type, "uint32_t" },
{ "usym", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
+{ "vmregs", DT_IDENT_ARRAY, 0, DIF_VAR_VMREGS, DT_ATTR_STABCMN, DT_VERS_1_7,
+ &dt_idops_regs, NULL },
{ "vtimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_VTIMESTAMP,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint64_t" },
@@ -1339,6 +1362,7 @@ dtrace_close(dtrace_hdl_t *dtp)
dt_epid_destroy(dtp);
dt_aggid_destroy(dtp);
dt_format_destroy(dtp);
+ dt_strdata_destroy(dtp);
dt_buffered_destroy(dtp);
dt_aggregate_destroy(dtp);
free(dtp->dt_buf.dtbd_data);
diff --git a/lib/libdtrace/common/dt_options.c b/lib/libdtrace/common/dt_options.c
index 5353bfae528d..426f8cb73c7a 100644
--- a/lib/libdtrace/common/dt_options.c
+++ b/lib/libdtrace/common/dt_options.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/types.h>
@@ -837,30 +835,6 @@ dt_options_load(dtrace_hdl_t *dtp)
return (0);
}
-/*ARGSUSED*/
-static int
-dt_opt_preallocate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
-{
- dtrace_optval_t size;
- void *p;
-
- if (arg == NULL || dt_optval_parse(arg, &size) != 0)
- return (dt_set_errno(dtp, EDT_BADOPTVAL));
-
- if (size > SIZE_MAX)
- size = SIZE_MAX;
-
- if ((p = dt_zalloc(dtp, size)) == NULL) {
- do {
- size /= 2;
- } while ((p = dt_zalloc(dtp, size)) == NULL);
- }
-
- dt_free(dtp, p);
-
- return (0);
-}
-
typedef struct dt_option {
const char *o_name;
int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
@@ -899,7 +873,6 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "linktype", dt_opt_linktype },
{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
{ "pgmax", dt_opt_pgmax },
- { "preallocate", dt_opt_preallocate },
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
{ "stdc", dt_opt_stdc },
{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
diff --git a/lib/libdtrace/common/dt_parser.c b/lib/libdtrace/common/dt_parser.c
index 9aabc18565db..05715894a7df 100644
--- a/lib/libdtrace/common/dt_parser.c
+++ b/lib/libdtrace/common/dt_parser.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -21,12 +20,10 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* DTrace D Language Parser
*
@@ -472,9 +469,9 @@ dt_node_name(const dt_node_t *dnp, char *buf, size_t len)
case DT_NODE_XLATOR:
(void) snprintf(buf, len, "translator <%s> (%s)",
dt_type_name(dnp->dn_xlator->dx_dst_ctfp,
- dnp->dn_xlator->dx_dst_type, n1, sizeof (n1)),
+ dnp->dn_xlator->dx_dst_type, n1, sizeof (n1)),
dt_type_name(dnp->dn_xlator->dx_src_ctfp,
- dnp->dn_xlator->dx_src_type, n2, sizeof (n2)));
+ dnp->dn_xlator->dx_src_type, n2, sizeof (n2)));
break;
case DT_NODE_PROG:
(void) snprintf(buf, len, "%s", "program");
@@ -723,12 +720,19 @@ dt_node_type_name(const dt_node_t *dnp, char *buf, size_t len)
size_t
dt_node_type_size(const dt_node_t *dnp)
{
+ ctf_id_t base;
+
if (dnp->dn_kind == DT_NODE_STRING)
return (strlen(dnp->dn_string) + 1);
if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL)
return (dt_ident_size(dnp->dn_ident));
+ base = ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type);
+
+ if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
+ return (0);
+
return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
}
@@ -1440,9 +1444,9 @@ dt_node_decl(void)
"\t current: %s\n\tprevious: %s\n",
dmp->dm_name, dsp->ds_ident,
dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,
- n1, sizeof (n1)),
+ n1, sizeof (n1)),
dt_type_name(ott.dtt_ctfp, ott.dtt_type,
- n2, sizeof (n2)));
+ n2, sizeof (n2)));
} else if (!exists && dt_module_extern(dtp, dmp,
dsp->ds_ident, &dtt) == NULL) {
xyerror(D_UNKNOWN,
@@ -1452,7 +1456,7 @@ dt_node_decl(void)
dt_dprintf("extern %s`%s type=<%s>\n",
dmp->dm_name, dsp->ds_ident,
dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,
- n1, sizeof (n1)));
+ n1, sizeof (n1)));
}
break;
}
@@ -1756,8 +1760,7 @@ dt_node_offsetof(dt_decl_t *ddp, char *s)
ctf_id_t type;
uint_t kind;
- name = alloca(strlen(s) + 1);
- (void) strcpy(name, s);
+ name = strdupa(s);
free(s);
err = dt_decl_type(ddp, &dtt);
diff --git a/lib/libdtrace/common/dt_pragma.c b/lib/libdtrace/common/dt_pragma.c
index a8bab85c008a..9fae5ac42c40 100644
--- a/lib/libdtrace/common/dt_pragma.c
+++ b/lib/libdtrace/common/dt_pragma.c
@@ -20,18 +20,20 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <assert.h>
#include <strings.h>
#include <alloca.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
#include <dt_parser.h>
#include <dt_impl.h>
#include <dt_provider.h>
@@ -199,6 +201,29 @@ dt_pragma_binding(const char *prname, dt_node_t *dnp)
dtp->dt_globals->dh_defer = &dt_pragma_apply;
}
+static void
+dt_pragma_depends_finddep(dtrace_hdl_t *dtp, const char *lname, char *lib,
+ size_t len)
+{
+ dt_dirpath_t *dirp;
+ struct stat sbuf;
+ int found = 0;
+
+ for (dirp = dt_list_next(&dtp->dt_lib_path); dirp != NULL;
+ dirp = dt_list_next(dirp)) {
+ (void) snprintf(lib, len, "%s/%s", dirp->dir_path, lname);
+
+ if (stat(lib, &sbuf) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ xyerror(D_PRAGMA_DEPEND,
+ "failed to find dependency in libpath: %s", lname);
+}
+
/*
* The #pragma depends_on directive can be used to express a dependency on a
* module, provider or library which if not present will cause processing to
@@ -228,16 +253,13 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
if (yypcb->pcb_cflags & DTRACE_C_CTL) {
assert(dtp->dt_filetag != NULL);
- /*
- * We have the file we are working on in dtp->dt_filetag
- * so find that node and add the dependency in.
- */
+ dt_pragma_depends_finddep(dtp, nnp->dn_string, lib,
+ sizeof (lib));
+
dld = dt_lib_depend_lookup(&dtp->dt_lib_dep,
dtp->dt_filetag);
assert(dld != NULL);
- (void) snprintf(lib, sizeof (lib), "%s%s",
- dld->dtld_libpath, nnp->dn_string);
if ((dt_lib_depend_add(dtp, &dld->dtld_dependencies,
lib)) != 0) {
xyerror(D_PRAGMA_DEPEND,
@@ -259,8 +281,8 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
dtp->dt_filetag);
assert(dld != NULL);
- (void) snprintf(lib, sizeof (lib), "%s%s",
- dld->dtld_libpath, nnp->dn_string);
+ dt_pragma_depends_finddep(dtp, nnp->dn_string, lib,
+ sizeof (lib));
dld = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted,
lib);
assert(dld != NULL);
@@ -337,8 +359,7 @@ dt_pragma_option(const char *prname, dt_node_t *dnp)
"superfluous arguments specified for #pragma %s\n", prname);
}
- opt = alloca(strlen(dnp->dn_string) + 1);
- (void) strcpy(opt, dnp->dn_string);
+ opt = strdupa(dnp->dn_string);
if ((val = strchr(opt, '=')) != NULL)
*val++ = '\0';
diff --git a/lib/libdtrace/common/dt_print.c b/lib/libdtrace/common/dt_print.c
new file mode 100644
index 000000000000..261fc8ced4d5
--- /dev/null
+++ b/lib/libdtrace/common/dt_print.c
@@ -0,0 +1,648 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ */
+
+/*
+ * DTrace print() action
+ *
+ * This file contains the post-processing logic for the print() action. The
+ * print action behaves identically to trace() in that it generates a
+ * DTRACEACT_DIFEXPR action, but the action argument field refers to a CTF type
+ * string stored in the DOF string table (similar to printf formats). We
+ * take the result of the trace action and post-process it in the fashion of
+ * MDB's ::print dcmd.
+ *
+ * This implementation differs from MDB's in the following ways:
+ *
+ * - We do not expose any options or flags. The behavior of print() is
+ * equivalent to "::print -tn".
+ *
+ * - MDB will display "holes" in structures (unused padding between
+ * members).
+ *
+ * - When printing arrays of structures, MDB will leave a trailing ','
+ * after the last element.
+ *
+ * - MDB will print time_t types as date and time.
+ *
+ * - MDB will detect when an enum is actually the OR of several flags,
+ * and print it out with the constituent flags separated.
+ *
+ * - For large arrays, MDB will print the first few members and then
+ * print a "..." continuation line.
+ *
+ * - MDB will break and wrap arrays at 80 columns.
+ *
+ * - MDB prints out floats and doubles by hand, as it must run in kmdb
+ * context. We're able to leverage the printf() format strings,
+ * but the result is a slightly different format.
+ */
+
+#include <sys/sysmacros.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <alloca.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <dt_module.h>
+#include <dt_printf.h>
+#include <dt_string.h>
+#include <dt_impl.h>
+
+/* determines whether the given integer CTF encoding is a character */
+#define CTF_IS_CHAR(e) \
+ (((e).cte_format & (CTF_INT_CHAR | CTF_INT_SIGNED)) == \
+ (CTF_INT_CHAR | CTF_INT_SIGNED) && (e).cte_bits == NBBY)
+/* determines whether the given CTF kind is a struct or union */
+#define CTF_IS_STRUCTLIKE(k) \
+ ((k) == CTF_K_STRUCT || (k) == CTF_K_UNION)
+
+/*
+ * Print structure passed down recursively through printing algorithm.
+ */
+typedef struct dt_printarg {
+ caddr_t pa_addr; /* base address of trace data */
+ ctf_file_t *pa_ctfp; /* CTF container */
+ int pa_depth; /* member depth */
+ int pa_nest; /* nested array depth */
+ FILE *pa_file; /* output file */
+} dt_printarg_t;
+
+static int dt_print_member(const char *, ctf_id_t, ulong_t, int, void *);
+
+/*
+ * Safe version of ctf_type_name() that will fall back to just "<ctfid>" if it
+ * can't resolve the type.
+ */
+static void
+dt_print_type_name(ctf_file_t *ctfp, ctf_id_t id, char *buf, size_t buflen)
+{
+ if (ctf_type_name(ctfp, id, buf, buflen) == NULL)
+ (void) snprintf(buf, buflen, "<%ld>", id);
+}
+
+/*
+ * Print any necessary trailing braces for structures or unions. We don't get
+ * invoked when a struct or union ends, so we infer the need to print braces
+ * based on the depth the last time we printed something and the new depth.
+ */
+static void
+dt_print_trailing_braces(dt_printarg_t *pap, int depth)
+{
+ int d;
+
+ for (d = pap->pa_depth; d > depth; d--) {
+ (void) fprintf(pap->pa_file, "%*s}%s",
+ (d + pap->pa_nest - 1) * 4, "",
+ d == depth + 1 ? "" : "\n");
+ }
+}
+
+/*
+ * Print the appropriate amount of indentation given the current depth and
+ * array nesting.
+ */
+static void
+dt_print_indent(dt_printarg_t *pap)
+{
+ (void) fprintf(pap->pa_file, "%*s",
+ (pap->pa_depth + pap->pa_nest) * 4, "");
+}
+
+/*
+ * Print a bitfield. It's worth noting that the D compiler support for
+ * bitfields is currently broken; printing "D`user_desc_t" (pulled in by the
+ * various D provider files) will produce incorrect results compared to
+ * "genunix`user_desc_t".
+ */
+static void
+print_bitfield(dt_printarg_t *pap, ulong_t off, ctf_encoding_t *ep)
+{
+ FILE *fp = pap->pa_file;
+ caddr_t addr = pap->pa_addr + off / NBBY;
+ uint64_t mask = (1ULL << ep->cte_bits) - 1;
+ uint64_t value = 0;
+ size_t size = (ep->cte_bits + (NBBY - 1)) / NBBY;
+ uint8_t *buf = (uint8_t *)&value;
+ uint8_t shift;
+
+ /*
+ * On big-endian machines, we need to adjust the buf pointer to refer
+ * to the lowest 'size' bytes in 'value', and we need to shift based on
+ * the offset from the end of the data, not the offset of the start.
+ */
+#ifdef _BIG_ENDIAN
+ buf += sizeof (value) - size;
+ off += ep->cte_bits;
+#endif
+ bcopy(addr, buf, size);
+ shift = off % NBBY;
+
+ /*
+ * Offsets are counted from opposite ends on little- and
+ * big-endian machines.
+ */
+#ifdef _BIG_ENDIAN
+ shift = NBBY - shift;
+#endif
+
+ /*
+ * If the bits we want do not begin on a byte boundary, shift the data
+ * right so that the value is in the lowest 'cte_bits' of 'value'.
+ */
+ if (off % NBBY != 0)
+ value >>= shift;
+ value &= mask;
+
+ (void) fprintf(fp, "%#llx", (u_longlong_t)value);
+}
+
+/*
+ * Dump the contents of memory as a fixed-size integer in hex.
+ */
+static void
+dt_print_hex(FILE *fp, caddr_t addr, size_t size)
+{
+ switch (size) {
+ case sizeof (uint8_t):
+ (void) fprintf(fp, "%#x", *(uint8_t *)addr);
+ break;
+ case sizeof (uint16_t):
+ /* LINTED - alignment */
+ (void) fprintf(fp, "%#x", *(uint16_t *)addr);
+ break;
+ case sizeof (uint32_t):
+ /* LINTED - alignment */
+ (void) fprintf(fp, "%#x", *(uint32_t *)addr);
+ break;
+ case sizeof (uint64_t):
+ (void) fprintf(fp, "%#llx",
+ /* LINTED - alignment */
+ (unsigned long long)*(uint64_t *)addr);
+ break;
+ default:
+ (void) fprintf(fp, "<invalid size %u>", (uint_t)size);
+ }
+}
+
+/*
+ * Print an integer type. Before dumping the contents via dt_print_hex(), we
+ * first check the encoding to see if it's part of a bitfield or a character.
+ */
+static void
+dt_print_int(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
+{
+ FILE *fp = pap->pa_file;
+ ctf_file_t *ctfp = pap->pa_ctfp;
+ ctf_encoding_t e;
+ size_t size;
+ caddr_t addr = pap->pa_addr + off / NBBY;
+
+ if (ctf_type_encoding(ctfp, base, &e) == CTF_ERR) {
+ (void) fprintf(fp, "<unknown encoding>");
+ return;
+ }
+
+ /*
+ * This comes from MDB - it's not clear under what circumstances this
+ * would be found.
+ */
+ if (e.cte_format & CTF_INT_VARARGS) {
+ (void) fprintf(fp, "...");
+ return;
+ }
+
+ /*
+ * We print this as a bitfield if the bit encoding indicates it's not
+ * an even power of two byte size, or is larger than 8 bytes.
+ */
+ size = e.cte_bits / NBBY;
+ if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)) != 0) {
+ print_bitfield(pap, off, &e);
+ return;
+ }
+
+ /*
+ * If this is a character, print it out as such.
+ */
+ if (CTF_IS_CHAR(e)) {
+ char c = *(char *)addr;
+ if (isprint(c))
+ (void) fprintf(fp, "'%c'", c);
+ else if (c == 0)
+ (void) fprintf(fp, "'\\0'");
+ else
+ (void) fprintf(fp, "'\\%03o'", c);
+ return;
+ }
+
+ dt_print_hex(fp, addr, size);
+}
+
+/*
+ * Print a floating point (float, double, long double) value.
+ */
+/* ARGSUSED */
+static void
+dt_print_float(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
+{
+ FILE *fp = pap->pa_file;
+ ctf_file_t *ctfp = pap->pa_ctfp;
+ ctf_encoding_t e;
+ caddr_t addr = pap->pa_addr + off / NBBY;
+
+ if (ctf_type_encoding(ctfp, base, &e) == 0) {
+ if (e.cte_format == CTF_FP_SINGLE &&
+ e.cte_bits == sizeof (float) * NBBY) {
+ /* LINTED - alignment */
+ (void) fprintf(fp, "%+.7e", *((float *)addr));
+ } else if (e.cte_format == CTF_FP_DOUBLE &&
+ e.cte_bits == sizeof (double) * NBBY) {
+ /* LINTED - alignment */
+ (void) fprintf(fp, "%+.7e", *((double *)addr));
+ } else if (e.cte_format == CTF_FP_LDOUBLE &&
+ e.cte_bits == sizeof (long double) * NBBY) {
+ /* LINTED - alignment */
+ (void) fprintf(fp, "%+.16LE", *((long double *)addr));
+ } else {
+ (void) fprintf(fp, "<unknown encoding>");
+ }
+ }
+}
+
+/*
+ * A pointer is printed as a fixed-size integer. This is used both for
+ * pointers and functions.
+ */
+static void
+dt_print_ptr(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
+{
+ FILE *fp = pap->pa_file;
+ ctf_file_t *ctfp = pap->pa_ctfp;
+ caddr_t addr = pap->pa_addr + off / NBBY;
+ size_t size = ctf_type_size(ctfp, base);
+
+ dt_print_hex(fp, addr, size);
+}
+
+/*
+ * Print out an array. This is somewhat complex, as we must manually visit
+ * each member, and recursively invoke ctf_type_visit() for each member. If
+ * the members are non-structs, then we print them out directly:
+ *
+ * [ 0x14, 0x2e, 0 ]
+ *
+ * If they are structs, then we print out the necessary leading and trailing
+ * braces, to end up with:
+ *
+ * [
+ * type {
+ * ...
+ * },
+ * type {
+ * ...
+ * }
+ * ]
+ *
+ * We also use a heuristic to detect whether the array looks like a character
+ * array. If the encoding indicates it's a character, and we have all
+ * printable characters followed by a null byte, then we display it as a
+ * string:
+ *
+ * [ "string" ]
+ */
+static void
+dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
+{
+ FILE *fp = pap->pa_file;
+ ctf_file_t *ctfp = pap->pa_ctfp;
+ caddr_t addr = pap->pa_addr + off / NBBY;
+ ctf_arinfo_t car;
+ ssize_t eltsize;
+ ctf_encoding_t e;
+ int i;
+ boolean_t isstring;
+ int kind;
+ ctf_id_t rtype;
+
+ if (ctf_array_info(ctfp, base, &car) == CTF_ERR) {
+ (void) fprintf(fp, "0x%p", (void *)addr);
+ return;
+ }
+
+ if ((eltsize = ctf_type_size(ctfp, car.ctr_contents)) < 0 ||
+ (rtype = ctf_type_resolve(ctfp, car.ctr_contents)) == CTF_ERR ||
+ (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR) {
+ (void) fprintf(fp, "<invalid type %lu>", car.ctr_contents);
+ return;
+ }
+
+ /* see if this looks like a string */
+ isstring = B_FALSE;
+ if (kind == CTF_K_INTEGER &&
+ ctf_type_encoding(ctfp, rtype, &e) != CTF_ERR && CTF_IS_CHAR(e)) {
+ char c;
+ for (i = 0; i < car.ctr_nelems; i++) {
+ c = *((char *)addr + eltsize * i);
+ if (!isprint(c) || c == '\0')
+ break;
+ }
+
+ if (i != car.ctr_nelems && c == '\0')
+ isstring = B_TRUE;
+ }
+
+ /*
+ * As a slight aesthetic optimization, if we are a top-level type, then
+ * don't bother printing out the brackets. This lets print("foo") look
+ * like:
+ *
+ * string "foo"
+ *
+ * As D will internally represent this as a char[256] array.
+ */
+ if (!isstring || pap->pa_depth != 0)
+ (void) fprintf(fp, "[ ");
+
+ if (isstring)
+ (void) fprintf(fp, "\"");
+
+ for (i = 0; i < car.ctr_nelems; i++) {
+ if (isstring) {
+ char c = *((char *)addr + eltsize * i);
+ if (c == '\0')
+ break;
+ (void) fprintf(fp, "%c", c);
+ } else {
+ /*
+ * Recursively invoke ctf_type_visit() on each member.
+ * We setup a new printarg struct with 'pa_nest' set to
+ * indicate that we are within a nested array.
+ */
+ dt_printarg_t pa = *pap;
+ pa.pa_nest += pap->pa_depth + 1;
+ pa.pa_depth = 0;
+ pa.pa_addr = addr + eltsize * i;
+ (void) ctf_type_visit(ctfp, car.ctr_contents,
+ dt_print_member, &pa);
+
+ dt_print_trailing_braces(&pa, 0);
+ if (i != car.ctr_nelems - 1)
+ (void) fprintf(fp, ", ");
+ else if (CTF_IS_STRUCTLIKE(kind))
+ (void) fprintf(fp, "\n");
+ }
+ }
+
+ if (isstring)
+ (void) fprintf(fp, "\"");
+
+ if (!isstring || pap->pa_depth != 0) {
+ if (CTF_IS_STRUCTLIKE(kind))
+ dt_print_indent(pap);
+ else
+ (void) fprintf(fp, " ");
+ (void) fprintf(fp, "]");
+ }
+}
+
+/*
+ * This isued by both structs and unions to print the leading brace.
+ */
+/* ARGSUSED */
+static void
+dt_print_structlike(ctf_id_t id, ulong_t off, dt_printarg_t *pap)
+{
+ (void) fprintf(pap->pa_file, "{");
+}
+
+/*
+ * For enums, we try to print the enum name, and fall back to the value if it
+ * can't be determined. We do not do any fancy flag processing like mdb.
+ */
+/* ARGSUSED */
+static void
+dt_print_enum(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
+{
+ FILE *fp = pap->pa_file;
+ ctf_file_t *ctfp = pap->pa_ctfp;
+ const char *ename;
+ int value = 0;
+
+ if ((ename = ctf_enum_name(ctfp, base, value)) != NULL)
+ (void) fprintf(fp, "%s", ename);
+ else
+ (void) fprintf(fp, "%d", value);
+}
+
+/*
+ * Forward declaration. There's not much to do here without the complete
+ * type information, so just print out this fact and drive on.
+ */
+/* ARGSUSED */
+static void
+dt_print_tag(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
+{
+ (void) fprintf(pap->pa_file, "<forward decl>");
+}
+
+typedef void dt_printarg_f(ctf_id_t, ulong_t, dt_printarg_t *);
+
+static dt_printarg_f *const dt_printfuncs[] = {
+ dt_print_int, /* CTF_K_INTEGER */
+ dt_print_float, /* CTF_K_FLOAT */
+ dt_print_ptr, /* CTF_K_POINTER */
+ dt_print_array, /* CTF_K_ARRAY */
+ dt_print_ptr, /* CTF_K_FUNCTION */
+ dt_print_structlike, /* CTF_K_STRUCT */
+ dt_print_structlike, /* CTF_K_UNION */
+ dt_print_enum, /* CTF_K_ENUM */
+ dt_print_tag /* CTF_K_FORWARD */
+};
+
+/*
+ * Print one member of a structure. This callback is invoked from
+ * ctf_type_visit() recursively.
+ */
+static int
+dt_print_member(const char *name, ctf_id_t id, ulong_t off, int depth,
+ void *data)
+{
+ char type[DT_TYPE_NAMELEN];
+ int kind;
+ dt_printarg_t *pap = data;
+ FILE *fp = pap->pa_file;
+ ctf_file_t *ctfp = pap->pa_ctfp;
+ boolean_t arraymember;
+ boolean_t brief;
+ ctf_encoding_t e;
+ ctf_id_t rtype;
+
+ dt_print_trailing_braces(pap, depth);
+ /*
+ * dt_print_trailing_braces() doesn't include the trailing newline; add
+ * it here if necessary.
+ */
+ if (depth < pap->pa_depth)
+ (void) fprintf(fp, "\n");
+ pap->pa_depth = depth;
+
+ if ((rtype = ctf_type_resolve(ctfp, id)) == CTF_ERR ||
+ (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR ||
+ kind < CTF_K_INTEGER || kind > CTF_K_FORWARD) {
+ dt_print_indent(pap);
+ (void) fprintf(fp, "%s = <invalid type %lu>", name, id);
+ return (0);
+ }
+
+ dt_print_type_name(ctfp, id, type, sizeof (type));
+
+ arraymember = (pap->pa_nest != 0 && depth == 0);
+ brief = (arraymember && !CTF_IS_STRUCTLIKE(kind));
+
+ if (!brief) {
+ /*
+ * If this is a direct array member and a struct (otherwise
+ * brief would be true), then print a trailing newline, as the
+ * array printing code doesn't include it because it might be a
+ * simple type.
+ */
+ if (arraymember)
+ (void) fprintf(fp, "\n");
+ dt_print_indent(pap);
+
+ /* always print the type */
+ (void) fprintf(fp, "%s", type);
+ if (name[0] != '\0') {
+ /*
+ * For aesthetics, we don't include a space between the
+ * type name and member name if the type is a pointer.
+ * This will give us "void *foo =" instead of "void *
+ * foo =". Unions also have the odd behavior that the
+ * type name is returned as "union ", with a trailing
+ * space, so we also avoid printing a space if the type
+ * name already ends with a space.
+ */
+ if (type[strlen(type) - 1] != '*' &&
+ type[strlen(type) -1] != ' ') {
+ (void) fprintf(fp, " ");
+ }
+ (void) fprintf(fp, "%s", name);
+
+ /*
+ * If this looks like a bitfield, or is an integer not
+ * aligned on a byte boundary, print the number of
+ * bits after the name.
+ */
+ if (kind == CTF_K_INTEGER &&
+ ctf_type_encoding(ctfp, id, &e) == 0) {
+ ulong_t bits = e.cte_bits;
+ ulong_t size = bits / NBBY;
+
+ if (bits % NBBY != 0 ||
+ off % NBBY != 0 ||
+ size > 8 ||
+ size != ctf_type_size(ctfp, id)) {
+ (void) fprintf(fp, " :%lu", bits);
+ }
+ }
+
+ (void) fprintf(fp, " =");
+ }
+ (void) fprintf(fp, " ");
+ }
+
+ dt_printfuncs[kind - 1](rtype, off, pap);
+
+ /* direct simple array members are not separated by newlines */
+ if (!brief)
+ (void) fprintf(fp, "\n");
+
+ return (0);
+}
+
+/*
+ * Main print function invoked by dt_consume_cpu().
+ */
+int
+dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
+ caddr_t addr, size_t len)
+{
+ const char *s;
+ char *object;
+ dt_printarg_t pa;
+ ctf_id_t id;
+ dt_module_t *dmp;
+
+ /*
+ * Split the fully-qualified type ID (module`id). This should
+ * always be the format, but if for some reason we don't find the
+ * expected value, return 0 to fall back to the generic trace()
+ * behavior.
+ */
+ for (s = typename; *s != '\0' && *s != '`'; s++)
+ ;
+
+ if (*s != '`')
+ return (0);
+
+ object = alloca(s - typename + 1);
+ bcopy(typename, object, s - typename);
+ object[s - typename] = '\0';
+ id = atoi(s + 1);
+
+ /*
+ * Try to get the CTF kind for this id. If something has gone horribly
+ * wrong and we can't resolve the ID, bail out and let trace() do the
+ * work.
+ */
+ dmp = dt_module_lookup_by_name(dtp, object);
+ if (dmp == NULL || ctf_type_kind(dt_module_getctf(dtp, dmp),
+ id) == CTF_ERR) {
+ return (0);
+ }
+
+ /* setup the print structure and kick off the main print routine */
+ pa.pa_addr = addr;
+ pa.pa_ctfp = dt_module_getctf(dtp, dmp);
+ pa.pa_nest = 0;
+ pa.pa_depth = 0;
+ pa.pa_file = fp;
+ (void) ctf_type_visit(pa.pa_ctfp, id, dt_print_member, &pa);
+
+ dt_print_trailing_braces(&pa, 0);
+
+ return (len);
+}
diff --git a/lib/libdtrace/common/dt_printf.c b/lib/libdtrace/common/dt_printf.c
index 52904789bc7e..eabc42338bcc 100644
--- a/lib/libdtrace/common/dt_printf.c
+++ b/lib/libdtrace/common/dt_printf.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -1300,6 +1301,14 @@ pfprint_lquantize(dtrace_hdl_t *dtp, FILE *fp, const char *format,
return (dt_print_lquantize(dtp, fp, addr, size, normal));
}
+/*ARGSUSED*/
+static int
+pfprint_llquantize(dtrace_hdl_t *dtp, FILE *fp, const char *format,
+ const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal)
+{
+ return (dt_print_llquantize(dtp, fp, addr, size, normal));
+}
+
static int
dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
const dtrace_recdesc_t *recs, uint_t nrecs, const void *buf,
@@ -1485,6 +1494,9 @@ dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
case DTRACEAGG_LQUANTIZE:
func = pfprint_lquantize;
break;
+ case DTRACEAGG_LLQUANTIZE:
+ func = pfprint_llquantize;
+ break;
case DTRACEACT_MOD:
func = pfprint_mod;
break;
diff --git a/lib/libdtrace/common/dt_program.c b/lib/libdtrace/common/dt_program.c
index 19f377de26ac..7d725bd0af86 100644
--- a/lib/libdtrace/common/dt_program.c
+++ b/lib/libdtrace/common/dt_program.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <unistd.h>
@@ -347,6 +348,7 @@ dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
if (sdp->dtsd_fmtdata != NULL)
dt_printf_destroy(sdp->dtsd_fmtdata);
+ dt_free(dtp, sdp->dtsd_strdata);
dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc);
dt_free(dtp, sdp);
diff --git a/lib/libdtrace/common/dt_string.c b/lib/libdtrace/common/dt_string.c
index 3a5315eef99a..782d66c2b8a6 100644
--- a/lib/libdtrace/common/dt_string.c
+++ b/lib/libdtrace/common/dt_string.c
@@ -29,23 +29,6 @@
#include <ctype.h>
#include <dt_string.h>
-#include <dt_impl.h>
-
-/*
- * Create a copy of string s, but only duplicate the first n bytes.
- */
-char *
-strndup(const char *s, size_t n)
-{
- char *s2 = malloc(n + 1);
-
- if (s2 == NULL)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
-
- (void) strncpy(s2, s, n);
- s2[n] = '\0';
- return (s2);
-}
/*
* Transform string s inline, converting each embedded C escape sequence string
diff --git a/lib/libdtrace/common/dt_string.h b/lib/libdtrace/common/dt_string.h
index 1fd412b1ad74..a9bb7a1eb70a 100644
--- a/lib/libdtrace/common/dt_string.h
+++ b/lib/libdtrace/common/dt_string.h
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,14 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _DT_STRING_H
#define _DT_STRING_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <strings.h>
@@ -36,7 +33,6 @@
extern "C" {
#endif
-extern char *strndup(const char *, size_t);
extern size_t stresc2chr(char *);
extern char *strchr2esc(const char *, size_t);
extern const char *strbasename(const char *);
diff --git a/lib/libdtrace/common/dt_subr.c b/lib/libdtrace/common/dt_subr.c
index 97221c84d6cc..f586504cfbcc 100644
--- a/lib/libdtrace/common/dt_subr.c
+++ b/lib/libdtrace/common/dt_subr.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -222,8 +221,7 @@ dtrace_str2attr(const char *str, dtrace_attribute_t *attr)
return (-1); /* invalid function arguments */
*attr = _dtrace_maxattr;
- p = alloca(strlen(str) + 1);
- (void) strcpy(p, str);
+ p = strdupa(str);
if ((p = dt_getstrattr(p, &q)) == NULL)
return (0);
diff --git a/lib/libdtrace/common/dtrace.h b/lib/libdtrace/common/dtrace.h
index 1c041207c0ae..87df1ca4402a 100644
--- a/lib/libdtrace/common/dtrace.h
+++ b/lib/libdtrace/common/dtrace.h
@@ -24,11 +24,13 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ */
+
#ifndef _DTRACE_H
#define _DTRACE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/dtrace.h>
#include <stdarg.h>
#include <stdio.h>
@@ -148,6 +150,7 @@ typedef struct dtrace_stmtdesc {
dtrace_actdesc_t *dtsd_action_last; /* last action in action list */
void *dtsd_aggdata; /* aggregation data */
void *dtsd_fmtdata; /* type-specific output data */
+ void *dtsd_strdata; /* type-specific string data */
void (*dtsd_callback)(); /* callback function for EPID */
void *dtsd_data; /* callback data pointer */
dtrace_attribute_t dtsd_descattr; /* probedesc attributes */
@@ -240,6 +243,18 @@ extern int dtrace_freopen(dtrace_hdl_t *, FILE *, void *,
const void *, size_t);
/*
+ * Type-specific output printing
+ *
+ * The print() action will associate a string data record that is actually the
+ * fully-qualified type name of the data traced by the DIFEXPR action. This is
+ * stored in the same 'format' record from the kernel, but we know by virtue of
+ * the fact that the action is still DIFEXPR that it is actually a reference to
+ * plain string data.
+ */
+extern int dtrace_print(dtrace_hdl_t *, FILE *, const char *,
+ caddr_t, size_t);
+
+/*
* DTrace Work Interface
*/
typedef enum {
diff --git a/lib/libdtrace/i386/regs.d.in b/lib/libdtrace/i386/regs.d.in
index 3328f33515b0..d18c5f7ff1fb 100644
--- a/lib/libdtrace/i386/regs.d.in
+++ b/lib/libdtrace/i386/regs.d.in
@@ -23,8 +23,9 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2011 Joyent, Inc. All rights reserved.
+ */
inline int R_GS = @GS@;
#pragma D binding "1.0" R_GS
@@ -115,3 +116,149 @@ inline int R_R14 = @REG_R14@;
inline int R_R15 = @REG_R15@;
#pragma D binding "1.0" R_R15
+enum vmregs_vmx {
+ VMX_VIRTUAL_PROCESSOR_ID = 0x00000000,
+ VMX_GUEST_ES_SELECTOR = 0x00000800,
+ VMX_GUEST_CS_SELECTOR = 0x00000802,
+ VMX_GUEST_SS_SELECTOR = 0x00000804,
+ VMX_GUEST_DS_SELECTOR = 0x00000806,
+ VMX_GUEST_FS_SELECTOR = 0x00000808,
+ VMX_GUEST_GS_SELECTOR = 0x0000080a,
+ VMX_GUEST_LDTR_SELECTOR = 0x0000080c,
+ VMX_GUEST_TR_SELECTOR = 0x0000080e,
+ VMX_HOST_ES_SELECTOR = 0x00000c00,
+ VMX_HOST_CS_SELECTOR = 0x00000c02,
+ VMX_HOST_SS_SELECTOR = 0x00000c04,
+ VMX_HOST_DS_SELECTOR = 0x00000c06,
+ VMX_HOST_FS_SELECTOR = 0x00000c08,
+ VMX_HOST_GS_SELECTOR = 0x00000c0a,
+ VMX_HOST_TR_SELECTOR = 0x00000c0c,
+ VMX_IO_BITMAP_A = 0x00002000,
+ VMX_IO_BITMAP_A_HIGH = 0x00002001,
+ VMX_IO_BITMAP_B = 0x00002002,
+ VMX_IO_BITMAP_B_HIGH = 0x00002003,
+ VMX_MSR_BITMAP = 0x00002004,
+ VMX_MSR_BITMAP_HIGH = 0x00002005,
+ VMX_VM_EXIT_MSR_STORE_ADDR = 0x00002006,
+ VMX_VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
+ VMX_VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
+ VMX_VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
+ VMX_VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
+ VMX_VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
+ VMX_TSC_OFFSET = 0x00002010,
+ VMX_TSC_OFFSET_HIGH = 0x00002011,
+ VMX_VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
+ VMX_VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
+ VMX_APIC_ACCESS_ADDR = 0x00002014,
+ VMX_APIC_ACCESS_ADDR_HIGH = 0x00002015,
+ VMX_EPT_POINTER = 0x0000201a,
+ VMX_EPT_POINTER_HIGH = 0x0000201b,
+ VMX_GUEST_PHYSICAL_ADDRESS = 0x00002400,
+ VMX_GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
+ VMX_VMCS_LINK_POINTER = 0x00002800,
+ VMX_VMCS_LINK_POINTER_HIGH = 0x00002801,
+ VMX_GUEST_IA32_DEBUGCTL = 0x00002802,
+ VMX_GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
+ VMX_GUEST_IA32_PAT = 0x00002804,
+ VMX_GUEST_IA32_PAT_HIGH = 0x00002805,
+ VMX_GUEST_PDPTR0 = 0x0000280a,
+ VMX_GUEST_PDPTR0_HIGH = 0x0000280b,
+ VMX_GUEST_PDPTR1 = 0x0000280c,
+ VMX_GUEST_PDPTR1_HIGH = 0x0000280d,
+ VMX_GUEST_PDPTR2 = 0x0000280e,
+ VMX_GUEST_PDPTR2_HIGH = 0x0000280f,
+ VMX_GUEST_PDPTR3 = 0x00002810,
+ VMX_GUEST_PDPTR3_HIGH = 0x00002811,
+ VMX_HOST_IA32_PAT = 0x00002c00,
+ VMX_HOST_IA32_PAT_HIGH = 0x00002c01,
+ VMX_PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
+ VMX_CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
+ VMX_EXCEPTION_BITMAP = 0x00004004,
+ VMX_PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
+ VMX_PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
+ VMX_CR3_TARGET_COUNT = 0x0000400a,
+ VMX_VM_EXIT_CONTROLS = 0x0000400c,
+ VMX_VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
+ VMX_VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
+ VMX_VM_ENTRY_CONTROLS = 0x00004012,
+ VMX_VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
+ VMX_VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
+ VMX_VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
+ VMX_VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
+ VMX_TPR_THRESHOLD = 0x0000401c,
+ VMX_SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
+ VMX_PLE_GAP = 0x00004020,
+ VMX_PLE_WINDOW = 0x00004022,
+ VMX_VM_INSTRUCTION_ERROR = 0x00004400,
+ VMX_VM_EXIT_REASON = 0x00004402,
+ VMX_VM_EXIT_INTR_INFO = 0x00004404,
+ VMX_VM_EXIT_INTR_ERROR_CODE = 0x00004406,
+ VMX_IDT_VECTORING_INFO_FIELD = 0x00004408,
+ VMX_IDT_VECTORING_ERROR_CODE = 0x0000440a,
+ VMX_VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
+ VMX_VMX_INSTRUCTION_INFO = 0x0000440e,
+ VMX_GUEST_ES_LIMIT = 0x00004800,
+ VMX_GUEST_CS_LIMIT = 0x00004802,
+ VMX_GUEST_SS_LIMIT = 0x00004804,
+ VMX_GUEST_DS_LIMIT = 0x00004806,
+ VMX_GUEST_FS_LIMIT = 0x00004808,
+ VMX_GUEST_GS_LIMIT = 0x0000480a,
+ VMX_GUEST_LDTR_LIMIT = 0x0000480c,
+ VMX_GUEST_TR_LIMIT = 0x0000480e,
+ VMX_GUEST_GDTR_LIMIT = 0x00004810,
+ VMX_GUEST_IDTR_LIMIT = 0x00004812,
+ VMX_GUEST_ES_AR_BYTES = 0x00004814,
+ VMX_GUEST_CS_AR_BYTES = 0x00004816,
+ VMX_GUEST_SS_AR_BYTES = 0x00004818,
+ VMX_GUEST_DS_AR_BYTES = 0x0000481a,
+ VMX_GUEST_FS_AR_BYTES = 0x0000481c,
+ VMX_GUEST_GS_AR_BYTES = 0x0000481e,
+ VMX_GUEST_LDTR_AR_BYTES = 0x00004820,
+ VMX_GUEST_TR_AR_BYTES = 0x00004822,
+ VMX_GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
+ VMX_GUEST_ACTIVITY_STATE = 0X00004826,
+ VMX_GUEST_SYSENTER_CS = 0x0000482A,
+ VMX_HOST_IA32_SYSENTER_CS = 0x00004c00,
+ VMX_CR0_GUEST_HOST_MASK = 0x00006000,
+ VMX_CR4_GUEST_HOST_MASK = 0x00006002,
+ VMX_CR0_READ_SHADOW = 0x00006004,
+ VMX_CR4_READ_SHADOW = 0x00006006,
+ VMX_CR3_TARGET_VALUE0 = 0x00006008,
+ VMX_CR3_TARGET_VALUE1 = 0x0000600a,
+ VMX_CR3_TARGET_VALUE2 = 0x0000600c,
+ VMX_CR3_TARGET_VALUE3 = 0x0000600e,
+ VMX_EXIT_QUALIFICATION = 0x00006400,
+ VMX_GUEST_LINEAR_ADDRESS = 0x0000640a,
+ VMX_GUEST_CR0 = 0x00006800,
+ VMX_GUEST_CR3 = 0x00006802,
+ VMX_GUEST_CR4 = 0x00006804,
+ VMX_GUEST_ES_BASE = 0x00006806,
+ VMX_GUEST_CS_BASE = 0x00006808,
+ VMX_GUEST_SS_BASE = 0x0000680a,
+ VMX_GUEST_DS_BASE = 0x0000680c,
+ VMX_GUEST_FS_BASE = 0x0000680e,
+ VMX_GUEST_GS_BASE = 0x00006810,
+ VMX_GUEST_LDTR_BASE = 0x00006812,
+ VMX_GUEST_TR_BASE = 0x00006814,
+ VMX_GUEST_GDTR_BASE = 0x00006816,
+ VMX_GUEST_IDTR_BASE = 0x00006818,
+ VMX_GUEST_DR7 = 0x0000681a,
+ VMX_GUEST_RSP = 0x0000681c,
+ VMX_GUEST_RIP = 0x0000681e,
+ VMX_GUEST_RFLAGS = 0x00006820,
+ VMX_GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
+ VMX_GUEST_SYSENTER_ESP = 0x00006824,
+ VMX_GUEST_SYSENTER_EIP = 0x00006826,
+ VMX_HOST_CR0 = 0x00006c00,
+ VMX_HOST_CR3 = 0x00006c02,
+ VMX_HOST_CR4 = 0x00006c04,
+ VMX_HOST_FS_BASE = 0x00006c06,
+ VMX_HOST_GS_BASE = 0x00006c08,
+ VMX_HOST_TR_BASE = 0x00006c0a,
+ VMX_HOST_GDTR_BASE = 0x00006c0c,
+ VMX_HOST_IDTR_BASE = 0x00006c0e,
+ VMX_HOST_IA32_SYSENTER_ESP = 0x00006c10,
+ VMX_HOST_IA32_SYSENTER_EIP = 0x00006c12,
+ VMX_HOST_RSP = 0x00006c14,
+ VMX_HOST_RIP = 0x00006c16
+};