diff options
Diffstat (limited to 'lib/libdtrace/common')
-rw-r--r-- | lib/libdtrace/common/dt_cc.c | 6 | ||||
-rw-r--r-- | lib/libdtrace/common/dt_impl.h | 2 | ||||
-rw-r--r-- | lib/libdtrace/common/dt_link.c | 38 | ||||
-rw-r--r-- | lib/libdtrace/common/dt_open.c | 12 | ||||
-rw-r--r-- | lib/libdtrace/common/dt_pid.c | 8 | ||||
-rw-r--r-- | lib/libdtrace/common/dt_pragma.c | 48 |
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); |