summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c')
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c75
1 files changed, 69 insertions, 6 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
index af17501..d33fb95 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
@@ -83,6 +83,14 @@ dt_module_syminit32(dt_module_t *dmp)
uint_t i, n = dmp->dm_nsymelems;
uint_t asrsv = 0;
+#if defined(__FreeBSD__)
+ GElf_Ehdr ehdr;
+ int is_elf_obj;
+
+ gelf_getehdr(dmp->dm_elf, &ehdr);
+ is_elf_obj = (ehdr.e_type == ET_REL);
+#endif
+
for (i = 0; i < n; i++, sym++) {
const char *name = base + sym->st_name;
uchar_t type = ELF32_ST_TYPE(sym->st_info);
@@ -97,8 +105,12 @@ dt_module_syminit32(dt_module_t *dmp)
(ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
asrsv++; /* reserve space in the address map */
-#if !defined(sun)
+#if defined(__FreeBSD__)
sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
+ if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
+ sym->st_shndx < ehdr.e_shnum)
+ sym->st_value +=
+ dmp->dm_sec_offsets[sym->st_shndx];
#endif
}
@@ -117,6 +129,14 @@ dt_module_syminit64(dt_module_t *dmp)
uint_t i, n = dmp->dm_nsymelems;
uint_t asrsv = 0;
+#if defined(__FreeBSD__)
+ GElf_Ehdr ehdr;
+ int is_elf_obj;
+
+ gelf_getehdr(dmp->dm_elf, &ehdr);
+ is_elf_obj = (ehdr.e_type == ET_REL);
+#endif
+
for (i = 0; i < n; i++, sym++) {
const char *name = base + sym->st_name;
uchar_t type = ELF64_ST_TYPE(sym->st_info);
@@ -130,9 +150,12 @@ dt_module_syminit64(dt_module_t *dmp)
if (sym->st_value != 0 &&
(ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
asrsv++; /* reserve space in the address map */
-
-#if !defined(sun)
+#if defined(__FreeBSD__)
sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
+ if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
+ sym->st_shndx < ehdr.e_shnum)
+ sym->st_value +=
+ dmp->dm_sec_offsets[sym->st_shndx];
#endif
}
@@ -722,7 +745,12 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
free(dmp->dm_asmap);
dmp->dm_asmap = NULL;
}
-
+#if defined(__FreeBSD__)
+ if (dmp->dm_sec_offsets != NULL) {
+ free(dmp->dm_sec_offsets);
+ dmp->dm_sec_offsets = NULL;
+ }
+#endif
dmp->dm_symfree = 0;
dmp->dm_nsymbuckets = 0;
dmp->dm_nsymelems = 0;
@@ -846,9 +874,12 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
(void) snprintf(fname, sizeof (fname),
"%s/%s/object", OBJFS_ROOT, name);
#else
+ GElf_Ehdr ehdr;
GElf_Phdr ph;
char name[MAXPATHLEN];
+ uintptr_t mapbase, alignmask;
int i = 0;
+ int is_elf_obj;
(void) strlcpy(name, k_stat->name, sizeof(name));
(void) strlcpy(fname, k_stat->pathname, sizeof(fname));
@@ -893,7 +924,20 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
dt_module_destroy(dtp, dmp);
return;
}
-
+#if defined(__FreeBSD__)
+ mapbase = (uintptr_t)k_stat->address;
+ gelf_getehdr(dmp->dm_elf, &ehdr);
+ is_elf_obj = (ehdr.e_type == ET_REL);
+ if (is_elf_obj) {
+ dmp->dm_sec_offsets =
+ malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets));
+ if (dmp->dm_sec_offsets == NULL) {
+ dt_dprintf("failed to allocate memory\n");
+ dt_module_destroy(dtp, dmp);
+ return;
+ }
+ }
+#endif
/*
* Iterate over the section headers locating various sections of
* interest and use their attributes to flesh out the dt_module_t.
@@ -902,7 +946,19 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
(s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
continue; /* skip any malformed sections */
-
+#if defined(__FreeBSD__)
+ if (sh.sh_size == 0)
+ continue;
+ if (is_elf_obj && (sh.sh_type == SHT_PROGBITS ||
+ sh.sh_type == SHT_NOBITS)) {
+ alignmask = sh.sh_addralign - 1;
+ mapbase += alignmask;
+ mapbase &= ~alignmask;
+ sh.sh_addr = mapbase;
+ dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
+ mapbase += sh.sh_size;
+ }
+#endif
if (strcmp(s, ".text") == 0) {
dmp->dm_text_size = sh.sh_size;
dmp->dm_text_va = sh.sh_addr;
@@ -927,6 +983,13 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
#if defined(sun)
dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
#else
+ /*
+ * Include .rodata and special sections into .text.
+ * This depends on default section layout produced by GNU ld
+ * for ELF objects and libraries:
+ * [Text][R/O data][R/W data][Dynamic][BSS][Non loadable]
+ */
+ dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va;
#if defined(__i386__)
/*
* Find the first load section and figure out the relocation
OpenPOWER on IntegriCloud