diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index d0977eb638e4..d349f6ea3d6a 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -773,6 +773,7 @@ dt_symtab_lookup(Elf_Data *data_sym, int start, int end, uintptr_t addr, #define DT_OP_RET 0xd65f03c0 #define DT_OP_CALL26 0x94000000 #define DT_OP_JUMP26 0x14000000 +#define DT_REL_NONE R_AACH64_NONE static int dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, @@ -831,7 +832,8 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, return (0); } #elif defined(__arm__) -/* XXX */ +#define DT_REL_NONE R_ARM_NONE + static int dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, uint32_t *off) @@ -841,7 +843,8 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, return (-1); } #elif defined(__mips__) -/* XXX */ +#define DT_REL_NONE R_MIPS_NONE + static int dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, uint32_t *off) @@ -861,7 +864,8 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, #define DT_IS_BRANCH(inst) ((inst & 0xfc000000) == 0x48000000) #define DT_IS_BL(inst) (DT_IS_BRANCH(inst) && (inst & 0x01)) -/* XXX */ +#define DT_REL_NONE R_PPC_NONE + static int dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, uint32_t *off) @@ -878,7 +882,8 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, * We only know about some specific relocation types. */ if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 && - GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24) + GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24 && + GELF_R_TYPE(rela->r_info) != R_PPC_NONE) return (-1); /* @@ -932,7 +937,7 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, return (0); } #elif defined(__riscv) -/* XXX */ +#define DT_REL_NONE R_RISCV_NONE static int dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, uint32_t *off) @@ -952,6 +957,8 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, #define DT_OP_XOR_EAX_0 0x33 #define DT_OP_XOR_EAX_1 0xc0 +#define DT_REL_NONE R_386_NONE + static int dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, uint32_t *off) @@ -974,7 +981,8 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, * x86 architectures. */ if (GELF_R_TYPE(rela->r_info) != R_386_PC32 && - GELF_R_TYPE(rela->r_info) != R_386_PLT32) + GELF_R_TYPE(rela->r_info) != R_386_PLT32 && + GELF_R_TYPE(rela->r_info) != R_386_NONE) return (-1); /* @@ -1273,6 +1281,11 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) * We take a first pass through all the relocations to * populate our string table and count the number of extra * symbols we'll require. + * + * We also handle the case where the object has already been + * processed, to support incremental rebuilds. Relocations + * of interest are converted to type NONE, but all information + * needed to reconstruct the output DOF is retained. */ strtab = dt_strtab_create(1); nsym = 0; @@ -1280,7 +1293,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) istr = data_str->d_size; for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) { - if (shdr_rel.sh_type == SHT_RELA) { if (gelf_getrela(data_rel, i, &rela) == NULL) continue; @@ -1345,7 +1357,12 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) objkey, s); if (dt_strtab_index(strtab, p) == -1) { - nsym++; + /* + * Do not add new symbols if this object file + * has already been processed. + */ + if (GELF_R_TYPE(rela.r_info) != DT_REL_NONE) + nsym++; (void) dt_strtab_insert(strtab, p); } @@ -1353,13 +1370,14 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) } /* - * If any probes were found, allocate the additional space for - * the symbol table and string table, copying the old data into - * the new buffers, and marking the buffers as dirty. We inject - * those newly allocated buffers into the libelf data + * If any new probes were found, allocate the additional space + * for the symbol table and string table, copying the old data + * into the new buffers, and marking the buffers as dirty. We + * inject those newly allocated buffers into the libelf data * structures, but are still responsible for freeing them once * we're done with the elf handle. */ + osym = isym; if (nsym > 0) { /* * The first byte of the string table is reserved for @@ -1411,9 +1429,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) shdr_sym.sh_size += nsym * symsize; (void) gelf_update_shdr(scn_sym, &shdr_sym); - osym = isym; nsym += isym; - } else { + } else if (dt_strtab_empty(strtab)) { dt_strtab_destroy(strtab); continue; } @@ -1423,7 +1440,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) * modifications described above. */ for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) { - if (shdr_rel.sh_type == SHT_RELA) { if (gelf_getrela(data_rel, i, &rela) == NULL) continue; @@ -1490,32 +1506,51 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) bind = GELF_ST_BIND(fsym.st_info) == STB_WEAK ? STB_WEAK : STB_GLOBAL; - - /* - * Emit an alias for the symbol. It needs to be - * non-preemptible so that .SUNW_dof relocations - * may be resolved at static link time. Aliases - * of weak symbols are given a non-unique name - * so that they may be merged by the linker. - */ - dsym = fsym; - dsym.st_name = istr; - dsym.st_info = GELF_ST_INFO(bind, STT_FUNC); - dsym.st_other = GELF_ST_VISIBILITY(STV_HIDDEN); - (void) gelf_update_sym(data_sym, isym, &dsym); - r = (char *) data_str->d_buf + istr; s = (char *) data_str->d_buf + fsym.st_name; - if (bind == STB_WEAK) - istr += sprintf(r, dt_weaksymfmt, - dt_symprefix, s); - else - istr += sprintf(r, dt_symfmt, - dt_symprefix, objkey, s); - istr++; - isym++; - assert(isym <= nsym); - } else + if (GELF_R_TYPE(rela.r_info) != DT_REL_NONE) { + /* + * Emit an alias for the symbol. It + * needs to be non-preemptible so that + * .SUNW_dof relocations may be resolved + * at static link time. Aliases of weak + * symbols are given a non-unique name + * so that they may be merged by the + * linker. + */ + dsym = fsym; + dsym.st_name = istr; + dsym.st_info = GELF_ST_INFO(bind, + STT_FUNC); + dsym.st_other = + GELF_ST_VISIBILITY(STV_HIDDEN); + (void) gelf_update_sym(data_sym, isym, + &dsym); + isym++; + assert(isym <= nsym); + + r = (char *) data_str->d_buf + istr; + if (bind == STB_WEAK) { + istr += sprintf(r, + dt_weaksymfmt, dt_symprefix, + s); + } else { + istr += sprintf(r, dt_symfmt, + dt_symprefix, objkey, s); + } + istr++; + } else { + if (bind == STB_WEAK) { + (void) asprintf(&r, + dt_weaksymfmt, dt_symprefix, + s); + } else { + (void) asprintf(&r, dt_symfmt, + dt_symprefix, objkey, s); + } + } + } else { goto err; + } if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) { return (dt_link_error(dtp, elf, fd, bufs, @@ -1544,24 +1579,18 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) } /* - * Our linker doesn't understand the SUNW_IGNORE ndx and - * will try to use this relocation when we build the - * final executable. Since we are done processing this - * relocation, mark it as inexistant and let libelf - * remove it from the file. - * If this wasn't done, we would have garbage added to - * the executable file as the symbol is going to be - * change from UND to ABS. + * We are done with this relocation, but it must be + * preserved in order to support incremental rebuilds. */ if (shdr_rel.sh_type == SHT_RELA) { - rela.r_offset = 0; - rela.r_info = 0; - rela.r_addend = 0; + rela.r_info = + GELF_R_INFO(GELF_R_SYM(rela.r_info), 0); (void) gelf_update_rela(data_rel, i, &rela); } else { GElf_Rel rel; - rel.r_offset = 0; - rel.r_info = 0; + rel.r_offset = rela.r_offset; + rela.r_info = + GELF_R_INFO(GELF_R_SYM(rela.r_info), 0); (void) gelf_update_rel(data_rel, i, &rel); } @@ -1614,19 +1643,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, size_t len; int eprobes = 0, ret = 0; - if (access(file, R_OK) == 0) { - fprintf(stderr, "dtrace: target object (%s) already exists. " - "Please remove the target\ndtrace: object and rebuild all " - "the source objects if you wish to run the DTrace\n" - "dtrace: linking process again\n", file); - /* - * Several build infrastructures run DTrace twice (e.g. - * postgres) and we don't want the build to fail. Return - * 0 here since this isn't really a fatal error. - */ - return (0); - } - /* * A NULL program indicates a special use in which we just link * together a bunch of object files specified in objv and then diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c index a735b6674a1e..6279ffacdaeb 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.c @@ -206,6 +206,13 @@ dt_strtab_copyin(dt_strtab_t *sp, const char *str, size_t len) return (-1); } +boolean_t +dt_strtab_empty(dt_strtab_t *sp) +{ + /* Always contains "\0". */ + return (sp->str_nstrs == 1); +} + ssize_t dt_strtab_index(dt_strtab_t *sp, const char *str) { diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h index 551dabbf6765..80006b6b3962 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_strtab.h @@ -58,6 +58,7 @@ typedef ssize_t dt_strtab_write_f(const char *, size_t, size_t, void *); extern dt_strtab_t *dt_strtab_create(size_t); extern void dt_strtab_destroy(dt_strtab_t *); +extern boolean_t dt_strtab_empty(dt_strtab_t *); extern ssize_t dt_strtab_index(dt_strtab_t *, const char *); extern ssize_t dt_strtab_insert(dt_strtab_t *, const char *); extern size_t dt_strtab_size(const dt_strtab_t *); diff --git a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh index 5767865429e8..50f825769af1 100755 --- a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh +++ b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh @@ -201,10 +201,6 @@ exclude EXFAIL common/usdt/tst.eliminate.ksh # Generated headers include , so _DTRACE_VERSION is always defined. exclude EXFAIL common/usdt/tst.nodtrace.ksh -# The second dtrace -G invocation returns an error with "no probes found," which -# makes sense to me. Not yet sure what the expected behaviour is here. -exclude EXFAIL common/usdt/tst.static2.ksh - # Uses the Solaris-specific ppriv(1). exclude EXFAIL common/usdt/tst.user.ksh