summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorahl <none@none>2006-03-30 01:12:03 -0800
committerahl <none@none>2006-03-30 01:12:03 -0800
commitac448965596bc1c42f7accb3023f48d5fa9b8180 (patch)
tree2fec65de48a83b92568802081a1e3981d2aab1f7
parent507c32411f3f101e90ca2120f042b5ee698ba1d5 (diff)
downloadillumos-joyent-ac448965596bc1c42f7accb3023f48d5fa9b8180.tar.gz
6405927 USDT is-enabled probes
6405929 USDT DOF with zero probes results in an unsatisfiable memory allocation 6405932 dead variables in usr/src/uts/common/dtrace/dtrace.c 6405939 ::dofdump doesn't use section sizes correctly
-rw-r--r--usr/src/cmd/mdb/common/modules/dtrace/dof.c78
-rw-r--r--usr/src/cmd/mdb/common/modules/dtrace/dtrace.c10
-rw-r--r--usr/src/lib/libdtrace/common/dt_dof.c42
-rw-r--r--usr/src/lib/libdtrace/common/dt_dof.h9
-rw-r--r--usr/src/lib/libdtrace/common/dt_link.c206
-rw-r--r--usr/src/lib/libdtrace/common/dt_open.c6
-rw-r--r--usr/src/lib/libdtrace/common/dt_program.c24
-rw-r--r--usr/src/lib/libdtrace/common/dt_program.h9
-rw-r--r--usr/src/lib/libdtrace/common/dt_provider.c55
-rw-r--r--usr/src/lib/libdtrace/common/dt_provider.h11
-rw-r--r--usr/src/uts/common/dtrace/dtrace.c153
-rw-r--r--usr/src/uts/common/dtrace/fasttrap.c116
-rw-r--r--usr/src/uts/common/sys/dtrace.h15
-rw-r--r--usr/src/uts/common/sys/fasttrap.h11
-rw-r--r--usr/src/uts/common/sys/fasttrap_impl.h42
-rw-r--r--usr/src/uts/intel/dtrace/fasttrap_isa.c67
-rw-r--r--usr/src/uts/sparc/dtrace/fasttrap_isa.c48
17 files changed, 646 insertions, 256 deletions
diff --git a/usr/src/cmd/mdb/common/modules/dtrace/dof.c b/usr/src/cmd/mdb/common/modules/dtrace/dof.c
index e305d849ca..5631c4c3b4 100644
--- a/usr/src/cmd/mdb/common/modules/dtrace/dof.c
+++ b/usr/src/cmd/mdb/common/modules/dtrace/dof.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -828,19 +828,20 @@ dof_sect_strtab(uintptr_t addr, dof_sec_t *sec)
}
static int
-dof_sect_provider(uintptr_t addr, dof_sec_t *sec, dof_sec_t *dofs)
+dof_sect_provider(dof_hdr_t *dofh, uintptr_t addr, dof_sec_t *sec,
+ dof_sec_t *dofs)
{
dof_provider_t pv;
dof_probe_t *pb;
- char *strtab;
- uint32_t *offs;
+ char *strtab, *p;
+ uint32_t *offs, *enoffs;
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)) {
+ sz = MIN(sec->dofs_size, sizeof (dof_provider_t));
+ if (mdb_vread(&pv, sz, addr + sec->dofs_offset) != sz) {
mdb_warn("failed to read DOF provider");
return (-1);
}
@@ -870,13 +871,25 @@ dof_sect_provider(uintptr_t addr, dof_sec_t *sec, dof_sec_t *dofs)
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");
+ mdb_warn("failed to read offsets");
return (-1);
}
+ enoffs = NULL;
+ if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 ||
+ pv.dofpv_prenoffs == 0) {
+ sz = dofs[pv.dofpv_prenoffs].dofs_size;
+ enoffs = mdb_alloc(sz, UM_SLEEP | UM_GC);
+ if (mdb_vread(enoffs, sz, addr +
+ dofs[pv.dofpv_prenoffs].dofs_offset) != sz) {
+ mdb_warn("failed to read is-enabled offsets");
+ 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) {
+ p = mdb_alloc(sz, UM_SLEEP | UM_GC);
+ if (mdb_vread(p, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) {
mdb_warn("failed to read probes");
return (-1);
}
@@ -884,39 +897,56 @@ dof_sect_provider(uintptr_t addr, dof_sec_t *sec, dof_sec_t *dofs)
(void) mdb_inc_indent(2);
for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) {
+ pb = (dof_probe_t *)(uintptr_t)(p +
+ i * dofs[pv.dofpv_probes].dofs_entsize);
+
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);
+ strtab + pb->dofpr_func,
+ strtab + pb->dofpr_name);
(void) mdb_inc_indent(2);
- mdb_printf("addr: %p\n", (ulong_t)pb[i].dofpr_addr);
+ mdb_printf("addr: %p\n", (ulong_t)pb->dofpr_addr);
mdb_printf("offs: ");
- for (j = 0; j < pb[i].dofpr_noffs; j++) {
+ for (j = 0; j < pb->dofpr_noffs; j++) {
mdb_printf("%s %x", "," + (j == 0),
- offs[pb[i].dofpr_offidx + j]);
+ offs[pb->dofpr_offidx + j]);
}
mdb_printf("\n");
+ if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) {
+ mdb_printf("enoffs: ");
+ if (enoffs == NULL) {
+ if (pb->dofpr_nenoffs != 0)
+ mdb_printf("<error>");
+ } else {
+ for (j = 0; j < pb->dofpr_nenoffs; j++) {
+ mdb_printf("%s %x", "," + (j == 0),
+ enoffs[pb->dofpr_enoffidx + j]);
+ }
+ }
+ mdb_printf("\n");
+ }
+
mdb_printf("nargs:");
- narg = pb[i].dofpr_nargv;
- for (j = 0; j < pb[i].dofpr_nargc; j++) {
+ narg = pb->dofpr_nargv;
+ for (j = 0; j < pb->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++) {
+ xarg = pb->dofpr_xargv;
+ for (j = 0; j < pb->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++) {
+ for (j = 0; j < pb->dofpr_xargc; j++) {
mdb_printf("%s %d->%d", "," + (j == 0),
- args[pb[i].dofpr_argidx + j], j);
+ args[pb->dofpr_argidx + j], j);
}
(void) mdb_dec_indent(2);
@@ -990,7 +1020,7 @@ dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
(void) mdb_inc_indent(2);
switch (dofs[i].dofs_type) {
case DOF_SECT_PROVIDER:
- (void) dof_sect_provider(addr, &dofs[i], dofs);
+ (void) dof_sect_provider(&dofh, addr, &dofs[i], dofs);
break;
case DOF_SECT_STRTAB:
(void) dof_sect_strtab(addr, &dofs[i]);
diff --git a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c
index e051dc481b..55decccef3 100644
--- a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c
+++ b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -457,7 +457,7 @@ dtracemdb_dof_create(dtrace_state_t *state)
dof->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE;
dof->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
- dof->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1;
+ dof->dofh_ident[DOF_ID_VERSION] = DOF_VERSION;
dof->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION;
dof->dofh_ident[DOF_ID_DIFIREG] = DIF_DIR_NREGS;
dof->dofh_ident[DOF_ID_DIFTREG] = DIF_DTR_NREGS;
diff --git a/usr/src/lib/libdtrace/common/dt_dof.c b/usr/src/lib/libdtrace/common/dt_dof.c
index 9795e019d9..718a2dc0c5 100644
--- a/usr/src/lib/libdtrace/common/dt_dof.c
+++ b/usr/src/lib/libdtrace/common/dt_dof.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -62,6 +62,7 @@ dt_dof_init(dtrace_hdl_t *dtp)
dt_buf_create(dtp, &ddo->ddo_probes, "probe data", 0);
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_enoffs, "probe is-enabled offs", 0);
dt_buf_create(dtp, &ddo->ddo_rels, "probe rels", 0);
dt_buf_create(dtp, &ddo->ddo_xlms, "xlate members", 0);
@@ -83,6 +84,7 @@ dt_dof_fini(dtrace_hdl_t *dtp)
dt_buf_destroy(dtp, &ddo->ddo_probes);
dt_buf_destroy(dtp, &ddo->ddo_args);
dt_buf_destroy(dtp, &ddo->ddo_offs);
+ dt_buf_destroy(dtp, &ddo->ddo_enoffs);
dt_buf_destroy(dtp, &ddo->ddo_rels);
dt_buf_destroy(dtp, &ddo->ddo_xlms);
@@ -122,6 +124,7 @@ dt_dof_reset(dtrace_hdl_t *dtp, dtrace_prog_t *pgp)
dt_buf_reset(dtp, &ddo->ddo_probes);
dt_buf_reset(dtp, &ddo->ddo_args);
dt_buf_reset(dtp, &ddo->ddo_offs);
+ dt_buf_reset(dtp, &ddo->ddo_enoffs);
dt_buf_reset(dtp, &ddo->ddo_rels);
dt_buf_reset(dtp, &ddo->ddo_xlms);
@@ -428,17 +431,29 @@ dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
dofpr.dofpr_nargc = prp->pr_nargc;
dofpr.dofpr_xargc = prp->pr_xargc;
- dofpr.dofpr_pad = 0;
+ dofpr.dofpr_pad1 = 0;
+ dofpr.dofpr_pad2 = 0;
for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) {
+ dt_dprintf("adding probe for %s:%s\n", pip->pi_fname,
+ prp->pr_name);
+
dofpr.dofpr_func = dof_add_string(ddo, pip->pi_fname);
+
+ assert(pip->pi_noffs > 0);
+
dofpr.dofpr_offidx =
dt_buf_len(&ddo->ddo_offs) / sizeof (uint32_t);
dofpr.dofpr_noffs = pip->pi_noffs;
-
dt_buf_write(dtp, &ddo->ddo_offs, pip->pi_offs,
pip->pi_noffs * sizeof (uint32_t), sizeof (uint32_t));
+ dofpr.dofpr_enoffidx =
+ dt_buf_len(&ddo->ddo_enoffs) / sizeof (uint32_t);
+ dofpr.dofpr_nenoffs = pip->pi_nenoffs;
+ dt_buf_write(dtp, &ddo->ddo_enoffs, pip->pi_enoffs,
+ pip->pi_noffs * sizeof (uint32_t), sizeof (uint32_t));
+
/*
* If pi_rname isn't set, the relocation will be against the
* function name. If it is, the relocation will be against
@@ -497,6 +512,7 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
dt_buf_reset(dtp, &ddo->ddo_probes);
dt_buf_reset(dtp, &ddo->ddo_args);
dt_buf_reset(dtp, &ddo->ddo_offs);
+ dt_buf_reset(dtp, &ddo->ddo_enoffs);
dt_buf_reset(dtp, &ddo->ddo_rels);
(void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo);
@@ -513,11 +529,18 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t));
+ assert(dt_buf_len(&ddo->ddo_offs) > 0);
+
dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS,
sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs));
dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t));
+ dofpv.dofpv_prenoffs = dof_add_lsect(ddo, NULL, DOF_SECT_PRENOFFS,
+ sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_enoffs));
+
+ dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_enoffs, sizeof (uint_t));
+
dofpv.dofpv_strtab = ddo->ddo_strsec;
dofpv.dofpv_name = dof_add_string(ddo, pvp->pv_desc.dtvd_name);
@@ -549,7 +572,7 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
}
static int
-dof_hdr(dtrace_hdl_t *dtp, dof_hdr_t *hp)
+dof_hdr(dtrace_hdl_t *dtp, uint8_t dofversion, dof_hdr_t *hp)
{
/*
* If our config values cannot fit in a uint8_t, we can't generate a
@@ -574,7 +597,7 @@ dof_hdr(dtrace_hdl_t *dtp, dof_hdr_t *hp)
hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_ILP32;
hp->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
- hp->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1;
+ hp->dofh_ident[DOF_ID_VERSION] = dofversion;
hp->dofh_ident[DOF_ID_DIFVERS] = dtp->dt_conf.dtc_difversion;
hp->dofh_ident[DOF_ID_DIFIREG] = dtp->dt_conf.dtc_difintregs;
hp->dofh_ident[DOF_ID_DIFTREG] = dtp->dt_conf.dtc_diftupregs;
@@ -617,7 +640,7 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
flags |= dtp->dt_dflags;
- if (dof_hdr(dtp, &h) != 0)
+ if (dof_hdr(dtp, pgp->dp_dofversion, &h) != 0)
return (NULL);
if (dt_dof_reset(dtp, pgp) != 0)
@@ -885,7 +908,8 @@ dtrace_getopt_dof(dtrace_hdl_t *dtp)
len += sizeof (dof_optdesc_t) * nopts;
- if ((dof = dt_zalloc(dtp, len)) == NULL || dof_hdr(dtp, dof) != 0) {
+ if ((dof = dt_zalloc(dtp, len)) == NULL ||
+ dof_hdr(dtp, DOF_VERSION, dof) != 0) {
dt_free(dtp, dof);
return (NULL);
}
diff --git a/usr/src/lib/libdtrace/common/dt_dof.h b/usr/src/lib/libdtrace/common/dt_dof.h
index 9d20f624e7..e0a4bf5250 100644
--- a/usr/src/lib/libdtrace/common/dt_dof.h
+++ b/usr/src/lib/libdtrace/common/dt_dof.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,6 +51,7 @@ typedef struct dt_dof {
dt_buf_t ddo_probes; /* probe section data */
dt_buf_t ddo_args; /* probe arguments section data */
dt_buf_t ddo_offs; /* probe offsets section data */
+ dt_buf_t ddo_enoffs; /* is-enabled offsets section data */
dt_buf_t ddo_rels; /* probe relocation section data */
dt_buf_t ddo_xlms; /* xlate members section data */
} dt_dof_t;
diff --git a/usr/src/lib/libdtrace/common/dt_link.c b/usr/src/lib/libdtrace/common/dt_link.c
index ffc95fac06..60fe4b5f36 100644
--- a/usr/src/lib/libdtrace/common/dt_link.c
+++ b/usr/src/lib/libdtrace/common/dt_link.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -47,6 +47,7 @@
#include <dt_impl.h>
#include <dt_provider.h>
+#include <dt_program.h>
#include <dt_string.h>
#define ESHDR_NULL 0
@@ -742,6 +743,7 @@ dt_symtab_lookup(Elf_Data *data_sym, uintptr_t addr, uint_t shn, GElf_Sym *sym)
#define DT_OP_RET 0x81c7e008
#define DT_OP_NOP 0x01000000
#define DT_OP_CALL 0x40000000
+#define DT_OP_CLR_O0 0x90102000
#define DT_IS_MOV_O7(inst) (((inst) & 0xffffe000) == 0x9e100000)
#define DT_IS_RESTORE(inst) (((inst) & 0xc1f80000) == 0x81e80000)
@@ -750,8 +752,10 @@ dt_symtab_lookup(Elf_Data *data_sym, uintptr_t addr, uint_t shn, GElf_Sym *sym)
#define DT_RS2(inst) ((inst) & 0x1f)
#define DT_MAKE_RETL(reg) (0x81c02008 | ((reg) << 14))
+/*ARGSUSED*/
static int
-dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
+dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
+ uint32_t *off)
{
uint32_t *ip;
@@ -769,22 +773,25 @@ dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
return (-1);
/*
- * We may have already processed this object file in an earlier
- * linker invocation in which case we'd expect to see a ret/restore
- * pair, a retl-like/mov pair or a nop; return success in that case.
+ * We may have already processed this object file in an earlier linker
+ * invocation. Check to see if the present instruction sequence matches
+ * the one we would install.
*/
- if (DT_IS_RESTORE(ip[1])) {
- if (ip[0] == DT_OP_RET) {
- return (0);
- }
- } else if (DT_IS_MOV_O7(ip[1])) {
- if (DT_IS_RETL(ip[0])) {
+ if (isenabled) {
+ if (ip[0] == DT_OP_CLR_O0)
return (0);
- }
} else {
- if (ip[0] == DT_OP_NOP) {
- (*off) += sizeof (ip[0]);
- return (0);
+ if (DT_IS_RESTORE(ip[1])) {
+ if (ip[0] == DT_OP_RET)
+ return (0);
+ } else if (DT_IS_MOV_O7(ip[1])) {
+ if (DT_IS_RETL(ip[0]))
+ return (0);
+ } else {
+ if (ip[0] == DT_OP_NOP) {
+ (*off) += sizeof (ip[0]);
+ return (0);
+ }
}
}
@@ -797,22 +804,39 @@ dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
return (-1);
}
- /*
- * If the call is followed by a restore, it's a tail call so change
- * the call to a ret. If the call if followed by a mov of a register
- * into %o7, it's a tail call in leaf context so change the call to
- * a retl-like instruction that returns to that register value + 8
- * (rather than the typical %o7 + 8). Otherwise we adjust the offset
- * to land on what was once the delay slot of the call so we
- * correctly get all the arguments.
- */
- if (DT_IS_RESTORE(ip[1])) {
- ip[0] = DT_OP_RET;
- } else if (DT_IS_MOV_O7(ip[1])) {
- ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
+ if (isenabled) {
+ /*
+ * It would necessarily indicate incorrect usage if an is-
+ * enabled probe were tail-called so flag that as an error.
+ * It's also potentially (very) tricky to handle gracefully,
+ * but could be done if this were a desired use scenario.
+ */
+ if (DT_IS_RESTORE(ip[1]) || DT_IS_MOV_O7(ip[1])) {
+ dt_dprintf("tail call to is-enabled probe at %llx\n",
+ (u_longlong_t)rela->r_offset);
+ return (-1);
+ }
+
+ ip[0] = DT_OP_CLR_O0;
} else {
- ip[0] = DT_OP_NOP;
- (*off) += sizeof (ip[0]);
+ /*
+ * If the call is followed by a restore, it's a tail call so
+ * change the call to a ret. If the call if followed by a mov
+ * of a register into %o7, it's a tail call in leaf context
+ * so change the call to a retl-like instruction that returns
+ * to that register value + 8 (rather than the typical %o7 +
+ * 8). Otherwise we adjust the offset to land on what was
+ * once the delay slot of the call so we correctly get all
+ * the arguments.
+ */
+ if (DT_IS_RESTORE(ip[1])) {
+ ip[0] = DT_OP_RET;
+ } else if (DT_IS_MOV_O7(ip[1])) {
+ ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
+ } else {
+ ip[0] = DT_OP_NOP;
+ (*off) += sizeof (ip[0]);
+ }
}
return (0);
@@ -822,16 +846,22 @@ dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
#define DT_OP_NOP 0x90
#define DT_OP_CALL 0xe8
+#define DT_OP_REX_RAX 0x48
+#define DT_OP_XOR_EAX_0 0x33
+#define DT_OP_XOR_EAX_1 0xc0
static int
-dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
+dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
+ uint32_t *off)
{
uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
/*
* On x86, the first byte of the instruction is the call opcode and
* the next four bytes are the 32-bit address; the relocation is for
- * the address so we back up one byte to land on the opcode.
+ * the address operand. We back up the offset to the first byte of
+ * the instruction. For is-enabled probes, we later advance the offset
+ * so that it hits the first nop in the instruction sequence.
*/
(*off) -= 1;
@@ -845,13 +875,31 @@ dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
return (-1);
/*
- * We may have already processed this object file in an earlier
- * linker invocation in which case we'd expect to see a bunch
- * of nops; return success in that case.
+ * We may have already processed this object file in an earlier linker
+ * invocation. Check to see if the present instruction sequence matches
+ * the one we would install. For is-enabled probes, we advance the
+ * offset to the first nop instruction in the sequence.
*/
- if (ip[0] == DT_OP_NOP && ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
- ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
- return (0);
+ if (!isenabled) {
+ if (ip[0] == DT_OP_NOP && ip[1] == DT_OP_NOP &&
+ ip[2] == DT_OP_NOP && ip[3] == DT_OP_NOP &&
+ ip[4] == DT_OP_NOP)
+ return (0);
+ } else if (dtp->dt_oflags & DTRACE_O_LP64) {
+ if (ip[0] == DT_OP_REX_RAX &&
+ ip[1] == DT_OP_XOR_EAX_0 && ip[2] == DT_OP_XOR_EAX_1 &&
+ ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) {
+ (*off) += 3;
+ return (0);
+ }
+ } else {
+ if (ip[0] == DT_OP_XOR_EAX_0 && ip[1] == DT_OP_XOR_EAX_1 &&
+ ip[2] == DT_OP_NOP && ip[3] == DT_OP_NOP &&
+ ip[4] == DT_OP_NOP) {
+ (*off) += 2;
+ return (0);
+ }
+ }
/*
* We only expect a call instrution with a 32-bit displacement.
@@ -862,11 +910,34 @@ dt_modtext(char *p, GElf_Rela *rela, uint32_t *off)
return (-1);
}
- ip[0] = DT_OP_NOP;
- ip[1] = DT_OP_NOP;
- ip[2] = DT_OP_NOP;
- ip[3] = DT_OP_NOP;
- ip[4] = DT_OP_NOP;
+ /*
+ * Establish the instruction sequence -- all nops for probes, and an
+ * instruction to clear the return value register (%eax/%rax) followed
+ * by nops for is-enabled probes. For is-enabled probes, we advance
+ * the offset to the first nop. This isn't stricly necessary but makes
+ * for more readable disassembly when the probe is enabled.
+ */
+ if (!isenabled) {
+ ip[0] = DT_OP_NOP;
+ ip[1] = DT_OP_NOP;
+ ip[2] = DT_OP_NOP;
+ ip[3] = DT_OP_NOP;
+ ip[4] = DT_OP_NOP;
+ } else if (dtp->dt_oflags & DTRACE_O_LP64) {
+ ip[0] = DT_OP_REX_RAX;
+ ip[1] = DT_OP_XOR_EAX_0;
+ ip[2] = DT_OP_XOR_EAX_1;
+ ip[3] = DT_OP_NOP;
+ ip[4] = DT_OP_NOP;
+ (*off) += 3;
+ } else {
+ ip[0] = DT_OP_XOR_EAX_0;
+ ip[1] = DT_OP_XOR_EAX_1;
+ ip[2] = DT_OP_NOP;
+ ip[3] = DT_OP_NOP;
+ ip[4] = DT_OP_NOP;
+ (*off) += 2;
+ }
return (0);
}
@@ -904,12 +975,13 @@ dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
}
static int
-process_obj(dtrace_hdl_t *dtp, const char *obj)
+process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
{
- static const char dt_prefix[] = "__dtrace_";
+ static const char dt_prefix[] = "__dtrace";
+ static const char dt_enabled[] = "enabled";
static const char dt_symprefix[] = "$dtrace";
static const char dt_symfmt[] = "%s%d.%s";
- int fd, i, ndx, mod = 0;
+ int fd, i, ndx, eprobe, mod = 0;
Elf *elf = NULL;
GElf_Ehdr ehdr;
Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
@@ -1037,7 +1109,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
/*
* We're looking for relocations to symbols matching this form:
*
- * __dtrace_<prov>___<probe>
+ * __dtrace[enabled]_<prov>___<probe>
*
* For the generated object, we need to record the location
* identified by the relocation, and create a new relocation
@@ -1192,6 +1264,25 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
continue;
s += sizeof (dt_prefix) - 1;
+
+ /*
+ * Check to see if this is an 'is-enabled' check as
+ * opposed to a normal probe.
+ */
+ if (strncmp(s, dt_enabled,
+ sizeof (dt_enabled) - 1) == 0) {
+ s += sizeof (dt_enabled) - 1;
+ eprobe = 1;
+ *eprobesp = 1;
+ dt_dprintf("is-enabled probe\n");
+ } else {
+ eprobe = 0;
+ dt_dprintf("normal probe\n");
+ }
+
+ if (*s++ != '_')
+ goto err;
+
if ((p = strstr(s, "___")) == NULL ||
p - s >= sizeof (pname))
goto err;
@@ -1257,10 +1348,12 @@ process_obj(dtrace_hdl_t *dtp, const char *obj)
assert(fsym.st_value <= rela.r_offset);
off = rela.r_offset - fsym.st_value;
- if (dt_modtext(data_tgt->d_buf, &rela, &off) != 0)
+ if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
+ &rela, &off) != 0) {
goto err;
+ }
- if (dt_probe_define(pvp, prp, s, r, off) != 0) {
+ if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0) {
return (dt_link_error(dtp, elf, fd, bufs,
"failed to allocate space for probe"));
}
@@ -1318,7 +1411,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
int fd, status, i, cur;
char *cmd, tmp;
size_t len;
- int ret = 0;
+ int eprobes = 0, ret = 0;
/*
* A NULL program indicates a special use in which we just link
@@ -1367,10 +1460,17 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
}
for (i = 0; i < objc; i++) {
- if (process_obj(dtp, objv[i]) != 0)
+ if (process_obj(dtp, objv[i], &eprobes) != 0)
return (-1); /* errno is set for us */
}
+ /*
+ * If there are is-enabled probes then we need to force use of DOF
+ * version 2.
+ */
+ if (eprobes && pgp->dp_dofversion < DOF_VERSION_2)
+ pgp->dp_dofversion = DOF_VERSION_2;
+
if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
return (-1); /* errno is set for us */
diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c
index b857661728..79e29c3c7f 100644
--- a/usr/src/lib/libdtrace/common/dt_open.c
+++ b/usr/src/lib/libdtrace/common/dt_open.c
@@ -96,14 +96,16 @@
#define DT_VERS_1_1 DT_VERSION_NUMBER(1, 1, 0)
#define DT_VERS_1_2 DT_VERSION_NUMBER(1, 2, 0)
#define DT_VERS_1_2_1 DT_VERSION_NUMBER(1, 2, 1)
-#define DT_VERS_LATEST DT_VERS_1_2_1
-#define DT_VERS_STRING "Sun D 1.2.1"
+#define DT_VERS_1_2_2 DT_VERSION_NUMBER(1, 2, 2)
+#define DT_VERS_LATEST DT_VERS_1_2_2
+#define DT_VERS_STRING "Sun D 1.2.2"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
DT_VERS_1_1, /* D API 1.1.0 Solaris Express 6/05 */
DT_VERS_1_2, /* D API 1.2.0 Solaris 10 Update 1 */
DT_VERS_1_2_1, /* D API 1.2.1 Solaris Express 4/06 */
+ DT_VERS_1_2_2, /* D API 1.2.2 Solaris Express 6/06 */
0
};
diff --git a/usr/src/lib/libdtrace/common/dt_program.c b/usr/src/lib/libdtrace/common/dt_program.c
index e0d3ada107..d751c4817b 100644
--- a/usr/src/lib/libdtrace/common/dt_program.c
+++ b/usr/src/lib/libdtrace/common/dt_program.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -50,6 +49,13 @@ dt_program_create(dtrace_hdl_t *dtp)
else
(void) dt_set_errno(dtp, EDT_NOMEM);
+ /*
+ * By default, programs start with DOF version 1 so that output files
+ * containing DOF are backward compatible. If a program requires new
+ * DOF features, the version is increased as needed.
+ */
+ pgp->dp_dofversion = DOF_VERSION_1;
+
return (pgp);
}
@@ -425,6 +431,10 @@ dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
if (fprintf(infop->dthi_out, ");\n") < 0)
return (dt_set_errno(dtp, errno));
+ if (fprintf(infop->dthi_out, "extern int "
+ "__dtraceenabled_%s___%s(void);\n", infop->dthi_pfname, fname) < 0)
+ return (dt_set_errno(dtp, errno));
+
return (0);
}
@@ -481,6 +491,14 @@ dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
if (fprintf(infop->dthi_out, ")\n") < 0)
return (dt_set_errno(dtp, errno));
+ if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() \\\n",
+ infop->dthi_pmname, mname) < 0)
+ return (dt_set_errno(dtp, errno));
+
+ if (fprintf(infop->dthi_out, "\t__dtraceenabled_%s___%s()\n",
+ infop->dthi_pfname, fname) < 0)
+ return (dt_set_errno(dtp, errno));
+
return (0);
}
diff --git a/usr/src/lib/libdtrace/common/dt_program.h b/usr/src/lib/libdtrace/common/dt_program.h
index b4311baed2..3fe1c39136 100644
--- a/usr/src/lib/libdtrace/common/dt_program.h
+++ b/usr/src/lib/libdtrace/common/dt_program.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,6 +46,7 @@ struct dtrace_prog {
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 */
+ uint8_t dp_dofversion; /* DOF version this program requires */
};
extern dtrace_prog_t *dt_program_create(dtrace_hdl_t *);
diff --git a/usr/src/lib/libdtrace/common/dt_provider.c b/usr/src/lib/libdtrace/common/dt_provider.c
index 056442aa8f..9c5ff9e1a1 100644
--- a/usr/src/lib/libdtrace/common/dt_provider.c
+++ b/usr/src/lib/libdtrace/common/dt_provider.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -498,6 +498,7 @@ dt_probe_destroy(dt_probe_t *prp)
for (pip = prp->pr_inst; pip != NULL; pip = pip_next) {
pip_next = pip->pi_next;
dt_free(dtp, pip->pi_offs);
+ dt_free(dtp, pip->pi_enoffs);
dt_free(dtp, pip);
}
@@ -508,10 +509,12 @@ dt_probe_destroy(dt_probe_t *prp)
int
dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp,
- const char *fname, const char *rname, uint32_t offset)
+ const char *fname, const char *rname, uint32_t offset, int isenabled)
{
dtrace_hdl_t *dtp = pvp->pv_hdl;
dt_probe_instance_t *pip;
+ uint32_t **offs;
+ uint_t *noffs, *maxoffs;
assert(fname != NULL);
@@ -526,7 +529,15 @@ dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp,
if ((pip = dt_zalloc(dtp, sizeof (*pip))) == NULL)
return (-1);
- if ((pip->pi_offs = dt_alloc(dtp, sizeof (uint32_t))) == NULL) {
+ if ((pip->pi_offs = dt_zalloc(dtp,
+ sizeof (uint32_t))) == NULL) {
+ dt_free(dtp, pip);
+ return (-1);
+ }
+
+ if ((pip->pi_enoffs = dt_zalloc(dtp,
+ sizeof (uint32_t))) == NULL) {
+ dt_free(dtp, pip->pi_offs);
dt_free(dtp, pip);
return (-1);
}
@@ -540,34 +551,48 @@ dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp,
}
(void) strcpy(pip->pi_rname, rname);
}
+
pip->pi_noffs = 0;
pip->pi_maxoffs = 1;
+ pip->pi_nenoffs = 0;
+ pip->pi_maxenoffs = 1;
+
pip->pi_next = prp->pr_inst;
prp->pr_inst = pip;
}
- if (pip->pi_noffs == pip->pi_maxoffs) {
- uint_t new_max = pip->pi_maxoffs * 2;
+ if (isenabled) {
+ offs = &pip->pi_enoffs;
+ noffs = &pip->pi_nenoffs;
+ maxoffs = &pip->pi_maxenoffs;
+ } else {
+ offs = &pip->pi_offs;
+ noffs = &pip->pi_noffs;
+ maxoffs = &pip->pi_maxoffs;
+ }
+
+ if (*noffs == *maxoffs) {
+ uint_t new_max = *maxoffs * 2;
uint32_t *new_offs = dt_alloc(dtp, sizeof (uint32_t) * new_max);
if (new_offs == NULL)
return (-1);
- bcopy(pip->pi_offs, new_offs,
- sizeof (uint32_t) * pip->pi_maxoffs);
+ bcopy(*offs, new_offs, sizeof (uint32_t) * *maxoffs);
- dt_free(dtp, pip->pi_offs);
- pip->pi_maxoffs = new_max;
- pip->pi_offs = new_offs;
+ dt_free(dtp, *offs);
+ *maxoffs = new_max;
+ *offs = new_offs;
}
- dt_dprintf("defined probe %s:%s %s() +0x%x (%s)\n",
+ dt_dprintf("defined probe %s %s:%s %s() +0x%x (%s)\n",
+ isenabled ? "(is-enabled)" : "",
pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, fname, offset,
rname != NULL ? rname : fname);
- assert(pip->pi_noffs < pip->pi_maxoffs);
- pip->pi_offs[pip->pi_noffs++] = offset;
+ assert(*noffs < *maxoffs);
+ *offs[(*noffs)++] = offset;
return (0);
}
diff --git a/usr/src/lib/libdtrace/common/dt_provider.h b/usr/src/lib/libdtrace/common/dt_provider.h
index 97436557d4..af4ec33dcb 100644
--- a/usr/src/lib/libdtrace/common/dt_provider.h
+++ b/usr/src/lib/libdtrace/common/dt_provider.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -67,8 +67,11 @@ typedef struct dt_probe_instance {
char pi_fname[DTRACE_FUNCNAMELEN]; /* function name */
char pi_rname[DTRACE_FUNCNAMELEN + 20]; /* mangled relocation name */
uint32_t *pi_offs; /* offsets into the function */
+ uint32_t *pi_enoffs; /* is-enabled offsets */
uint_t pi_noffs; /* number of offsets */
uint_t pi_maxoffs; /* size of pi_offs allocation */
+ uint_t pi_nenoffs; /* number of is-enabled offsets */
+ uint_t pi_maxenoffs; /* size of pi_enoffs allocation */
struct dt_probe_instance *pi_next; /* next instance in the list */
} dt_probe_instance_t;
@@ -104,7 +107,7 @@ extern void dt_probe_declare(dt_provider_t *, dt_probe_t *);
extern void dt_probe_destroy(dt_probe_t *);
extern int dt_probe_define(dt_provider_t *, dt_probe_t *,
- const char *, const char *, uint32_t);
+ const char *, const char *, uint32_t, int);
extern dt_node_t *dt_probe_tag(dt_probe_t *, uint_t, dt_node_t *);
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
index 3ee6670006..eabf7a8016 100644
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -183,8 +184,6 @@ static dtrace_ecb_t *dtrace_ecb_create_cache; /* cached created ECB */
static dtrace_genid_t dtrace_probegen; /* current probe generation */
static dtrace_helpers_t *dtrace_deferred_pid; /* deferred helper list */
static dtrace_enabling_t *dtrace_retained; /* list of retained enablings */
-static dtrace_state_t *dtrace_state; /* temporary variable */
-static int dtrace_err; /* temporary variable */
/*
* DTrace Locking
@@ -6638,10 +6637,10 @@ dtrace_helper_provide_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid)
{
uintptr_t daddr = (uintptr_t)dhp->dofhp_dof;
dof_hdr_t *dof = (dof_hdr_t *)daddr;
- dof_sec_t *str_sec, *prb_sec, *arg_sec, *off_sec;
+ dof_sec_t *str_sec, *prb_sec, *arg_sec, *off_sec, *enoff_sec;
dof_provider_t *provider;
dof_probe_t *probe;
- uint32_t *off;
+ uint32_t *off, *enoff;
uint8_t *arg;
char *strtab;
uint_t i, nprobes;
@@ -6664,6 +6663,17 @@ dtrace_helper_provide_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid)
strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
off = (uint32_t *)(uintptr_t)(daddr + off_sec->dofs_offset);
arg = (uint8_t *)(uintptr_t)(daddr + arg_sec->dofs_offset);
+ enoff = NULL;
+
+ /*
+ * See dtrace_helper_provider_validate().
+ */
+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
+ provider->dofpv_prenoffs != 0) {
+ enoff_sec = (dof_sec_t *)(uintptr_t)(daddr + dof->dofh_secoff +
+ provider->dofpv_prenoffs * dof->dofh_secsize);
+ enoff = (uint32_t *)(uintptr_t)(daddr + enoff_sec->dofs_offset);
+ }
nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize;
@@ -6690,6 +6700,13 @@ dtrace_helper_provide_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid)
dhpb.dthpb_base = probe->dofpr_addr;
dhpb.dthpb_offs = off + probe->dofpr_offidx;
dhpb.dthpb_noffs = probe->dofpr_noffs;
+ if (enoff != NULL) {
+ dhpb.dthpb_enoffs = enoff + probe->dofpr_enoffidx;
+ dhpb.dthpb_nenoffs = probe->dofpr_nenoffs;
+ } else {
+ dhpb.dthpb_enoffs = NULL;
+ dhpb.dthpb_nenoffs = 0;
+ }
dhpb.dthpb_args = arg + probe->dofpr_argidx;
dhpb.dthpb_nargc = probe->dofpr_nargc;
dhpb.dthpb_xargc = probe->dofpr_xargc;
@@ -10015,7 +10032,7 @@ dtrace_dof_create(dtrace_state_t *state)
dof->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE;
dof->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
- dof->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1;
+ dof->dofh_ident[DOF_ID_VERSION] = DOF_VERSION;
dof->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION;
dof->dofh_ident[DOF_ID_DIFIREG] = DIF_DIR_NREGS;
dof->dofh_ident[DOF_ID_DIFTREG] = DIF_DTR_NREGS;
@@ -10733,7 +10750,8 @@ dtrace_dof_slurp(dof_hdr_t *dof, dtrace_vstate_t *vstate, cred_t *cr,
return (-1);
}
- if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) {
+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
+ dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_2) {
dtrace_dof_error(dof, "DOF version mismatch");
return (-1);
}
@@ -12456,7 +12474,7 @@ static int
dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec)
{
uintptr_t daddr = (uintptr_t)dof;
- dof_sec_t *str_sec, *prb_sec, *arg_sec, *off_sec;
+ dof_sec_t *str_sec, *prb_sec, *arg_sec, *off_sec, *enoff_sec;
dof_provider_t *provider;
dof_probe_t *probe;
uint8_t *arg;
@@ -12472,6 +12490,18 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec)
return (-1);
}
+ /*
+ * The section needs to be large enough to contain the DOF provider
+ * structure appropriate for the given version.
+ */
+ if (sec->dofs_size <
+ ((dof->dofh_ident[DOF_ID_VERSION] == DOF_VERSION_1) ?
+ offsetof(dof_provider_t, dofpv_prenoffs) :
+ sizeof (dof_provider_t))) {
+ dtrace_dof_error(dof, "provider section too small");
+ return (-1);
+ }
+
provider = (dof_provider_t *)(uintptr_t)(daddr + sec->dofs_offset);
str_sec = dtrace_dof_sect(dof, DOF_SECT_STRTAB, provider->dofpv_strtab);
prb_sec = dtrace_dof_sect(dof, DOF_SECT_PROBES, provider->dofpv_probes);
@@ -12482,6 +12512,13 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec)
arg_sec == NULL || off_sec == NULL)
return (-1);
+ enoff_sec = NULL;
+
+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
+ provider->dofpv_prenoffs != 0 && (enoff_sec = dtrace_dof_sect(dof,
+ DOF_SECT_PRENOFFS, provider->dofpv_prenoffs)) == NULL)
+ return (-1);
+
strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
if (provider->dofpv_name >= str_sec->dofs_size ||
@@ -12543,8 +12580,12 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec)
return (-1);
}
-
- if (probe->dofpr_offidx + probe->dofpr_noffs <
+ /*
+ * The offset count must not wrap the index and there must be
+ * at least one offset. The offsets must also not overflow the
+ * section's data.
+ */
+ if (probe->dofpr_offidx + probe->dofpr_noffs <=
probe->dofpr_offidx ||
(probe->dofpr_offidx + probe->dofpr_noffs) *
off_sec->dofs_entsize > off_sec->dofs_size) {
@@ -12552,6 +12593,31 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec)
return (-1);
}
+ if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) {
+ /*
+ * If there's no is-enabled offset section, make sure
+ * there aren't any is-enabled offsets. Otherwise
+ * perform the same checks as for probe offsets
+ * (immediately above), except that having zero
+ * is-enabled offsets is permitted.
+ */
+ if (enoff_sec == NULL) {
+ if (probe->dofpr_enoffidx != 0 ||
+ probe->dofpr_nenoffs != 0) {
+ dtrace_dof_error(dof, "is-enabled "
+ "offsets with null section");
+ return (-1);
+ }
+ } else if (probe->dofpr_enoffidx +
+ probe->dofpr_nenoffs < probe->dofpr_enoffidx ||
+ (probe->dofpr_enoffidx + probe->dofpr_nenoffs) *
+ enoff_sec->dofs_entsize > enoff_sec->dofs_size) {
+ dtrace_dof_error(dof, "invalid is-enabled "
+ "offset");
+ return (-1);
+ }
+ }
+
if (probe->dofpr_argidx + probe->dofpr_xargc <
probe->dofpr_argidx ||
(probe->dofpr_argidx + probe->dofpr_xargc) *
@@ -12615,7 +12681,8 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp)
dtrace_helpers_t *help;
dtrace_vstate_t *vstate;
dtrace_enabling_t *enab = NULL;
- int i, gen, rv, nhelpers = 0, destroy = 1;
+ int i, gen, rv, nhelpers = 0, nprovs = 0, destroy = 1;
+ uintptr_t daddr = (uintptr_t)dof;
ASSERT(MUTEX_HELD(&dtrace_lock));
@@ -12631,6 +12698,27 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp)
}
/*
+ * Look for helper providers and validate their descriptions.
+ */
+ if (dhp != NULL) {
+ for (i = 0; i < dof->dofh_secnum; i++) {
+ dof_sec_t *sec = (dof_sec_t *)(uintptr_t)(daddr +
+ dof->dofh_secoff + i * dof->dofh_secsize);
+
+ if (sec->dofs_type != DOF_SECT_PROVIDER)
+ continue;
+
+ if (dtrace_helper_provider_validate(dof, sec) != 0) {
+ dtrace_enabling_destroy(enab);
+ dtrace_dof_destroy(dof);
+ return (-1);
+ }
+
+ nprovs++;
+ }
+ }
+
+ /*
* Now we need to walk through the ECB descriptions in the enabling.
*/
for (i = 0; i < enab->dten_ndesc; i++) {
@@ -12655,7 +12743,6 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp)
(void) dtrace_helper_destroygen(help->dthps_generation);
dtrace_enabling_destroy(enab);
dtrace_dof_destroy(dof);
- dtrace_err = rv;
return (-1);
}
@@ -12665,43 +12752,18 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp)
if (nhelpers < enab->dten_ndesc)
dtrace_dof_error(dof, "unmatched helpers");
- if (dhp != NULL) {
- uintptr_t daddr = (uintptr_t)dof;
- int err = 0, count = 0;
-
- /*
- * Look for helper probes.
- */
- for (i = 0; i < dof->dofh_secnum; i++) {
- dof_sec_t *sec = (dof_sec_t *)(uintptr_t)(daddr +
- dof->dofh_secoff + i * dof->dofh_secsize);
-
- if (sec->dofs_type != DOF_SECT_PROVIDER)
- continue;
-
- if (dtrace_helper_provider_validate(dof, sec) != 0) {
- err = 1;
- break;
- }
-
- count++;
- }
-
- dhp->dofhp_dof = (uint64_t)(uintptr_t)dof;
- if (err == 0 && count > 0 &&
- dtrace_helper_provider_add(dhp) == 0)
- destroy = 0;
- else
- dhp = NULL;
- }
-
gen = help->dthps_generation++;
dtrace_enabling_destroy(enab);
- if (dhp != NULL) {
- mutex_exit(&dtrace_lock);
- dtrace_helper_provider_register(curproc, help, dhp);
- mutex_enter(&dtrace_lock);
+ if (dhp != NULL && nprovs > 0) {
+ dhp->dofhp_dof = (uint64_t)(uintptr_t)dof;
+ if (dtrace_helper_provider_add(dhp) == 0) {
+ mutex_exit(&dtrace_lock);
+ dtrace_helper_provider_register(curproc, help, dhp);
+ mutex_enter(&dtrace_lock);
+
+ destroy = 0;
+ }
}
if (destroy)
@@ -13460,7 +13522,6 @@ dtrace_ioctl_helper(int cmd, intptr_t arg, int *rv)
return (rval);
mutex_enter(&dtrace_lock);
- dtrace_err = 0;
/*
* dtrace_helper_slurp() takes responsibility for the dof --
diff --git a/usr/src/uts/common/dtrace/fasttrap.c b/usr/src/uts/common/dtrace/fasttrap.c
index 3829012db5..30394b4ee4 100644
--- a/usr/src/uts/common/dtrace/fasttrap.c
+++ b/usr/src/uts/common/dtrace/fasttrap.c
@@ -52,7 +52,6 @@
#include <sys/vmsystm.h>
#include <sys/prsystm.h>
-
#include <vm/as.h>
#include <vm/seg.h>
#include <vm/seg_dev.h>
@@ -510,7 +509,7 @@ fasttrap_tracepoint_enable(proc_t *p, fasttrap_probe_t *probe, uint_t index)
* like to install. If we can't find a match, and have an allocated
* tracepoint ready to go, enable that one now.
*
- * A tracepoint whose proc is defunct is also considered defunct.
+ * A tracepoint whose process is defunct is also considered defunct.
*/
again:
mutex_enter(&bucket->ftb_mtx);
@@ -535,17 +534,26 @@ again:
*/
ASSERT(tp->ftt_ids != NULL || tp->ftt_retids != NULL);
- if (probe->ftp_type == DTFTP_RETURN ||
- probe->ftp_type == DTFTP_POST_OFFSETS) {
- id->fti_next = tp->ftt_retids;
- membar_producer();
- tp->ftt_retids = id;
- membar_producer();
- } else {
+ switch (id->fti_ptype) {
+ case DTFTP_ENTRY:
+ case DTFTP_OFFSETS:
+ case DTFTP_IS_ENABLED:
id->fti_next = tp->ftt_ids;
membar_producer();
tp->ftt_ids = id;
membar_producer();
+ break;
+
+ case DTFTP_RETURN:
+ case DTFTP_POST_OFFSETS:
+ id->fti_next = tp->ftt_retids;
+ membar_producer();
+ tp->ftt_retids = id;
+ membar_producer();
+ break;
+
+ default:
+ ASSERT(0);
}
mutex_exit(&bucket->ftb_mtx);
@@ -603,20 +611,29 @@ again:
ASSERT(new_tp->ftt_ids == NULL);
ASSERT(new_tp->ftt_retids == NULL);
- if (probe->ftp_type == DTFTP_RETURN ||
- probe->ftp_type == DTFTP_POST_OFFSETS) {
- id->fti_next = NULL;
- new_tp->ftt_retids = id;
- } else {
+ switch (id->fti_ptype) {
+ case DTFTP_ENTRY:
+ case DTFTP_OFFSETS:
+ case DTFTP_IS_ENABLED:
id->fti_next = NULL;
new_tp->ftt_ids = id;
+ break;
+
+ case DTFTP_RETURN:
+ case DTFTP_POST_OFFSETS:
+ id->fti_next = NULL;
+ new_tp->ftt_retids = id;
+ break;
+
+ default:
+ ASSERT(0);
}
/*
* If the ISA-dependent initialization goes to plan, go back to the
* beginning and try to install this freshly made tracepoint.
*/
- if (fasttrap_tracepoint_init(p, probe, new_tp, pc) == 0)
+ if (fasttrap_tracepoint_init(p, new_tp, pc, id->fti_ptype) == 0)
goto again;
new_tp->ftt_ids = NULL;
@@ -639,6 +656,7 @@ fasttrap_tracepoint_disable(proc_t *p, fasttrap_probe_t *probe, uint_t index)
pid = probe->ftp_pid;
pc = probe->ftp_tps[index].fit_tp->ftt_pc;
+ id = &probe->ftp_tps[index].fit_id;
ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid);
@@ -659,13 +677,22 @@ fasttrap_tracepoint_disable(proc_t *p, fasttrap_probe_t *probe, uint_t index)
*/
ASSERT(tp != NULL);
- if (probe->ftp_type == DTFTP_RETURN ||
- probe->ftp_type == DTFTP_POST_OFFSETS) {
- ASSERT(tp->ftt_retids != NULL);
- idp = &tp->ftt_retids;
- } else {
+ switch (id->fti_ptype) {
+ case DTFTP_ENTRY:
+ case DTFTP_OFFSETS:
+ case DTFTP_IS_ENABLED:
ASSERT(tp->ftt_ids != NULL);
idp = &tp->ftt_ids;
+ break;
+
+ case DTFTP_RETURN:
+ case DTFTP_POST_OFFSETS:
+ ASSERT(tp->ftt_retids != NULL);
+ idp = &tp->ftt_retids;
+ break;
+
+ default:
+ ASSERT(0);
}
while ((*idp)->fti_probe != probe) {
@@ -1548,7 +1575,6 @@ fasttrap_add_probe(fasttrap_probe_spec_t *pdata)
pp->ftp_fsize = pdata->ftps_size;
pp->ftp_pid = pdata->ftps_pid;
pp->ftp_ntps = pdata->ftps_noffs;
- pp->ftp_type = pdata->ftps_type;
for (i = 0; i < pdata->ftps_noffs; i++) {
tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),
@@ -1560,6 +1586,7 @@ fasttrap_add_probe(fasttrap_probe_spec_t *pdata)
pp->ftp_tps[i].fit_tp = tp;
pp->ftp_tps[i].fit_id.fti_probe = pp;
+ pp->ftp_tps[i].fit_id.fti_ptype = pdata->ftps_type;
}
pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
@@ -1589,7 +1616,6 @@ fasttrap_add_probe(fasttrap_probe_spec_t *pdata)
pp->ftp_fsize = pdata->ftps_size;
pp->ftp_pid = pdata->ftps_pid;
pp->ftp_ntps = 1;
- pp->ftp_type = pdata->ftps_type;
tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),
KM_SLEEP);
@@ -1600,6 +1626,7 @@ fasttrap_add_probe(fasttrap_probe_spec_t *pdata)
pp->ftp_tps[0].fit_tp = tp;
pp->ftp_tps[0].fit_id.fti_probe = pp;
+ pp->ftp_tps[0].fit_id.fti_ptype = pdata->ftps_type;
pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
pdata->ftps_mod, pdata->ftps_func, name_str,
@@ -1712,7 +1739,8 @@ fasttrap_meta_create_probe(void *arg, void *parg,
fasttrap_probe_t *pp;
fasttrap_tracepoint_t *tp;
size_t size;
- int i;
+ int i, j;
+ uint32_t ntps;
mutex_enter(&provider->ftp_mtx);
@@ -1722,31 +1750,31 @@ fasttrap_meta_create_probe(void *arg, void *parg,
return;
}
- atomic_add_32(&fasttrap_total, dhpb->dthpb_noffs);
+ ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs;
+
+ atomic_add_32(&fasttrap_total, ntps);
if (fasttrap_total > fasttrap_max) {
- atomic_add_32(&fasttrap_total, -dhpb->dthpb_noffs);
+ atomic_add_32(&fasttrap_total, -ntps);
mutex_exit(&provider->ftp_mtx);
return;
}
- size = sizeof (fasttrap_probe_t) +
- sizeof (pp->ftp_tps[0]) * (dhpb->dthpb_noffs - 1);
+ ASSERT(dhpb->dthpb_noffs > 0);
+ size = sizeof (fasttrap_probe_t) + sizeof (pp->ftp_tps[0]) * (ntps - 1);
pp = kmem_zalloc(size, KM_SLEEP);
pp->ftp_prov = provider;
pp->ftp_pid = provider->ftp_pid;
- pp->ftp_ntps = dhpb->dthpb_noffs;
-#ifdef __sparc
- pp->ftp_type = DTFTP_POST_OFFSETS;
-#else
- pp->ftp_type = DTFTP_OFFSETS;
-#endif
+ pp->ftp_ntps = ntps;
pp->ftp_nargs = dhpb->dthpb_xargc;
pp->ftp_xtypes = dhpb->dthpb_xtypes;
pp->ftp_ntypes = dhpb->dthpb_ntypes;
- for (i = 0; i < pp->ftp_ntps; i++) {
+ /*
+ * First create a tracepoint for each actual point of interest.
+ */
+ for (i = 0; i < dhpb->dthpb_noffs; i++) {
tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP);
tp->ftt_proc = provider->ftp_proc;
@@ -1755,6 +1783,26 @@ fasttrap_meta_create_probe(void *arg, void *parg,
pp->ftp_tps[i].fit_tp = tp;
pp->ftp_tps[i].fit_id.fti_probe = pp;
+#ifdef __sparc
+ pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_POST_OFFSETS;
+#else
+ pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_OFFSETS;
+#endif
+ }
+
+ /*
+ * Then create a tracepoint for each is-enabled point.
+ */
+ for (j = 0; i < ntps; i++, j++) {
+ tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP);
+
+ tp->ftt_proc = provider->ftp_proc;
+ tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_enoffs[j];
+ tp->ftt_pid = provider->ftp_pid;
+
+ pp->ftp_tps[i].fit_tp = tp;
+ pp->ftp_tps[i].fit_id.fti_probe = pp;
+ pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_IS_ENABLED;
}
/*
diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h
index 57765c1d31..48d876a651 100644
--- a/usr/src/uts/common/sys/dtrace.h
+++ b/usr/src/uts/common/sys/dtrace.h
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -599,8 +600,9 @@ typedef struct dof_hdr {
#define DOF_ENCODE_NATIVE DOF_ENCODE_LSB
#endif
-#define DOF_VERSION_1 1 /* DOF_ID_VERSION */
-#define DOF_VERSION DOF_VERSION_1
+#define DOF_VERSION_1 1 /* DOF version 1: Solaris 10 FCS */
+#define DOF_VERSION_2 2 /* DOF version 2: Solaris Express 6/06 */
+#define DOF_VERSION DOF_VERSION_2 /* Latest DOF version */
#define DOF_FL_VALID 0 /* mask of all valid dofh_flags bits */
@@ -645,6 +647,7 @@ typedef struct dof_sec {
#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_SECT_PRENOFFS 26 /* uint32_t array (enabled offsets) */
#define DOF_SECF_LOAD 1 /* section should be loaded */
@@ -719,6 +722,7 @@ typedef struct dof_provider {
dof_attr_t dofpv_funcattr; /* function attributes */
dof_attr_t dofpv_nameattr; /* name attributes */
dof_attr_t dofpv_argsattr; /* args attributes */
+ dof_secidx_t dofpv_prenoffs; /* link to DOF_SECT_PRENOFFS section */
} dof_provider_t;
typedef struct dof_probe {
@@ -732,7 +736,10 @@ typedef struct dof_probe {
uint8_t dofpr_nargc; /* native argument count */
uint8_t dofpr_xargc; /* translated argument count */
uint16_t dofpr_noffs; /* number of offset entries for probe */
- uint32_t dofpr_pad; /* reserved for future use */
+ uint32_t dofpr_enoffidx; /* index of first is-enabled offset */
+ uint16_t dofpr_nenoffs; /* number of is-enabled offsets */
+ uint16_t dofpr_pad1; /* reserved for future use */
+ uint32_t dofpr_pad2; /* reserved for future use */
} dof_probe_t;
typedef struct dof_xlator {
@@ -2082,7 +2089,9 @@ typedef struct dtrace_helper_probedesc {
char *dthpb_name; /* probe name */
uint64_t dthpb_base; /* base address */
uint32_t *dthpb_offs; /* offsets array */
+ uint32_t *dthpb_enoffs; /* is-enabled offsets array */
uint32_t dthpb_noffs; /* offsets count */
+ uint32_t dthpb_nenoffs; /* is-enabled offsets count */
uint8_t *dthpb_args; /* argument mapping array */
uint8_t dthpb_xargc; /* translated argument count */
uint8_t dthpb_nargc; /* native argument count */
diff --git a/usr/src/uts/common/sys/fasttrap.h b/usr/src/uts/common/sys/fasttrap.h
index 2eddfd3560..7f803144bc 100644
--- a/usr/src/uts/common/sys/fasttrap.h
+++ b/usr/src/uts/common/sys/fasttrap.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,7 +46,8 @@ typedef enum fasttrap_probe_type {
DTFTP_ENTRY,
DTFTP_RETURN,
DTFTP_OFFSETS,
- DTFTP_POST_OFFSETS
+ DTFTP_POST_OFFSETS,
+ DTFTP_IS_ENABLED
} fasttrap_probe_type_t;
typedef struct fasttrap_probe_spec {
diff --git a/usr/src/uts/common/sys/fasttrap_impl.h b/usr/src/uts/common/sys/fasttrap_impl.h
index 7f500951aa..4d3dd2f7be 100644
--- a/usr/src/uts/common/sys/fasttrap_impl.h
+++ b/usr/src/uts/common/sys/fasttrap_impl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -96,6 +96,7 @@ typedef struct fasttrap_tracepoint fasttrap_tracepoint_t;
struct fasttrap_id {
fasttrap_probe_t *fti_probe; /* referrring probe */
fasttrap_id_t *fti_next; /* enabled probe list on tp */
+ fasttrap_probe_type_t fti_ptype; /* probe type */
};
typedef struct fasttrap_id_tp {
@@ -109,12 +110,11 @@ struct fasttrap_probe {
fasttrap_provider_t *ftp_prov; /* this probe's provider */
uintptr_t ftp_faddr; /* associated function's addr */
size_t ftp_fsize; /* associated function's size */
- fasttrap_probe_type_t ftp_type; /* type of probe */
- uint_t ftp_enabled; /* is this probe enabled */
uint64_t ftp_gen; /* modification generation */
uint64_t ftp_ntps; /* number of tracepoints */
uint8_t *ftp_argmap; /* native to translated args */
uint8_t ftp_nargs; /* translated argument count */
+ uint8_t ftp_enabled; /* is this probe enabled */
char *ftp_xtypes; /* translated types index */
char *ftp_ntypes; /* native types index */
fasttrap_id_tp_t ftp_tps[1]; /* flexible array */
@@ -125,26 +125,26 @@ struct fasttrap_probe {
&(id)->fti_probe->ftp_tps[0])
struct fasttrap_tracepoint {
- fasttrap_proc_t *ftt_proc; /* associated process struct */
- uintptr_t ftt_pc; /* address of tracepoint */
- pid_t ftt_pid; /* pid of tracepoint */
- fasttrap_machtp_t ftt_mtp; /* ISA-specific portion */
- fasttrap_id_t *ftt_ids; /* NULL-terminated list */
- fasttrap_id_t *ftt_retids; /* NULL-terminated list */
- fasttrap_tracepoint_t *ftt_next; /* link in global hash */
+ fasttrap_proc_t *ftt_proc; /* associated process struct */
+ uintptr_t ftt_pc; /* address of tracepoint */
+ pid_t ftt_pid; /* pid of tracepoint */
+ fasttrap_machtp_t ftt_mtp; /* ISA-specific portion */
+ fasttrap_id_t *ftt_ids; /* NULL-terminated list */
+ fasttrap_id_t *ftt_retids; /* NULL-terminated list */
+ fasttrap_tracepoint_t *ftt_next; /* link in global hash */
};
typedef struct fasttrap_bucket {
- kmutex_t ftb_mtx;
- void *ftb_data;
+ kmutex_t ftb_mtx; /* bucket lock */
+ void *ftb_data; /* data payload */
- uint8_t ftb_pad[64 - sizeof (kmutex_t) - sizeof (void *)];
+ uint8_t ftb_pad[64 - sizeof (kmutex_t) - sizeof (void *)];
} fasttrap_bucket_t;
typedef struct fasttrap_hash {
- ulong_t fth_nent;
- ulong_t fth_mask;
- fasttrap_bucket_t *fth_table;
+ ulong_t fth_nent; /* power-of-2 num. of entries */
+ ulong_t fth_mask; /* fth_nent - 1 */
+ fasttrap_bucket_t *fth_table; /* array of buckets */
} fasttrap_hash_t;
/*
@@ -170,8 +170,8 @@ extern fasttrap_hash_t fasttrap_tpoints;
/*
* Must be implemented by fasttrap_isa.c
*/
-extern int fasttrap_tracepoint_init(proc_t *, fasttrap_probe_t *,
- fasttrap_tracepoint_t *, uintptr_t);
+extern int fasttrap_tracepoint_init(proc_t *, fasttrap_tracepoint_t *,
+ uintptr_t, fasttrap_probe_type_t);
extern int fasttrap_tracepoint_install(proc_t *, fasttrap_tracepoint_t *);
extern int fasttrap_tracepoint_remove(proc_t *, fasttrap_tracepoint_t *);
diff --git a/usr/src/uts/intel/dtrace/fasttrap_isa.c b/usr/src/uts/intel/dtrace/fasttrap_isa.c
index bf2ab2f6c6..4be5fab23e 100644
--- a/usr/src/uts/intel/dtrace/fasttrap_isa.c
+++ b/usr/src/uts/intel/dtrace/fasttrap_isa.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,10 +41,10 @@
* Lossless User-Land Tracing on x86
* ---------------------------------
*
- * Most instructions' execution is not dependent on their address; for these
- * instrutions it is sufficient to copy them into the user process's address
- * space and execute them. To effectively single-step an instruction in
- * user-land, we copy out the following sequence of instructions to scratch
+ * The execution of most instructions is not dependent on the address; for
+ * these instructions it is sufficient to copy them into the user process's
+ * address space and execute them. To effectively single-step an instruction
+ * in user-land, we copy out the following sequence of instructions to scratch
* space in the user thread's ulwp_t structure.
*
* We then set the program counter (%eip or %rip) to point to this scratch
@@ -222,8 +222,8 @@ fasttrap_anarg(struct regs *rp, int function_entry, int argno)
/*ARGSUSED*/
int
-fasttrap_tracepoint_init(proc_t *p, fasttrap_probe_t *probe,
- fasttrap_tracepoint_t *tp, uintptr_t pc)
+fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc,
+ fasttrap_probe_type_t type)
{
uint8_t instr[FASTTRAP_MAX_INSTR_SIZE + 10];
size_t len = FASTTRAP_MAX_INSTR_SIZE;
@@ -737,6 +737,7 @@ fasttrap_pid_probe(struct regs *rp)
fasttrap_tracepoint_t *tp, tp_local;
pid_t pid;
dtrace_icookie_t cookie;
+ uint_t is_enabled = 0;
/*
* It's possible that a user (in a veritable orgy of bad planning)
@@ -809,7 +810,7 @@ fasttrap_pid_probe(struct regs *rp)
for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
fasttrap_probe_t *probe = id->fti_probe;
- if (probe->ftp_type == DTFTP_ENTRY) {
+ if (id->fti_ptype == DTFTP_ENTRY) {
/*
* We note that this was an entry
* probe to help ustack() find the
@@ -822,6 +823,15 @@ fasttrap_pid_probe(struct regs *rp)
rp->r_r8);
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);
dtrace_interrupt_enable(cookie);
+ } else if (id->fti_ptype == DTFTP_IS_ENABLED) {
+ /*
+ * Note that in this case, we don't
+ * call dtrace_probe() since it's only
+ * an artificial probe meant to change
+ * the flow of control so that it
+ * encounters the true probe.
+ */
+ is_enabled = 1;
} else if (probe->ftp_argmap == NULL) {
dtrace_probe(probe->ftp_id, rp->r_rdi,
rp->r_rsi, rp->r_rdx, rp->r_rcx,
@@ -858,7 +868,7 @@ fasttrap_pid_probe(struct regs *rp)
for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
fasttrap_probe_t *probe = id->fti_probe;
- if (probe->ftp_type == DTFTP_ENTRY) {
+ if (id->fti_ptype == DTFTP_ENTRY) {
/*
* We note that this was an entry
* probe to help ustack() find the
@@ -870,6 +880,15 @@ fasttrap_pid_probe(struct regs *rp)
s3, s4, s5);
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);
dtrace_interrupt_enable(cookie);
+ } else if (id->fti_ptype == DTFTP_IS_ENABLED) {
+ /*
+ * Note that in this case, we don't
+ * call dtrace_probe() since it's only
+ * an artificial probe meant to change
+ * the flow of control so that it
+ * encounters the true probe.
+ */
+ is_enabled = 1;
} else if (probe->ftp_argmap == NULL) {
dtrace_probe(probe->ftp_id, s0, s1,
s2, s3, s4);
@@ -904,6 +923,29 @@ fasttrap_pid_probe(struct regs *rp)
*/
rp->r_pc = pc + tp->ftt_size;
+ /*
+ * If there's an is-enabled probe connected to this tracepoint it
+ * means that there was a 'xorl %eax, %eax' or 'xorq %rax, %rax'
+ * instruction that was placed there by DTrace when the binary was
+ * linked. As this probe is, in fact, enabled, we need to stuff 1
+ * into %eax or %rax. Accordingly, we can bypass all the instruction
+ * emulation logic since we know the inevitable result. It's possible
+ * that a user could construct a scenario where the 'is-enabled'
+ * probe was on some other instruction, but that would be a rather
+ * exotic way to shoot oneself in the foot.
+ */
+ if (is_enabled) {
+ rp->r_r0 = 1;
+ new_pc = rp->r_pc;
+ goto done;
+ }
+
+ /*
+ * We emulate certain types of instructions to ensure correctness
+ * (in the case of position dependent instructions) or optimize
+ * common cases. The rest we have the thread execute back in user-
+ * land.
+ */
switch (tp->ftt_type) {
case FASTTRAP_T_RET:
case FASTTRAP_T_RET16:
@@ -1393,6 +1435,7 @@ fasttrap_pid_probe(struct regs *rp)
panic("fasttrap: mishandled an instruction");
}
+done:
/*
* If there were no return probes when we first found the tracepoint,
* we should feel no obligation to honor any return probes that were
diff --git a/usr/src/uts/sparc/dtrace/fasttrap_isa.c b/usr/src/uts/sparc/dtrace/fasttrap_isa.c
index d84b208650..93d627adb7 100644
--- a/usr/src/uts/sparc/dtrace/fasttrap_isa.c
+++ b/usr/src/uts/sparc/dtrace/fasttrap_isa.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -309,7 +308,7 @@ fasttrap_return_common(struct regs *rp, uintptr_t pc, pid_t pid,
for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
fasttrap_probe_t *probe = id->fti_probe;
- if (probe->ftp_type == DTFTP_POST_OFFSETS) {
+ if (id->fti_ptype == DTFTP_POST_OFFSETS) {
if (probe->ftp_argmap == NULL) {
dtrace_probe(probe->ftp_id, rp->r_o0, rp->r_o1,
rp->r_o2, rp->r_o3, rp->r_o4);
@@ -394,7 +393,7 @@ fasttrap_pid_probe(struct regs *rp)
uintptr_t orig_pc = pc;
fasttrap_bucket_t *bucket;
kmutex_t *pid_mtx;
- uint_t fake_restore = 0;
+ uint_t fake_restore = 0, is_enabled = 0;
dtrace_icookie_t cookie;
/*
@@ -453,12 +452,18 @@ fasttrap_pid_probe(struct regs *rp)
for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
fasttrap_probe_t *probe = id->fti_probe;
- int isentry;
+ int isentry = (id->fti_ptype == DTFTP_ENTRY);
+
+ if (id->fti_ptype == DTFTP_IS_ENABLED) {
+ is_enabled = 1;
+ continue;
+ }
+
/*
* We note that this was an entry probe to help ustack() find
* the first caller.
*/
- if ((isentry = (probe->ftp_type == DTFTP_ENTRY)) != 0) {
+ if (isentry) {
cookie = dtrace_interrupt_disable();
DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);
}
@@ -480,7 +485,25 @@ fasttrap_pid_probe(struct regs *rp)
tp = &tp_local;
/*
- * We emulate certain types of instructions do ensure correctness
+ * If there's an is-enabled probe conntected to this tracepoint it
+ * means that there was a 'mov %g0, %o0' instruction that was placed
+ * there by DTrace when the binary was linked. As this probe is, in
+ * fact, enabled, we need to stuff 1 into %o0. Accordingly, we can
+ * bypass all the instruction emulation logic since we know the
+ * inevitable result. It's possible that a user could construct a
+ * scenario where the 'is-enabled' probe was on some other
+ * instruction, but that would be a rather exotic way to shoot oneself
+ * in the foot.
+ */
+ if (is_enabled) {
+ rp->r_o0 = 1;
+ pc = rp->r_npc;
+ npc = pc + 4;
+ goto done;
+ }
+
+ /*
+ * We emulate certain types of instructions to ensure correctness
* (in the case of position dependent instructions) or optimize
* common cases. The rest we have the thread execute back in user-
* land.
@@ -928,6 +951,7 @@ fasttrap_pid_probe(struct regs *rp)
ASSERT(pc != rp->r_g7 + 4);
ASSERT(pc != rp->r_g7 + 8);
+done:
/*
* If there were no return probes when we first found the tracepoint,
* we should feel no obligation to honor any return probes that were
@@ -1029,8 +1053,8 @@ fasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp)
}
int
-fasttrap_tracepoint_init(proc_t *p, fasttrap_probe_t *probe,
- fasttrap_tracepoint_t *tp, uintptr_t pc)
+fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc,
+ fasttrap_probe_type_t type)
{
uint32_t instr;
int32_t disp;
@@ -1224,7 +1248,7 @@ fasttrap_tracepoint_init(proc_t *p, fasttrap_probe_t *probe,
* (near FASTTRAP_T_SAVE) for details.
*/
if (fasttrap_optimize_save != 0 &&
- probe->ftp_type == DTFTP_ENTRY &&
+ type == DTFTP_ENTRY &&
I(instr) == 1 && RD(instr) == R_SP)
tp->ftt_type = FASTTRAP_T_SAVE;
break;