aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
index c52826c6b818..e74367b5c507 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
@@ -261,7 +261,7 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
sym->st_value = 0;
sym->st_size = 0;
sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_FUNC);
- sym->st_other = ELF32_ST_VISIBILITY(STV_HIDDEN);
+ sym->st_other = 0;
sym->st_shndx = SHN_UNDEF;
rel++;
@@ -445,7 +445,7 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
sym->st_value = 0;
sym->st_size = 0;
sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
- sym->st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
+ sym->st_other = 0;
sym->st_shndx = SHN_UNDEF;
rel++;
@@ -1187,6 +1187,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
static const char dt_enabled[] = "enabled";
static const char dt_symprefix[] = "$dtrace";
static const char dt_symfmt[] = "%s%ld.%s";
+ static const char dt_weaksymfmt[] = "%s.%s";
char probename[DTRACE_NAMELEN];
int fd, i, ndx, eprobe, mod = 0;
Elf *elf = NULL;
@@ -1548,44 +1549,46 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
if (dt_symtab_lookup(data_sym, osym, isym,
rela.r_offset, shdr_rel.sh_info, &fsym,
- (emachine1 == EM_PPC64), elf) != 0 &&
- dt_symtab_lookup(data_sym, 0, osym,
+ (emachine1 == EM_PPC64), elf) == 0) {
+ if (fsym.st_name > data_str->d_size)
+ goto err;
+
+ r = s = (char *) data_str->d_buf + fsym.st_name;
+ assert(strstr(s, dt_symprefix) == s);
+ s = strchr(s, '.') + 1;
+ } else if (dt_symtab_lookup(data_sym, 0, osym,
rela.r_offset, shdr_rel.sh_info, &fsym,
- (emachine1 == EM_PPC64), elf) != 0)
- goto err;
-
- if (fsym.st_name > data_str->d_size)
- goto err;
-
- assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
-
- /*
- * If this is our first time encountering this symbol,
- * emit an alias.
- */
- s = (char *)data_str->d_buf + fsym.st_name;
-
- if (strncmp(s, dt_symprefix,
- sizeof (dt_symprefix) - 1) != 0) {
- u_int bind = GELF_ST_BIND(fsym.st_info);
-
+ (emachine1 == EM_PPC64), elf) == 0) {
+ u_int bind;
+
+ 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 == STB_LOCAL ?
- STB_GLOBAL : bind, STT_FUNC);
+ 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;
- istr += 1 + sprintf(r, dt_symfmt, dt_symprefix, objkey,
- s);
+ 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 {
- r = s;
- s = strchr(s, '.');
- assert(s != NULL);
- s++;
- }
+ } else
+ goto err;
if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
return (dt_link_error(dtp, elf, fd, bufs,