From 9fb18331e48faf6ddb1fd1aa6aebab24b0a8f583 Mon Sep 17 00:00:00 2001 From: avg Date: Sat, 21 Aug 2010 19:02:49 +0000 Subject: [PATCH] MFC r210425: dtrace: correctly map sections to addresses in elf object modules (amd64) git-svn-id: svn://svn.freebsd.org/base/stable/8@211589 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- .../lib/libdtrace/common/dt_impl.h | 1 + .../lib/libdtrace/common/dt_module.c | 75 +++++++++++++++++-- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h index 6bcc5bc49..a712d2495 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h @@ -137,6 +137,7 @@ typedef struct dt_module { dt_idhash_t *dm_extern; /* external symbol definitions */ #if !defined(sun) caddr_t dm_reloc_offset; /* Symbol relocation offset. */ + uintptr_t *dm_sec_offsets; #endif } dt_module_t; diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c index af175012b..d33fb95e4 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 -- 2.45.0