summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/dtrace/dtrace.c13
-rw-r--r--usr/src/cmd/mdb/Makefile.common9
-rw-r--r--usr/src/cmd/mdb/Makefile.module9
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_rawfile.c31
-rw-r--r--usr/src/cmd/mdb/common/modules/dtrace/dof.c1092
-rw-r--r--usr/src/cmd/mdb/common/modules/dtrace/dtrace.c1053
-rw-r--r--usr/src/cmd/mdb/common/modules/dtrace/mkdof.sh52
-rw-r--r--usr/src/cmd/mdb/intel/amd64/dof/Makefile44
-rw-r--r--usr/src/cmd/mdb/intel/amd64/dtrace/Makefile22
-rw-r--r--usr/src/cmd/mdb/intel/ia32/dof/Makefile43
-rw-r--r--usr/src/cmd/mdb/intel/ia32/dtrace/Makefile22
-rw-r--r--usr/src/cmd/mdb/sparc/v7/dof/Makefile43
-rw-r--r--usr/src/cmd/mdb/sparc/v9/dof/Makefile44
-rw-r--r--usr/src/cmd/mdb/sparc/v9/dtrace/Makefile22
-rw-r--r--usr/src/lib/libdtrace/Makefile.com7
-rw-r--r--usr/src/lib/libdtrace/common/dt_as.c134
-rw-r--r--usr/src/lib/libdtrace/common/dt_as.h6
-rw-r--r--usr/src/lib/libdtrace/common/dt_cc.c87
-rw-r--r--usr/src/lib/libdtrace/common/dt_cg.c91
-rw-r--r--usr/src/lib/libdtrace/common/dt_dis.c87
-rw-r--r--usr/src/lib/libdtrace/common/dt_dof.c173
-rw-r--r--usr/src/lib/libdtrace/common/dt_dof.h5
-rw-r--r--usr/src/lib/libdtrace/common/dt_errtags.h1
-rw-r--r--usr/src/lib/libdtrace/common/dt_grammar.y4
-rw-r--r--usr/src/lib/libdtrace/common/dt_handle.c4
-rw-r--r--usr/src/lib/libdtrace/common/dt_ident.c25
-rw-r--r--usr/src/lib/libdtrace/common/dt_impl.h26
-rw-r--r--usr/src/lib/libdtrace/common/dt_lex.l1
-rw-r--r--usr/src/lib/libdtrace/common/dt_link.c62
-rw-r--r--usr/src/lib/libdtrace/common/dt_open.c8
-rw-r--r--usr/src/lib/libdtrace/common/dt_options.c20
-rw-r--r--usr/src/lib/libdtrace/common/dt_parser.c139
-rw-r--r--usr/src/lib/libdtrace/common/dt_parser.h11
-rw-r--r--usr/src/lib/libdtrace/common/dt_pcb.c18
-rw-r--r--usr/src/lib/libdtrace/common/dt_pcb.h5
-rw-r--r--usr/src/lib/libdtrace/common/dt_pid.c1
-rw-r--r--usr/src/lib/libdtrace/common/dt_proc.c10
-rw-r--r--usr/src/lib/libdtrace/common/dt_program.c75
-rw-r--r--usr/src/lib/libdtrace/common/dt_program.h62
-rw-r--r--usr/src/lib/libdtrace/common/dt_provider.c106
-rw-r--r--usr/src/lib/libdtrace/common/dt_provider.h7
-rw-r--r--usr/src/lib/libdtrace/common/dt_subr.c63
-rw-r--r--usr/src/lib/libdtrace/common/dt_xlator.c208
-rw-r--r--usr/src/lib/libdtrace/common/dt_xlator.h17
-rw-r--r--usr/src/lib/libdtrace/common/dtrace.h29
-rw-r--r--usr/src/lib/libdtrace/common/mknames.sh53
-rw-r--r--usr/src/lib/libdtrace/spec/dtrace.spec40
-rw-r--r--usr/src/lib/libproc/common/Pscantext.c4
-rw-r--r--usr/src/pkgdefs/SUNWdtrc/prototype_com2
-rw-r--r--usr/src/pkgdefs/SUNWdtrc/prototype_i3866
-rw-r--r--usr/src/pkgdefs/SUNWdtrc/prototype_sparc5
-rw-r--r--usr/src/pkgdefs/SUNWmdb/prototype_com1
-rw-r--r--usr/src/uts/common/sys/dtrace.h36
53 files changed, 2631 insertions, 1507 deletions
diff --git a/usr/src/cmd/dtrace/dtrace.c b/usr/src/cmd/dtrace/dtrace.c
index a88aa26273..b8cc044d87 100644
--- a/usr/src/cmd/dtrace/dtrace.c
+++ b/usr/src/cmd/dtrace/dtrace.c
@@ -1347,8 +1347,10 @@ main(int argc, char *argv[])
for (i = 0; i < g_cmdc; i++)
exec_prog(&g_cmdv[i]);
- if (done && !g_grabanon)
+ if (done && !g_grabanon) {
+ dtrace_close(g_dtp);
return (g_status);
+ }
break;
case DMODE_ANON:
@@ -1358,8 +1360,10 @@ main(int argc, char *argv[])
dof_prune(g_ofile); /* strip out any old DOF directives */
etcsystem_prune(); /* string out any forceload directives */
- if (g_cmdc == 0)
+ if (g_cmdc == 0) {
+ dtrace_close(g_dtp);
return (g_status);
+ }
if ((g_ofp = fopen(g_ofile, "a")) == NULL)
fatal("failed to open output file '%s'", g_ofile);
@@ -1388,6 +1392,7 @@ main(int argc, char *argv[])
etcsystem_add();
error("run update_drv(1M) or reboot to enable changes\n");
+ dtrace_close(g_dtp);
return (g_status);
case DMODE_LINK:
@@ -1402,9 +1407,10 @@ main(int argc, char *argv[])
if (dtrace_program_link(g_dtp, NULL, DTRACE_D_PROBES,
g_ofile, g_cmdc, objv) != 0)
- dfatal("failed to link %s", g_ofile);
+ dfatal(NULL); /* dtrace_errmsg() only */
}
+ dtrace_close(g_dtp);
return (g_status);
case DMODE_LIST:
@@ -1420,6 +1426,7 @@ main(int argc, char *argv[])
if (g_cmdc == 0)
(void) dtrace_probe_iter(g_dtp, NULL, list_probe, NULL);
+ dtrace_close(g_dtp);
return (g_status);
}
diff --git a/usr/src/cmd/mdb/Makefile.common b/usr/src/cmd/mdb/Makefile.common
index e0ec96f9f9..c28b9c84fb 100644
--- a/usr/src/cmd/mdb/Makefile.common
+++ b/usr/src/cmd/mdb/Makefile.common
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -29,13 +29,14 @@
# subdirectory will need to build.
#
COMMON_MODULES_PROC = \
- mdb_ds \
- mdb_test \
+ dof \
libc \
libnvpair \
libsysevent \
libumem \
- libuutil
+ libuutil \
+ mdb_ds \
+ mdb_test
#
# MDB modules used for debugging user processes which are only 32-bit
diff --git a/usr/src/cmd/mdb/Makefile.module b/usr/src/cmd/mdb/Makefile.module
index 64d7371505..ae107750e2 100644
--- a/usr/src/cmd/mdb/Makefile.module
+++ b/usr/src/cmd/mdb/Makefile.module
@@ -45,7 +45,7 @@ KMODFILE = kmod/$(KMODULE)
# The mess below is designed to pick the right set of objects to build and/or
# lint. We have three flavors:
#
-# 1. proc modules. Only $(MODOBJS) are built.
+# 1. proc and raw modules. Only $(MODOBJS) are built.
# 2. kvm modules for systems without kmdb. Only $(MODOBJS) are built.
# 3. kvm modules for systems with kmdb. $(MODOBJS) and $(KMODOBJS) are built.
#
@@ -71,6 +71,7 @@ TARGETS_disasm_mdb = $(MODFILE)
TARGETS_disasm_both = $(TARGETS_disasm_mdb) $(TARGETS_disasm_kmdb)
TARGETS_disasm = $(TARGETS_disasm_$(TARGETS_kvm_type))
TARGETS_proc = $(MODFILE)
+TARGETS_raw = $(MODFILE)
TARGETS = $(TARGETS_$(MDBTGT))
# Where should we install that which we've built?
@@ -84,6 +85,7 @@ ROOTTGTS_disasm_mdb = $(ROOTMOD)/$(MODULE)
ROOTTGTS_disasm_both = $(ROOTTGTS_disasm_mdb) $(ROOTTGTS_disasm_kmdb)
ROOTTGTS_disasm = $(ROOTTGTS_disasm_$(TARGETS_kvm_type))
ROOTTGTS_proc = $(ROOTMOD)/$(MODULE)
+ROOTTGTS_raw = $(ROOTMOD)/$(MODULE)
ROOTTGTS = $(ROOTTGTS_$(MDBTGT))
# What should we lint?
@@ -98,6 +100,7 @@ LINTFILES_disasm_both = $(KLINTOBJS) $(LINTOBJS)
LINTFILES_disasm_mdb = $(LINTOBJS)
LINTFILES_disasm = $(LINTFILES_disasm_$(TARGETS_kvm_type))
LINTFILES_proc = $(LINTOBJS)
+LINTFILES_raw = $(LINTOBJS)
LINTFILES = $(LINTFILES_$(MDBTGT))
kvm_TGTFLAGS = -D_KERNEL
@@ -146,10 +149,10 @@ clean.lint:
$(RM) $(LINTFILES)
clean:
- $(RM) $(MODOBJS) $(KMODOBJS)
+ $(RM) $(MODOBJS) $(KMODOBJS) $(CLEANFILES)
clobber: clean clean.lint
- $(RM) $(MODFILE) $(KMODFILE)
+ $(RM) $(MODFILE) $(KMODFILE) $(CLOBBERFILES)
lint: $$(LINTFILES)
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c b/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c
index 1bfc6030d0..db322cdf6f 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_rawfile.c
@@ -44,6 +44,7 @@
#include <mdb/mdb_err.h>
#include <mdb/mdb.h>
+#include <sys/dtrace.h>
#include <fcntl.h>
typedef struct rf_data {
@@ -297,10 +298,20 @@ static const mdb_dcmd_t rf_dcmds[] = {
{ NULL }
};
+static const struct rf_magic {
+ const char *rfm_str;
+ size_t rfm_len;
+ const char *rfm_mod;
+} rf_magic[] = {
+ { DOF_MAG_STRING, DOF_MAG_STRLEN, "dof" },
+ { NULL, 0, NULL }
+};
+
static void
rf_activate(mdb_tgt_t *t)
{
rf_data_t *rf = t->t_data;
+ const struct rf_magic *m;
mdb_var_t *v;
off64_t size;
@@ -308,14 +319,30 @@ rf_activate(mdb_tgt_t *t)
/*
* We set the legacy adb variable 'd' to be the size of the file (data
- * segment). To get this value, we call seek() on the underlying
- * fdio.
+ * segment). To get this value, we call seek() on the underlying fdio.
*/
if (rf->r_object_fio != NULL) {
size = IOP_SEEK(rf->r_object_fio, 0, SEEK_END);
if ((v = mdb_nv_lookup(&mdb.m_nv, "d")) != NULL)
mdb_nv_set_value(v, size);
}
+
+ /*
+ * Load any debugging support modules that match the file type, as
+ * determined by our poor man's /etc/magic. If many clients need
+ * to use this feature, rf_magic[] should be computed dynamically.
+ */
+ for (m = rf_magic; m->rfm_str != NULL; m++) {
+ char *buf = mdb_alloc(m->rfm_len, UM_SLEEP);
+
+ if (mdb_tgt_vread(t, buf, m->rfm_len, 0) == m->rfm_len &&
+ bcmp(buf, m->rfm_str, m->rfm_len) == 0) {
+ (void) mdb_module_load(m->rfm_mod,
+ MDB_MOD_LOCAL | MDB_MOD_SILENT);
+ }
+
+ mdb_free(buf, m->rfm_len);
+ }
}
static void
diff --git a/usr/src/cmd/mdb/common/modules/dtrace/dof.c b/usr/src/cmd/mdb/common/modules/dtrace/dof.c
new file mode 100644
index 0000000000..ee170a7b85
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/dtrace/dof.c
@@ -0,0 +1,1092 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <mdb/mdb_modapi.h>
+#include <dtrace.h>
+
+#ifdef _LP64
+#define DIFO_ADDRWIDTH 11
+#else
+#define DIFO_ADDRWIDTH 8
+#endif
+
+extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *);
+extern const char *dof_sec_name(uint32_t);
+
+extern const mdb_walker_t kernel_walkers[];
+extern const mdb_dcmd_t kernel_dcmds[];
+
+/*ARGSUSED*/
+static void
+dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name,
+ DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
+}
+
+/*ARGSUSED*/
+static void
+dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr));
+}
+
+/*ARGSUSED*/
+static void
+dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s [%%r%u], %%r%u", name,
+ DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
+}
+
+/*ARGSUSED*/
+static void
+dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s %%r%u, [%%r%u]", name,
+ DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
+}
+
+/*ARGSUSED*/
+static void
+dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%s", name);
+}
+
+/*ARGSUSED*/
+static void
+dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s %%r%u, %%r%u", name,
+ DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
+}
+
+/*ARGSUSED*/
+static void
+dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s %%r%u, %%r%u", name,
+ DIF_INSTR_R1(instr), DIF_INSTR_R2(instr));
+}
+
+/*ARGSUSED*/
+static void
+dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr));
+}
+
+static const char *
+dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope)
+{
+ dtrace_difv_t *dvp;
+ size_t varsize;
+ caddr_t addr = NULL, str;
+ uint_t i;
+
+ if (dp == NULL)
+ return (NULL);
+
+ varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
+ dvp = mdb_alloc(varsize, UM_SLEEP);
+
+ if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
+ mdb_free(dvp, varsize);
+ return ("<unreadable>");
+ }
+
+ for (i = 0; i < dp->dtdo_varlen; i++) {
+ if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) {
+ if (dvp[i].dtdv_name < dp->dtdo_strlen)
+ addr = dp->dtdo_strtab + dvp[i].dtdv_name;
+ break;
+ }
+ }
+
+ mdb_free(dvp, varsize);
+
+ if (addr == NULL)
+ return (NULL);
+
+ str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC);
+
+ for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) {
+ if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1)
+ return ("<unreadable>");
+ }
+
+ return (str);
+}
+
+static uint_t
+dis_scope(const char *name)
+{
+ switch (name[2]) {
+ case 'l': return (DIFV_SCOPE_LOCAL);
+ case 't': return (DIFV_SCOPE_THREAD);
+ case 'g': return (DIFV_SCOPE_GLOBAL);
+ default: return (-1u);
+ }
+}
+
+static void
+dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ uint_t var = DIF_INSTR_R1(instr);
+ const char *vname;
+
+ mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name,
+ var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
+
+ if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
+ mdb_printf("\t\t! %s", vname);
+}
+
+static void
+dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ uint_t var = DIF_INSTR_VAR(instr);
+ const char *vname;
+
+ mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr));
+
+ if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
+ mdb_printf("\t\t! %s", vname);
+}
+
+static void
+dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ uint_t var = DIF_INSTR_VAR(instr);
+ const char *vname;
+
+ mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var);
+
+ if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
+ mdb_printf("\t\t! %s", vname);
+}
+
+static void
+dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ uint_t intptr = DIF_INSTR_INTEGER(instr);
+
+ mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name,
+ intptr, DIF_INSTR_RD(instr));
+
+ if (dp != NULL && intptr < dp->dtdo_intlen) {
+ uint64_t *ip = mdb_alloc(dp->dtdo_intlen *
+ sizeof (uint64_t), UM_SLEEP | UM_GC);
+
+ if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t),
+ (uintptr_t)dp->dtdo_inttab) == -1)
+ mdb_warn("failed to read data at %p", dp->dtdo_inttab);
+ else
+ mdb_printf("\t\t! 0x%llx", ip[intptr]);
+ }
+}
+
+static void
+dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ uint_t strptr = DIF_INSTR_STRING(instr);
+
+ mdb_printf("%-4s DIF_STRING[%u], %%r%u", name,
+ strptr, DIF_INSTR_RD(instr));
+
+ if (dp != NULL && strptr < dp->dtdo_strlen) {
+ char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
+
+ if (mdb_vread(str, dp->dtdo_strlen,
+ (uintptr_t)dp->dtdo_strtab) == -1)
+ mdb_warn("failed to read data at %p", dp->dtdo_strtab);
+ else
+ mdb_printf("\t\t! \"%s\"", str + strptr);
+ }
+}
+
+/*ARGSUSED*/
+static void
+dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr));
+}
+
+/*ARGSUSED*/
+static void
+dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ uint_t subr = DIF_INSTR_SUBR(instr);
+
+ mdb_printf("%-4s DIF_SUBR(%u), %%r%u\t\t! %s",
+ name, subr, DIF_INSTR_RD(instr), dtrace_subrstr(NULL, subr));
+}
+
+/*ARGSUSED*/
+static void
+dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" };
+ uint_t type = DIF_INSTR_TYPE(instr);
+
+ mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u",
+ name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr));
+
+ if (type < sizeof (tnames) / sizeof (tnames[0]))
+ mdb_printf("\t! %s", tnames[type]);
+}
+
+/*ARGSUSED*/
+static void
+dis_xlate(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
+{
+ mdb_printf("%-4s DIF_XLREF[%u], %%r%u", name,
+ DIF_INSTR_XLREF(instr), DIF_INSTR_RD(instr));
+}
+
+static char *
+dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
+{
+ char kind[8];
+
+ switch (t->dtdt_kind) {
+ case DIF_TYPE_CTF:
+ (void) strcpy(kind, "D type");
+ break;
+ case DIF_TYPE_STRING:
+ (void) strcpy(kind, "string");
+ break;
+ default:
+ (void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind);
+ }
+
+ if (t->dtdt_flags & DIF_TF_BYREF) {
+ (void) mdb_snprintf(buf, len,
+ "%s by ref (size %lu)",
+ kind, (ulong_t)t->dtdt_size);
+ } else {
+ (void) mdb_snprintf(buf, len, "%s (size %lu)",
+ kind, (ulong_t)t->dtdt_size);
+ }
+
+ return (buf);
+}
+
+static int
+dis(uintptr_t addr, dtrace_difo_t *dp)
+{
+ static const struct opent {
+ const char *op_name;
+ void (*op_func)(const dtrace_difo_t *,
+ const char *, dif_instr_t);
+ } optab[] = {
+ { "(illegal opcode)", dis_str },
+ { "or", dis_log }, /* DIF_OP_OR */
+ { "xor", dis_log }, /* DIF_OP_XOR */
+ { "and", dis_log }, /* DIF_OP_AND */
+ { "sll", dis_log }, /* DIF_OP_SLL */
+ { "srl", dis_log }, /* DIF_OP_SRL */
+ { "sub", dis_log }, /* DIF_OP_SUB */
+ { "add", dis_log }, /* DIF_OP_ADD */
+ { "mul", dis_log }, /* DIF_OP_MUL */
+ { "sdiv", dis_log }, /* DIF_OP_SDIV */
+ { "udiv", dis_log }, /* DIF_OP_UDIV */
+ { "srem", dis_log }, /* DIF_OP_SREM */
+ { "urem", dis_log }, /* DIF_OP_UREM */
+ { "not", dis_r1rd }, /* DIF_OP_NOT */
+ { "mov", dis_r1rd }, /* DIF_OP_MOV */
+ { "cmp", dis_cmp }, /* DIF_OP_CMP */
+ { "tst", dis_tst }, /* DIF_OP_TST */
+ { "ba", dis_branch }, /* DIF_OP_BA */
+ { "be", dis_branch }, /* DIF_OP_BE */
+ { "bne", dis_branch }, /* DIF_OP_BNE */
+ { "bg", dis_branch }, /* DIF_OP_BG */
+ { "bgu", dis_branch }, /* DIF_OP_BGU */
+ { "bge", dis_branch }, /* DIF_OP_BGE */
+ { "bgeu", dis_branch }, /* DIF_OP_BGEU */
+ { "bl", dis_branch }, /* DIF_OP_BL */
+ { "blu", dis_branch }, /* DIF_OP_BLU */
+ { "ble", dis_branch }, /* DIF_OP_BLE */
+ { "bleu", dis_branch }, /* DIF_OP_BLEU */
+ { "ldsb", dis_load }, /* DIF_OP_LDSB */
+ { "ldsh", dis_load }, /* DIF_OP_LDSH */
+ { "ldsw", dis_load }, /* DIF_OP_LDSW */
+ { "ldub", dis_load }, /* DIF_OP_LDUB */
+ { "lduh", dis_load }, /* DIF_OP_LDUH */
+ { "lduw", dis_load }, /* DIF_OP_LDUW */
+ { "ldx", dis_load }, /* DIF_OP_LDX */
+ { "ret", dis_ret }, /* DIF_OP_RET */
+ { "nop", dis_str }, /* DIF_OP_NOP */
+ { "setx", dis_setx }, /* DIF_OP_SETX */
+ { "sets", dis_sets }, /* DIF_OP_SETS */
+ { "scmp", dis_cmp }, /* DIF_OP_SCMP */
+ { "ldga", dis_lda }, /* DIF_OP_LDGA */
+ { "ldgs", dis_ldv }, /* DIF_OP_LDGS */
+ { "stgs", dis_stv }, /* DIF_OP_STGS */
+ { "ldta", dis_lda }, /* DIF_OP_LDTA */
+ { "ldts", dis_ldv }, /* DIF_OP_LDTS */
+ { "stts", dis_stv }, /* DIF_OP_STTS */
+ { "sra", dis_log }, /* DIF_OP_SRA */
+ { "call", dis_call }, /* DIF_OP_CALL */
+ { "pushtr", dis_pushts }, /* DIF_OP_PUSHTR */
+ { "pushtv", dis_pushts }, /* DIF_OP_PUSHTV */
+ { "popts", dis_str }, /* DIF_OP_POPTS */
+ { "flushts", dis_str }, /* DIF_OP_FLUSHTS */
+ { "ldgaa", dis_ldv }, /* DIF_OP_LDGAA */
+ { "ldtaa", dis_ldv }, /* DIF_OP_LDTAA */
+ { "stgaa", dis_stv }, /* DIF_OP_STGAA */
+ { "sttaa", dis_stv }, /* DIF_OP_STTAA */
+ { "ldls", dis_ldv }, /* DIF_OP_LDLS */
+ { "stls", dis_stv }, /* DIF_OP_STLS */
+ { "allocs", dis_r1rd }, /* DIF_OP_ALLOCS */
+ { "copys", dis_log }, /* DIF_OP_COPYS */
+ { "stb", dis_store }, /* DIF_OP_STB */
+ { "sth", dis_store }, /* DIF_OP_STH */
+ { "stw", dis_store }, /* DIF_OP_STW */
+ { "stx", dis_store }, /* DIF_OP_STX */
+ { "uldsb", dis_load }, /* DIF_OP_ULDSB */
+ { "uldsh", dis_load }, /* DIF_OP_ULDSH */
+ { "uldsw", dis_load }, /* DIF_OP_ULDSW */
+ { "uldub", dis_load }, /* DIF_OP_ULDUB */
+ { "ulduh", dis_load }, /* DIF_OP_ULDUH */
+ { "ulduw", dis_load }, /* DIF_OP_ULDUW */
+ { "uldx", dis_load }, /* DIF_OP_ULDX */
+ { "rldsb", dis_load }, /* DIF_OP_RLDSB */
+ { "rldsh", dis_load }, /* DIF_OP_RLDSH */
+ { "rldsw", dis_load }, /* DIF_OP_RLDSW */
+ { "rldub", dis_load }, /* DIF_OP_RLDUB */
+ { "rlduh", dis_load }, /* DIF_OP_RLDUH */
+ { "rlduw", dis_load }, /* DIF_OP_RLDUW */
+ { "rldx", dis_load }, /* DIF_OP_RLDX */
+ { "xlate", dis_xlate }, /* DIF_OP_XLATE */
+ { "xlarg", dis_xlate }, /* DIF_OP_XLARG */
+ };
+
+ dif_instr_t instr, opcode;
+ const struct opent *op;
+
+ if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) {
+ mdb_warn("failed to read DIF instruction at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ opcode = DIF_INSTR_OP(instr);
+
+ if (opcode >= sizeof (optab) / sizeof (optab[0]))
+ opcode = 0; /* force invalid opcode message */
+
+ op = &optab[opcode];
+ mdb_printf("%0*p %08x ", DIFO_ADDRWIDTH, addr, instr);
+ op->op_func(dp, op->op_name, instr);
+ mdb_printf("\n");
+ mdb_set_dot(addr + sizeof (dif_instr_t));
+
+ return (DCMD_OK);
+}
+
+/*ARGSUSED*/
+int
+difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dtrace_difo_t difo, *dp = &difo;
+ uintptr_t instr, limit;
+ dtrace_difv_t *dvp;
+ size_t varsize;
+ ulong_t i;
+ char type[64];
+ char *str;
+
+ if (!(flags & DCMD_ADDRSPEC))
+ return (DCMD_USAGE);
+
+ if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) {
+ mdb_warn("couldn't read dtrace_difo_t at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n",
+ addr, dp->dtdo_refcnt);
+ mdb_printf("%<b>%-*s %-8s %s%</b>\n", DIFO_ADDRWIDTH, "ADDR",
+ "OPCODE", "INSTRUCTION");
+
+ mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf);
+ limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t);
+
+ while ((instr = mdb_get_dot()) < limit)
+ dis(instr, dp);
+
+ if (dp->dtdo_varlen != 0) {
+ mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n",
+ "NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
+ }
+
+ varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
+ dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC);
+
+ if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
+ mdb_warn("couldn't read dtdo_vartab");
+ return (DCMD_ERR);
+ }
+
+ str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
+
+ if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) {
+ mdb_warn("couldn't read dtdo_strtab");
+ return (DCMD_ERR);
+ }
+
+ for (i = 0; i < dp->dtdo_varlen; i++) {
+ dtrace_difv_t *v = &dvp[i];
+ char kind[4], scope[4], flags[16] = { 0 };
+
+ switch (v->dtdv_kind) {
+ case DIFV_KIND_ARRAY:
+ (void) strcpy(kind, "arr");
+ break;
+ case DIFV_KIND_SCALAR:
+ (void) strcpy(kind, "scl");
+ break;
+ default:
+ (void) mdb_snprintf(kind, sizeof (kind),
+ "%u", v->dtdv_kind);
+ }
+
+ switch (v->dtdv_scope) {
+ case DIFV_SCOPE_GLOBAL:
+ (void) strcpy(scope, "glb");
+ break;
+ case DIFV_SCOPE_THREAD:
+ (void) strcpy(scope, "tls");
+ break;
+ case DIFV_SCOPE_LOCAL:
+ (void) strcpy(scope, "loc");
+ break;
+ default:
+ (void) mdb_snprintf(scope, sizeof (scope),
+ "%u", v->dtdv_scope);
+ }
+
+ if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) {
+ (void) mdb_snprintf(flags, sizeof (flags), "/0x%x",
+ v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD));
+ }
+
+ if (v->dtdv_flags & DIFV_F_REF)
+ (void) strcat(flags, "/r");
+ if (v->dtdv_flags & DIFV_F_MOD)
+ (void) strcat(flags, "/w");
+
+ mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n",
+ &str[v->dtdv_name],
+ v->dtdv_id, kind, scope, flags + 1,
+ dis_typestr(&v->dtdv_type, type, sizeof (type)));
+ }
+
+ mdb_printf("\n%<b>RETURN%</b>\n%s\n\n",
+ dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
+
+ return (DCMD_OK);
+}
+
+/*ARGSUSED*/
+int
+difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ if (!(flags & DCMD_ADDRSPEC))
+ return (DCMD_USAGE);
+
+ return (dis(addr, NULL));
+}
+
+/*ARGSUSED*/
+int
+dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dof_hdr_t h;
+
+ if (argc != 0)
+ return (DCMD_USAGE);
+
+ if (!(flags & DCMD_ADDRSPEC))
+ addr = 0; /* assume base of file in file target */
+
+ if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) {
+ mdb_warn("failed to read header at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n",
+ h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1],
+ h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]);
+
+ switch (h.dofh_ident[DOF_ID_MODEL]) {
+ case DOF_MODEL_ILP32:
+ mdb_printf("dofh_ident.id_model = ILP32\n");
+ break;
+ case DOF_MODEL_LP64:
+ mdb_printf("dofh_ident.id_model = LP64\n");
+ break;
+ default:
+ mdb_printf("dofh_ident.id_model = 0x%x\n",
+ h.dofh_ident[DOF_ID_MODEL]);
+ }
+
+ switch (h.dofh_ident[DOF_ID_ENCODING]) {
+ case DOF_ENCODE_LSB:
+ mdb_printf("dofh_ident.id_encoding = LSB\n");
+ break;
+ case DOF_ENCODE_MSB:
+ mdb_printf("dofh_ident.id_encoding = MSB\n");
+ break;
+ default:
+ mdb_printf("dofh_ident.id_encoding = 0x%x\n",
+ h.dofh_ident[DOF_ID_ENCODING]);
+ }
+
+ mdb_printf("dofh_ident.id_version = %u\n",
+ h.dofh_ident[DOF_ID_VERSION]);
+ mdb_printf("dofh_ident.id_difvers = %u\n",
+ h.dofh_ident[DOF_ID_DIFVERS]);
+ mdb_printf("dofh_ident.id_difireg = %u\n",
+ h.dofh_ident[DOF_ID_DIFIREG]);
+ mdb_printf("dofh_ident.id_diftreg = %u\n",
+ h.dofh_ident[DOF_ID_DIFTREG]);
+
+ mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags);
+ mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize);
+ mdb_printf("dofh_secsize = %u\n", h.dofh_secsize);
+ mdb_printf("dofh_secnum = %u\n", h.dofh_secnum);
+ mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff);
+ mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz);
+ mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz);
+
+ return (DCMD_OK);
+}
+
+/*ARGSUSED*/
+static int
+dof_sec_walk(uintptr_t addr, void *ignored, int *sec)
+{
+ mdb_printf("%3d ", (*sec)++);
+ (void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL);
+ return (WALK_NEXT);
+}
+
+/*ARGSUSED*/
+int
+dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ const char *name;
+ dof_sec_t s;
+
+ if (!(flags & DCMD_ADDRSPEC))
+ mdb_printf("%<u>%-3s ", "NDX");
+
+ if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) {
+ mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n",
+ "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET",
+ "SIZE");
+ }
+
+ if (!(flags & DCMD_ADDRSPEC)) {
+ int sec = 0;
+
+ if (mdb_walk("dof_sec",
+ (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) {
+ mdb_warn("failed to walk dof_sec");
+ return (DCMD_ERR);
+ }
+ return (DCMD_OK);
+ }
+
+ if (argc != 0)
+ return (DCMD_USAGE);
+
+ if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
+ mdb_warn("failed to read section header at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("%?p ", addr);
+
+ if ((name = dof_sec_name(s.dofs_type)) != NULL)
+ mdb_printf("%-10s ", name);
+ else
+ mdb_printf("%-10u ", s.dofs_type);
+
+ mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align,
+ s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size);
+
+ return (DCMD_OK);
+}
+
+int
+dof_sec_walk_init(mdb_walk_state_t *wsp)
+{
+ dof_hdr_t h, *hp;
+ size_t size;
+
+ if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) {
+ mdb_warn("failed to read DOF header at %p", wsp->walk_addr);
+ return (WALK_ERR);
+ }
+
+ size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum;
+ hp = mdb_alloc(size, UM_SLEEP);
+
+ if (mdb_vread(hp, size, wsp->walk_addr) != size) {
+ mdb_warn("failed to read DOF sections at %p", wsp->walk_addr);
+ mdb_free(hp, size);
+ return (WALK_ERR);
+ }
+
+ wsp->walk_arg = (void *)0;
+ wsp->walk_data = hp;
+
+ return (WALK_NEXT);
+}
+
+int
+dof_sec_walk_step(mdb_walk_state_t *wsp)
+{
+ uint_t i = (uintptr_t)wsp->walk_arg;
+ size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i;
+ dof_hdr_t *hp = wsp->walk_data;
+ dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off);
+
+ if (i >= hp->dofh_secnum)
+ return (WALK_DONE);
+
+ wsp->walk_arg = (void *)(uintptr_t)(i + 1);
+ return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata));
+}
+
+void
+dof_sec_walk_fini(mdb_walk_state_t *wsp)
+{
+ dof_hdr_t *hp = wsp->walk_data;
+ mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum);
+}
+
+/*ARGSUSED*/
+int
+dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dof_ecbdesc_t e;
+
+ if (argc != 0 || !(flags & DCMD_ADDRSPEC))
+ return (DCMD_USAGE);
+
+ if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) {
+ mdb_warn("failed to read ecbdesc at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("dofe_probes = %d\n", e.dofe_probes);
+ mdb_printf("dofe_actions = %d\n", e.dofe_actions);
+ mdb_printf("dofe_pred = %d\n", e.dofe_pred);
+ mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg);
+
+ return (DCMD_OK);
+}
+
+/*ARGSUSED*/
+int
+dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dof_probedesc_t p;
+
+ if (argc != 0 || !(flags & DCMD_ADDRSPEC))
+ return (DCMD_USAGE);
+
+ if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) {
+ mdb_warn("failed to read probedesc at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("dofp_strtab = %d\n", p.dofp_strtab);
+ mdb_printf("dofp_provider = %u\n", p.dofp_provider);
+ mdb_printf("dofp_mod = %u\n", p.dofp_mod);
+ mdb_printf("dofp_func = %u\n", p.dofp_func);
+ mdb_printf("dofp_name = %u\n", p.dofp_name);
+ mdb_printf("dofp_id = %u\n", p.dofp_id);
+
+ return (DCMD_OK);
+}
+
+/*ARGSUSED*/
+int
+dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dof_actdesc_t a;
+
+ if (argc != 0 || !(flags & DCMD_ADDRSPEC))
+ return (DCMD_USAGE);
+
+ if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) {
+ mdb_warn("failed to read actdesc at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("dofa_difo = %d\n", a.dofa_difo);
+ mdb_printf("dofa_strtab = %d\n", a.dofa_strtab);
+ mdb_printf("dofa_kind = %u\n", a.dofa_kind);
+ mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple);
+ mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg);
+ mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg);
+
+ return (DCMD_OK);
+}
+
+/*ARGSUSED*/
+int
+dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dof_relohdr_t r;
+
+ if (argc != 0 || !(flags & DCMD_ADDRSPEC))
+ return (DCMD_USAGE);
+
+ if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
+ mdb_warn("failed to read relohdr at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("dofr_strtab = %d\n", r.dofr_strtab);
+ mdb_printf("dofr_relsec = %d\n", r.dofr_relsec);
+ mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec);
+
+ return (DCMD_OK);
+}
+
+/*ARGSUSED*/
+int
+dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dof_relodesc_t r;
+
+ if (argc != 0 || !(flags & DCMD_ADDRSPEC))
+ return (DCMD_USAGE);
+
+ if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
+ mdb_warn("failed to read relodesc at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("dofr_name = %u\n", r.dofr_name);
+ mdb_printf("dofr_type = %u\n", r.dofr_type);
+ mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset);
+ mdb_printf("dofr_data = 0x%llx\n", r.dofr_data);
+
+ return (DCMD_OK);
+}
+
+static int
+dof_sect_strtab(uintptr_t addr, dof_sec_t *sec)
+{
+ char *strtab;
+ size_t sz, i;
+
+ sz = (size_t)sec->dofs_size;
+ strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
+ if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) {
+ mdb_warn("failed to read string table");
+ return (1);
+ }
+
+ mdb_printf("size = %lx\n", sz);
+
+ for (i = 0; i < sz; i++) {
+ if (strtab[i] == '\0')
+ mdb_printf("\\0");
+ else
+ mdb_printf("%c", strtab[i]);
+ }
+
+ mdb_printf("\n");
+
+ return (0);
+}
+
+static int
+dof_sect_provider(uintptr_t addr, dof_sec_t *sec, dof_sec_t *dofs)
+{
+ dof_provider_t pv;
+ dof_probe_t *pb;
+ char *strtab;
+ uint32_t *offs;
+ uint8_t *args = NULL;
+ size_t sz;
+ int i, j;
+ dof_stridx_t narg, xarg;
+
+ if (mdb_vread(&pv, sizeof (dof_provider_t),
+ addr + sec->dofs_offset) != sizeof (dof_provider_t)) {
+ mdb_warn("failed to read DOF provider");
+ return (-1);
+ }
+
+ sz = dofs[pv.dofpv_strtab].dofs_size;
+ strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
+ if (mdb_vread(strtab, sz, addr +
+ dofs[pv.dofpv_strtab].dofs_offset) != sz) {
+ mdb_warn("failed to read string table");
+ return (-1);
+ }
+
+ mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset),
+ strtab + pv.dofpv_name);
+
+ sz = dofs[pv.dofpv_prargs].dofs_size;
+ if (sz != 0) {
+ args = mdb_alloc(sz, UM_SLEEP | UM_GC);
+ if (mdb_vread(args, sz, addr +
+ dofs[pv.dofpv_prargs].dofs_offset) != sz) {
+ mdb_warn("failed to read args");
+ return (-1);
+ }
+ }
+
+ sz = dofs[pv.dofpv_proffs].dofs_size;
+ offs = mdb_alloc(sz, UM_SLEEP | UM_GC);
+ if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset)
+ != sz) {
+ mdb_warn("failed to read offs");
+ return (-1);
+ }
+
+ sz = dofs[pv.dofpv_probes].dofs_size;
+ pb = mdb_alloc(sz, UM_SLEEP | UM_GC);
+ if (mdb_vread(pb, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) {
+ mdb_warn("failed to read probes");
+ return (-1);
+ }
+
+ (void) mdb_inc_indent(2);
+
+ for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) {
+ mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr +
+ dofs[pv.dofpv_probes].dofs_offset +
+ i * dofs[pv.dofpv_probes].dofs_entsize),
+ strtab + pb[i].dofpr_func,
+ strtab + pb[i].dofpr_name);
+
+ (void) mdb_inc_indent(2);
+ mdb_printf("addr: %p\n", (ulong_t)pb[i].dofpr_addr);
+ mdb_printf("offs: ");
+ for (j = 0; j < pb[i].dofpr_noffs; j++) {
+ mdb_printf("%s %x", "," + (j == 0),
+ offs[pb[i].dofpr_offidx + j]);
+ }
+ mdb_printf("\n");
+
+ mdb_printf("nargs:");
+ narg = pb[i].dofpr_nargv;
+ for (j = 0; j < pb[i].dofpr_nargc; j++) {
+ mdb_printf("%s %s", "," + (j == 0), strtab + narg);
+ narg += strlen(strtab + narg) + 1;
+ }
+ mdb_printf("\n");
+ mdb_printf("xargs:");
+ xarg = pb[i].dofpr_xargv;
+ for (j = 0; j < pb[i].dofpr_xargc; j++) {
+ mdb_printf("%s %s", "," + (j == 0), strtab + xarg);
+ xarg += strlen(strtab + xarg) + 1;
+ }
+ mdb_printf("\n");
+ mdb_printf("map: ");
+ for (j = 0; j < pb[i].dofpr_xargc; j++) {
+ mdb_printf("%s %d->%d", "," + (j == 0),
+ args[pb[i].dofpr_argidx + j], j);
+ }
+
+ (void) mdb_dec_indent(2);
+ mdb_printf("\n}\n");
+ }
+
+ (void) mdb_dec_indent(2);
+ mdb_printf("}\n");
+
+ return (0);
+}
+
+static int
+dof_sect_prargs(uintptr_t addr, dof_sec_t *sec)
+{
+ int i;
+ uint8_t arg;
+
+ for (i = 0; i < sec->dofs_size; i++) {
+ if (mdb_vread(&arg, sizeof (arg),
+ addr + sec->dofs_offset + i) != sizeof (arg)) {
+ mdb_warn("failed to read argument");
+ return (1);
+ }
+
+ mdb_printf("%d ", arg);
+
+ if (i % 20 == 19)
+ mdb_printf("\n");
+ }
+
+ mdb_printf("\n");
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ dof_hdr_t dofh;
+ dof_sec_t *dofs;
+ const char *name;
+ int i;
+
+ if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) {
+ mdb_warn("failed to read DOF header");
+ return (DCMD_ERR);
+ }
+
+ dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum,
+ UM_SLEEP | UM_GC);
+
+ for (i = 0; i < dofh.dofh_secnum; i++) {
+ if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff +
+ addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) {
+ mdb_warn("failed to read DOF sections");
+ return (DCMD_ERR);
+ }
+ }
+
+ for (i = 0; i < dofh.dofh_secnum; i++) {
+ mdb_printf("%lx Section %d: ", (ulong_t)
+ (dofh.dofh_secoff + addr + i * dofh.dofh_secsize), i);
+
+ if ((name = dof_sec_name(dofs[i].dofs_type)) != NULL)
+ mdb_printf("%s\n", name);
+ else
+ mdb_printf("%u\n", dofs[i].dofs_type);
+
+ (void) mdb_inc_indent(2);
+ switch (dofs[i].dofs_type) {
+ case DOF_SECT_PROVIDER:
+ (void) dof_sect_provider(addr, &dofs[i], dofs);
+ break;
+ case DOF_SECT_STRTAB:
+ (void) dof_sect_strtab(addr, &dofs[i]);
+ break;
+ case DOF_SECT_PRARGS:
+ (void) dof_sect_prargs(addr, &dofs[i]);
+ break;
+ }
+ (void) mdb_dec_indent(2);
+
+ mdb_printf("\n");
+ }
+
+ return (DCMD_OK);
+}
+
+static const mdb_dcmd_t common_dcmds[] = {
+ { "difinstr", ":", "disassemble a DIF instruction", difinstr },
+ { "difo", ":", "print a DIF object", difo },
+ { "dof_hdr", "?", "print a DOF header", dof_hdr },
+ { "dof_sec", ":", "print a DOF section header", dof_sec },
+ { "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc },
+ { "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc },
+ { "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc },
+ { "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr },
+ { "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc },
+ { "dofdump", ":", "dump DOF", dofdump },
+ { NULL }
+};
+
+static const mdb_walker_t common_walkers[] = {
+ { "dof_sec", "walk DOF section header table given header address",
+ dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini },
+ { NULL }
+};
+
+static mdb_modinfo_t modinfo = {
+ MDB_API_VERSION, NULL, NULL
+};
+
+const mdb_modinfo_t *
+_mdb_init(void)
+{
+ uint_t d = 0, kd = 0, w = 0, kw = 0;
+ const mdb_walker_t *wp;
+ const mdb_dcmd_t *dp;
+
+ for (dp = common_dcmds; dp->dc_name != NULL; dp++)
+ d++; /* count common dcmds */
+
+ for (wp = common_walkers; wp->walk_name != NULL; wp++)
+ w++; /* count common walkers */
+
+#ifdef _KERNEL
+ for (dp = kernel_dcmds; dp->dc_name != NULL; dp++)
+ kd++; /* count kernel dcmds */
+
+ for (wp = kernel_walkers; wp->walk_name != NULL; wp++)
+ kw++; /* count common walkers */
+#endif
+
+ modinfo.mi_dcmds = mdb_zalloc(sizeof (*dp) * (d + kd + 1), UM_SLEEP);
+ modinfo.mi_walkers = mdb_zalloc(sizeof (*wp) * (w + kw + 1), UM_SLEEP);
+
+ bcopy(common_dcmds, (void *)modinfo.mi_dcmds, sizeof (*dp) * d);
+ bcopy(common_walkers, (void *)modinfo.mi_walkers, sizeof (*wp) * w);
+
+#ifdef _KERNEL
+ bcopy(kernel_dcmds, (void *)
+ (modinfo.mi_dcmds + d), sizeof (*dp) * kd);
+ bcopy(kernel_walkers, (void *)
+ (modinfo.mi_walkers + w), sizeof (*wp) * kw);
+#endif
+ return (&modinfo);
+}
+
+void
+_mdb_fini(void)
+{
+ const mdb_walker_t *wp;
+ const mdb_dcmd_t *dp;
+ uint_t d = 0, w = 0;
+
+ for (dp = modinfo.mi_dcmds; dp->dc_name != NULL; dp++)
+ d++;
+
+ for (wp = modinfo.mi_walkers; wp->walk_name != NULL; wp++)
+ w++;
+
+ mdb_free((void *)modinfo.mi_dcmds, sizeof (*dp) * (d + 1));
+ mdb_free((void *)modinfo.mi_walkers, sizeof (*wp) * (w + 1));
+}
diff --git a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c
index ba69f040c1..8d919c33e6 100644
--- a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c
+++ b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c
@@ -47,535 +47,6 @@
#include <errno.h>
#include <math.h>
-#ifdef _LP64
-#define DIFO_ADDRWIDTH 11
-#else
-#define DIFO_ADDRWIDTH 8
-#endif
-
-int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *);
-
-/*ARGSUSED*/
-static void
-dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name,
- DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
-}
-
-/*ARGSUSED*/
-static void
-dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr));
-}
-
-/*ARGSUSED*/
-static void
-dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s [%%r%u], %%r%u", name,
- DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
-}
-
-/*ARGSUSED*/
-static void
-dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s %%r%u, [%%r%u]", name,
- DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
-}
-
-/*ARGSUSED*/
-static void
-dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%s", name);
-}
-
-/*ARGSUSED*/
-static void
-dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s %%r%u, %%r%u", name,
- DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
-}
-
-/*ARGSUSED*/
-static void
-dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s %%r%u, %%r%u", name,
- DIF_INSTR_R1(instr), DIF_INSTR_R2(instr));
-}
-
-/*ARGSUSED*/
-static void
-dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr));
-}
-
-static const char *
-dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope)
-{
- dtrace_difv_t *dvp;
- size_t varsize;
- caddr_t addr = NULL, str;
- uint_t i;
-
- if (dp == NULL)
- return (NULL);
-
- varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
- dvp = mdb_alloc(varsize, UM_SLEEP);
-
- if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
- mdb_free(dvp, varsize);
- return ("<unreadable>");
- }
-
- for (i = 0; i < dp->dtdo_varlen; i++) {
- if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) {
- if (dvp[i].dtdv_name < dp->dtdo_strlen)
- addr = dp->dtdo_strtab + dvp[i].dtdv_name;
- break;
- }
- }
-
- mdb_free(dvp, varsize);
-
- if (addr == NULL)
- return (NULL);
-
- str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC);
-
- for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) {
- if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1)
- return ("<unreadable>");
- }
-
- return (str);
-}
-
-static uint_t
-dis_scope(const char *name)
-{
- switch (name[2]) {
- case 'l': return (DIFV_SCOPE_LOCAL);
- case 't': return (DIFV_SCOPE_THREAD);
- case 'g': return (DIFV_SCOPE_GLOBAL);
- default: return (-1u);
- }
-}
-
-static void
-dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- uint_t var = DIF_INSTR_R1(instr);
- const char *vname;
-
- mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name,
- var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
-
- if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
- mdb_printf("\t\t! %s", vname);
-}
-
-static void
-dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- uint_t var = DIF_INSTR_VAR(instr);
- const char *vname;
-
- mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr));
-
- if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
- mdb_printf("\t\t! %s", vname);
-}
-
-static void
-dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- uint_t var = DIF_INSTR_VAR(instr);
- const char *vname;
-
- mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var);
-
- if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
- mdb_printf("\t\t! %s", vname);
-}
-
-static void
-dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- uint_t intptr = DIF_INSTR_INTEGER(instr);
-
- mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name,
- intptr, DIF_INSTR_RD(instr));
-
- if (dp != NULL && intptr < dp->dtdo_intlen) {
- uint64_t *ip = mdb_alloc(dp->dtdo_intlen *
- sizeof (uint64_t), UM_SLEEP | UM_GC);
-
- if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t),
- (uintptr_t)dp->dtdo_inttab) == -1)
- mdb_warn("failed to read data at %p", dp->dtdo_inttab);
- else
- mdb_printf("\t\t! 0x%llx", ip[intptr]);
- }
-}
-
-static void
-dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- uint_t strptr = DIF_INSTR_STRING(instr);
-
- mdb_printf("%-4s DIF_STRING[%u], %%r%u", name,
- strptr, DIF_INSTR_RD(instr));
-
- if (dp != NULL && strptr < dp->dtdo_strlen) {
- char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
-
- if (mdb_vread(str, dp->dtdo_strlen,
- (uintptr_t)dp->dtdo_strtab) == -1)
- mdb_warn("failed to read data at %p", dp->dtdo_strtab);
- else
- mdb_printf("\t\t! \"%s\"", str + strptr);
- }
-}
-
-/*ARGSUSED*/
-static void
-dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr));
-}
-
-/*ARGSUSED*/
-static void
-dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- static struct {
- const char *name;
- int subr;
- } snames[] = {
- { "rand", DIF_SUBR_RAND },
- { "mutex_owned", DIF_SUBR_MUTEX_OWNED },
- { "mutex_owner", DIF_SUBR_MUTEX_OWNER },
- { "mutex_type_adaptive", DIF_SUBR_MUTEX_TYPE_ADAPTIVE },
- { "mutex_type_spin", DIF_SUBR_MUTEX_TYPE_SPIN },
- { "rw_read_held", DIF_SUBR_RW_READ_HELD },
- { "rw_write_held", DIF_SUBR_RW_WRITE_HELD },
- { "rw_iswriter", DIF_SUBR_RW_ISWRITER },
- { "copyin", DIF_SUBR_COPYIN },
- { "copyinstr", DIF_SUBR_COPYINSTR },
- { "speculation", DIF_SUBR_SPECULATION },
- { "progenyof", DIF_SUBR_PROGENYOF },
- { "strlen", DIF_SUBR_STRLEN },
- { "copyout", DIF_SUBR_COPYOUT },
- { "copyoutstr", DIF_SUBR_COPYOUTSTR },
- { "alloca", DIF_SUBR_ALLOCA },
- { "bcopy", DIF_SUBR_BCOPY },
- { "copyinto", DIF_SUBR_COPYINTO },
- { "msgdsize", DIF_SUBR_MSGDSIZE },
- { "msgsize", DIF_SUBR_MSGSIZE },
- { "getmajor", DIF_SUBR_GETMAJOR },
- { "getminor", DIF_SUBR_GETMINOR },
- { "ddi_pathname", DIF_SUBR_DDI_PATHNAME },
- { "strjoin", DIF_SUBR_STRJOIN },
- { "lltostr", DIF_SUBR_LLTOSTR },
- { "basename", DIF_SUBR_BASENAME },
- { "dirname", DIF_SUBR_DIRNAME },
- { "cleanpath", DIF_SUBR_CLEANPATH },
- { "strchr", DIF_SUBR_STRCHR },
- { "strrchr", DIF_SUBR_STRRCHR },
- { "strstr", DIF_SUBR_STRSTR },
- { "strtok", DIF_SUBR_STRTOK },
- { "substr", DIF_SUBR_SUBSTR },
- { "index", DIF_SUBR_INDEX },
- { "rindex", DIF_SUBR_RINDEX },
- { NULL, 0 }
- };
-
- uint_t subr = DIF_INSTR_SUBR(instr), i;
-
- mdb_printf("%-4s DIF_SUBR(%u), %%r%u", name, subr, DIF_INSTR_RD(instr));
-
- for (i = 0; snames[i].name != NULL; i++) {
- if (subr == snames[i].subr) {
- mdb_printf("\t\t! %s", snames[i].name);
- return;
- }
- }
-}
-
-/*ARGSUSED*/
-static void
-dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
-{
- static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" };
- uint_t type = DIF_INSTR_TYPE(instr);
-
- mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u",
- name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr));
-
- if (type < sizeof (tnames) / sizeof (tnames[0]))
- mdb_printf("\t! %s", tnames[type]);
-}
-
-static char *
-dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
-{
- char kind[8];
-
- switch (t->dtdt_kind) {
- case DIF_TYPE_CTF:
- (void) strcpy(kind, "D type");
- break;
- case DIF_TYPE_STRING:
- (void) strcpy(kind, "string");
- break;
- default:
- (void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind);
- }
-
- if (t->dtdt_flags & DIF_TF_BYREF) {
- (void) mdb_snprintf(buf, len,
- "%s by ref (size %lu)",
- kind, (ulong_t)t->dtdt_size);
- } else {
- (void) mdb_snprintf(buf, len, "%s (size %lu)",
- kind, (ulong_t)t->dtdt_size);
- }
-
- return (buf);
-}
-
-static int
-dis(uintptr_t addr, dtrace_difo_t *dp)
-{
- static const struct opent {
- const char *op_name;
- void (*op_func)(const dtrace_difo_t *,
- const char *, dif_instr_t);
- } optab[] = {
- { "(illegal opcode)", dis_str },
- { "or", dis_log }, /* DIF_OP_OR */
- { "xor", dis_log }, /* DIF_OP_XOR */
- { "and", dis_log }, /* DIF_OP_AND */
- { "sll", dis_log }, /* DIF_OP_SLL */
- { "srl", dis_log }, /* DIF_OP_SRL */
- { "sub", dis_log }, /* DIF_OP_SUB */
- { "add", dis_log }, /* DIF_OP_ADD */
- { "mul", dis_log }, /* DIF_OP_MUL */
- { "sdiv", dis_log }, /* DIF_OP_SDIV */
- { "udiv", dis_log }, /* DIF_OP_UDIV */
- { "srem", dis_log }, /* DIF_OP_SREM */
- { "urem", dis_log }, /* DIF_OP_UREM */
- { "not", dis_r1rd }, /* DIF_OP_NOT */
- { "mov", dis_r1rd }, /* DIF_OP_MOV */
- { "cmp", dis_cmp }, /* DIF_OP_CMP */
- { "tst", dis_tst }, /* DIF_OP_TST */
- { "ba", dis_branch }, /* DIF_OP_BA */
- { "be", dis_branch }, /* DIF_OP_BE */
- { "bne", dis_branch }, /* DIF_OP_BNE */
- { "bg", dis_branch }, /* DIF_OP_BG */
- { "bgu", dis_branch }, /* DIF_OP_BGU */
- { "bge", dis_branch }, /* DIF_OP_BGE */
- { "bgeu", dis_branch }, /* DIF_OP_BGEU */
- { "bl", dis_branch }, /* DIF_OP_BL */
- { "blu", dis_branch }, /* DIF_OP_BLU */
- { "ble", dis_branch }, /* DIF_OP_BLE */
- { "bleu", dis_branch }, /* DIF_OP_BLEU */
- { "ldsb", dis_load }, /* DIF_OP_LDSB */
- { "ldsh", dis_load }, /* DIF_OP_LDSH */
- { "ldsw", dis_load }, /* DIF_OP_LDSW */
- { "ldub", dis_load }, /* DIF_OP_LDUB */
- { "lduh", dis_load }, /* DIF_OP_LDUH */
- { "lduw", dis_load }, /* DIF_OP_LDUW */
- { "ldx", dis_load }, /* DIF_OP_LDX */
- { "ret", dis_ret }, /* DIF_OP_RET */
- { "nop", dis_str }, /* DIF_OP_NOP */
- { "setx", dis_setx }, /* DIF_OP_SETX */
- { "sets", dis_sets }, /* DIF_OP_SETS */
- { "scmp", dis_cmp }, /* DIF_OP_SCMP */
- { "ldga", dis_lda }, /* DIF_OP_LDGA */
- { "ldgs", dis_ldv }, /* DIF_OP_LDGS */
- { "stgs", dis_stv }, /* DIF_OP_STGS */
- { "ldta", dis_lda }, /* DIF_OP_LDTA */
- { "ldts", dis_ldv }, /* DIF_OP_LDTS */
- { "stts", dis_stv }, /* DIF_OP_STTS */
- { "sra", dis_log }, /* DIF_OP_SRA */
- { "call", dis_call }, /* DIF_OP_CALL */
- { "pushtr", dis_pushts }, /* DIF_OP_PUSHTR */
- { "pushtv", dis_pushts }, /* DIF_OP_PUSHTV */
- { "popts", dis_str }, /* DIF_OP_POPTS */
- { "flushts", dis_str }, /* DIF_OP_FLUSHTS */
- { "ldgaa", dis_ldv }, /* DIF_OP_LDGAA */
- { "ldtaa", dis_ldv }, /* DIF_OP_LDTAA */
- { "stgaa", dis_stv }, /* DIF_OP_STGAA */
- { "sttaa", dis_stv }, /* DIF_OP_STTAA */
- { "ldls", dis_ldv }, /* DIF_OP_LDLS */
- { "stls", dis_stv }, /* DIF_OP_STLS */
- { "allocs", dis_r1rd }, /* DIF_OP_ALLOCS */
- { "copys", dis_log }, /* DIF_OP_COPYS */
- { "stb", dis_store }, /* DIF_OP_STB */
- { "sth", dis_store }, /* DIF_OP_STH */
- { "stw", dis_store }, /* DIF_OP_STW */
- { "stx", dis_store }, /* DIF_OP_STX */
- { "uldsb", dis_load }, /* DIF_OP_ULDSB */
- { "uldsh", dis_load }, /* DIF_OP_ULDSH */
- { "uldsw", dis_load }, /* DIF_OP_ULDSW */
- { "uldub", dis_load }, /* DIF_OP_ULDUB */
- { "ulduh", dis_load }, /* DIF_OP_ULDUH */
- { "ulduw", dis_load }, /* DIF_OP_ULDUW */
- { "uldx", dis_load }, /* DIF_OP_ULDX */
- { "rldsb", dis_load }, /* DIF_OP_RLDSB */
- { "rldsh", dis_load }, /* DIF_OP_RLDSH */
- { "rldsw", dis_load }, /* DIF_OP_RLDSW */
- { "rldub", dis_load }, /* DIF_OP_RLDUB */
- { "rlduh", dis_load }, /* DIF_OP_RLDUH */
- { "rlduw", dis_load }, /* DIF_OP_RLDUW */
- { "rldx", dis_load }, /* DIF_OP_RLDX */
- };
-
- dif_instr_t instr, opcode;
- const struct opent *op;
-
- if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) {
- mdb_warn("failed to read DIF instruction at %p", addr);
- return (DCMD_ERR);
- }
-
- opcode = DIF_INSTR_OP(instr);
-
- if (opcode >= sizeof (optab) / sizeof (optab[0]))
- opcode = 0; /* force invalid opcode message */
-
- op = &optab[opcode];
- mdb_printf("%0*p %08x ", DIFO_ADDRWIDTH, addr, instr);
- op->op_func(dp, op->op_name, instr);
- mdb_printf("\n");
- mdb_set_dot(addr + sizeof (dif_instr_t));
-
- return (DCMD_OK);
-}
-
-/*ARGSUSED*/
-int
-difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dtrace_difo_t difo, *dp = &difo;
- uintptr_t instr, limit;
- dtrace_difv_t *dvp;
- size_t varsize;
- ulong_t i;
- char type[64];
- char *str;
-
- if (!(flags & DCMD_ADDRSPEC))
- return (DCMD_USAGE);
-
- if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) {
- mdb_warn("couldn't read dtrace_difo_t at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n",
- addr, dp->dtdo_refcnt);
- mdb_printf("%<b>%-*s %-8s %s%</b>\n", DIFO_ADDRWIDTH, "ADDR",
- "OPCODE", "INSTRUCTION");
-
- mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf);
- limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t);
-
- while ((instr = mdb_get_dot()) < limit)
- dis(instr, dp);
-
- if (dp->dtdo_varlen != 0) {
- mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n",
- "NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
- }
-
- varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
- dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC);
-
- if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
- mdb_warn("couldn't read dtdo_vartab");
- return (DCMD_ERR);
- }
-
- str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
-
- if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) {
- mdb_warn("couldn't read dtdo_strtab");
- return (DCMD_ERR);
- }
-
- for (i = 0; i < dp->dtdo_varlen; i++) {
- dtrace_difv_t *v = &dvp[i];
- char kind[4], scope[4], flags[16] = { 0 };
-
- switch (v->dtdv_kind) {
- case DIFV_KIND_ARRAY:
- (void) strcpy(kind, "arr");
- break;
- case DIFV_KIND_SCALAR:
- (void) strcpy(kind, "scl");
- break;
- default:
- (void) mdb_snprintf(kind, sizeof (kind),
- "%u", v->dtdv_kind);
- }
-
- switch (v->dtdv_scope) {
- case DIFV_SCOPE_GLOBAL:
- (void) strcpy(scope, "glb");
- break;
- case DIFV_SCOPE_THREAD:
- (void) strcpy(scope, "tls");
- break;
- case DIFV_SCOPE_LOCAL:
- (void) strcpy(scope, "loc");
- break;
- default:
- (void) mdb_snprintf(scope, sizeof (scope),
- "%u", v->dtdv_scope);
- }
-
- if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) {
- (void) mdb_snprintf(flags, sizeof (flags), "/0x%x",
- v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD));
- }
-
- if (v->dtdv_flags & DIFV_F_REF)
- (void) strcat(flags, "/r");
- if (v->dtdv_flags & DIFV_F_MOD)
- (void) strcat(flags, "/w");
-
- mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n",
- &str[v->dtdv_name],
- v->dtdv_id, kind, scope, flags + 1,
- dis_typestr(&v->dtdv_type, type, sizeof (type)));
- }
-
- mdb_printf("\n%<b>RETURN%</b>\n%s\n\n",
- dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
-
- return (DCMD_OK);
-}
-
-/*ARGSUSED*/
-int
-difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- if (!(flags & DCMD_ADDRSPEC))
- return (DCMD_USAGE);
-
- return (dis(addr, NULL));
-}
-
/*ARGSUSED*/
int
id2probe(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
@@ -606,302 +77,6 @@ out:
return (DCMD_OK);
}
-/*ARGSUSED*/
-int
-dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_hdr_t h;
-
- if (argc != 0)
- return (DCMD_USAGE);
-
- if (!(flags & DCMD_ADDRSPEC))
- addr = 0; /* assume base of file in file target */
-
- if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) {
- mdb_warn("failed to read header at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n",
- h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1],
- h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]);
-
- switch (h.dofh_ident[DOF_ID_MODEL]) {
- case DOF_MODEL_ILP32:
- mdb_printf("dofh_ident.id_model = ILP32\n");
- break;
- case DOF_MODEL_LP64:
- mdb_printf("dofh_ident.id_model = LP64\n");
- break;
- default:
- mdb_printf("dofh_ident.id_model = 0x%x\n",
- h.dofh_ident[DOF_ID_MODEL]);
- }
-
- switch (h.dofh_ident[DOF_ID_ENCODING]) {
- case DOF_ENCODE_LSB:
- mdb_printf("dofh_ident.id_encoding = LSB\n");
- break;
- case DOF_ENCODE_MSB:
- mdb_printf("dofh_ident.id_encoding = MSB\n");
- break;
- default:
- mdb_printf("dofh_ident.id_encoding = 0x%x\n",
- h.dofh_ident[DOF_ID_ENCODING]);
- }
-
- mdb_printf("dofh_ident.id_version = %u\n",
- h.dofh_ident[DOF_ID_VERSION]);
- mdb_printf("dofh_ident.id_difvers = %u\n",
- h.dofh_ident[DOF_ID_DIFVERS]);
- mdb_printf("dofh_ident.id_difireg = %u\n",
- h.dofh_ident[DOF_ID_DIFIREG]);
- mdb_printf("dofh_ident.id_diftreg = %u\n",
- h.dofh_ident[DOF_ID_DIFTREG]);
-
- mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags);
- mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize);
- mdb_printf("dofh_secsize = %u\n", h.dofh_secsize);
- mdb_printf("dofh_secnum = %u\n", h.dofh_secnum);
- mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff);
- mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz);
- mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz);
-
- return (DCMD_OK);
-}
-
-/*ARGSUSED*/
-static int
-dof_sec_walk(uintptr_t addr, void *ignored, int *sec)
-{
- mdb_printf("%3d ", (*sec)++);
- (void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL);
- return (WALK_NEXT);
-}
-
-static const char *
-dof_sec_typename(uint32_t type)
-{
- static const char *const types[] = {
- "none", "comments", "source", "ecbdesc", "probedesc", "actdesc",
- "difohdr", "dif", "strtab", "vartab", "reltab", "typtab",
- "urelhdr", "krelhdr", "optdesc", "provider", "probes",
- "prargs", "proffs", "inttab", "utsname"
- };
- static char buf[32];
-
- if (type < sizeof (types) / sizeof (types[0]))
- return (types[type]);
-
- mdb_snprintf(buf, sizeof (buf), "%u", type);
- return (buf);
-}
-
-/*ARGSUSED*/
-int
-dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_sec_t s;
-
- if (!(flags & DCMD_ADDRSPEC))
- mdb_printf("%<u>%-3s ", "NDX");
-
- if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) {
- mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n",
- "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET",
- "SIZE");
- }
-
- if (!(flags & DCMD_ADDRSPEC)) {
- int sec = 0;
-
- if (mdb_walk("dof_sec",
- (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) {
- mdb_warn("failed to walk dof_sec");
- return (DCMD_ERR);
- }
- return (DCMD_OK);
- }
-
- if (argc != 0)
- return (DCMD_USAGE);
-
- if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
- mdb_warn("failed to read section header at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("%?p ", addr);
- mdb_printf("%-10s ", dof_sec_typename(s.dofs_type));
-
- mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align,
- s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size);
-
- return (DCMD_OK);
-}
-
-int
-dof_sec_walk_init(mdb_walk_state_t *wsp)
-{
- dof_hdr_t h, *hp;
- size_t size;
-
- if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) {
- mdb_warn("failed to read DOF header at %p", wsp->walk_addr);
- return (WALK_ERR);
- }
-
- size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum;
- hp = mdb_alloc(size, UM_SLEEP);
-
- if (mdb_vread(hp, size, wsp->walk_addr) != size) {
- mdb_warn("failed to read DOF sections at %p", wsp->walk_addr);
- mdb_free(hp, size);
- return (WALK_ERR);
- }
-
- wsp->walk_arg = (void *)0;
- wsp->walk_data = hp;
-
- return (WALK_NEXT);
-}
-
-int
-dof_sec_walk_step(mdb_walk_state_t *wsp)
-{
- uint_t i = (uintptr_t)wsp->walk_arg;
- size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i;
- dof_hdr_t *hp = wsp->walk_data;
- dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off);
-
- if (i >= hp->dofh_secnum)
- return (WALK_DONE);
-
- wsp->walk_arg = (void *)(uintptr_t)(i + 1);
- return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata));
-}
-
-void
-dof_sec_walk_fini(mdb_walk_state_t *wsp)
-{
- dof_hdr_t *hp = wsp->walk_data;
- mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum);
-}
-
-/*ARGSUSED*/
-int
-dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_ecbdesc_t e;
-
- if (argc != 0 || !(flags & DCMD_ADDRSPEC))
- return (DCMD_USAGE);
-
- if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) {
- mdb_warn("failed to read ecbdesc at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("dofe_probes = %d\n", e.dofe_probes);
- mdb_printf("dofe_actions = %d\n", e.dofe_actions);
- mdb_printf("dofe_pred = %d\n", e.dofe_pred);
- mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg);
-
- return (DCMD_OK);
-}
-
-/*ARGSUSED*/
-int
-dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_probedesc_t p;
-
- if (argc != 0 || !(flags & DCMD_ADDRSPEC))
- return (DCMD_USAGE);
-
- if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) {
- mdb_warn("failed to read probedesc at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("dofp_strtab = %d\n", p.dofp_strtab);
- mdb_printf("dofp_provider = %u\n", p.dofp_provider);
- mdb_printf("dofp_mod = %u\n", p.dofp_mod);
- mdb_printf("dofp_func = %u\n", p.dofp_func);
- mdb_printf("dofp_name = %u\n", p.dofp_name);
- mdb_printf("dofp_id = %u\n", p.dofp_id);
-
- return (DCMD_OK);
-}
-
-/*ARGSUSED*/
-int
-dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_actdesc_t a;
-
- if (argc != 0 || !(flags & DCMD_ADDRSPEC))
- return (DCMD_USAGE);
-
- if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) {
- mdb_warn("failed to read actdesc at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("dofa_difo = %d\n", a.dofa_difo);
- mdb_printf("dofa_strtab = %d\n", a.dofa_strtab);
- mdb_printf("dofa_kind = %u\n", a.dofa_kind);
- mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple);
- mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg);
- mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg);
-
- return (DCMD_OK);
-}
-
-/*ARGSUSED*/
-int
-dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_relohdr_t r;
-
- if (argc != 0 || !(flags & DCMD_ADDRSPEC))
- return (DCMD_USAGE);
-
- if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
- mdb_warn("failed to read relohdr at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("dofr_strtab = %d\n", r.dofr_strtab);
- mdb_printf("dofr_relsec = %d\n", r.dofr_relsec);
- mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec);
-
- return (DCMD_OK);
-}
-
-/*ARGSUSED*/
-int
-dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_relodesc_t r;
-
- if (argc != 0 || !(flags & DCMD_ADDRSPEC))
- return (DCMD_USAGE);
-
- if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
- mdb_warn("failed to read relodesc at %p", addr);
- return (DCMD_ERR);
- }
-
- mdb_printf("dofr_name = %u\n", r.dofr_name);
- mdb_printf("dofr_type = %u\n", r.dofr_type);
- mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset);
- mdb_printf("dofr_data = 0x%llx\n", r.dofr_data);
-
- return (DCMD_OK);
-}
-
void
dtrace_help(void)
{
@@ -3088,221 +2263,9 @@ dtrace_dynstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
-static int
-dof_sect_strtab(uintptr_t addr, dof_sec_t *sec)
-{
- char *strtab;
- size_t sz, i;
-
- sz = (size_t)sec->dofs_size;
- strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
- if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) {
- mdb_warn("failed to read string table");
- return (1);
- }
-
- mdb_printf("size = %lx\n", sz);
-
- for (i = 0; i < sz; i++) {
- if (strtab[i] == '\0')
- mdb_printf("\\0");
- else
- mdb_printf("%c", strtab[i]);
- }
-
- mdb_printf("\n");
-
- return (0);
-}
-
-static int
-dof_sect_provider(uintptr_t addr, dof_sec_t *sec, dof_sec_t *dofs)
-{
- dof_provider_t pv;
- dof_probe_t *pb;
- char *strtab;
- uint32_t *offs;
- uint8_t *args = NULL;
- size_t sz;
- int i, j;
- dof_stridx_t narg, xarg;
-
- if (mdb_vread(&pv, sizeof (dof_provider_t),
- addr + sec->dofs_offset) != sizeof (dof_provider_t)) {
- mdb_warn("failed to read DOF provider");
- return (-1);
- }
-
- sz = dofs[pv.dofpv_strtab].dofs_size;
- strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
- if (mdb_vread(strtab, sz, addr +
- dofs[pv.dofpv_strtab].dofs_offset) != sz) {
- mdb_warn("failed to read string table");
- return (-1);
- }
-
- mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset),
- strtab + pv.dofpv_name);
-
- sz = dofs[pv.dofpv_prargs].dofs_size;
- if (sz != 0) {
- args = mdb_alloc(sz, UM_SLEEP | UM_GC);
- if (mdb_vread(args, sz, addr +
- dofs[pv.dofpv_prargs].dofs_offset) != sz) {
- mdb_warn("failed to read args");
- return (-1);
- }
- }
-
- sz = dofs[pv.dofpv_proffs].dofs_size;
- offs = mdb_alloc(sz, UM_SLEEP | UM_GC);
- if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset)
- != sz) {
- mdb_warn("failed to read offs");
- return (-1);
- }
-
- sz = dofs[pv.dofpv_probes].dofs_size;
- pb = mdb_alloc(sz, UM_SLEEP | UM_GC);
- if (mdb_vread(pb, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) {
- mdb_warn("failed to read probes");
- return (-1);
- }
-
- (void) mdb_inc_indent(2);
-
- for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) {
- mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr +
- dofs[pv.dofpv_probes].dofs_offset +
- i * dofs[pv.dofpv_probes].dofs_entsize),
- strtab + pb[i].dofpr_func,
- strtab + pb[i].dofpr_name);
-
- (void) mdb_inc_indent(2);
- mdb_printf("addr: %p\n", (ulong_t)pb[i].dofpr_addr);
- mdb_printf("offs: ");
- for (j = 0; j < pb[i].dofpr_noffs; j++) {
- mdb_printf("%s %x", "," + (j == 0),
- offs[pb[i].dofpr_offidx + j]);
- }
- mdb_printf("\n");
-
- mdb_printf("nargs:");
- narg = pb[i].dofpr_nargv;
- for (j = 0; j < pb[i].dofpr_nargc; j++) {
- mdb_printf("%s %s", "," + (j == 0), strtab + narg);
- narg += strlen(strtab + narg) + 1;
- }
- mdb_printf("\n");
- mdb_printf("xargs:");
- xarg = pb[i].dofpr_xargv;
- for (j = 0; j < pb[i].dofpr_xargc; j++) {
- mdb_printf("%s %s", "," + (j == 0), strtab + xarg);
- xarg += strlen(strtab + xarg) + 1;
- }
- mdb_printf("\n");
- mdb_printf("map: ");
- for (j = 0; j < pb[i].dofpr_xargc; j++) {
- mdb_printf("%s %d->%d", "," + (j == 0),
- args[pb[i].dofpr_argidx + j], j);
- }
-
- (void) mdb_dec_indent(2);
- mdb_printf("\n}\n");
- }
-
- (void) mdb_dec_indent(2);
- mdb_printf("}\n");
-
- return (0);
-}
-
-static int
-dof_sect_prargs(uintptr_t addr, dof_sec_t *sec)
-{
- int i;
- uint8_t arg;
-
- for (i = 0; i < sec->dofs_size; i++) {
- if (mdb_vread(&arg, sizeof (arg),
- addr + sec->dofs_offset + i) != sizeof (arg)) {
- mdb_warn("failed to read argument");
- return (1);
- }
-
- mdb_printf("%d ", arg);
-
- if (i % 20 == 19)
- mdb_printf("\n");
- }
-
- mdb_printf("\n");
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
-{
- dof_hdr_t dofh;
- dof_sec_t *dofs;
- int i;
-
- if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) {
- mdb_warn("failed to read DOF header");
- return (DCMD_ERR);
- }
-
- dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum,
- UM_SLEEP | UM_GC);
-
- for (i = 0; i < dofh.dofh_secnum; i++) {
- if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff +
- addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) {
- mdb_warn("failed to read DOF sections");
- return (DCMD_ERR);
- }
- }
-
- for (i = 0; i < dofh.dofh_secnum; i++) {
- mdb_printf("%lx Section %d: %s\n", (ulong_t)(dofh.dofh_secoff +
- addr + i * dofh.dofh_secsize), i,
- dof_sec_typename(dofs[i].dofs_type));
-
- (void) mdb_inc_indent(2);
- switch (dofs[i].dofs_type) {
- case DOF_SECT_PROVIDER:
- (void) dof_sect_provider(addr, &dofs[i], dofs);
- break;
- case DOF_SECT_STRTAB:
- (void) dof_sect_strtab(addr, &dofs[i]);
- break;
- case DOF_SECT_PRARGS:
- (void) dof_sect_prargs(addr, &dofs[i]);
- break;
- }
- (void) mdb_dec_indent(2);
-
- mdb_printf("\n");
- }
-
- return (DCMD_OK);
-}
-
-static const mdb_dcmd_t dcmds[] = {
+const mdb_dcmd_t kernel_dcmds[] = {
{ "id2probe", ":", "translate a dtrace_id_t to a dtrace_probe_t",
id2probe },
- { "difinstr", ":", "disassemble a DIF instruction", difinstr },
- { "difo", ":", "print a DIF object", difo },
- { "dof_hdr", "?", "print a DOF header", dof_hdr },
- { "dof_sec", ":", "print a DOF section header", dof_sec },
- { "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc },
- { "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc },
- { "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc },
- { "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr },
- { "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc },
- { "dofdump", ":", "dump DOF", dofdump },
{ "dtrace", ":[-c cpu]", "print dtrace(1M)-like output",
dtrace, dtrace_help },
{ "dtrace_errhash", ":", "print DTrace error hash", dtrace_errhash },
@@ -3317,9 +2280,7 @@ static const mdb_dcmd_t dcmds[] = {
{ NULL }
};
-static const mdb_walker_t walkers[] = {
- { "dof_sec", "walk DOF section header table given header address",
- dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini },
+const mdb_walker_t kernel_walkers[] = {
{ "dtrace_errhash", "walk hash of DTrace error messasges",
dtrace_errhash_init, dtrace_errhash_step },
{ "dtrace_helptrace", "walk DTrace helper trace entries",
@@ -3332,13 +2293,3 @@ static const mdb_walker_t walkers[] = {
dtrace_dynvar_init, dtrace_dynvar_step, dtrace_dynvar_fini },
{ NULL }
};
-
-static const mdb_modinfo_t modinfo = {
- MDB_API_VERSION, dcmds, walkers
-};
-
-const mdb_modinfo_t *
-_mdb_init(void)
-{
- return (&modinfo);
-}
diff --git a/usr/src/cmd/mdb/common/modules/dtrace/mkdof.sh b/usr/src/cmd/mdb/common/modules/dtrace/mkdof.sh
new file mode 100644
index 0000000000..4709d8577b
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/dtrace/mkdof.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+echo "\
+/*\n\
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.\n\
+ * Use is subject to license terms.\n\
+ */\n\
+\n\
+#pragma ident\t\"%Z%%M%\t%I%\t%E% SMI\"\n\
+\n\
+#include <sys/dtrace.h>\n\
+\n\
+const char *\n\
+dof_sec_name(uint32_t type)\n\
+{\n\
+ switch (type) {"
+
+pattern='^#define[ ]DOF_SECT_\([A-Z0-9_]*\)[ ]*.*$'
+replace=' case DOF_SECT_\1: return ("\1");'
+
+sed -n "s/$pattern/$replace/p"
+
+echo "\
+ default: return (NULL);\n\
+ }\n\
+}"
diff --git a/usr/src/cmd/mdb/intel/amd64/dof/Makefile b/usr/src/cmd/mdb/intel/amd64/dof/Makefile
new file mode 100644
index 0000000000..2ab0ab6051
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/amd64/dof/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = dof.so
+MDBTGT = raw
+
+MODSRCS = dof.c dof_names.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.amd64
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/dtrace
+
+LDLIBS += -ldtrace
+CLEANFILES += dof_names.c
+
+dof_names.c: $(MODSRCS_DIR)/mkdof.sh $(SRC)/uts/common/sys/dtrace.h
+ sh $(MODSRCS_DIR)/mkdof.sh < $(SRC)/uts/common/sys/dtrace.h > $@
diff --git a/usr/src/cmd/mdb/intel/amd64/dtrace/Makefile b/usr/src/cmd/mdb/intel/amd64/dtrace/Makefile
index c31dc22b14..12abad56c1 100644
--- a/usr/src/cmd/mdb/intel/amd64/dtrace/Makefile
+++ b/usr/src/cmd/mdb/intel/amd64/dtrace/Makefile
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -28,27 +28,19 @@
MODULE = dtrace.so
MDBTGT = kvm
-MODSRCS = dtrace.c
+MODSRCS = dtrace.c dof.c dof_names.c
include ../../../../Makefile.cmd
include ../../../../Makefile.cmd.64
include ../../Makefile.amd64
include ../../../Makefile.module
-#
-# The dtrace dmod isn't currently built for kmdb.
-#
MODULE_BUILD_TYPE = mdb
+MODSRCS_DIR = ../../../common/modules/dtrace
-#
-# This is unfortunately necessarily to be able to include mdb_param.h.
-# See the optimistic comment in genunix's Makefile about how this is a
-# "temporary" kludge.
-#
CPPFLAGS += -I$(SRC)/uts/i86pc
-
-#
-# Until mdb itself links with libdtrace.so, the dtrace.so module needs to
-# pull in libdtrace.so.
-#
LDLIBS += -ldtrace -lm
+CLEANFILES += dof_names.c
+
+dof_names.c: $(MODSRCS_DIR)/mkdof.sh $(SRC)/uts/common/sys/dtrace.h
+ sh $(MODSRCS_DIR)/mkdof.sh < $(SRC)/uts/common/sys/dtrace.h > $@
diff --git a/usr/src/cmd/mdb/intel/ia32/dof/Makefile b/usr/src/cmd/mdb/intel/ia32/dof/Makefile
new file mode 100644
index 0000000000..79743fe541
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/ia32/dof/Makefile
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = dof.so
+MDBTGT = raw
+
+MODSRCS = dof.c dof_names.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/dtrace
+
+LDLIBS += -ldtrace
+CLEANFILES += dof_names.c
+
+dof_names.c: $(MODSRCS_DIR)/mkdof.sh $(SRC)/uts/common/sys/dtrace.h
+ sh $(MODSRCS_DIR)/mkdof.sh < $(SRC)/uts/common/sys/dtrace.h > $@
diff --git a/usr/src/cmd/mdb/intel/ia32/dtrace/Makefile b/usr/src/cmd/mdb/intel/ia32/dtrace/Makefile
index 8ca968c512..22223fa876 100644
--- a/usr/src/cmd/mdb/intel/ia32/dtrace/Makefile
+++ b/usr/src/cmd/mdb/intel/ia32/dtrace/Makefile
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -28,26 +28,18 @@
MODULE = dtrace.so
MDBTGT = kvm
-MODSRCS = dtrace.c
+MODSRCS = dtrace.c dof.c dof_names.c
include ../../../../Makefile.cmd
include ../../Makefile.ia32
include ../../../Makefile.module
-#
-# The dtrace dmod isn't currently built for kmdb.
-#
MODULE_BUILD_TYPE = mdb
+MODSRCS_DIR = ../../../common/modules/dtrace
-#
-# This is unfortunately necessarily to be able to include mdb_param.h.
-# See the optimistic comment in genunix's Makefile about how this is a
-# "temporary" kludge.
-#
CPPFLAGS += -I$(SRC)/uts/i86pc
-
-#
-# Until mdb itself links with libdtrace.so, the dtrace.so module needs to
-# pull in libdtrace.so.
-#
LDLIBS += -ldtrace -lm
+CLEANFILES += dof_names.c
+
+dof_names.c: $(MODSRCS_DIR)/mkdof.sh $(SRC)/uts/common/sys/dtrace.h
+ sh $(MODSRCS_DIR)/mkdof.sh < $(SRC)/uts/common/sys/dtrace.h > $@
diff --git a/usr/src/cmd/mdb/sparc/v7/dof/Makefile b/usr/src/cmd/mdb/sparc/v7/dof/Makefile
new file mode 100644
index 0000000000..bbe3ee6aca
--- /dev/null
+++ b/usr/src/cmd/mdb/sparc/v7/dof/Makefile
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = dof.so
+MDBTGT = raw
+
+MODSRCS = dof.c dof_names.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.sparcv7
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/dtrace
+
+LDLIBS += -ldtrace
+CLEANFILES += dof_names.c
+
+dof_names.c: $(MODSRCS_DIR)/mkdof.sh $(SRC)/uts/common/sys/dtrace.h
+ sh $(MODSRCS_DIR)/mkdof.sh < $(SRC)/uts/common/sys/dtrace.h > $@
diff --git a/usr/src/cmd/mdb/sparc/v9/dof/Makefile b/usr/src/cmd/mdb/sparc/v9/dof/Makefile
new file mode 100644
index 0000000000..63a6c78fe3
--- /dev/null
+++ b/usr/src/cmd/mdb/sparc/v9/dof/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = dof.so
+MDBTGT = raw
+
+MODSRCS = dof.c dof_names.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.sparcv9
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/dtrace
+
+LDLIBS += -ldtrace
+CLEANFILES += dof_names.c
+
+dof_names.c: $(MODSRCS_DIR)/mkdof.sh $(SRC)/uts/common/sys/dtrace.h
+ sh $(MODSRCS_DIR)/mkdof.sh < $(SRC)/uts/common/sys/dtrace.h > $@
diff --git a/usr/src/cmd/mdb/sparc/v9/dtrace/Makefile b/usr/src/cmd/mdb/sparc/v9/dtrace/Makefile
index cf62ce2396..75b057c0b6 100644
--- a/usr/src/cmd/mdb/sparc/v9/dtrace/Makefile
+++ b/usr/src/cmd/mdb/sparc/v9/dtrace/Makefile
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -28,27 +28,19 @@
MODULE = dtrace.so
MDBTGT = kvm
-MODSRCS = dtrace.c
+MODSRCS = dtrace.c dof.c dof_names.c
include ../../../../Makefile.cmd
include ../../../../Makefile.cmd.64
include ../../Makefile.sparcv9
include ../../../Makefile.module
-#
-# The dtrace dmod isn't currently built for kmdb.
-#
MODULE_BUILD_TYPE = mdb
+MODSRCS_DIR = ../../../common/modules/dtrace
-#
-# This is unfortunately necessarily to be able to include mdb_param.h.
-# See the optimistic comment in genunix's Makefile about how this is a
-# "temporary" kludge.
-#
CPPFLAGS += -I$(SRC)/uts/sun4u
-
-#
-# Until mdb itself links with libdtrace.so, the dtrace.so module needs to
-# pull in libdtrace.so.
-#
LDLIBS += -ldtrace -lm
+CLEANFILES += dof_names.c
+
+dof_names.c: $(MODSRCS_DIR)/mkdof.sh $(SRC)/uts/common/sys/dtrace.h
+ sh $(MODSRCS_DIR)/mkdof.sh < $(SRC)/uts/common/sys/dtrace.h > $@
diff --git a/usr/src/lib/libdtrace/Makefile.com b/usr/src/lib/libdtrace/Makefile.com
index 3bb3575d61..c8db3eaec8 100644
--- a/usr/src/lib/libdtrace/Makefile.com
+++ b/usr/src/lib/libdtrace/Makefile.com
@@ -51,6 +51,7 @@ LIBSRCS = \
dt_program.c \
dt_map.c \
dt_module.c \
+ dt_names.c \
dt_parser.c \
dt_pcb.c \
dt_pid.c \
@@ -93,7 +94,8 @@ SPECMAPFILE = $(MAPDIR)/mapfile
CLEANFILES += dt_lex.c dt_grammar.c dt_grammar.h y.output
CLEANFILES += ../common/procfs.sed ../common/procfs.d
CLEANFILES += ../common/io.sed ../common/io.d
-CLEANFILES += ../common/dt_errtags.c ../common/errno.d ../common/signal.d
+CLEANFILES += ../common/errno.d ../common/signal.d
+CLEANFILES += ../common/dt_errtags.c ../common/dt_names.c
CLOBBERFILES += drti.o
@@ -144,6 +146,9 @@ pics/dt_lex.o pics/dt_grammar.o := CCVERBOSE =
../common/dt_errtags.c: ../common/mkerrtags.sh ../common/dt_errtags.h
sh ../common/mkerrtags.sh < ../common/dt_errtags.h > $@
+../common/dt_names.c: ../common/mknames.sh $(SRC)/uts/common/sys/dtrace.h
+ sh ../common/mknames.sh < $(SRC)/uts/common/sys/dtrace.h > $@
+
../common/errno.d: ../common/mkerrno.sh $(SRC)/uts/common/sys/errno.h
sh ../common/mkerrno.sh < $(SRC)/uts/common/sys/errno.h > $@
diff --git a/usr/src/lib/libdtrace/common/dt_as.c b/usr/src/lib/libdtrace/common/dt_as.c
index b8ad867ac3..457b8fd721 100644
--- a/usr/src/lib/libdtrace/common/dt_as.c
+++ b/usr/src/lib/libdtrace/common/dt_as.c
@@ -126,7 +126,7 @@ dt_copyvar(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
bzero(&dn, sizeof (dn));
dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type);
- dt_node_diftype(&dn, &dvp->dtdv_type);
+ dt_node_diftype(pcb->pcb_hdl, &dn, &dvp->dtdv_type);
idp->di_flags &= ~(DT_IDFLG_DIFR | DT_IDFLG_DIFW);
return (0);
@@ -139,6 +139,51 @@ dt_copystr(const char *s, size_t n, size_t off, dt_pcb_t *pcb)
return (n);
}
+/*
+ * Rewrite the xlate/xlarg instruction at dtdo_buf[i] so that the instruction's
+ * xltab index reflects the offset 'xi' of the assigned dtdo_xlmtab[] location.
+ * We track the cumulative references to translators and members in the pcb's
+ * pcb_asxrefs[] array, a two-dimensional array of bitmaps indexed by the
+ * global translator id and then by the corresponding translator member id.
+ */
+static void
+dt_as_xlate(dt_pcb_t *pcb, dtrace_difo_t *dp,
+ uint_t i, uint_t xi, dt_node_t *dnp)
+{
+ dtrace_hdl_t *dtp = pcb->pcb_hdl;
+ dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator;
+
+ assert(i < dp->dtdo_len);
+ assert(xi < dp->dtdo_xlmlen);
+
+ assert(dnp->dn_kind == DT_NODE_MEMBER);
+ assert(dnp->dn_membexpr->dn_kind == DT_NODE_XLATOR);
+
+ assert(dxp->dx_id < dtp->dt_xlatorid);
+ assert(dnp->dn_membid < dxp->dx_nmembers);
+
+ if (pcb->pcb_asxrefs == NULL) {
+ pcb->pcb_asxreflen = dtp->dt_xlatorid;
+ pcb->pcb_asxrefs =
+ dt_zalloc(dtp, sizeof (ulong_t *) * pcb->pcb_asxreflen);
+ if (pcb->pcb_asxrefs == NULL)
+ longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
+ }
+
+ if (pcb->pcb_asxrefs[dxp->dx_id] == NULL) {
+ pcb->pcb_asxrefs[dxp->dx_id] =
+ dt_zalloc(dtp, BT_SIZEOFMAP(dxp->dx_nmembers));
+ if (pcb->pcb_asxrefs[dxp->dx_id] == NULL)
+ longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
+ }
+
+ dp->dtdo_buf[i] = DIF_INSTR_XLATE(
+ DIF_INSTR_OP(dp->dtdo_buf[i]), xi, DIF_INSTR_RD(dp->dtdo_buf[i]));
+
+ BT_SET(pcb->pcb_asxrefs[dxp->dx_id], dnp->dn_membid);
+ dp->dtdo_xlmtab[xi] = dnp;
+}
+
static void
dt_as_undef(const dt_ident_t *idp, uint_t offset)
{
@@ -172,11 +217,11 @@ dt_as(dt_pcb_t *pcb)
uint_t i;
uint_t kmask, kbits, umask, ubits;
- uint_t krel = 0, urel = 0;
+ uint_t krel = 0, urel = 0, xlrefs = 0;
/*
* Select bitmasks based upon the desired symbol linking policy. We
- * test (di_ident->di_flags & xmask) == xbits to determine if the
+ * test (di_extern->di_flags & xmask) == xbits to determine if the
* symbol should have a relocation entry generated in the loop below.
*
* DT_LINK_KERNEL = kernel symbols static, user symbols dynamic
@@ -216,20 +261,18 @@ dt_as(dt_pcb_t *pcb)
dtp->dt_linkmode);
}
- if ((dp = malloc(sizeof (dtrace_difo_t))) == NULL)
- longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
+ assert(pcb->pcb_difo == NULL);
+ pcb->pcb_difo = dt_zalloc(dtp, sizeof (dtrace_difo_t));
- assert(yypcb->pcb_difo == NULL);
- yypcb->pcb_difo = dp;
+ if ((dp = pcb->pcb_difo) == NULL)
+ longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
- bzero(dp, sizeof (dtrace_difo_t));
- dp->dtdo_refcnt = 1;
- dp->dtdo_buf = malloc(sizeof (dif_instr_t) * dlp->dl_len);
+ dp->dtdo_buf = dt_alloc(dtp, sizeof (dif_instr_t) * dlp->dl_len);
if (dp->dtdo_buf == NULL)
longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
- if ((labels = malloc(sizeof (uint_t) * dlp->dl_label)) == NULL)
+ if ((labels = dt_alloc(dtp, sizeof (uint_t) * dlp->dl_label)) == NULL)
longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
/*
@@ -246,13 +289,25 @@ dt_as(dt_pcb_t *pcb)
dip->di_instr != DIF_INSTR_NOP)
dp->dtdo_buf[i++] = dip->di_instr;
- if ((idp = dip->di_ident) == NULL)
- continue; /* no relocation entry needed */
-
- if ((idp->di_flags & kmask) == kbits)
- krel++;
- else if ((idp->di_flags & umask) == ubits)
- urel++;
+ if (dip->di_extern == NULL)
+ continue; /* no external references needed */
+
+ switch (DIF_INSTR_OP(dip->di_instr)) {
+ case DIF_OP_SETX:
+ idp = dip->di_extern;
+ if ((idp->di_flags & kmask) == kbits)
+ krel++;
+ else if ((idp->di_flags & umask) == ubits)
+ urel++;
+ break;
+ case DIF_OP_XLATE:
+ case DIF_OP_XLARG:
+ xlrefs++;
+ break;
+ default:
+ xyerror(D_UNKNOWN, "unexpected assembler relocation "
+ "for opcode 0x%x\n", DIF_INSTR_OP(dip->di_instr));
+ }
}
assert(i == dlp->dl_len);
@@ -281,8 +336,8 @@ dt_as(dt_pcb_t *pcb)
}
}
- free(labels);
- yypcb->pcb_asvidx = 0;
+ dt_free(dtp, labels);
+ pcb->pcb_asvidx = 0;
/*
* Allocate memory for the appropriate number of variable records and
@@ -294,7 +349,7 @@ dt_as(dt_pcb_t *pcb)
(void) dt_idhash_iter(pcb->pcb_locals, dt_countvar, &n);
if (n != 0) {
- dp->dtdo_vartab = malloc(n * sizeof (dtrace_difv_t));
+ dp->dtdo_vartab = dt_alloc(dtp, n * sizeof (dtrace_difv_t));
dp->dtdo_varlen = (uint32_t)n;
if (dp->dtdo_vartab == NULL)
@@ -310,7 +365,8 @@ dt_as(dt_pcb_t *pcb)
* entries based upon our kernel and user counts from the first pass.
*/
if (krel != 0) {
- dp->dtdo_kreltab = malloc(krel * sizeof (dof_relodesc_t));
+ dp->dtdo_kreltab = dt_alloc(dtp,
+ krel * sizeof (dof_relodesc_t));
dp->dtdo_krelen = krel;
if (dp->dtdo_kreltab == NULL)
@@ -318,23 +374,33 @@ dt_as(dt_pcb_t *pcb)
}
if (urel != 0) {
- dp->dtdo_ureltab = malloc(urel * sizeof (dof_relodesc_t));
+ dp->dtdo_ureltab = dt_alloc(dtp,
+ urel * sizeof (dof_relodesc_t));
dp->dtdo_urelen = urel;
if (dp->dtdo_ureltab == NULL)
longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
}
+ if (xlrefs != 0) {
+ dp->dtdo_xlmtab = dt_zalloc(dtp, sizeof (dt_node_t *) * xlrefs);
+ dp->dtdo_xlmlen = xlrefs;
+
+ if (dp->dtdo_xlmtab == NULL)
+ longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
+ }
+
/*
* If any relocations are needed, make another pass through the
* instruction list and fill in the relocation table entries.
*/
- if (krel + urel != 0) {
+ if (krel + urel + xlrefs != 0) {
uint_t knodef = pcb->pcb_cflags & DTRACE_C_KNODEF;
uint_t unodef = pcb->pcb_cflags & DTRACE_C_UNODEF;
dof_relodesc_t *krp = dp->dtdo_kreltab;
dof_relodesc_t *urp = dp->dtdo_ureltab;
+ dt_node_t **xlp = dp->dtdo_xlmtab;
i = 0; /* dtdo_buf[] index */
@@ -349,7 +415,15 @@ dt_as(dt_pcb_t *pcb)
i++; /* advance dtdo_buf[] index */
- if ((idp = dip->di_ident) == NULL)
+ if (DIF_INSTR_OP(dip->di_instr) == DIF_OP_XLATE ||
+ DIF_INSTR_OP(dip->di_instr) == DIF_OP_XLARG) {
+ assert(dp->dtdo_buf[i - 1] == dip->di_instr);
+ dt_as_xlate(pcb, dp, i - 1, (uint_t)
+ (xlp++ - dp->dtdo_xlmtab), dip->di_extern);
+ continue;
+ }
+
+ if ((idp = dip->di_extern) == NULL)
continue; /* no relocation entry needed */
if ((idp->di_flags & kmask) == kbits) {
@@ -381,6 +455,7 @@ dt_as(dt_pcb_t *pcb)
assert(krp == dp->dtdo_kreltab + dp->dtdo_krelen);
assert(urp == dp->dtdo_ureltab + dp->dtdo_urelen);
+ assert(xlp == dp->dtdo_xlmtab + dp->dtdo_xlmlen);
assert(i == dp->dtdo_len);
}
@@ -389,7 +464,7 @@ dt_as(dt_pcb_t *pcb)
* chunks from the string table into the final string buffer.
*/
if ((n = dt_strtab_size(pcb->pcb_strtab)) != 0) {
- if ((dp->dtdo_strtab = malloc(n)) == NULL)
+ if ((dp->dtdo_strtab = dt_alloc(dtp, n)) == NULL)
longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
(void) dt_strtab_write(pcb->pcb_strtab,
@@ -402,7 +477,8 @@ dt_as(dt_pcb_t *pcb)
* integer constants from the table into the final integer buffer.
*/
if ((n = dt_inttab_size(pcb->pcb_inttab)) != 0) {
- if ((dp->dtdo_inttab = malloc(n * sizeof (uint64_t))) == NULL)
+ if ((dp->dtdo_inttab = dt_alloc(dtp,
+ n * sizeof (uint64_t))) == NULL)
longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
dt_inttab_write(pcb->pcb_inttab, dp->dtdo_inttab);
@@ -414,12 +490,12 @@ dt_as(dt_pcb_t *pcb)
* node saved in pcb_dret, and then clear pcb_difo and pcb_dret
* now that the assembler has completed successfully.
*/
- dt_node_diftype(pcb->pcb_dret, &dp->dtdo_rtype);
+ dt_node_diftype(dtp, pcb->pcb_dret, &dp->dtdo_rtype);
pcb->pcb_difo = NULL;
pcb->pcb_dret = NULL;
if (pcb->pcb_cflags & DTRACE_C_DIFV)
- dtrace_difo_print(dp, stderr);
+ dt_dis(dp, stderr);
return (dp);
}
diff --git a/usr/src/lib/libdtrace/common/dt_as.h b/usr/src/lib/libdtrace/common/dt_as.h
index 0bf02a6a5e..2acd940912 100644
--- a/usr/src/lib/libdtrace/common/dt_as.h
+++ b/usr/src/lib/libdtrace/common/dt_as.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,12 +36,10 @@
extern "C" {
#endif
-struct dt_ident;
-
typedef struct dt_irnode {
uint_t di_label; /* label number or DT_LBL_NONE */
dif_instr_t di_instr; /* instruction opcode */
- struct dt_ident *di_ident; /* ident pointer for relocation */
+ void *di_extern; /* opcode-specific external reference */
struct dt_irnode *di_next; /* next instruction */
} dt_irnode_t;
diff --git a/usr/src/lib/libdtrace/common/dt_cc.c b/usr/src/lib/libdtrace/common/dt_cc.c
index ab957f5d05..0648923bcb 100644
--- a/usr/src/lib/libdtrace/common/dt_cc.c
+++ b/usr/src/lib/libdtrace/common/dt_cc.c
@@ -103,6 +103,7 @@
#undef _POSIX_PTHREAD_SEMANTICS
#include <dt_module.h>
+#include <dt_program.h>
#include <dt_provider.h>
#include <dt_printf.h>
#include <dt_pid.h>
@@ -292,19 +293,17 @@ dt_stmt_append(dtrace_stmtdesc_t *sdp, const dt_node_t *dnp)
static void
dt_action_difconst(dtrace_actdesc_t *ap, uint_t id, dtrace_actkind_t kind)
{
- dtrace_difo_t *dp = malloc(sizeof (dtrace_difo_t));
+ dtrace_hdl_t *dtp = yypcb->pcb_hdl;
+ dtrace_difo_t *dp = dt_zalloc(dtp, sizeof (dtrace_difo_t));
if (dp == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
- bzero(dp, sizeof (dtrace_difo_t));
- dtrace_difo_hold(dp);
-
- dp->dtdo_buf = malloc(sizeof (dif_instr_t) * 2);
- dp->dtdo_inttab = malloc(sizeof (uint64_t));
+ dp->dtdo_buf = dt_alloc(dtp, sizeof (dif_instr_t) * 2);
+ dp->dtdo_inttab = dt_alloc(dtp, sizeof (uint64_t));
if (dp->dtdo_buf == NULL || dp->dtdo_inttab == NULL) {
- dtrace_difo_release(dp);
+ dt_difo_free(dtp, dp);
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
}
@@ -606,7 +605,7 @@ dt_action_printflike(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
str = DT_FREOPEN_RESTORE;
}
- sdp->dtsd_fmtdata = dt_printf_create(yypcb->pcb_hdl, str);
+ sdp->dtsd_fmtdata = dt_printf_create(dtp, str);
dt_printf_validate(sdp->dtsd_fmtdata, DT_PRINTF_EXACTLEN,
dnp->dn_ident, 1, DTRACEACT_AGGREGATION, arg1);
@@ -615,19 +614,17 @@ dt_action_printflike(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
dif_instr_t *dbuf;
dtrace_difo_t *dp;
- if ((dbuf = malloc(sizeof (dif_instr_t))) == NULL ||
- (dp = malloc(sizeof (dtrace_difo_t))) == NULL) {
- free(dbuf);
+ if ((dbuf = dt_alloc(dtp, sizeof (dif_instr_t))) == NULL ||
+ (dp = dt_zalloc(dtp, sizeof (dtrace_difo_t))) == NULL) {
+ dt_free(dtp, dbuf);
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
}
dbuf[0] = DIF_INSTR_RET(DIF_REG_R0); /* ret %r0 */
- bzero(dp, sizeof (dtrace_difo_t));
dp->dtdo_buf = dbuf;
dp->dtdo_len = 1;
dp->dtdo_rtype = dt_int_rtype;
- dp->dtdo_refcnt = 1;
ap = dt_stmt_action(dtp, sdp);
ap->dtad_difo = dp;
@@ -1146,7 +1143,7 @@ dt_compile_one_clause(dtrace_hdl_t *dtp, dt_node_t *cnp, dt_node_t *pnp)
if (DT_TREEDUMP_PASS(dtp, 2))
dt_node_printr(cnp, stderr, 0);
- if ((edp = dtrace_ecbdesc_create(dtp, pnp->dn_desc)) == NULL)
+ if ((edp = dt_ecbdesc_create(dtp, pnp->dn_desc)) == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
assert(yypcb->pcb_ecbdesc == NULL);
@@ -1189,7 +1186,7 @@ dt_compile_one_clause(dtrace_hdl_t *dtp, dt_node_t *cnp, dt_node_t *pnp)
}
assert(yypcb->pcb_ecbdesc == edp);
- dtrace_ecbdesc_release(edp);
+ dt_ecbdesc_release(dtp, edp);
dt_endcontext(dtp);
yypcb->pcb_ecbdesc = NULL;
}
@@ -1203,6 +1200,19 @@ dt_compile_clause(dtrace_hdl_t *dtp, dt_node_t *cnp)
dt_compile_one_clause(dtp, cnp, pnp);
}
+static void
+dt_compile_xlator(dt_node_t *dnp)
+{
+ dt_xlator_t *dxp = dnp->dn_xlator;
+ dt_node_t *mnp;
+
+ for (mnp = dnp->dn_members; mnp != NULL; mnp = mnp->dn_list) {
+ assert(dxp->dx_membdif[mnp->dn_membid] == NULL);
+ dt_cg(yypcb, mnp);
+ dxp->dx_membdif[mnp->dn_membid] = dt_as(yypcb);
+ }
+}
+
void
dt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp)
{
@@ -1539,7 +1549,7 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
dt_dprintf("skipping library: %s\n",
dtrace_errmsg(dtp, dtrace_errno(dtp)));
} else
- dtrace_program_destroy(dtp, pgp);
+ dt_program_destroy(dtp, pgp);
}
(void) closedir(dirp);
@@ -1671,7 +1681,7 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
!(yypcb->pcb_cflags & DTRACE_C_EMPTY))
xyerror(D_EMPTY, "empty D program translation unit\n");
- if ((yypcb->pcb_prog = dtrace_program_create(dtp)) == NULL)
+ if ((yypcb->pcb_prog = dt_program_create(dtp)) == NULL)
longjmp(yypcb->pcb_jmpbuf, dtrace_errno(dtp));
for (; dnp != NULL; dnp = dnp->dn_list) {
@@ -1679,13 +1689,22 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
case DT_NODE_CLAUSE:
dt_compile_clause(dtp, dnp);
break;
+ case DT_NODE_XLATOR:
+ if (dtp->dt_xlatemode == DT_XL_DYNAMIC)
+ dt_compile_xlator(dnp);
+ break;
case DT_NODE_PROVIDER:
(void) dt_node_cook(dnp, DT_IDFLG_REF);
break;
}
}
- rv = pcb.pcb_prog;
+ yypcb->pcb_prog->dp_xrefs = yypcb->pcb_asxrefs;
+ yypcb->pcb_prog->dp_xrefslen = yypcb->pcb_asxreflen;
+ yypcb->pcb_asxrefs = NULL;
+ yypcb->pcb_asxreflen = 0;
+
+ rv = yypcb->pcb_prog;
break;
case DT_CTX_DEXPR:
@@ -1759,35 +1778,3 @@ dtrace_type_fcompile(dtrace_hdl_t *dtp, FILE *fp, dtrace_typeinfo_t *dtt)
DTRACE_PROBESPEC_NONE, dtt, 0, 0, NULL, fp, NULL);
return (dtp->dt_errno ? -1 : 0);
}
-
-dtrace_difo_t *
-dtrace_difo_create(dtrace_hdl_t *dtp, const char *s)
-{
- return (dt_compile(dtp, DT_CTX_DEXPR,
- DTRACE_PROBESPEC_NONE, NULL, 0, 0, NULL, NULL, s));
-}
-
-void
-dtrace_difo_hold(dtrace_difo_t *dp)
-{
- dp->dtdo_refcnt++;
- assert(dp->dtdo_refcnt != 0);
-}
-
-void
-dtrace_difo_release(dtrace_difo_t *dp)
-{
- assert(dp->dtdo_refcnt != 0);
-
- if (--dp->dtdo_refcnt != 0)
- return;
-
- free(dp->dtdo_buf);
- free(dp->dtdo_inttab);
- free(dp->dtdo_strtab);
- free(dp->dtdo_vartab);
- free(dp->dtdo_kreltab);
- free(dp->dtdo_ureltab);
-
- free(dp);
-}
diff --git a/usr/src/lib/libdtrace/common/dt_cg.c b/usr/src/lib/libdtrace/common/dt_cg.c
index 8fc42615f8..4557c6f85c 100644
--- a/usr/src/lib/libdtrace/common/dt_cg.c
+++ b/usr/src/lib/libdtrace/common/dt_cg.c
@@ -53,7 +53,7 @@ dt_cg_node_alloc(uint_t label, dif_instr_t instr)
dip->di_label = label;
dip->di_instr = instr;
- dip->di_ident = NULL;
+ dip->di_extern = NULL;
dip->di_next = NULL;
return (dip);
@@ -102,7 +102,7 @@ dt_cg_xsetx(dt_irlist_t *dlp, dt_ident_t *idp, uint_t lbl, int reg, uint64_t x)
dt_irlist_append(dlp, dt_cg_node_alloc(lbl, instr));
if (idp != NULL)
- dlp->dl_last->di_ident = idp;
+ dlp->dl_last->di_extern = idp;
}
static void
@@ -532,7 +532,7 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args,
uint_t op;
int reg;
- dt_node_diftype(dnp, &t);
+ dt_node_diftype(yypcb->pcb_hdl, dnp, &t);
isp->dis_args[i].dn_reg = dnp->dn_reg; /* re-use register */
dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
@@ -1089,8 +1089,10 @@ dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
dxp->dx_ident->di_id = 0;
+ if (dnp->dn_right->dn_reg != -1)
+ dt_regset_free(drp, dnp->dn_right->dn_reg);
+
assert(dnp->dn_reg == dnp->dn_right->dn_reg);
- dt_regset_free(drp, dnp->dn_right->dn_reg);
dnp->dn_reg = r1;
}
@@ -1207,6 +1209,7 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
dt_probe_t *prp = yypcb->pcb_probe;
uintmax_t saved = dnp->dn_args->dn_value;
+ dt_ident_t *idp = dnp->dn_ident;
dif_instr_t instr;
uint_t op;
@@ -1214,31 +1217,41 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
int reg, n;
assert(dnp->dn_kind == DT_NODE_VAR);
- assert(!(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL));
+ assert(!(idp->di_flags & DT_IDFLG_LOCAL));
assert(dnp->dn_args->dn_kind == DT_NODE_INT);
assert(dnp->dn_args->dn_list == NULL);
/*
* If this is a reference in the args[] array, temporarily modify the
- * array index according to the static argument mapping (if any).
+ * array index according to the static argument mapping (if any),
+ * unless the argument reference is provided by a dynamic translator.
+ * If we're using a dynamic translator for args[], then just set dn_reg
+ * to an invalid reg and return: DIF_OP_XLARG will fetch the arg later.
*/
- if (dnp->dn_ident->di_id == DIF_VAR_ARGS)
+ if (idp->di_id == DIF_VAR_ARGS) {
+ if ((idp->di_kind == DT_IDENT_XLPTR ||
+ idp->di_kind == DT_IDENT_XLSOU) &&
+ dt_xlator_dynamic(idp->di_data)) {
+ dnp->dn_reg = -1;
+ return;
+ }
dnp->dn_args->dn_value = prp->pr_mapping[saved];
+ }
dt_cg_node(dnp->dn_args, dlp, drp);
dnp->dn_args->dn_value = saved;
dnp->dn_reg = dnp->dn_args->dn_reg;
- if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
+ if (idp->di_flags & DT_IDFLG_TLS)
op = DIF_OP_LDTA;
else
op = DIF_OP_LDGA;
- dnp->dn_ident->di_flags |= DT_IDFLG_DIFR;
+ idp->di_flags |= DT_IDFLG_DIFR;
- instr = DIF_INSTR_LDA(op, dnp->dn_ident->di_id,
+ instr = DIF_INSTR_LDA(op, idp->di_id,
dnp->dn_args->dn_reg, dnp->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1254,7 +1267,7 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
* 32-bit argument must be retrieved from the stack, it is possible
* (and it some cases, likely) that the upper bits will be garbage.
*/
- if (dnp->dn_ident->di_id != DIF_VAR_ARGS || !dt_node_is_scalar(dnp))
+ if (idp->di_id != DIF_VAR_ARGS || !dt_node_is_scalar(dnp))
return;
if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
@@ -1590,6 +1603,40 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
break;
case DT_TOK_XLATE:
+ /*
+ * An xlate operator appears in either an XLATOR, indicating a
+ * reference to a dynamic translator, or an OP2, indicating
+ * use of the xlate operator in the user's program. For the
+ * dynamic case, generate an xlate opcode with a reference to
+ * the corresponding member, pre-computed for us in dn_members.
+ */
+ if (dnp->dn_kind == DT_NODE_XLATOR) {
+ dt_xlator_t *dxp = dnp->dn_xlator;
+
+ assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
+ assert(dxp->dx_ident->di_id != 0);
+
+ if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ if (dxp->dx_arg == -1) {
+ instr = DIF_INSTR_MOV(
+ dxp->dx_ident->di_id, dnp->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+ op = DIF_OP_XLATE;
+ } else
+ op = DIF_OP_XLARG;
+
+ instr = DIF_INSTR_XLATE(op, 0, dnp->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ dlp->dl_last->di_extern = dnp->dn_xmember;
+ break;
+ }
+
+ assert(dnp->dn_kind == DT_NODE_OP2);
dt_cg_node(dnp->dn_right, dlp, drp);
dnp->dn_reg = dnp->dn_right->dn_reg;
break;
@@ -1634,7 +1681,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
dxp->dx_ident->di_id = 0;
- dt_regset_free(drp, dnp->dn_left->dn_reg);
+ if (dnp->dn_left->dn_reg != -1)
+ dt_regset_free(drp, dnp->dn_left->dn_reg);
break;
}
@@ -1855,6 +1903,7 @@ void
dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
{
dif_instr_t instr;
+ dt_xlator_t *dxp;
if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
@@ -1886,8 +1935,26 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
"of dynamic type\n");
}
+ /*
+ * If we're generating code for a translator body, assign the input
+ * parameter to the first available register (i.e. caller passes %r1).
+ */
+ if (dnp->dn_kind == DT_NODE_MEMBER) {
+ dxp = dnp->dn_membxlator;
+ dnp = dnp->dn_membexpr;
+
+ dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
+ dxp->dx_ident->di_id = dt_regset_alloc(pcb->pcb_regs);
+ }
+
dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
instr = DIF_INSTR_RET(dnp->dn_reg);
dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ if (dnp->dn_kind == DT_NODE_MEMBER) {
+ dt_regset_free(pcb->pcb_regs, dxp->dx_ident->di_id);
+ dxp->dx_ident->di_id = 0;
+ dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
+ }
}
diff --git a/usr/src/lib/libdtrace/common/dt_dis.c b/usr/src/lib/libdtrace/common/dt_dis.c
index 5f09127262..f4bb0c4bba 100644
--- a/usr/src/lib/libdtrace/common/dt_dis.c
+++ b/usr/src/lib/libdtrace/common/dt_dis.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,8 +28,9 @@
#include <strings.h>
#include <stdio.h>
-#include <dt_ident.h>
+
#include <dt_impl.h>
+#include <dt_ident.h>
/*ARGSUSED*/
static void
@@ -198,50 +199,16 @@ dt_dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
static void
dt_dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t in, FILE *fp)
{
- static const struct {
- const char *name;
- int subr;
- } snames[] = {
- { "rand", DIF_SUBR_RAND },
- { "mutex_owned", DIF_SUBR_MUTEX_OWNED },
- { "mutex_owner", DIF_SUBR_MUTEX_OWNER },
- { "mutex_type_adaptive", DIF_SUBR_MUTEX_TYPE_ADAPTIVE },
- { "mutex_type_spin", DIF_SUBR_MUTEX_TYPE_SPIN },
- { "rw_read_held", DIF_SUBR_RW_READ_HELD },
- { "rw_write_held", DIF_SUBR_RW_WRITE_HELD },
- { "rw_iswriter", DIF_SUBR_RW_ISWRITER },
- { "copyin", DIF_SUBR_COPYIN },
- { "copyinstr", DIF_SUBR_COPYINSTR },
- { "speculation", DIF_SUBR_SPECULATION },
- { "progenyof", DIF_SUBR_PROGENYOF },
- { "strlen", DIF_SUBR_STRLEN },
- { "copyout", DIF_SUBR_COPYOUT },
- { "copyoutstr", DIF_SUBR_COPYOUTSTR },
- { "alloca", DIF_SUBR_ALLOCA },
- { "bcopy", DIF_SUBR_BCOPY },
- { "copyinto", DIF_SUBR_COPYINTO },
- { "msgdsize", DIF_SUBR_MSGDSIZE },
- { "msgsize", DIF_SUBR_MSGSIZE },
- { NULL, 0 }
- };
-
- uint_t subr = DIF_INSTR_SUBR(in), i;
+ uint_t subr = DIF_INSTR_SUBR(in);
- (void) fprintf(fp, "%-4s DIF_SUBR(%u), %%r%u",
- name, subr, DIF_INSTR_RD(in));
-
- for (i = 0; snames[i].name != NULL; i++) {
- if (subr == snames[i].subr) {
- (void) fprintf(fp, "\t\t! %s", snames[i].name);
- return;
- }
- }
+ (void) fprintf(fp, "%-4s DIF_SUBR(%u), %%r%u\t\t! %s",
+ name, subr, DIF_INSTR_RD(in), dtrace_subrstr(NULL, subr));
}
/*ARGSUSED*/
static void
-dt_dis_pushts(const dtrace_difo_t *dp, const char *name,
- dif_instr_t in, FILE *fp)
+dt_dis_pushts(const dtrace_difo_t *dp,
+ const char *name, dif_instr_t in, FILE *fp)
{
static const char *const tnames[] = { "D type", "string" };
uint_t type = DIF_INSTR_TYPE(in);
@@ -253,6 +220,22 @@ dt_dis_pushts(const dtrace_difo_t *dp, const char *name,
(void) fprintf(fp, "\t! DT_TYPE(%u) = %s", type, tnames[type]);
}
+static void
+dt_dis_xlate(const dtrace_difo_t *dp,
+ const char *name, dif_instr_t in, FILE *fp)
+{
+ uint_t xlr = DIF_INSTR_XLREF(in);
+
+ (void) fprintf(fp, "%-4s DT_XLREF[%u], %%r%u",
+ name, xlr, DIF_INSTR_RD(in));
+
+ if (xlr < dp->dtdo_xlmlen) {
+ (void) fprintf(fp, "\t\t! DT_XLREF[%u] = %u.%s", xlr,
+ (uint_t)dp->dtdo_xlmtab[xlr]->dn_membexpr->dn_xlator->dx_id,
+ dp->dtdo_xlmtab[xlr]->dn_membname);
+ }
+}
+
static char *
dt_dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
{
@@ -343,7 +326,7 @@ dt_dis_rtab(const char *rtag, const dtrace_difo_t *dp, FILE *fp,
}
void
-dtrace_difo_print(const dtrace_difo_t *dp, FILE *fp)
+dt_dis(const dtrace_difo_t *dp, FILE *fp)
{
static const struct opent {
const char *op_name;
@@ -428,14 +411,15 @@ dtrace_difo_print(const dtrace_difo_t *dp, FILE *fp)
{ "rlduh", dt_dis_load }, /* DIF_OP_RLDUH */
{ "rlduw", dt_dis_load }, /* DIF_OP_RLDUW */
{ "rldx", dt_dis_load }, /* DIF_OP_RLDX */
+ { "xlate", dt_dis_xlate }, /* DIF_OP_XLATE */
+ { "xlarg", dt_dis_xlate }, /* DIF_OP_XLARG */
};
const struct opent *op;
ulong_t i = 0;
- char type[64];
+ char type[DT_TYPE_NAMELEN];
- (void) fprintf(fp, "DIFO 0x%p refcnt=%u returns %s\n",
- (void *)dp, dp->dtdo_refcnt,
+ (void) fprintf(fp, "\nDIFO 0x%p returns %s\n", (void *)dp,
dt_dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
(void) fprintf(fp, "%-3s %-8s %s\n",
@@ -506,6 +490,19 @@ dtrace_difo_print(const dtrace_difo_t *dp, FILE *fp)
dt_dis_typestr(&v->dtdv_type, type, sizeof (type)));
}
+ if (dp->dtdo_xlmlen != 0) {
+ (void) fprintf(fp, "\n%-4s %-3s %-12s %s\n",
+ "XLID", "ARG", "MEMBER", "TYPE");
+ }
+
+ for (i = 0; i < dp->dtdo_xlmlen; i++) {
+ dt_node_t *dnp = dp->dtdo_xlmtab[i];
+ dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator;
+ (void) fprintf(fp, "%-4u %-3d %-12s %s\n",
+ (uint_t)dxp->dx_id, dxp->dx_arg, dnp->dn_membname,
+ dt_node_type_name(dnp, type, sizeof (type)));
+ }
+
if (dp->dtdo_krelen != 0)
dt_dis_rtab("KREL", dp, fp, dp->dtdo_kreltab, dp->dtdo_krelen);
diff --git a/usr/src/lib/libdtrace/common/dt_dof.c b/usr/src/lib/libdtrace/common/dt_dof.c
index 45ec0119e7..8fdc7a9381 100644
--- a/usr/src/lib/libdtrace/common/dt_dof.c
+++ b/usr/src/lib/libdtrace/common/dt_dof.c
@@ -38,7 +38,9 @@
#include <dt_impl.h>
#include <dt_strtab.h>
+#include <dt_program.h>
#include <dt_provider.h>
+#include <dt_xlator.h>
#include <dt_dof.h>
void
@@ -49,6 +51,8 @@ dt_dof_init(dtrace_hdl_t *dtp)
ddo->ddo_hdl = dtp;
ddo->ddo_nsecs = 0;
ddo->ddo_strsec = DOF_SECIDX_NONE;
+ ddo->ddo_xlimport = NULL;
+ ddo->ddo_xlexport = NULL;
dt_buf_create(dtp, &ddo->ddo_secs, "section headers", 0);
dt_buf_create(dtp, &ddo->ddo_strs, "string table", 0);
@@ -59,6 +63,8 @@ dt_dof_init(dtrace_hdl_t *dtp)
dt_buf_create(dtp, &ddo->ddo_args, "probe args", 0);
dt_buf_create(dtp, &ddo->ddo_offs, "probe offs", 0);
dt_buf_create(dtp, &ddo->ddo_rels, "probe rels", 0);
+
+ dt_buf_create(dtp, &ddo->ddo_xlms, "xlate members", 0);
}
void
@@ -66,6 +72,9 @@ dt_dof_fini(dtrace_hdl_t *dtp)
{
dt_dof_t *ddo = &dtp->dt_dof;
+ dt_free(dtp, ddo->ddo_xlimport);
+ dt_free(dtp, ddo->ddo_xlexport);
+
dt_buf_destroy(dtp, &ddo->ddo_secs);
dt_buf_destroy(dtp, &ddo->ddo_strs);
dt_buf_destroy(dtp, &ddo->ddo_ldata);
@@ -75,16 +84,36 @@ dt_dof_fini(dtrace_hdl_t *dtp)
dt_buf_destroy(dtp, &ddo->ddo_args);
dt_buf_destroy(dtp, &ddo->ddo_offs);
dt_buf_destroy(dtp, &ddo->ddo_rels);
+
+ dt_buf_destroy(dtp, &ddo->ddo_xlms);
}
-void
-dt_dof_reset(dtrace_hdl_t *dtp)
+static int
+dt_dof_reset(dtrace_hdl_t *dtp, dtrace_prog_t *pgp)
{
dt_dof_t *ddo = &dtp->dt_dof;
+ uint_t i, nx = dtp->dt_xlatorid;
+
+ assert(ddo->ddo_hdl == dtp);
+ ddo->ddo_pgp = pgp;
ddo->ddo_nsecs = 0;
ddo->ddo_strsec = DOF_SECIDX_NONE;
+ dt_free(dtp, ddo->ddo_xlimport);
+ dt_free(dtp, ddo->ddo_xlexport);
+
+ ddo->ddo_xlimport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx);
+ ddo->ddo_xlexport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx);
+
+ if (nx != 0 && (ddo->ddo_xlimport == NULL || ddo->ddo_xlexport == NULL))
+ return (-1); /* errno is set for us */
+
+ for (i = 0; i < nx; i++) {
+ ddo->ddo_xlimport[i] = DOF_SECIDX_NONE;
+ ddo->ddo_xlexport[i] = DOF_SECIDX_NONE;
+ }
+
dt_buf_reset(dtp, &ddo->ddo_secs);
dt_buf_reset(dtp, &ddo->ddo_strs);
dt_buf_reset(dtp, &ddo->ddo_ldata);
@@ -94,6 +123,9 @@ dt_dof_reset(dtrace_hdl_t *dtp)
dt_buf_reset(dtp, &ddo->ddo_args);
dt_buf_reset(dtp, &ddo->ddo_offs);
dt_buf_reset(dtp, &ddo->ddo_rels);
+
+ dt_buf_reset(dtp, &ddo->ddo_xlms);
+ return (0);
}
/*
@@ -176,7 +208,7 @@ dof_attr(const dtrace_attribute_t *ap)
static dof_secidx_t
dof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp)
{
- dof_secidx_t dsecs[4]; /* enough for all possible DIFO sections */
+ dof_secidx_t dsecs[5]; /* enough for all possible DIFO sections */
uint_t nsecs = 0;
dof_difohdr_t *dofd;
@@ -210,6 +242,35 @@ dof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp)
sizeof (dtrace_difv_t) * dp->dtdo_varlen);
}
+ if (dp->dtdo_xlmtab != NULL) {
+ dof_xlref_t *xlt, *xlp;
+ dt_node_t **pnp;
+
+ xlt = alloca(sizeof (dof_xlref_t) * dp->dtdo_xlmlen);
+ pnp = dp->dtdo_xlmtab;
+
+ /*
+ * dtdo_xlmtab contains pointers to the translator members.
+ * The translator itself is in sect ddo_xlimport[dxp->dx_id].
+ * The XLMEMBERS entries are in order by their dn_membid, so
+ * the member section offset is the population count of bits
+ * in ddo_pgp->dp_xlrefs[] up to and not including dn_membid.
+ */
+ for (xlp = xlt; xlp < xlt + dp->dtdo_xlmlen; xlp++) {
+ dt_node_t *dnp = *pnp++;
+ dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator;
+
+ xlp->dofxr_xlator = ddo->ddo_xlimport[dxp->dx_id];
+ xlp->dofxr_member = dt_popcb(
+ ddo->ddo_pgp->dp_xrefs[dxp->dx_id], dnp->dn_membid);
+ xlp->dofxr_argn = (uint32_t)dxp->dx_arg;
+ }
+
+ dsecs[nsecs++] = dof_add_lsect(ddo, xlt, DOF_SECT_XLTAB,
+ sizeof (dof_secidx_t), 0, sizeof (dof_xlref_t),
+ sizeof (dof_xlref_t) * dp->dtdo_xlmlen);
+ }
+
/*
* Copy the return type and the array of section indices that form the
* DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR.
@@ -266,6 +327,66 @@ dof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp)
return (hdrsec);
}
+static void
+dof_add_translator(dt_dof_t *ddo, const dt_xlator_t *dxp, uint_t type)
+{
+ dtrace_hdl_t *dtp = ddo->ddo_hdl;
+ dof_xlmember_t dofxm;
+ dof_xlator_t dofxl;
+ dof_secidx_t *xst;
+
+ char buf[DT_TYPE_NAMELEN];
+ dt_node_t *dnp;
+ uint_t i = 0;
+
+ assert(type == DOF_SECT_XLIMPORT || type == DOF_SECT_XLEXPORT);
+ xst = type == DOF_SECT_XLIMPORT ? ddo->ddo_xlimport : ddo->ddo_xlexport;
+
+ if (xst[dxp->dx_id] != DOF_SECIDX_NONE)
+ return; /* translator has already been emitted */
+
+ dt_buf_reset(dtp, &ddo->ddo_xlms);
+
+ /*
+ * Generate an array of dof_xlmember_t's into ddo_xlms. If we are
+ * importing the translator, add only those members referenced by the
+ * program and set the dofxm_difo reference of each member to NONE. If
+ * we're exporting the translator, add all members and a DIFO for each.
+ */
+ for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list, i++) {
+ if (type == DOF_SECT_XLIMPORT) {
+ if (!BT_TEST(ddo->ddo_pgp->dp_xrefs[dxp->dx_id], i))
+ continue; /* member is not referenced */
+ dofxm.dofxm_difo = DOF_SECIDX_NONE;
+ } else {
+ dofxm.dofxm_difo = dof_add_difo(ddo,
+ dxp->dx_membdif[dnp->dn_membid]);
+ }
+
+ dofxm.dofxm_name = dof_add_string(ddo, dnp->dn_membname);
+ dt_node_diftype(dtp, dnp, &dofxm.dofxm_type);
+
+ dt_buf_write(dtp, &ddo->ddo_xlms,
+ &dofxm, sizeof (dofxm), sizeof (uint32_t));
+ }
+
+ dofxl.dofxl_members = dof_add_lsect(ddo, NULL, DOF_SECT_XLMEMBERS,
+ sizeof (uint32_t), 0, sizeof (dofxm), dt_buf_len(&ddo->ddo_xlms));
+
+ dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_xlms, sizeof (uint32_t));
+
+ dofxl.dofxl_strtab = ddo->ddo_strsec;
+ dofxl.dofxl_argv = dof_add_string(ddo, ctf_type_name(
+ dxp->dx_src_ctfp, dxp->dx_src_type, buf, sizeof (buf)));
+ dofxl.dofxl_argc = 1;
+ dofxl.dofxl_type = dof_add_string(ddo, ctf_type_name(
+ dxp->dx_dst_ctfp, dxp->dx_dst_type, buf, sizeof (buf)));
+ dofxl.dofxl_attr = dof_attr(&dxp->dx_souid.di_attr);
+
+ xst[dxp->dx_id] = dof_add_lsect(ddo, &dofxl, type,
+ sizeof (uint32_t), 0, 0, sizeof (dofxl));
+}
+
/*ARGSUSED*/
static int
dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
@@ -339,10 +460,30 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
dtrace_hdl_t *dtp = ddo->ddo_hdl;
dof_provider_t dofpv;
dof_relohdr_t dofr;
+ dof_secidx_t *dofs;
+ ulong_t xr, nxr;
+ id_t i;
if (pvp->pv_flags & DT_PROVIDER_IMPL)
return; /* ignore providers that are exported by dtrace(7D) */
+ nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax);
+ dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1));
+ xr = 1; /* reserve dofs[0] for the provider itself */
+
+ /*
+ * For each translator referenced by the provider (pv_xrefs), emit an
+ * exported translator section for it if one hasn't been created yet.
+ */
+ for (i = 0; i < pvp->pv_xrmax; i++) {
+ if (BT_TEST(pvp->pv_xrefs, i) &&
+ dtp->dt_xlatemode == DT_XL_DYNAMIC) {
+ dof_add_translator(ddo,
+ dt_xlator_lookup_id(dtp, i), DOF_SECT_XLEXPORT);
+ dofs[xr++] = ddo->ddo_xlexport[i];
+ }
+ }
+
dt_buf_reset(dtp, &ddo->ddo_probes);
dt_buf_reset(dtp, &ddo->ddo_args);
dt_buf_reset(dtp, &ddo->ddo_offs);
@@ -376,7 +517,7 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name);
dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args);
- (void) dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER,
+ dofs[0] = dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER,
sizeof (dof_secidx_t), 0, 0, sizeof (dof_provider_t));
dofr.dofr_strtab = dofpv.dofpv_strtab;
@@ -389,6 +530,12 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
(void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR,
sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t));
+
+ if (nxr != 0 && dtp->dt_xlatemode == DT_XL_DYNAMIC) {
+ (void) dof_add_lsect(ddo, dofs, DOF_SECT_PREXPORT,
+ sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t),
+ sizeof (dof_secidx_t) * (nxr + 1));
+ }
}
static int
@@ -443,6 +590,7 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
uint_t maxfmt = 0;
dt_provider_t *pvp;
+ dt_xlator_t *dxp;
dof_actdesc_t *dofa;
dof_sec_t *sp;
size_t ssize, lsize;
@@ -462,8 +610,8 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
if (dof_hdr(dtp, &h) != 0)
return (NULL);
- assert(ddo->ddo_hdl == dtp);
- dt_dof_reset(dtp);
+ if (dt_dof_reset(dtp, pgp) != 0)
+ return (NULL);
/*
* Iterate through the statement list computing the maximum number of
@@ -497,6 +645,19 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
(void) dof_add_string(ddo, "");
/*
+ * If there are references to dynamic translators in the program, add
+ * an imported translator table entry for each referenced translator.
+ */
+ if (pgp->dp_xrefslen != 0) {
+ for (dxp = dt_list_next(&dtp->dt_xlators);
+ dxp != NULL; dxp = dt_list_next(dxp)) {
+ if (dxp->dx_id < pgp->dp_xrefslen &&
+ pgp->dp_xrefs[dxp->dx_id] != NULL)
+ dof_add_translator(ddo, dxp, DOF_SECT_XLIMPORT);
+ }
+ }
+
+ /*
* Now iterate through the statement list, creating the DOF section
* headers and data for each one and adding them to our buffers.
*/
diff --git a/usr/src/lib/libdtrace/common/dt_dof.h b/usr/src/lib/libdtrace/common/dt_dof.h
index aa169f7653..9d20f624e7 100644
--- a/usr/src/lib/libdtrace/common/dt_dof.h
+++ b/usr/src/lib/libdtrace/common/dt_dof.h
@@ -39,8 +39,11 @@ extern "C" {
typedef struct dt_dof {
dtrace_hdl_t *ddo_hdl; /* libdtrace handle */
+ dtrace_prog_t *ddo_pgp; /* current program */
uint_t ddo_nsecs; /* number of sections */
dof_secidx_t ddo_strsec; /* global strings section index */
+ dof_secidx_t *ddo_xlimport; /* imported xlator section indices */
+ dof_secidx_t *ddo_xlexport; /* exported xlator section indices */
dt_buf_t ddo_secs; /* section headers */
dt_buf_t ddo_strs; /* global strings */
dt_buf_t ddo_ldata; /* loadable section data */
@@ -49,11 +52,11 @@ typedef struct dt_dof {
dt_buf_t ddo_args; /* probe arguments section data */
dt_buf_t ddo_offs; /* probe offsets section data */
dt_buf_t ddo_rels; /* probe relocation section data */
+ dt_buf_t ddo_xlms; /* xlate members section data */
} dt_dof_t;
extern void dt_dof_init(dtrace_hdl_t *);
extern void dt_dof_fini(dtrace_hdl_t *);
-extern void dt_dof_reset(dtrace_hdl_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdtrace/common/dt_errtags.h b/usr/src/lib/libdtrace/common/dt_errtags.h
index ade849d075..b8489cd7fc 100644
--- a/usr/src/lib/libdtrace/common/dt_errtags.h
+++ b/usr/src/lib/libdtrace/common/dt_errtags.h
@@ -228,6 +228,7 @@ typedef enum {
D_PROV_INCOMPAT, /* provider/probe interface mismatch */
D_PROV_PRDUP, /* duplicate probe declaration */
D_PROV_PRARGLEN, /* probe argument list too long */
+ D_PROV_PRXLATOR, /* probe argument translator missing */
D_FREOPEN_INVALID /* frename() filename is invalid */
} dt_errtag_t;
diff --git a/usr/src/lib/libdtrace/common/dt_grammar.y b/usr/src/lib/libdtrace/common/dt_grammar.y
index b107e774ac..e981514db8 100644
--- a/usr/src/lib/libdtrace/common/dt_grammar.y
+++ b/usr/src/lib/libdtrace/common/dt_grammar.y
@@ -288,10 +288,10 @@ provider_probe_list:
provider_probe:
DT_KEY_PROBE DT_TOK_IDENT function DT_TOK_COLON function ';' {
- $$ = dt_node_probe($2, $3, $5);
+ $$ = dt_node_probe($2, 2, $3, $5);
}
| DT_KEY_PROBE DT_TOK_IDENT function ';' {
- $$ = dt_node_probe($2, $3, NULL);
+ $$ = dt_node_probe($2, 1, $3, NULL);
}
;
diff --git a/usr/src/lib/libdtrace/common/dt_handle.c b/usr/src/lib/libdtrace/common/dt_handle.c
index ab1bf05ff8..2e8e668010 100644
--- a/usr/src/lib/libdtrace/common/dt_handle.c
+++ b/usr/src/lib/libdtrace/common/dt_handle.c
@@ -31,10 +31,12 @@
#include <strings.h>
#include <errno.h>
#include <unistd.h>
-#include <dt_impl.h>
#include <assert.h>
#include <alloca.h>
+#include <dt_impl.h>
+#include <dt_program.h>
+
static const char _dt_errprog[] =
"dtrace:::ERROR"
"{"
diff --git a/usr/src/lib/libdtrace/common/dt_ident.c b/usr/src/lib/libdtrace/common/dt_ident.c
index fc4ca99406..e2be36a9c8 100644
--- a/usr/src/lib/libdtrace/common/dt_ident.c
+++ b/usr/src/lib/libdtrace/common/dt_ident.c
@@ -310,7 +310,7 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
dt_probe_t *prp = yypcb->pcb_probe;
- dt_node_t *nnp, *xnp;
+ dt_node_t tag, *nnp, *xnp;
dt_xlator_t *dxp;
dt_ident_t *xidp;
@@ -349,8 +349,7 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
}
/*
- * In order to support statically-defined KSDT translators, look up the
- * native and translated argument types for the representative probe.
+ * Look up the native and translated argument types for the probe.
* If no translation is needed, these will be the same underlying node.
* If translation is needed, look up the appropriate translator. Once
* we have the appropriate node, create a new dt_ident_t for this node,
@@ -369,10 +368,11 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
"%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value);
}
- if (nnp == xnp || dt_node_is_argcompat(nnp, xnp)) {
+ if (dtp->dt_xlatemode == DT_XL_STATIC && (
+ nnp == xnp || dt_node_is_argcompat(nnp, xnp))) {
dnp->dn_ident = dt_ident_create(idp->di_name, idp->di_kind,
idp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
- idp->di_vers, idp->di_ops, idp->di_iarg, dtp->dt_gen);
+ idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen);
if (dnp->dn_ident == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
@@ -382,17 +382,22 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
prp->pr_argv[ap->dn_value].dtt_type);
} else if ((dxp = dt_xlator_lookup(dtp,
- nnp, xnp, DT_XLATE_FUZZY)) != NULL) {
+ nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
+ dxp = dt_xlator_lookup(dtp, dt_probe_tag(prp, ap->dn_value, &tag),
+ xnp, DT_XLATE_EXACT | DT_XLATE_EXTERN)) != NULL) {
xidp = dt_xlator_ident(dxp, xnp->dn_ctfp, xnp->dn_type);
dnp->dn_ident = dt_ident_create(idp->di_name, xidp->di_kind,
xidp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
- idp->di_vers, idp->di_ops, idp->di_iarg, dtp->dt_gen);
+ idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen);
if (dnp->dn_ident == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
+ if (dt_xlator_dynamic(dxp))
+ dxp->dx_arg = (int)ap->dn_value;
+
/*
* Propagate relevant members from the translator's internal
* dt_ident_t. This code must be kept in sync with the state
@@ -803,7 +808,8 @@ dt_idhash_delete(dt_idhash_t *dhp, dt_ident_t *key)
assert(dhp->dh_nelems != 0);
dhp->dh_nelems--;
- dt_ident_destroy(idp);
+ if (!(idp->di_flags & DT_IDFLG_ORPHAN))
+ dt_ident_destroy(idp);
}
static int
@@ -963,6 +969,9 @@ dt_ident_resolve(dt_ident_t *idp)
while (idp->di_flags & DT_IDFLG_INLINE) {
const dt_node_t *dnp = ((dt_idnode_t *)idp->di_iarg)->din_root;
+ if (dnp == NULL)
+ break; /* can't resolve any further yet */
+
switch (dnp->dn_kind) {
case DT_NODE_VAR:
case DT_NODE_SYM:
diff --git a/usr/src/lib/libdtrace/common/dt_impl.h b/usr/src/lib/libdtrace/common/dt_impl.h
index 3df15e2340..055f3744e2 100644
--- a/usr/src/lib/libdtrace/common/dt_impl.h
+++ b/usr/src/lib/libdtrace/common/dt_impl.h
@@ -56,6 +56,7 @@ struct dt_module; /* see below */
struct dt_pfdict; /* see <dt_printf.h> */
struct dt_arg; /* see below */
struct dt_provider; /* see <dt_provider.h> */
+struct dt_xlator; /* see <dt_xlator.h> */
typedef struct dt_intrinsic {
const char *din_name; /* string name of the intrinsic type */
@@ -189,6 +190,8 @@ struct dtrace_hdl {
ulong_t dt_gen; /* compiler generation number */
dt_list_t dt_programs; /* linked list of dtrace_prog_t's */
dt_list_t dt_xlators; /* linked list of dt_xlator_t's */
+ struct dt_xlator **dt_xlatormap; /* dt_xlator_t's indexed by dx_id */
+ id_t dt_xlatorid; /* next dt_xlator_t id to assign */
dt_ident_t *dt_externs; /* linked list of external symbol identifiers */
dt_idhash_t *dt_macros; /* hash table of macro variable identifiers */
dt_idhash_t *dt_aggs; /* hash table of aggregation identifiers */
@@ -243,6 +246,7 @@ struct dtrace_hdl {
uint_t dt_prcmode; /* dtrace process create mode (see dt_proc.h) */
uint_t dt_linkmode; /* dtrace symbol linking mode (see below) */
uint_t dt_linktype; /* dtrace link output file type (see below) */
+ uint_t dt_xlatemode; /* dtrace translator linking mode (see below) */
uint_t dt_stdcmode; /* dtrace stdc compatibility mode (see below) */
uint_t dt_treedump; /* dtrace tree debug bitmap (see below) */
uint64_t dt_options[DTRACEOPT_MAX]; /* dtrace run-time options */
@@ -302,6 +306,13 @@ struct dtrace_hdl {
#define DT_LTYP_DOF 1 /* produce stand-alone DOF */
/*
+ * Values for the dt_xlatemode property, which is used to determine whether
+ * references to dynamic translators are permitted. Set using -xlate=<mode>.
+ */
+#define DT_XL_STATIC 0 /* require xlators to be statically defined */
+#define DT_XL_DYNAMIC 1 /* produce references to dynamic translators */
+
+/*
* Values for the dt_stdcmode property, which is used by the compiler when
* running cpp to determine the presence and setting of the __STDC__ macro.
*/
@@ -341,16 +352,6 @@ struct dtrace_hdl {
#define DT_STACK_CTFP(dtp) ((dtp)->dt_ddefs->dm_ctfp)
#define DT_STACK_TYPE(dtp) ((dtp)->dt_type_stack)
-typedef struct dt_stmt {
- dt_list_t ds_list; /* list forward/back pointers */
- dtrace_stmtdesc_t *ds_desc; /* pointer to statement description */
-} dt_stmt_t;
-
-struct dtrace_prog {
- dt_list_t dp_list; /* list forward/back pointers */
- dt_list_t dp_stmts; /* linked list of dt_stmt_t's */
-};
-
#define DT_ACT_PRINTF 0 /* printf() action */
#define DT_ACT_TRACE 1 /* trace() action */
#define DT_ACT_TRACEMEM 2 /* tracemem() action */
@@ -511,10 +512,14 @@ extern int dt_printf(dtrace_hdl_t *, FILE *, const char *, ...);
extern void *dt_zalloc(dtrace_hdl_t *, size_t);
extern void *dt_alloc(dtrace_hdl_t *, size_t);
extern void dt_free(dtrace_hdl_t *, void *);
+extern void dt_difo_free(dtrace_hdl_t *, dtrace_difo_t *);
extern int dt_gmatch(const char *, const char *);
extern char *dt_basename(char *);
+extern ulong_t dt_popc(ulong_t);
+extern ulong_t dt_popcb(const ulong_t *, ulong_t);
+
extern int dt_buffered_enable(dtrace_hdl_t *);
extern int dt_buffered_flush(dtrace_hdl_t *, dtrace_probedata_t *,
dtrace_recdesc_t *, dtrace_aggdata_t *);
@@ -541,6 +546,7 @@ extern void dt_pragma(dt_node_t *);
extern int dt_reduce(dtrace_hdl_t *, dt_version_t);
extern void dt_cg(dt_pcb_t *, dt_node_t *);
extern dtrace_difo_t *dt_as(dt_pcb_t *);
+extern void dt_dis(const dtrace_difo_t *, FILE *);
extern int dt_aggregate_go(dtrace_hdl_t *);
extern int dt_aggregate_init(dtrace_hdl_t *);
diff --git a/usr/src/lib/libdtrace/common/dt_lex.l b/usr/src/lib/libdtrace/common/dt_lex.l
index 76b7d0c7db..8c6a21b317 100644
--- a/usr/src/lib/libdtrace/common/dt_lex.l
+++ b/usr/src/lib/libdtrace/common/dt_lex.l
@@ -546,6 +546,7 @@ if (yypcb->pcb_token != 0) {
<S0>"\\"\n ; /* discard */
<S0>. yyerror("syntax error near \"%c\"\n", yytext[0]);
+<S1>"/*" yyerror("/* encountered inside a comment\n");
<S1>"*/" BEGIN(yypcb->pcb_cstate);
<S1>.|\n ; /* discard */
diff --git a/usr/src/lib/libdtrace/common/dt_link.c b/usr/src/lib/libdtrace/common/dt_link.c
index e680927059..45366995d0 100644
--- a/usr/src/lib/libdtrace/common/dt_link.c
+++ b/usr/src/lib/libdtrace/common/dt_link.c
@@ -868,9 +868,9 @@ dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
#error unknown ISA
#endif
-/*PRINTFLIKE2*/
+/*PRINTFLIKE3*/
static int
-dt_link_error(dtrace_hdl_t *dtp, const char *format, ...)
+dt_link_error(dtrace_hdl_t *dtp, Elf *elf, const char *format, ...)
{
va_list ap;
@@ -878,6 +878,9 @@ dt_link_error(dtrace_hdl_t *dtp, const char *format, ...)
dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
va_end(ap);
+ if (elf != NULL)
+ (void) elf_end(elf);
+
return (dt_set_errno(dtp, EDT_COMPILER));
}
@@ -886,7 +889,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
{
static const char dt_prefix[] = "__dtrace_";
int fd, i, ndx, mod = 0;
- Elf *elf;
+ Elf *elf = NULL;
GElf_Ehdr ehdr;
Elf_Scn *scn_rel, *scn_sym, *scn_tgt;
Elf_Data *data_rel, *data_sym, *data_tgt;
@@ -901,13 +904,12 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
uint32_t off, eclass, emachine1, emachine2;
if ((fd = open64(obj, O_RDWR)) == -1) {
- return (dt_link_error(dtp, "failed to open %s: %s", obj,
+ return (dt_link_error(dtp, elf, "failed to open %s: %s", obj,
strerror(errno)));
}
- if (elf_version(EV_CURRENT) == EV_NONE ||
- (elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
- return (dt_link_error(dtp, "failed to process %s: %s", obj,
+ if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
+ return (dt_link_error(dtp, elf, "failed to process %s: %s", obj,
elf_errmsg(elf_errno())));
}
@@ -915,14 +917,14 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
case ELF_K_ELF:
break;
case ELF_K_AR:
- return (dt_link_error(dtp, "archive files are not permitted %s;"
- " use the contents of the archive instead", obj));
+ return (dt_link_error(dtp, elf, "archives are not permitted;"
+ " use the contents of the archive instead: %s", obj));
default:
- return (dt_link_error(dtp, "invalid file type for %s", obj));
+ return (dt_link_error(dtp, elf, "invalid file type: %s", obj));
}
if (gelf_getehdr(elf, &ehdr) == NULL)
- return (dt_link_error(dtp, "corrupt object file %s", obj));
+ return (dt_link_error(dtp, elf, "corrupt file: %s", obj));
if (dtp->dt_oflags & DTRACE_O_LP64) {
eclass = ELFCLASS64;
@@ -941,13 +943,14 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
#endif
}
- if (ehdr.e_ident[EI_CLASS] != eclass)
- return (dt_link_error(dtp, "incorrect ELF class for object "
- "file %s", obj));
+ if (ehdr.e_ident[EI_CLASS] != eclass) {
+ return (dt_link_error(dtp, elf,
+ "incorrect ELF class for object file: %s", obj));
+ }
if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2)
- return (dt_link_error(dtp, "incorrect ELF machine type for "
- "object file %s", obj));
+ return (dt_link_error(dtp, elf, "incorrect ELF machine type "
+ "for object file: %s", obj));
scn_rel = NULL;
while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
@@ -1012,12 +1015,12 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
goto err;
if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, elf,
"no such provider %s", pname));
}
if ((prp = dt_probe_lookup(pvp, p)) == NULL) {
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, elf,
"no such probe %s", p));
}
@@ -1049,10 +1052,11 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
if (mod && elf_update(elf, ELF_C_WRITE) == -1)
goto err;
+ (void) elf_end(elf);
return (0);
err:
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, elf,
"an error was encountered while processing %s", obj));
}
@@ -1088,18 +1092,18 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
cur += snprintf(cmd + cur, len - cur, " %s", objv[i]);
if ((status = system(cmd)) == -1) {
- return (dt_link_error(dtp, "failed to run %s: %s",
+ return (dt_link_error(dtp, NULL, "failed to run %s: %s",
dtp->dt_ld_path, strerror(errno)));
}
if (WIFSIGNALED(status)) {
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, NULL,
"failed to link %s: %s failed due to signal %d",
file, dtp->dt_ld_path, WTERMSIG(status)));
}
if (WEXITSTATUS(status) != 0) {
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, NULL,
"failed to link %s: %s exited with status %d\n",
file, dtp->dt_ld_path, WEXITSTATUS(status)));
}
@@ -1126,7 +1130,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
* processes as /dev/fd/<fd>.
*/
if ((fd = open64(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, NULL,
"failed to open %s: %s", file, strerror(errno)));
}
@@ -1143,7 +1147,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
ret = errno;
if (ret != 0) {
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, NULL,
"failed to write %s: %s", file, strerror(ret)));
}
@@ -1153,7 +1157,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
break; /* fall through to the rest of dtrace_program_link() */
default:
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, NULL,
"invalid link type %u\n", dtp->dt_linktype));
}
@@ -1167,7 +1171,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
status = dump_elf32(dtp, dof, fd);
if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) {
- return (dt_link_error(dtp,
+ return (dt_link_error(dtp, NULL,
"failed to write %s: %s", file, strerror(errno)));
}
@@ -1190,7 +1194,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti);
if ((status = system(cmd)) == -1) {
- ret = dt_link_error(dtp, "failed to run %s: %s",
+ ret = dt_link_error(dtp, NULL, "failed to run %s: %s",
dtp->dt_ld_path, strerror(errno));
goto done;
}
@@ -1198,14 +1202,14 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
(void) close(fd); /* release temporary file */
if (WIFSIGNALED(status)) {
- ret = dt_link_error(dtp,
+ ret = dt_link_error(dtp, NULL,
"failed to link %s: %s failed due to signal %d",
file, dtp->dt_ld_path, WTERMSIG(status));
goto done;
}
if (WEXITSTATUS(status) != 0) {
- ret = dt_link_error(dtp,
+ ret = dt_link_error(dtp, NULL,
"failed to link %s: %s exited with status %d\n",
file, dtp->dt_ld_path, WEXITSTATUS(status));
goto done;
diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c
index a6970ae8d0..ae1eb076a6 100644
--- a/usr/src/lib/libdtrace/common/dt_open.c
+++ b/usr/src/lib/libdtrace/common/dt_open.c
@@ -47,6 +47,7 @@
#undef _POSIX_PTHREAD_SEMANTICS
#include <dt_impl.h>
+#include <dt_program.h>
#include <dt_module.h>
#include <dt_printf.h>
#include <dt_string.h>
@@ -831,6 +832,7 @@ alloc:
dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
dtp->dt_linkmode = DT_LINK_KERNEL;
dtp->dt_linktype = DT_LTYP_ELF;
+ dtp->dt_xlatemode = DT_XL_STATIC;
dtp->dt_stdcmode = DT_STDC_XA;
dtp->dt_version = version;
dtp->dt_fd = dtfd;
@@ -1176,7 +1178,7 @@ alloc:
return (set_open_errno(dtp, errp, EDT_HARDWIRE));
}
- dtrace_program_destroy(dtp, pgp);
+ dt_program_destroy(dtp, pgp);
/*
* Set up the default DTrace library path. Once set, the next call to
@@ -1216,11 +1218,13 @@ dtrace_close(dtrace_hdl_t *dtp)
int i;
while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
- dtrace_program_destroy(dtp, pgp);
+ dt_program_destroy(dtp, pgp);
while ((dxp = dt_list_next(&dtp->dt_xlators)) != NULL)
dt_xlator_destroy(dtp, dxp);
+ dt_free(dtp, dtp->dt_xlatormap);
+
for (idp = dtp->dt_externs; idp != NULL; idp = ndp) {
ndp = idp->di_next;
dt_ident_destroy(idp);
diff --git a/usr/src/lib/libdtrace/common/dt_options.c b/usr/src/lib/libdtrace/common/dt_options.c
index ae15a45413..5119368aca 100644
--- a/usr/src/lib/libdtrace/common/dt_options.c
+++ b/usr/src/lib/libdtrace/common/dt_options.c
@@ -427,6 +427,25 @@ dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
return (0);
}
+/*ARGSUSED*/
+static int
+dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ if (arg == NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (strcmp(arg, "dynamic") == 0)
+ dtp->dt_xlatemode = DT_XL_DYNAMIC;
+ else if (strcmp(arg, "static") == 0)
+ dtp->dt_xlatemode = DT_XL_STATIC;
+ else
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ return (0);
+}
+
+/*ARGSUSED*/
+
static int
dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
{
@@ -798,6 +817,7 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "iregs", dt_opt_iregs },
{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
+ { "late", dt_opt_xlate },
{ "lazyload", dt_opt_lazyload },
{ "ldpath", dt_opt_ld_path },
{ "libdir", dt_opt_libdir },
diff --git a/usr/src/lib/libdtrace/common/dt_parser.c b/usr/src/lib/libdtrace/common/dt_parser.c
index c53d5ca522..e55907615e 100644
--- a/usr/src/lib/libdtrace/common/dt_parser.c
+++ b/usr/src/lib/libdtrace/common/dt_parser.c
@@ -894,7 +894,7 @@ dt_node_is_dynamic(const dt_node_t *dnp)
if (dnp->dn_kind == DT_NODE_VAR &&
(dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) {
const dt_idnode_t *inp = dnp->dn_ident->di_iarg;
- return (dt_node_is_dynamic(inp->din_root));
+ return (inp->din_root ? dt_node_is_dynamic(inp->din_root) : 0);
}
return (dnp->dn_ctfp == DT_DYN_CTFP(yypcb->pcb_hdl) &&
@@ -1250,7 +1250,8 @@ dt_node_ident(char *name)
(idp->di_flags & DT_IDFLG_INLINE)) {
dt_idnode_t *inp = idp->di_iarg;
- if (inp->din_root->dn_kind == DT_NODE_INT) {
+ if (inp->din_root != NULL &&
+ inp->din_root->dn_kind == DT_NODE_INT) {
free(name);
dnp = dt_node_alloc(DT_NODE_INT);
@@ -2339,6 +2340,7 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
dt_xlator_t *dxp;
dt_node_t *dnp;
int edst, esrc;
+ uint_t kind;
char n1[DT_TYPE_NAMELEN];
char n2[DT_TYPE_NAMELEN];
@@ -2367,6 +2369,19 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
dt_node_type_name(&dn, n2, sizeof (n2)));
}
+ kind = ctf_type_kind(dst.dtt_ctfp,
+ ctf_type_resolve(dst.dtt_ctfp, dst.dtt_type));
+
+ if (kind == CTF_K_FORWARD) {
+ xyerror(D_XLATE_SOU, "incomplete struct/union/enum %s\n",
+ dt_type_name(dst.dtt_ctfp, dst.dtt_type, n1, sizeof (n1)));
+ }
+
+ if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {
+ xyerror(D_XLATE_SOU,
+ "translator output type must be a struct or union\n");
+ }
+
dxp = dt_xlator_create(dtp, &src, &dst, name, members, yypcb->pcb_list);
yybegin(YYS_CLAUSE);
free(name);
@@ -2382,7 +2397,7 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
}
dt_node_t *
-dt_node_probe(char *s, dt_node_t *nargs, dt_node_t *xargs)
+dt_node_probe(char *s, int protoc, dt_node_t *nargs, dt_node_t *xargs)
{
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
int nargc, xargc;
@@ -2428,7 +2443,7 @@ dt_node_probe(char *s, dt_node_t *nargs, dt_node_t *xargs)
}
if (dnp->dn_ident == NULL || dt_probe_create(dtp,
- dnp->dn_ident, nargs, nargc, xargs, xargc) == NULL)
+ dnp->dn_ident, protoc, nargs, nargc, xargs, xargc) == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
return (dnp);
@@ -2439,6 +2454,7 @@ dt_node_provider(char *name, dt_node_t *probes)
{
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
dt_node_t *dnp = dt_node_alloc(DT_NODE_PROVIDER);
+ dt_node_t *lnp;
dnp->dn_provname = name;
dnp->dn_probes = probes;
@@ -2467,22 +2483,18 @@ dt_node_provider(char *name, dt_node_t *probes)
dnp->dn_provider->pv_flags |= DT_PROVIDER_INTF;
/*
- * If the provider is being redeclared, put the pcb_list back on to the
- * hold list (undo the effect of YYS_DEFINE on allocation). Otherwise
- * store all parse nodes created since we consumed the DT_KEY_PROVIDER
+ * Store all parse nodes created since we consumed the DT_KEY_PROVIDER
* token with the provider and then restore our lexing state to CLAUSE.
+ * Note that if dnp->dn_provred is true, we may end up storing dups of
+ * a provider's interface and implementation: we eat this space because
+ * the implementation will likely need to redeclare probe members, and
+ * therefore may result in those member nodes becoming persistent.
*/
- if (dnp->dn_provred) {
- while (yypcb->pcb_list != NULL) {
- dt_node_t *pnp = yypcb->pcb_list;
- yypcb->pcb_list = pnp->dn_link;
- pnp->dn_link = yypcb->pcb_hold;
- yypcb->pcb_hold = pnp;
- }
- } else {
- assert(dnp->dn_provider->pv_nodes == NULL);
- dnp->dn_provider->pv_nodes = yypcb->pcb_list;
- }
+ for (lnp = yypcb->pcb_list; lnp->dn_link != NULL; lnp = lnp->dn_link)
+ continue; /* skip to end of allocation list */
+
+ lnp->dn_link = dnp->dn_provider->pv_nodes;
+ dnp->dn_provider->pv_nodes = yypcb->pcb_list;
yybegin(YYS_CLAUSE);
return (dnp);
@@ -4126,21 +4138,6 @@ dt_cook_xlator(dt_node_t *dnp, uint_t idflags)
dtrace_attribute_t attr = _dtrace_maxattr;
ctf_membinfo_t ctm;
- ctf_id_t type;
- uint_t kind;
-
- type = ctf_type_resolve(dxp->dx_dst_ctfp, dxp->dx_dst_type);
- kind = ctf_type_kind(dxp->dx_dst_ctfp, type);
-
- if (kind == CTF_K_FORWARD) {
- xyerror(D_XLATE_SOU, "incomplete struct/union/enum %s\n",
- dt_type_name(dxp->dx_dst_ctfp, type, n1, sizeof (n1)));
- }
-
- if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {
- xyerror(D_XLATE_SOU,
- "translator output type must be a struct or union\n");
- }
/*
* Before cooking each translator member, we push a reference to the
@@ -4220,10 +4217,9 @@ dt_node_provider_cmp_argv(dt_provider_t *pvp, dt_node_t *pnp, const char *kind,
/*
* Compare a new probe declaration with an existing probe definition (either
- * from a previous declaration or cached from the kernel). If the new decl has
- * both an input and output parameter list, compare both lists. If the new
- * decl has only one list, only compare the output lists (i.e. assume the new
- * declaration is a probe interface and does not specify implementation).
+ * from a previous declaration or cached from the kernel). If the existing
+ * definition and declaration both have an input and output parameter list,
+ * compare both lists. Otherwise compare only the output parameter lists.
*/
static void
dt_node_provider_cmp(dt_provider_t *pvp, dt_node_t *pnp,
@@ -4232,10 +4228,65 @@ dt_node_provider_cmp(dt_provider_t *pvp, dt_node_t *pnp,
dt_node_provider_cmp_argv(pvp, pnp, "output",
old->pr_xargc, old->pr_xargs, new->pr_xargc, new->pr_xargs);
- if (new->pr_nargs != new->pr_xargs) {
+ if (old->pr_nargs != old->pr_xargs && new->pr_nargs != new->pr_xargs) {
dt_node_provider_cmp_argv(pvp, pnp, "input",
old->pr_nargc, old->pr_nargs, new->pr_nargc, new->pr_nargs);
}
+
+ if (old->pr_nargs == old->pr_xargs && new->pr_nargs != new->pr_xargs) {
+ if (pvp->pv_flags & DT_PROVIDER_IMPL) {
+ dnerror(pnp, D_PROV_INCOMPAT,
+ "provider interface mismatch: %s\n"
+ "\t current: probe %s:%s has an output prototype\n"
+ "\tprevious: probe %s:%s has no output prototype\n",
+ pvp->pv_desc.dtvd_name, pvp->pv_desc.dtvd_name,
+ new->pr_ident->di_name, pvp->pv_desc.dtvd_name,
+ old->pr_ident->di_name);
+ }
+
+ if (old->pr_ident->di_gen == yypcb->pcb_hdl->dt_gen)
+ old->pr_ident->di_flags |= DT_IDFLG_ORPHAN;
+
+ dt_idhash_delete(pvp->pv_probes, old->pr_ident);
+ dt_probe_declare(pvp, new);
+ }
+}
+
+static void
+dt_cook_probe(dt_node_t *dnp, dt_provider_t *pvp)
+{
+ dtrace_hdl_t *dtp = yypcb->pcb_hdl;
+ dt_probe_t *prp = dnp->dn_ident->di_data;
+
+ dt_xlator_t *dxp;
+ uint_t i;
+
+ char n1[DT_TYPE_NAMELEN];
+ char n2[DT_TYPE_NAMELEN];
+
+ if (prp->pr_nargs == prp->pr_xargs)
+ return;
+
+ for (i = 0; i < prp->pr_xargc; i++) {
+ dt_node_t *xnp = prp->pr_xargv[i];
+ dt_node_t *nnp = prp->pr_nargv[prp->pr_mapping[i]];
+
+ if ((dxp = dt_xlator_lookup(dtp,
+ nnp, xnp, DT_XLATE_FUZZY)) != NULL) {
+ if (dt_provider_xref(dtp, pvp, dxp->dx_id) != 0)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
+ continue;
+ }
+
+ if (dt_node_is_argcompat(nnp, xnp))
+ continue; /* no translator defined and none required */
+
+ dnerror(dnp, D_PROV_PRXLATOR, "translator for %s:%s output "
+ "argument #%u from %s to %s is not defined\n",
+ pvp->pv_desc.dtvd_name, dnp->dn_ident->di_name, i + 1,
+ dt_node_type_name(nnp, n1, sizeof (n1)),
+ dt_node_type_name(xnp, n2, sizeof (n2)));
+ }
}
/*ARGSUSED*/
@@ -4271,6 +4322,8 @@ dt_cook_provider(dt_node_t *dnp, uint_t idflags)
dnp->dn_provname, probename);
} else
dt_probe_declare(pvp, pnp->dn_ident->di_data);
+
+ dt_cook_probe(pnp, pvp);
}
return (dnp);
@@ -4397,10 +4450,16 @@ dt_node_link(dt_node_t *lp, dt_node_t *rp)
return (lp);
}
+/*
+ * Compute the DOF dtrace_diftype_t representation of a node's type. This is
+ * called from a variety of places in the library so it cannot assume yypcb
+ * is valid: any references to handle-specific data must be made through 'dtp'.
+ */
void
-dt_node_diftype(const dt_node_t *dnp, dtrace_diftype_t *tp)
+dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)
{
- if (dt_node_is_string(dnp)) {
+ if (dnp->dn_ctfp == DT_STR_CTFP(dtp) &&
+ dnp->dn_type == DT_STR_TYPE(dtp)) {
tp->dtdt_kind = DIF_TYPE_STRING;
tp->dtdt_ckind = CTF_K_UNKNOWN;
} else {
diff --git a/usr/src/lib/libdtrace/common/dt_parser.h b/usr/src/lib/libdtrace/common/dt_parser.h
index d63013c1ef..127b013045 100644
--- a/usr/src/lib/libdtrace/common/dt_parser.h
+++ b/usr/src/lib/libdtrace/common/dt_parser.h
@@ -88,10 +88,13 @@ typedef struct dt_node {
struct {
char *_name; /* string name of member */
struct dt_node *_expr; /* expression node pointer */
+ dt_xlator_t *_xlator; /* translator reference */
+ uint_t _id; /* member identifier */
} _member;
struct {
dt_xlator_t *_xlator; /* translator reference */
+ struct dt_node *_xmemb; /* individual xlator member */
struct dt_node *_membs; /* list of member nodes */
} _xlator;
@@ -126,7 +129,10 @@ typedef struct dt_node {
#define dn_desc dn_u._pdesc._desc /* DT_NODE_PDESC */
#define dn_membname dn_u._member._name /* DT_NODE_MEMBER */
#define dn_membexpr dn_u._member._expr /* DT_NODE_MEMBER */
+#define dn_membxlator dn_u._member._xlator /* DT_NODE_MEMBER */
+#define dn_membid dn_u._member._id /* DT_NODE_MEMBER */
#define dn_xlator dn_u._xlator._xlator /* DT_NODE_XLATOR */
+#define dn_xmember dn_u._xlator._xmemb /* DT_NODE_XLATOR */
#define dn_members dn_u._xlator._membs /* DT_NODE_XLATOR */
#define dn_provname dn_u._provider._name /* DT_NODE_PROVIDER */
#define dn_provider dn_u._provider._pvp /* DT_NODE_PROVIDER */
@@ -200,7 +206,7 @@ extern dt_node_t *dt_node_clause(dt_node_t *, dt_node_t *, dt_node_t *);
extern dt_node_t *dt_node_inline(dt_node_t *);
extern dt_node_t *dt_node_member(dt_decl_t *, char *, dt_node_t *);
extern dt_node_t *dt_node_xlator(dt_decl_t *, dt_decl_t *, char *, dt_node_t *);
-extern dt_node_t *dt_node_probe(char *, dt_node_t *, dt_node_t *);
+extern dt_node_t *dt_node_probe(char *, int, dt_node_t *, dt_node_t *);
extern dt_node_t *dt_node_provider(char *, dt_node_t *);
extern dt_node_t *dt_node_program(dt_node_t *);
@@ -224,7 +230,8 @@ extern dt_ident_t *dt_node_resolve(const dt_node_t *, uint_t);
extern size_t dt_node_sizeof(const dt_node_t *);
extern void dt_node_promote(dt_node_t *, dt_node_t *, dt_node_t *);
-extern void dt_node_diftype(const dt_node_t *, dtrace_diftype_t *);
+extern void dt_node_diftype(dtrace_hdl_t *,
+ const dt_node_t *, dtrace_diftype_t *);
extern void dt_node_printr(dt_node_t *, FILE *, int);
extern const char *dt_node_name(const dt_node_t *, char *, size_t);
extern int dt_node_root(dt_node_t *);
diff --git a/usr/src/lib/libdtrace/common/dt_pcb.c b/usr/src/lib/libdtrace/common/dt_pcb.c
index 5b57a9c97f..d80c359bc1 100644
--- a/usr/src/lib/libdtrace/common/dt_pcb.c
+++ b/usr/src/lib/libdtrace/common/dt_pcb.c
@@ -49,6 +49,7 @@
#include <assert.h>
#include <dt_impl.h>
+#include <dt_program.h>
#include <dt_provider.h>
#include <dt_pcb.h>
@@ -108,6 +109,7 @@ void
dt_pcb_pop(dtrace_hdl_t *dtp, int err)
{
dt_pcb_t *pcb = yypcb;
+ uint_t i;
assert(pcb != NULL);
assert(pcb == dtp->dt_pcb);
@@ -125,14 +127,12 @@ dt_pcb_pop(dtrace_hdl_t *dtp, int err)
dt_xlator_t *dxp, *nxp;
dt_provider_t *pvp, *nvp;
- if (pcb->pcb_pred != NULL)
- dtrace_difo_release(pcb->pcb_pred);
if (pcb->pcb_prog != NULL)
- dtrace_program_destroy(dtp, pcb->pcb_prog);
+ dt_program_destroy(dtp, pcb->pcb_prog);
if (pcb->pcb_stmt != NULL)
- dtrace_stmt_destroy(pcb->pcb_stmt);
+ dtrace_stmt_destroy(dtp, pcb->pcb_stmt);
if (pcb->pcb_ecbdesc != NULL)
- dtrace_ecbdesc_release(pcb->pcb_ecbdesc);
+ dt_ecbdesc_release(dtp, pcb->pcb_ecbdesc);
for (dxp = dt_list_next(&dtp->dt_xlators); dxp; dxp = nxp) {
nxp = dt_list_next(dxp);
@@ -171,8 +171,12 @@ dt_pcb_pop(dtrace_hdl_t *dtp, int err)
dt_strtab_destroy(pcb->pcb_strtab);
if (pcb->pcb_regs != NULL)
dt_regset_destroy(pcb->pcb_regs);
- if (pcb->pcb_difo != NULL)
- dtrace_difo_release(pcb->pcb_difo);
+
+ for (i = 0; i < pcb->pcb_asxreflen; i++)
+ dt_free(dtp, pcb->pcb_asxrefs[i]);
+
+ dt_free(dtp, pcb->pcb_asxrefs);
+ dt_difo_free(dtp, pcb->pcb_difo);
free(pcb->pcb_filetag);
free(pcb->pcb_sflagv);
diff --git a/usr/src/lib/libdtrace/common/dt_pcb.h b/usr/src/lib/libdtrace/common/dt_pcb.h
index 709df8649f..0ba2c6b59c 100644
--- a/usr/src/lib/libdtrace/common/dt_pcb.h
+++ b/usr/src/lib/libdtrace/common/dt_pcb.h
@@ -67,14 +67,15 @@ typedef struct dt_pcb {
dt_strtab_t *pcb_strtab; /* string table for string references */
dt_regset_t *pcb_regs; /* register set for code generation */
dt_irlist_t pcb_ir; /* list of unrelocated IR instructions */
- uint_t pcb_asvidx; /* vartab index (used by assembler) */
+ uint_t pcb_asvidx; /* assembler vartab index (see dt_as.c) */
+ ulong_t **pcb_asxrefs; /* assembler imported xlators (see dt_as.c) */
+ uint_t pcb_asxreflen; /* assembler xlator map length (see dt_as.c) */
const dtrace_probedesc_t *pcb_pdesc; /* probedesc for current context */
struct dt_probe *pcb_probe; /* probe associated with current context */
dtrace_probeinfo_t pcb_pinfo; /* info associated with current context */
dtrace_attribute_t pcb_amin; /* stability minimum for compilation */
dt_node_t *pcb_dret; /* node containing return type for assembler */
dtrace_difo_t *pcb_difo; /* intermediate DIF object made by assembler */
- dtrace_difo_t *pcb_pred; /* intermediate predicate made by compiler */
dtrace_prog_t *pcb_prog; /* intermediate program made by compiler */
dtrace_stmtdesc_t *pcb_stmt; /* intermediate stmt made by compiler */
dtrace_ecbdesc_t *pcb_ecbdesc; /* intermediate ecbdesc made by cmplr */
diff --git a/usr/src/lib/libdtrace/common/dt_pid.c b/usr/src/lib/libdtrace/common/dt_pid.c
index 45ee926a61..7e92b13585 100644
--- a/usr/src/lib/libdtrace/common/dt_pid.c
+++ b/usr/src/lib/libdtrace/common/dt_pid.c
@@ -37,6 +37,7 @@
#include <stddef.h>
#include <dt_impl.h>
+#include <dt_program.h>
#include <dt_pid.h>
#include <dt_string.h>
diff --git a/usr/src/lib/libdtrace/common/dt_proc.c b/usr/src/lib/libdtrace/common/dt_proc.c
index ba925e18ab..ff5d4086ce 100644
--- a/usr/src/lib/libdtrace/common/dt_proc.c
+++ b/usr/src/lib/libdtrace/common/dt_proc.c
@@ -698,6 +698,16 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P)
dpr->dpr_quit = B_TRUE;
(void) _lwp_kill(dpr->dpr_tid, SIGCANCEL);
+ /*
+ * If the process is currently idling in dt_proc_stop(), re-
+ * enable breakpoints and poke it into running again.
+ */
+ if (dpr->dpr_stop & DT_PROC_STOP_IDLE) {
+ dt_proc_bpenable(dpr);
+ dpr->dpr_stop &= ~DT_PROC_STOP_IDLE;
+ (void) pthread_cond_broadcast(&dpr->dpr_cv);
+ }
+
while (!dpr->dpr_done)
(void) pthread_cond_wait(&dpr->dpr_cv, &dpr->dpr_lock);
diff --git a/usr/src/lib/libdtrace/common/dt_program.c b/usr/src/lib/libdtrace/common/dt_program.c
index 556dcb6e18..c87d86aa8e 100644
--- a/usr/src/lib/libdtrace/common/dt_program.c
+++ b/usr/src/lib/libdtrace/common/dt_program.c
@@ -33,12 +33,13 @@
#include <assert.h>
#include <dt_impl.h>
+#include <dt_program.h>
#include <dt_printf.h>
dtrace_prog_t *
-dtrace_program_create(dtrace_hdl_t *dtp)
+dt_program_create(dtrace_hdl_t *dtp)
{
- dtrace_prog_t *pgp = calloc(1, sizeof (dtrace_prog_t));
+ dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t));
if (pgp != NULL)
dt_list_append(&dtp->dt_programs, pgp);
@@ -49,18 +50,23 @@ dtrace_program_create(dtrace_hdl_t *dtp)
}
void
-dtrace_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp)
+dt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp)
{
dt_stmt_t *stp, *next;
+ uint_t i;
for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) {
next = dt_list_next(stp);
- dtrace_stmt_destroy(stp->ds_desc);
- free(stp);
+ dtrace_stmt_destroy(dtp, stp->ds_desc);
+ dt_free(dtp, stp);
}
+ for (i = 0; i < pgp->dp_xrefslen; i++)
+ dt_free(dtp, pgp->dp_xrefs[i]);
+
+ dt_free(dtp, pgp->dp_xrefs);
dt_list_delete(&dtp->dt_programs, pgp);
- free(pgp);
+ dt_free(dtp, pgp);
}
/*ARGSUSED*/
@@ -170,41 +176,35 @@ dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
return (0);
}
-void
-dtrace_ecbdesc_hold(dtrace_ecbdesc_t *edp)
+static void
+dt_ecbdesc_hold(dtrace_ecbdesc_t *edp)
{
edp->dted_refcnt++;
}
void
-dtrace_ecbdesc_release(dtrace_ecbdesc_t *edp)
+dt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp)
{
- dtrace_difo_t *dp;
-
if (--edp->dted_refcnt > 0)
return;
- if ((dp = edp->dted_pred.dtpdd_difo) != NULL)
- dtrace_difo_release(dp);
-
+ dt_difo_free(dtp, edp->dted_pred.dtpdd_difo);
assert(edp->dted_action == NULL);
- free(edp);
+ dt_free(dtp, edp);
}
dtrace_ecbdesc_t *
-dtrace_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
+dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
{
dtrace_ecbdesc_t *edp;
- if ((edp = malloc(sizeof (dtrace_ecbdesc_t))) == NULL) {
+ if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) {
(void) dt_set_errno(dtp, EDT_NOMEM);
return (NULL);
}
- bzero(edp, sizeof (dtrace_ecbdesc_t));
edp->dted_probe = *pdp;
- dtrace_ecbdesc_hold(edp);
-
+ dt_ecbdesc_hold(edp);
return (edp);
}
@@ -213,13 +213,10 @@ dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp)
{
dtrace_stmtdesc_t *sdp;
- if ((sdp = malloc(sizeof (dtrace_stmtdesc_t))) == NULL) {
- (void) dt_set_errno(dtp, EDT_NOMEM);
+ if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL)
return (NULL);
- }
- bzero(sdp, sizeof (dtrace_stmtdesc_t));
- dtrace_ecbdesc_hold(edp);
+ dt_ecbdesc_hold(edp);
sdp->dtsd_ecbdesc = edp;
sdp->dtsd_descattr = _dtrace_defattr;
sdp->dtsd_stmtattr = _dtrace_defattr;
@@ -233,10 +230,8 @@ dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
dtrace_actdesc_t *new;
dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
- if ((new = malloc(sizeof (dtrace_actdesc_t))) == NULL) {
- (void) dt_set_errno(dtp, EDT_NOMEM);
+ if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL)
return (NULL);
- }
if (sdp->dtsd_action_last != NULL) {
assert(sdp->dtsd_action != NULL);
@@ -267,10 +262,10 @@ dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
int
dtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp)
{
- dt_stmt_t *stp = malloc(sizeof (dt_stmt_t));
+ dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t));
if (stp == NULL)
- return (dt_set_errno(dtp, EDT_NOMEM));
+ return (-1); /* errno is set for us */
dt_list_append(&pgp->dp_stmts, stp);
stp->ds_desc = sdp;
@@ -295,7 +290,7 @@ dtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
}
void
-dtrace_stmt_destroy(dtrace_stmtdesc_t *sdp)
+dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
{
dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
@@ -319,11 +314,10 @@ dtrace_stmt_destroy(dtrace_stmtdesc_t *sdp)
assert(ap != NULL);
- if (ap == edp->dted_action) {
+ if (ap == edp->dted_action)
edp->dted_action = last->dtad_next;
- } else {
+ else
ap->dtad_next = last->dtad_next;
- }
/*
* We have now removed our action list from its ECB; we can
@@ -332,21 +326,16 @@ dtrace_stmt_destroy(dtrace_stmtdesc_t *sdp)
last->dtad_next = NULL;
for (ap = sdp->dtsd_action; ap != NULL; ap = next) {
- dtrace_difo_t *dp;
-
assert(ap->dtad_uarg == (uintptr_t)sdp);
-
- if ((dp = ap->dtad_difo) != NULL)
- dtrace_difo_release(dp);
-
+ dt_difo_free(dtp, ap->dtad_difo);
next = ap->dtad_next;
- free(ap);
+ dt_free(dtp, ap);
}
}
if (sdp->dtsd_fmtdata != NULL)
dt_printf_destroy(sdp->dtsd_fmtdata);
- dtrace_ecbdesc_release(sdp->dtsd_ecbdesc);
- free(sdp);
+ dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc);
+ dt_free(dtp, sdp);
}
diff --git a/usr/src/lib/libdtrace/common/dt_program.h b/usr/src/lib/libdtrace/common/dt_program.h
new file mode 100644
index 0000000000..b4311baed2
--- /dev/null
+++ b/usr/src/lib/libdtrace/common/dt_program.h
@@ -0,0 +1,62 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * 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 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _DT_PROGRAM_H
+#define _DT_PROGRAM_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dtrace.h>
+#include <dt_list.h>
+
+typedef struct dt_stmt {
+ dt_list_t ds_list; /* list forward/back pointers */
+ dtrace_stmtdesc_t *ds_desc; /* pointer to statement description */
+} dt_stmt_t;
+
+struct dtrace_prog {
+ dt_list_t dp_list; /* list forward/back pointers */
+ dt_list_t dp_stmts; /* linked list of dt_stmt_t's */
+ ulong_t **dp_xrefs; /* array of translator reference bitmaps */
+ uint_t dp_xrefslen; /* length of dp_xrefs array */
+};
+
+extern dtrace_prog_t *dt_program_create(dtrace_hdl_t *);
+extern void dt_program_destroy(dtrace_hdl_t *, dtrace_prog_t *);
+
+extern dtrace_ecbdesc_t *dt_ecbdesc_create(dtrace_hdl_t *,
+ const dtrace_probedesc_t *);
+extern void dt_ecbdesc_release(dtrace_hdl_t *, dtrace_ecbdesc_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DT_PROGRAM_H */
diff --git a/usr/src/lib/libdtrace/common/dt_provider.c b/usr/src/lib/libdtrace/common/dt_provider.c
index f55e91e932..50917074c7 100644
--- a/usr/src/lib/libdtrace/common/dt_provider.c
+++ b/usr/src/lib/libdtrace/common/dt_provider.c
@@ -58,6 +58,7 @@ dt_provider_t *
dt_provider_lookup(dtrace_hdl_t *dtp, const char *name)
{
uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_provbuckets;
+ dtrace_providerdesc_t desc;
dt_provider_t *pvp;
for (pvp = dtp->dt_provs[h]; pvp != NULL; pvp = pvp->pv_next) {
@@ -70,15 +71,18 @@ dt_provider_lookup(dtrace_hdl_t *dtp, const char *name)
return (NULL);
}
- if ((pvp = dt_provider_create(dtp, name)) == NULL)
- return (NULL); /* dt_errno is set for us */
+ bzero(&desc, sizeof (desc));
+ (void) strlcpy(desc.dtvd_name, name, DTRACE_PROVNAMELEN);
- if (dt_ioctl(dtp, DTRACEIOC_PROVIDER, &pvp->pv_desc) == -1) {
+ if (dt_ioctl(dtp, DTRACEIOC_PROVIDER, &desc) == -1) {
(void) dt_set_errno(dtp, errno == ESRCH ? EDT_NOPROV : errno);
- dt_provider_destroy(dtp, pvp);
return (NULL);
}
+ if ((pvp = dt_provider_create(dtp, name)) == NULL)
+ return (NULL); /* dt_errno is set for us */
+
+ bcopy(&desc, &pvp->pv_desc, sizeof (desc));
pvp->pv_flags |= DT_PROVIDER_IMPL;
return (pvp);
}
@@ -136,9 +140,35 @@ dt_provider_destroy(dtrace_hdl_t *dtp, dt_provider_t *pvp)
dt_idhash_destroy(pvp->pv_probes);
dt_node_link_free(&pvp->pv_nodes);
+ dt_free(dtp, pvp->pv_xrefs);
dt_free(dtp, pvp);
}
+int
+dt_provider_xref(dtrace_hdl_t *dtp, dt_provider_t *pvp, id_t id)
+{
+ size_t oldsize = BT_SIZEOFMAP(pvp->pv_xrmax);
+ size_t newsize = BT_SIZEOFMAP(dtp->dt_xlatorid);
+
+ assert(id >= 0 && id < dtp->dt_xlatorid);
+
+ if (newsize > oldsize) {
+ ulong_t *xrefs = dt_zalloc(dtp, newsize);
+
+ if (xrefs == NULL)
+ return (-1);
+
+ bcopy(pvp->pv_xrefs, xrefs, oldsize);
+ dt_free(dtp, pvp->pv_xrefs);
+
+ pvp->pv_xrefs = xrefs;
+ pvp->pv_xrmax = dtp->dt_xlatorid;
+ }
+
+ BT_SET(pvp->pv_xrefs, id);
+ return (0);
+}
+
static uint8_t
dt_probe_argmap(dt_node_t *xnp, dt_node_t *nnp)
{
@@ -258,7 +288,8 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
return (NULL);
}
- if ((prp = dt_probe_create(dtp, idp, nargs, nc, xargs, xc)) == NULL) {
+ if ((prp = dt_probe_create(dtp, idp, 2,
+ nargs, nc, xargs, xc)) == NULL) {
dt_ident_destroy(idp);
return (NULL);
}
@@ -356,7 +387,7 @@ dt_probe_lookup(dt_provider_t *pvp, const char *s)
}
dt_probe_t *
-dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp,
+dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp, int protoc,
dt_node_t *nargs, uint_t nargc, dt_node_t *xargs, uint_t xargc)
{
dt_module_t *dmp;
@@ -367,7 +398,14 @@ dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp,
assert(idp->di_kind == DT_IDENT_PROBE);
assert(idp->di_data == NULL);
- if (xargs == NULL) {
+ /*
+ * If only a single prototype is given, set xargc/s to nargc/s to
+ * simplify subsequent use. Note that we can have one or both of nargs
+ * and xargs be specified but set to NULL, indicating a void prototype.
+ */
+ if (protoc < 2) {
+ assert(xargs == NULL);
+ assert(xargc == 0);
xargs = nargs;
xargc = nargc;
}
@@ -519,6 +557,49 @@ dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp,
return (0);
}
+/*
+ * Lookup the dynamic translator type tag for the specified probe argument and
+ * assign the type to the specified node. If the type is not yet defined, add
+ * it to the "D" module's type container as a typedef for an unknown type.
+ */
+dt_node_t *
+dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp)
+{
+ dtrace_hdl_t *dtp = prp->pr_pvp->pv_hdl;
+ dtrace_typeinfo_t dtt;
+ size_t len;
+ char *tag;
+
+ len = snprintf(NULL, 0, "__dtrace_%s___%s_arg%u",
+ prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn);
+
+ tag = alloca(len + 1);
+
+ (void) snprintf(tag, len + 1, "__dtrace_%s___%s_arg%u",
+ prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn);
+
+ if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_DDEFS, tag, &dtt) != 0) {
+ dtt.dtt_object = DTRACE_OBJ_DDEFS;
+ dtt.dtt_ctfp = DT_DYN_CTFP(dtp);
+ dtt.dtt_type = ctf_add_typedef(DT_DYN_CTFP(dtp),
+ CTF_ADD_ROOT, tag, DT_DYN_TYPE(dtp));
+
+ if (dtt.dtt_type == CTF_ERR ||
+ ctf_update(dtt.dtt_ctfp) == CTF_ERR) {
+ xyerror(D_UNKNOWN, "cannot define type %s: %s\n",
+ tag, ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));
+ }
+ }
+
+ bzero(dnp, sizeof (dt_node_t));
+ dnp->dn_kind = DT_NODE_TYPE;
+
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_attr_assign(dnp, _dtrace_defattr);
+
+ return (dnp);
+}
+
/*ARGSUSED*/
static int
dt_probe_desc(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *arg)
@@ -628,7 +709,16 @@ dt_probe_info(dtrace_hdl_t *dtp,
}
}
- if ((prp = dt_probe_discover(pvp, &pd)) == NULL)
+ /*
+ * If we matched a probe exported by dtrace(7D), then discover
+ * the real attributes. Otherwise grab the static declaration.
+ */
+ if (pd.dtpd_id != DTRACE_IDNONE)
+ prp = dt_probe_discover(pvp, &pd);
+ else
+ prp = dt_probe_lookup(pvp, pd.dtpd_name);
+
+ if (prp == NULL)
return (NULL); /* dt_errno is set for us */
}
diff --git a/usr/src/lib/libdtrace/common/dt_provider.h b/usr/src/lib/libdtrace/common/dt_provider.h
index bd6a449538..8e4c9b855b 100644
--- a/usr/src/lib/libdtrace/common/dt_provider.h
+++ b/usr/src/lib/libdtrace/common/dt_provider.h
@@ -43,6 +43,8 @@ typedef struct dt_provider {
dtrace_providerdesc_t pv_desc; /* provider name and attributes */
dt_idhash_t *pv_probes; /* probe defs (if user-declared) */
dt_node_t *pv_nodes; /* parse node allocation list */
+ ulong_t *pv_xrefs; /* translator reference bitmap */
+ ulong_t pv_xrmax; /* number of valid bits in pv_xrefs */
ulong_t pv_gen; /* generation # that created me */
dtrace_hdl_t *pv_hdl; /* pointer to containing dtrace_hdl */
uint_t pv_flags; /* flags (see below) */
@@ -88,8 +90,9 @@ typedef struct dt_probe {
extern dt_provider_t *dt_provider_lookup(dtrace_hdl_t *, const char *);
extern dt_provider_t *dt_provider_create(dtrace_hdl_t *, const char *);
extern void dt_provider_destroy(dtrace_hdl_t *, dt_provider_t *);
+extern int dt_provider_xref(dtrace_hdl_t *, dt_provider_t *, id_t);
-extern dt_probe_t *dt_probe_create(dtrace_hdl_t *, dt_ident_t *,
+extern dt_probe_t *dt_probe_create(dtrace_hdl_t *, dt_ident_t *, int,
dt_node_t *, uint_t, dt_node_t *, uint_t);
extern dt_probe_t *dt_probe_info(dtrace_hdl_t *,
@@ -102,6 +105,8 @@ extern void dt_probe_destroy(dt_probe_t *);
extern int dt_probe_define(dt_provider_t *, dt_probe_t *,
const char *, uint32_t);
+extern dt_node_t *dt_probe_tag(dt_probe_t *, uint_t, dt_node_t *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libdtrace/common/dt_subr.c b/usr/src/lib/libdtrace/common/dt_subr.c
index 9da4627dee..31c2c4a4d4 100644
--- a/usr/src/lib/libdtrace/common/dt_subr.c
+++ b/usr/src/lib/libdtrace/common/dt_subr.c
@@ -717,6 +717,23 @@ dt_free(dtrace_hdl_t *dtp, void *data)
free(data);
}
+void
+dt_difo_free(dtrace_hdl_t *dtp, dtrace_difo_t *dp)
+{
+ if (dp == NULL)
+ return; /* simplify caller code */
+
+ dt_free(dtp, dp->dtdo_buf);
+ dt_free(dtp, dp->dtdo_inttab);
+ dt_free(dtp, dp->dtdo_strtab);
+ dt_free(dtp, dp->dtdo_vartab);
+ dt_free(dtp, dp->dtdo_kreltab);
+ dt_free(dtp, dp->dtdo_ureltab);
+ dt_free(dtp, dp->dtdo_xlmtab);
+
+ dt_free(dtp, dp);
+}
+
/*
* dt_gmatch() is similar to gmatch(3GEN) and dtrace(7D) globbing, but also
* implements the behavior that an empty pattern matches any string.
@@ -738,6 +755,52 @@ dt_basename(char *str)
return (last + 1);
}
+/*
+ * dt_popc() is a fast implementation of population count. The algorithm is
+ * from "Hacker's Delight" by Henry Warren, Jr with a 64-bit equivalent added.
+ */
+ulong_t
+dt_popc(ulong_t x)
+{
+#ifdef _ILP32
+ x = x - ((x >> 1) & 0x55555555UL);
+ x = (x & 0x33333333UL) + ((x >> 2) & 0x33333333UL);
+ x = (x + (x >> 4)) & 0x0F0F0F0FUL;
+ x = x + (x >> 8);
+ x = x + (x >> 16);
+ return (x & 0x3F);
+#endif
+#ifdef _LP64
+ x = x - ((x >> 1) & 0x5555555555555555ULL);
+ x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);
+ x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
+ x = x + (x >> 8);
+ x = x + (x >> 16);
+ x = x + (x >> 32);
+ return (x & 0x7F);
+#endif
+}
+
+/*
+ * dt_popcb() is a bitmap-based version of population count that returns the
+ * number of one bits in the specified bitmap 'bp' at bit positions below 'n'.
+ */
+ulong_t
+dt_popcb(const ulong_t *bp, ulong_t n)
+{
+ ulong_t maxb = n & BT_ULMASK;
+ ulong_t maxw = n >> BT_ULSHIFT;
+ ulong_t w, popc = 0;
+
+ if (n == 0)
+ return (0);
+
+ for (w = 0; w < maxw; w++)
+ popc += dt_popc(bp[w]);
+
+ return (popc + dt_popc(bp[maxw] & ((1UL << maxb) - 1)));
+}
+
struct _rwlock;
struct _lwp_mutex;
diff --git a/usr/src/lib/libdtrace/common/dt_xlator.c b/usr/src/lib/libdtrace/common/dt_xlator.c
index 354511988d..7ac0cc42f5 100644
--- a/usr/src/lib/libdtrace/common/dt_xlator.c
+++ b/usr/src/lib/libdtrace/common/dt_xlator.c
@@ -27,37 +27,108 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <strings.h>
-#include <stdlib.h>
+#include <assert.h>
#include <dt_xlator.h>
+#include <dt_parser.h>
+#include <dt_grammar.h>
+#include <dt_module.h>
#include <dt_impl.h>
+/*
+ * Create a member node corresponding to one of the output members of a dynamic
+ * translator. We set the member's dn_membexpr to a DT_NODE_XLATOR node that
+ * has dn_op set to DT_TOK_XLATE and refers back to the translator itself. The
+ * code generator will then use this as the indicator for dynamic translation.
+ */
+/*ARGSUSED*/
+static int
+dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
+{
+ dt_xlator_t *dxp = arg;
+ dtrace_hdl_t *dtp = dxp->dx_hdl;
+ dt_node_t *enp, *mnp;
+
+ if ((enp = dt_node_xalloc(dtp, DT_NODE_XLATOR)) == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+
+ enp->dn_link = dxp->dx_nodes;
+ dxp->dx_nodes = enp;
+
+ if ((mnp = dt_node_xalloc(dtp, DT_NODE_MEMBER)) == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+
+ mnp->dn_link = dxp->dx_nodes;
+ dxp->dx_nodes = mnp;
+
+ /*
+ * For the member expression, we use a DT_NODE_XLATOR/TOK_XLATE whose
+ * xlator refers back to the translator and whose dn_xmember refers to
+ * the current member. These refs will be used by dt_cg.c and dt_as.c.
+ */
+ enp->dn_op = DT_TOK_XLATE;
+ enp->dn_xlator = dxp;
+ enp->dn_xmember = mnp;
+ dt_node_type_assign(enp, dxp->dx_dst_ctfp, type);
+
+ /*
+ * For the member itself, we use a DT_NODE_MEMBER as usual with the
+ * appropriate name, output type, and member expression set to 'enp'.
+ */
+ if (dxp->dx_members != NULL) {
+ assert(enp->dn_link->dn_kind == DT_NODE_MEMBER);
+ enp->dn_link->dn_list = mnp;
+ } else
+ dxp->dx_members = mnp;
+
+ mnp->dn_membname = strdup(name);
+ mnp->dn_membexpr = enp;
+ dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type);
+
+ if (mnp->dn_membname == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+
+ return (0);
+}
+
dt_xlator_t *
dt_xlator_create(dtrace_hdl_t *dtp,
const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
const char *name, dt_node_t *members, dt_node_t *nodes)
{
- dt_xlator_t *dxp = malloc(sizeof (dt_xlator_t));
+ dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
dtrace_typeinfo_t ptr = *dst;
+ dt_xlator_t **map;
+ dt_node_t *dnp;
+ uint_t kind;
if (dxp == NULL)
return (NULL);
- if (dt_type_pointer(&ptr) == -1) {
- ptr.dtt_ctfp = NULL;
- ptr.dtt_type = CTF_ERR;
+ dxp->dx_hdl = dtp;
+ dxp->dx_id = dtp->dt_xlatorid++;
+ dxp->dx_gen = dtp->dt_gen;
+ dxp->dx_arg = -1;
+
+ if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
+ dt_free(dtp, dxp);
+ return (NULL);
}
- bzero(dxp, sizeof (dt_xlator_t));
dt_list_append(&dtp->dt_xlators, dxp);
- dxp->dx_locals = dt_idhash_create("translator", NULL, 0, 0);
+ bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
+ dt_free(dtp, dtp->dt_xlatormap);
+ dtp->dt_xlatormap = map;
+ dtp->dt_xlatormap[dxp->dx_id] = dxp;
- if (dxp->dx_locals == NULL)
- goto err; /* no memory for identifier hash */
+ if (dt_type_pointer(&ptr) == -1) {
+ ptr.dtt_ctfp = NULL;
+ ptr.dtt_type = CTF_ERR;
+ }
- dxp->dx_ident = dt_idhash_insert(dxp->dx_locals, name,
- DT_IDENT_SCALAR, DT_IDFLG_REF, 0, _dtrace_defattr, 0,
- &dt_idops_thaw, NULL, dtp->dt_gen);
+ dxp->dx_ident = dt_ident_create(name ? name : "T",
+ DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
+ _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);
if (dxp->dx_ident == NULL)
goto err; /* no memory for identifier */
@@ -65,9 +136,23 @@ dt_xlator_create(dtrace_hdl_t *dtp,
dxp->dx_ident->di_ctfp = src->dtt_ctfp;
dxp->dx_ident->di_type = src->dtt_type;
+ /*
+ * If an input parameter name is given, this is a static translator
+ * definition: create an idhash and identifier for the parameter.
+ */
+ if (name != NULL) {
+ dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);
+
+ if (dxp->dx_locals == NULL)
+ goto err; /* no memory for identifier hash */
+
+ dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
+ }
+
dxp->dx_souid.di_name = "translator";
dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
dxp->dx_souid.di_flags = DT_IDFLG_REF;
+ dxp->dx_souid.di_id = dxp->dx_id;
dxp->dx_souid.di_attr = _dtrace_defattr;
dxp->dx_souid.di_ops = &dt_idops_thaw;
dxp->dx_souid.di_data = dxp;
@@ -78,6 +163,7 @@ dt_xlator_create(dtrace_hdl_t *dtp,
dxp->dx_ptrid.di_name = "translator";
dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
+ dxp->dx_ptrid.di_id = dxp->dx_id;
dxp->dx_ptrid.di_attr = _dtrace_defattr;
dxp->dx_ptrid.di_ops = &dt_idops_thaw;
dxp->dx_ptrid.di_data = dxp;
@@ -105,9 +191,39 @@ dt_xlator_create(dtrace_hdl_t *dtp,
dxp->dx_dst_type = dst->dtt_type;
dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);
- dxp->dx_members = members;
- dxp->dx_nodes = nodes;
- dxp->dx_gen = dtp->dt_gen;
+ kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
+ assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);
+
+ /*
+ * If no input parameter is given, we're making a dynamic translator:
+ * create member nodes for every member of the output type. Otherwise
+ * retain the member and allocation node lists presented by the parser.
+ */
+ if (name == NULL) {
+ if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
+ dt_xlator_create_member, dxp) != 0)
+ goto err;
+ } else {
+ dxp->dx_members = members;
+ dxp->dx_nodes = nodes;
+ }
+
+ /*
+ * Assign member IDs to each member and allocate space for DIFOs
+ * if and when this translator is eventually compiled.
+ */
+ for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
+ dnp->dn_membxlator = dxp;
+ dnp->dn_membid = dxp->dx_nmembers++;
+ }
+
+ dxp->dx_membdif = dt_zalloc(dtp,
+ sizeof (dtrace_difo_t *) * dxp->dx_nmembers);
+
+ if (dxp->dx_membdif == NULL) {
+ dxp->dx_nmembers = 0;
+ goto err;
+ }
return (dxp);
@@ -119,14 +235,25 @@ err:
void
dt_xlator_destroy(dtrace_hdl_t *dtp, dt_xlator_t *dxp)
{
+ uint_t i;
+
dt_node_link_free(&dxp->dx_nodes);
- dt_idhash_destroy(dxp->dx_locals);
+
+ if (dxp->dx_locals != NULL)
+ dt_idhash_destroy(dxp->dx_locals);
+ else if (dxp->dx_ident != NULL)
+ dt_ident_destroy(dxp->dx_ident);
+
+ for (i = 0; i < dxp->dx_nmembers; i++)
+ dt_difo_free(dtp, dxp->dx_membdif[i]);
+
+ dt_free(dtp, dxp->dx_membdif);
dt_list_delete(&dtp->dt_xlators, dxp);
- free(dxp);
+ dt_free(dtp, dxp);
}
dt_xlator_t *
-dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flag)
+dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
{
ctf_file_t *src_ctfp = src->dn_ctfp;
ctf_id_t src_type = src->dn_type;
@@ -135,10 +262,12 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flag)
ctf_file_t *dst_ctfp = dst->dn_ctfp;
ctf_id_t dst_type = dst->dn_type;
ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type);
+ uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base);
- int ptr = ctf_type_kind(dst_ctfp, dst_base) == CTF_K_POINTER;
+ int ptr = dst_kind == CTF_K_POINTER;
+ dtrace_typeinfo_t src_dtt, dst_dtt;
dt_node_t xn = { 0 };
- dt_xlator_t *dxp;
+ dt_xlator_t *dxp = NULL;
if (src_base == CTF_ERR || dst_base == CTF_ERR)
return (NULL); /* fail if these are unresolvable types */
@@ -151,8 +280,12 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flag)
if (ptr) {
dst_type = ctf_type_reference(dst_ctfp, dst_type);
dst_base = ctf_type_resolve(dst_ctfp, dst_type);
+ dst_kind = ctf_type_kind(dst_ctfp, dst_base);
}
+ if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT)
+ return (NULL); /* fail if the output isn't a struct or union */
+
/*
* In order to find a matching translator, we iterate over the set of
* available translators in three passes. First, we look for a
@@ -171,7 +304,7 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flag)
goto out;
}
- if (flag == DT_XLATE_EXACT)
+ if (flags & DT_XLATE_EXACT)
goto out; /* skip remaining passes if exact match required */
for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
@@ -193,9 +326,32 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flag)
out:
if (ptr && dxp != NULL && dxp->dx_ptrid.di_type == CTF_ERR)
- return (NULL); /* no translation available to pointer type */
+ return (NULL); /* no translation available to pointer type */
- return (dxp);
+ if (dxp != NULL || !(flags & DT_XLATE_EXTERN) ||
+ dtp->dt_xlatemode == DT_XL_STATIC)
+ return (dxp); /* we succeeded or not allowed to extern */
+
+ /*
+ * If we get here, then we didn't find an existing translator, but the
+ * caller and xlatemode permit us to create an extern to a dynamic one.
+ */
+ src_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, src_ctfp)->dm_name;
+ src_dtt.dtt_ctfp = src_ctfp;
+ src_dtt.dtt_type = src_type;
+
+ dst_dtt.dtt_object = dt_module_lookup_by_ctf(dtp, dst_ctfp)->dm_name;
+ dst_dtt.dtt_ctfp = dst_ctfp;
+ dst_dtt.dtt_type = dst_type;
+
+ return (dt_xlator_create(dtp, &src_dtt, &dst_dtt, NULL, NULL, NULL));
+}
+
+dt_xlator_t *
+dt_xlator_lookup_id(dtrace_hdl_t *dtp, id_t id)
+{
+ assert(id >= 0 && id < dtp->dt_xlatorid);
+ return (dtp->dt_xlatormap[id]);
}
dt_ident_t *
@@ -219,3 +375,9 @@ dt_xlator_member(dt_xlator_t *dxp, const char *name)
return (NULL);
}
+
+int
+dt_xlator_dynamic(const dt_xlator_t *dxp)
+{
+ return (dxp->dx_locals == NULL);
+}
diff --git a/usr/src/lib/libdtrace/common/dt_xlator.h b/usr/src/lib/libdtrace/common/dt_xlator.h
index f71601d8d3..a30f3aff64 100644
--- a/usr/src/lib/libdtrace/common/dt_xlator.h
+++ b/usr/src/lib/libdtrace/common/dt_xlator.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -53,23 +53,32 @@ typedef struct dt_xlator {
ctf_id_t dx_dst_type; /* CTF reference for output type */
ctf_id_t dx_dst_base; /* CTF reference for output base */
struct dt_node *dx_members; /* list of member translations */
+ uint_t dx_nmembers; /* length of dx_members list */
+ dtrace_difo_t **dx_membdif; /* DIF for member expressions */
struct dt_node *dx_nodes; /* list of parse tree nodes */
+ dtrace_hdl_t *dx_hdl; /* back pointer to containing handle */
ulong_t dx_gen; /* generation number that created me */
+ id_t dx_id; /* global translator id */
+ int dx_arg; /* dynamic argument index */
} dt_xlator_t;
extern dt_xlator_t *dt_xlator_create(dtrace_hdl_t *,
const dtrace_typeinfo_t *, const dtrace_typeinfo_t *,
const char *, struct dt_node *, struct dt_node *);
-#define DT_XLATE_FUZZY 0 /* lookup any matching translator */
-#define DT_XLATE_EXACT 1 /* lookup only exact type matches */
+extern void dt_xlator_destroy(dtrace_hdl_t *, dt_xlator_t *);
+
+#define DT_XLATE_FUZZY 0x0 /* lookup any matching translator */
+#define DT_XLATE_EXACT 0x1 /* lookup only exact type matches */
+#define DT_XLATE_EXTERN 0x2 /* extern translator if none exists */
extern dt_xlator_t *dt_xlator_lookup(dtrace_hdl_t *,
struct dt_node *, struct dt_node *, int);
+extern dt_xlator_t *dt_xlator_lookup_id(dtrace_hdl_t *, id_t);
extern dt_ident_t *dt_xlator_ident(dt_xlator_t *, ctf_file_t *, ctf_id_t);
extern struct dt_node *dt_xlator_member(dt_xlator_t *, const char *);
-extern void dt_xlator_destroy(dtrace_hdl_t *, dt_xlator_t *);
+extern int dt_xlator_dynamic(const dt_xlator_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdtrace/common/dtrace.h b/usr/src/lib/libdtrace/common/dtrace.h
index 960c50e15a..efeb44550a 100644
--- a/usr/src/lib/libdtrace/common/dtrace.h
+++ b/usr/src/lib/libdtrace/common/dtrace.h
@@ -76,6 +76,7 @@ extern void dtrace_close(dtrace_hdl_t *);
extern int dtrace_errno(dtrace_hdl_t *);
extern const char *dtrace_errmsg(dtrace_hdl_t *, int);
extern const char *dtrace_faultstr(dtrace_hdl_t *, int);
+extern const char *dtrace_subrstr(dtrace_hdl_t *, int);
extern int dtrace_setopt(dtrace_hdl_t *, const char *, const char *);
extern int dtrace_getopt(dtrace_hdl_t *, const char *, dtrace_optval_t *);
@@ -87,9 +88,7 @@ extern int dtrace_ctlfd(dtrace_hdl_t *);
* DTrace Program Interface
*
* DTrace programs can be created by compiling ASCII text files containing
- * D programs, by compiling C strings that specify a D program, or by
- * manually constructing statements and adding them to an existing program.
- * The dtrace_program_create() function can be used to create an empty program.
+ * D programs or by compiling in-memory C strings that specify a D program.
* Once created, callers can examine the list of program statements and
* enable the probes and actions described by these statements.
*/
@@ -141,9 +140,6 @@ extern void dtrace_dof_destroy(dtrace_hdl_t *, void *);
extern void *dtrace_getopt_dof(dtrace_hdl_t *);
extern void *dtrace_geterr_dof(dtrace_hdl_t *);
-extern dtrace_prog_t *dtrace_program_create(dtrace_hdl_t *);
-extern void dtrace_program_destroy(dtrace_hdl_t *, dtrace_prog_t *);
-
typedef struct dtrace_stmtdesc {
dtrace_ecbdesc_t *dtsd_ecbdesc; /* ECB description */
dtrace_actdesc_t *dtsd_action; /* action list */
@@ -167,12 +163,7 @@ extern int dtrace_stmt_add(dtrace_hdl_t *, dtrace_prog_t *,
dtrace_stmtdesc_t *);
extern int dtrace_stmt_iter(dtrace_hdl_t *, dtrace_prog_t *,
dtrace_stmt_f *, void *);
-extern void dtrace_stmt_destroy(dtrace_stmtdesc_t *);
-
-extern dtrace_ecbdesc_t *dtrace_ecbdesc_create(dtrace_hdl_t *,
- const dtrace_probedesc_t *);
-extern void dtrace_ecbdesc_hold(dtrace_ecbdesc_t *);
-extern void dtrace_ecbdesc_release(dtrace_ecbdesc_t *);
+extern void dtrace_stmt_destroy(dtrace_hdl_t *, dtrace_stmtdesc_t *);
/*
* DTrace Data Consumption Interface
@@ -399,20 +390,6 @@ extern void dtrace_proc_release(dtrace_hdl_t *, struct ps_prochandle *);
extern void dtrace_proc_continue(dtrace_hdl_t *, struct ps_prochandle *);
/*
- * DTrace DIF Object (DIFO) Interface
- *
- * Library clients who wish to create their own custom DIF programs can use
- * the functions below to create a DIFO from a C string containing a D
- * expression statement. Clients may also create raw DIF on-the-fly without
- * invoking the D compiler by simply constructing the dtrace_difo_t by hand.
- */
-
-extern dtrace_difo_t *dtrace_difo_create(dtrace_hdl_t *, const char *);
-extern void dtrace_difo_print(const dtrace_difo_t *, FILE *);
-extern void dtrace_difo_hold(dtrace_difo_t *);
-extern void dtrace_difo_release(dtrace_difo_t *);
-
-/*
* DTrace Object, Symbol, and Type Interfaces
*
* Library clients can use libdtrace to perform symbol and C type information
diff --git a/usr/src/lib/libdtrace/common/mknames.sh b/usr/src/lib/libdtrace/common/mknames.sh
new file mode 100644
index 0000000000..7f90b7dd37
--- /dev/null
+++ b/usr/src/lib/libdtrace/common/mknames.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# 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 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+echo "\
+/*\n\
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.\n\
+ * Use is subject to license terms.\n\
+ */\n\
+\n\
+#pragma ident\t\"%Z%%M%\t%I%\t%E% SMI\"\n\
+\n\
+#include <dtrace.h>\n\
+\n\
+/*ARGSUSED*/
+const char *\n\
+dtrace_subrstr(dtrace_hdl_t *dtp, int subr)\n\
+{\n\
+ switch (subr) {"
+
+nawk '
+/^#define[ ]*DIF_SUBR_/ && $2 != "DIF_SUBR_MAX" {
+ printf("\tcase %s: return (\"%s\");\n", $2, tolower(substr($2, 10)));
+}'
+
+echo "\
+ default: return (\"unknown\");\n\
+ }\n\
+}"
diff --git a/usr/src/lib/libdtrace/spec/dtrace.spec b/usr/src/lib/libdtrace/spec/dtrace.spec
index 89ff4c0a43..52f9e63519 100644
--- a/usr/src/lib/libdtrace/spec/dtrace.spec
+++ b/usr/src/lib/libdtrace/spec/dtrace.spec
@@ -104,22 +104,6 @@ function dtrace_desc2str
version SUNWprivate_1.1
end
-function dtrace_difo_create
-version SUNWprivate_1.1
-end
-
-function dtrace_difo_hold
-version SUNWprivate_1.1
-end
-
-function dtrace_difo_print
-version SUNWprivate_1.1
-end
-
-function dtrace_difo_release
-version SUNWprivate_1.1
-end
-
function dtrace_dof_create
version SUNWprivate_1.1
end
@@ -128,18 +112,6 @@ function dtrace_dof_destroy
version SUNWprivate_1.1
end
-function dtrace_ecbdesc_create
-version SUNWprivate_1.1
-end
-
-function dtrace_ecbdesc_hold
-version SUNWprivate_1.1
-end
-
-function dtrace_ecbdesc_release
-version SUNWprivate_1.1
-end
-
function dtrace_errmsg
version SUNWprivate_1.1
end
@@ -260,14 +232,6 @@ function dtrace_proc_release
version SUNWprivate_1.1
end
-function dtrace_program_create
-version SUNWprivate_1.1
-end
-
-function dtrace_program_destroy
-version SUNWprivate_1.1
-end
-
function dtrace_program_exec
version SUNWprivate_1.1
end
@@ -340,6 +304,10 @@ function dtrace_str2attr
version SUNWprivate_1.1
end
+function dtrace_subrstr
+version SUNWprivate_1.1
+end
+
function dtrace_symbol_type
version SUNWprivate_1.1
end
diff --git a/usr/src/lib/libproc/common/Pscantext.c b/usr/src/lib/libproc/common/Pscantext.c
index d4cb853254..72d85c06f6 100644
--- a/usr/src/lib/libproc/common/Pscantext.c
+++ b/usr/src/lib/libproc/common/Pscantext.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -176,6 +176,8 @@ Pscantext(struct ps_prochandle *P)
}
}
+ free(prbuf);
+
if ((P->sysaddr = sysaddr) != 0)
return (0);
else
diff --git a/usr/src/pkgdefs/SUNWdtrc/prototype_com b/usr/src/pkgdefs/SUNWdtrc/prototype_com
index 925f7d256d..d4a10bb750 100644
--- a/usr/src/pkgdefs/SUNWdtrc/prototype_com
+++ b/usr/src/pkgdefs/SUNWdtrc/prototype_com
@@ -61,6 +61,8 @@ f none usr/lib/llib-ldtrace 644 root bin
f none usr/lib/llib-ldtrace.ln 644 root bin
d none usr/lib/mdb 755 root sys
d none usr/lib/mdb/kvm 755 root sys
+d none usr/lib/mdb/raw 755 root sys
+f none usr/lib/mdb/raw/dof.so 555 root sys
d none usr/sbin 755 root bin
l none usr/sbin/dtrace=../../usr/lib/isaexec
l none usr/sbin/intrstat=../../usr/lib/isaexec
diff --git a/usr/src/pkgdefs/SUNWdtrc/prototype_i386 b/usr/src/pkgdefs/SUNWdtrc/prototype_i386
index 7da9c78df9..f9d52af8d7 100644
--- a/usr/src/pkgdefs/SUNWdtrc/prototype_i386
+++ b/usr/src/pkgdefs/SUNWdtrc/prototype_i386
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,7 +28,6 @@
!include prototype_com
-f none usr/lib/mdb/kvm/dtrace.so 555 root sys
d none usr/sbin/i86 755 root bin
f none usr/sbin/i86/dtrace 555 root bin
f none usr/sbin/i86/intrstat 555 root bin
@@ -38,6 +37,9 @@ d none usr/lib/dtrace/64 755 root bin
f none usr/lib/dtrace/64/drti.o 644 root bin
d none usr/lib/mdb/kvm/amd64 755 root sys
f none usr/lib/mdb/kvm/amd64/dtrace.so 555 root sys
+f none usr/lib/mdb/kvm/dtrace.so 555 root sys
+d none usr/lib/mdb/raw/amd64 755 root sys
+f none usr/lib/mdb/raw/amd64/dof.so 555 root sys
d none usr/lib/amd64 755 root bin
f none usr/lib/amd64/libdtrace.so.1 755 root bin
s none usr/lib/amd64/libdtrace.so=libdtrace.so.1
diff --git a/usr/src/pkgdefs/SUNWdtrc/prototype_sparc b/usr/src/pkgdefs/SUNWdtrc/prototype_sparc
index 4a8da3815f..431fe87520 100644
--- a/usr/src/pkgdefs/SUNWdtrc/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWdtrc/prototype_sparc
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -31,6 +31,8 @@ d none usr/lib/dtrace/64 755 root bin
f none usr/lib/dtrace/64/drti.o 644 root bin
d none usr/lib/mdb/kvm/sparcv9 755 root sys
f none usr/lib/mdb/kvm/sparcv9/dtrace.so 555 root sys
+d none usr/lib/mdb/raw/sparcv9 755 root sys
+f none usr/lib/mdb/raw/sparcv9/dof.so 555 root sys
d none usr/lib/sparcv9 755 root bin
f none usr/lib/sparcv9/libdtrace.so.1 755 root bin
s none usr/lib/sparcv9/libdtrace.so=libdtrace.so.1
@@ -42,4 +44,3 @@ f none usr/sbin/sparcv9/dtrace 555 root bin
f none usr/sbin/sparcv9/intrstat 555 root bin
f none usr/sbin/sparcv9/lockstat 555 root bin
f none usr/sbin/sparcv9/plockstat 555 root bin
-
diff --git a/usr/src/pkgdefs/SUNWmdb/prototype_com b/usr/src/pkgdefs/SUNWmdb/prototype_com
index 27445bd4da..718ccb5b8c 100644
--- a/usr/src/pkgdefs/SUNWmdb/prototype_com
+++ b/usr/src/pkgdefs/SUNWmdb/prototype_com
@@ -52,4 +52,5 @@ f none usr/lib/mdb/proc/libuutil.so 555 root sys
f none usr/lib/mdb/proc/mdb_ds.so 555 root sys
f none usr/lib/mdb/proc/svc.configd.so 555 root sys
f none usr/lib/mdb/proc/svc.startd.so 555 root sys
+d none usr/lib/mdb/raw 755 root sys
d none usr/platform 755 root sys
diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h
index f10c15343e..6b6ca65fce 100644
--- a/usr/src/uts/common/sys/dtrace.h
+++ b/usr/src/uts/common/sys/dtrace.h
@@ -182,6 +182,8 @@ typedef enum dtrace_probespec {
#define DIF_OP_RLDUH 75 /* rlduh [r1], rd */
#define DIF_OP_RLDUW 76 /* rlduw [r1], rd */
#define DIF_OP_RLDX 77 /* rldx [r1], rd */
+#define DIF_OP_XLATE 78 /* xlate xlrindex, rd */
+#define DIF_OP_XLARG 79 /* xlarg xlrindex, rd */
#define DIF_INTOFF_MAX 0xffff /* highest integer table offset */
#define DIF_STROFF_MAX 0xffff /* highest string table offset */
@@ -280,6 +282,7 @@ typedef uint32_t dif_instr_t;
#define DIF_INSTR_STRING(i) (((i) >> 8) & 0xffff)
#define DIF_INSTR_SUBR(i) (((i) >> 8) & 0xffff)
#define DIF_INSTR_TYPE(i) (((i) >> 16) & 0xff)
+#define DIF_INSTR_XLREF(i) (((i) >> 8) & 0xffff)
#define DIF_INSTR_FMT(op, r1, r2, d) \
(((op) << 24) | ((r1) << 16) | ((r2) << 8) | (d))
@@ -304,6 +307,7 @@ typedef uint32_t dif_instr_t;
#define DIF_INSTR_FLUSHTS (DIF_OP_FLUSHTS << 24)
#define DIF_INSTR_ALLOCS(r1, d) (DIF_INSTR_FMT(DIF_OP_ALLOCS, r1, 0, d))
#define DIF_INSTR_COPYS(r1, r2, d) (DIF_INSTR_FMT(DIF_OP_COPYS, r1, r2, d))
+#define DIF_INSTR_XLATE(op, r, d) (((op) << 24) | ((r) << 8) | (d))
#define DIF_REG_R0 0 /* %r0 is always set to zero */
@@ -629,6 +633,11 @@ typedef struct dof_sec {
#define DOF_SECT_PROFFS 18 /* uint32_t array (probe arg offsets) */
#define DOF_SECT_INTTAB 19 /* uint64_t array */
#define DOF_SECT_UTSNAME 20 /* struct utsname */
+#define DOF_SECT_XLTAB 21 /* dof_xlref_t array */
+#define DOF_SECT_XLMEMBERS 22 /* dof_xlmember_t array */
+#define DOF_SECT_XLIMPORT 23 /* dof_xlator_t */
+#define DOF_SECT_XLEXPORT 24 /* dof_xlator_t */
+#define DOF_SECT_PREXPORT 25 /* dof_secidx_t array (exported objs) */
#define DOF_SECF_LOAD 1 /* section should be loaded */
@@ -719,6 +728,27 @@ typedef struct dof_probe {
uint32_t dofpr_pad; /* reserved for future use */
} dof_probe_t;
+typedef struct dof_xlator {
+ dof_secidx_t dofxl_members; /* link to DOF_SECT_XLMEMBERS section */
+ dof_secidx_t dofxl_strtab; /* link to DOF_SECT_STRTAB section */
+ dof_stridx_t dofxl_argv; /* input parameter type strings */
+ uint32_t dofxl_argc; /* input parameter list length */
+ dof_stridx_t dofxl_type; /* output type string name */
+ dof_attr_t dofxl_attr; /* output stability attributes */
+} dof_xlator_t;
+
+typedef struct dof_xlmember {
+ dof_secidx_t dofxm_difo; /* member link to DOF_SECT_DIFOHDR */
+ dof_stridx_t dofxm_name; /* member name */
+ dtrace_diftype_t dofxm_type; /* member type */
+} dof_xlmember_t;
+
+typedef struct dof_xlref {
+ dof_secidx_t dofxr_xlator; /* link to DOF_SECT_XLATORS section */
+ uint32_t dofxr_member; /* index of referenced dof_xlmember */
+ uint32_t dofxr_argn; /* index of argument for DIF_OP_XLARG */
+} dof_xlref_t;
+
/*
* DTrace Intermediate Format Object (DIFO)
*
@@ -748,8 +778,10 @@ typedef struct dtrace_difo {
#ifndef _KERNEL
dof_relodesc_t *dtdo_kreltab; /* kernel relocations */
dof_relodesc_t *dtdo_ureltab; /* user relocations */
- uint32_t dtdo_krelen; /* length of krelo table */
- uint32_t dtdo_urelen; /* length of urelo table */
+ struct dt_node **dtdo_xlmtab; /* translator references */
+ uint_t dtdo_krelen; /* length of krelo table */
+ uint_t dtdo_urelen; /* length of urelo table */
+ uint_t dtdo_xlmlen; /* length of translator table */
#endif
} dtrace_difo_t;