diff options
| author | Martin Matuska <mm@FreeBSD.org> | 2012-06-30 07:46:38 +0000 |
|---|---|---|
| committer | Martin Matuska <mm@FreeBSD.org> | 2012-06-30 07:46:38 +0000 |
| commit | 4a37bb98c980176bf8002f7ccd8807092ff8f9cf (patch) | |
| tree | fb4e00bd775ffa753a3b8466008fa3dbca70d12d /lib | |
| parent | e0ea83ebb1a4b194c927cb114766e8781676380b (diff) | |
Notes
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libctf/common/ctf_lib.c | 6 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_aggregate.c | 89 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_cc.c | 302 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_consume.c | 186 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_decl.c | 14 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_dof.c | 14 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_errtags.h | 30 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_ident.c | 8 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_impl.h | 13 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_map.c | 172 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_open.c | 32 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_options.c | 27 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_parser.c | 31 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_pragma.c | 49 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_print.c | 648 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_printf.c | 12 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_program.c | 2 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_string.c | 17 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_string.h | 12 | ||||
| -rw-r--r-- | lib/libdtrace/common/dt_subr.c | 6 | ||||
| -rw-r--r-- | lib/libdtrace/common/dtrace.h | 19 | ||||
| -rw-r--r-- | lib/libdtrace/i386/regs.d.in | 151 |
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 +}; |
