diff options
Diffstat (limited to 'usr/src')
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; |