summaryrefslogtreecommitdiffstats
path: root/lib/libdtrace/common
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libdtrace/common')
-rw-r--r--lib/libdtrace/common/dt_cc.c6
-rw-r--r--lib/libdtrace/common/dt_impl.h2
-rw-r--r--lib/libdtrace/common/dt_link.c38
-rw-r--r--lib/libdtrace/common/dt_open.c12
-rw-r--r--lib/libdtrace/common/dt_pid.c8
-rw-r--r--lib/libdtrace/common/dt_pragma.c48
6 files changed, 80 insertions, 34 deletions
diff --git a/lib/libdtrace/common/dt_cc.c b/lib/libdtrace/common/dt_cc.c
index 64b2922..575fb9c 100644
--- a/lib/libdtrace/common/dt_cc.c
+++ b/lib/libdtrace/common/dt_cc.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -2010,8 +2010,10 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
dt_dprintf("skipping library %s: %s\n",
dld->dtld_library,
dtrace_errmsg(dtp, dtrace_errno(dtp)));
- } else
+ } else {
+ dld->dtld_loaded = B_TRUE;
dt_program_destroy(dtp, pgp);
+ }
}
dt_lib_depend_free(dtp);
diff --git a/lib/libdtrace/common/dt_impl.h b/lib/libdtrace/common/dt_impl.h
index 2454e3b..9b22dfb 100644
--- a/lib/libdtrace/common/dt_impl.h
+++ b/lib/libdtrace/common/dt_impl.h
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -183,6 +184,7 @@ typedef struct dt_lib_depend {
char *dtld_libpath; /* library pathname */
uint_t dtld_finish; /* completion time in tsort for lib */
uint_t dtld_start; /* starting time in tsort for lib */
+ uint_t dtld_loaded; /* boolean: is this library loaded */
dt_list_t dtld_dependencies; /* linked-list of lib dependencies */
dt_list_t dtld_dependents; /* linked-list of lib dependents */
} dt_lib_depend_t;
diff --git a/lib/libdtrace/common/dt_link.c b/lib/libdtrace/common/dt_link.c
index 957d8f8..e317fe7 100644
--- a/lib/libdtrace/common/dt_link.c
+++ b/lib/libdtrace/common/dt_link.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -850,7 +850,9 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
#elif defined(__i386) || defined(__amd64)
#define DT_OP_NOP 0x90
+#define DT_OP_RET 0xc3
#define DT_OP_CALL 0xe8
+#define DT_OP_JMP32 0xe9
#define DT_OP_REX_RAX 0x48
#define DT_OP_XOR_EAX_0 0x33
#define DT_OP_XOR_EAX_1 0xc0
@@ -860,6 +862,7 @@ 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);
+ uint8_t ret;
/*
* On x86, the first byte of the instruction is the call opcode and
@@ -883,38 +886,43 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
* 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.
+ * offset to the first nop instruction in the sequence to match the
+ * text modification code below.
*/
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)
+ if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
+ 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) {
+ (ip[3] == DT_OP_NOP || ip[3] == DT_OP_RET) &&
+ 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) {
+ (ip[2] == DT_OP_NOP || ip[2] == DT_OP_RET) &&
+ 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.
+ * We expect either a call instrution with a 32-bit displacement or a
+ * jmp instruction with a 32-bit displacement acting as a tail-call.
*/
- if (ip[0] != DT_OP_CALL) {
- dt_dprintf("found %x instead of a call instruction at %llx\n",
- ip[0], (u_longlong_t)rela->r_offset);
+ if (ip[0] != DT_OP_CALL && ip[0] != DT_OP_JMP32) {
+ dt_dprintf("found %x instead of a call or jmp instruction at "
+ "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
return (-1);
}
+ ret = (ip[0] == DT_OP_JMP32) ? DT_OP_RET : DT_OP_NOP;
+
/*
* Establish the instruction sequence -- all nops for probes, and an
* instruction to clear the return value register (%eax/%rax) followed
@@ -923,7 +931,7 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
* for more readable disassembly when the probe is enabled.
*/
if (!isenabled) {
- ip[0] = DT_OP_NOP;
+ ip[0] = ret;
ip[1] = DT_OP_NOP;
ip[2] = DT_OP_NOP;
ip[3] = DT_OP_NOP;
@@ -932,13 +940,13 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
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[3] = ret;
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[2] = ret;
ip[3] = DT_OP_NOP;
ip[4] = DT_OP_NOP;
(*off) += 2;
diff --git a/lib/libdtrace/common/dt_open.c b/lib/libdtrace/common/dt_open.c
index 5c04bee..86f1864 100644
--- a/lib/libdtrace/common/dt_open.c
+++ b/lib/libdtrace/common/dt_open.c
@@ -103,8 +103,9 @@
#define DT_VERS_1_4_1 DT_VERSION_NUMBER(1, 4, 1)
#define DT_VERS_1_5 DT_VERSION_NUMBER(1, 5, 0)
#define DT_VERS_1_6 DT_VERSION_NUMBER(1, 6, 0)
-#define DT_VERS_LATEST DT_VERS_1_6
-#define DT_VERS_STRING "Sun D 1.6"
+#define DT_VERS_1_6_1 DT_VERSION_NUMBER(1, 6, 1)
+#define DT_VERS_LATEST DT_VERS_1_6_1
+#define DT_VERS_STRING "Sun D 1.6.1"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -117,6 +118,7 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_4_1, /* D API 1.4.1 Solaris Express 4/07 */
DT_VERS_1_5, /* D API 1.5 Solaris Express 7/07 */
DT_VERS_1_6, /* D API 1.6 */
+ DT_VERS_1_6_1, /* D API 1.6.1 */
0
};
@@ -1291,6 +1293,9 @@ dtrace_close(dtrace_hdl_t *dtp)
dt_dirpath_t *dirp;
int i;
+ if (dtp->dt_procs != NULL)
+ dt_proc_hash_destroy(dtp);
+
while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
dt_program_destroy(dtp, pgp);
@@ -1319,9 +1324,6 @@ dtrace_close(dtrace_hdl_t *dtp)
while ((pvp = dt_list_next(&dtp->dt_provlist)) != NULL)
dt_provider_destroy(dtp, pvp);
- if (dtp->dt_procs != NULL)
- dt_proc_hash_destroy(dtp);
-
if (dtp->dt_fd != -1)
(void) close(dtp->dt_fd);
if (dtp->dt_ftfd != -1)
diff --git a/lib/libdtrace/common/dt_pid.c b/lib/libdtrace/common/dt_pid.c
index 6346329..cf9498b 100644
--- a/lib/libdtrace/common/dt_pid.c
+++ b/lib/libdtrace/common/dt_pid.c
@@ -667,7 +667,13 @@ dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
assert(dpr != NULL);
(void) pthread_mutex_lock(&dpr->dpr_lock);
- err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr);
+ if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) {
+ /*
+ * Alert other retained enablings which may match
+ * against the newly created probes.
+ */
+ (void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
+ }
(void) pthread_mutex_unlock(&dpr->dpr_lock);
dt_proc_release(dtp, P);
diff --git a/lib/libdtrace/common/dt_pragma.c b/lib/libdtrace/common/dt_pragma.c
index 00b8269..a8bab85 100644
--- a/lib/libdtrace/common/dt_pragma.c
+++ b/lib/libdtrace/common/dt_pragma.c
@@ -18,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -210,6 +211,7 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
dt_node_t *nnp = cnp ? cnp->dn_list : NULL;
int found;
dt_lib_depend_t *dld;
+ char lib[MAXPATHLEN];
if (cnp == NULL || nnp == NULL ||
cnp->dn_kind != DT_NODE_IDENT || nnp->dn_kind != DT_NODE_IDENT) {
@@ -223,29 +225,53 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string);
found = mp != NULL && dt_module_getctf(dtp, mp) != NULL;
} else if (strcmp(cnp->dn_string, "library") == 0) {
-
- /*
- * We have the file we are working on in dtp->dt_filetag
- * so find that node and add the dependency in.
- */
if (yypcb->pcb_cflags & DTRACE_C_CTL) {
- char lib[MAXPATHLEN];
+ assert(dtp->dt_filetag != NULL);
+ /*
+ * We have the file we are working on in dtp->dt_filetag
+ * so find that node and add the dependency in.
+ */
dld = dt_lib_depend_lookup(&dtp->dt_lib_dep,
dtp->dt_filetag);
assert(dld != NULL);
- (void) snprintf(lib, MAXPATHLEN, "%s%s",
+ (void) snprintf(lib, sizeof (lib), "%s%s",
dld->dtld_libpath, nnp->dn_string);
if ((dt_lib_depend_add(dtp, &dld->dtld_dependencies,
lib)) != 0) {
xyerror(D_PRAGMA_DEPEND,
- "failed to add dependency %s:%s\n",
- lib,
+ "failed to add dependency %s:%s\n", lib,
dtrace_errmsg(dtp, dtrace_errno(dtp)));
}
+ } else {
+ /*
+ * By this point we have already performed a topological
+ * sort of the dependencies; we process this directive
+ * as satisfied as long as the dependency was properly
+ * loaded.
+ */
+ if (dtp->dt_filetag == NULL)
+ xyerror(D_PRAGMA_DEPEND, "main program may "
+ "not explicitly depend on a library");
+
+ dld = dt_lib_depend_lookup(&dtp->dt_lib_dep,
+ dtp->dt_filetag);
+ assert(dld != NULL);
+
+ (void) snprintf(lib, sizeof (lib), "%s%s",
+ dld->dtld_libpath, nnp->dn_string);
+ dld = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted,
+ lib);
+ assert(dld != NULL);
+
+ if (!dld->dtld_loaded)
+ xyerror(D_PRAGMA_DEPEND, "program requires "
+ "library \"%s\" which failed to load",
+ lib);
}
- found = 1;
+
+ found = B_TRUE;
} else {
xyerror(D_PRAGMA_INVAL, "invalid class %s "
"specified by #pragma %s\n", cnp->dn_string, prname);
OpenPOWER on IntegriCloud