svn commit: r211590 - stable/7/cddl/contrib/opensolaris/lib/libdtrace/common

Andriy Gapon avg at FreeBSD.org
Sat Aug 21 19:09:34 UTC 2010


Author: avg
Date: Sat Aug 21 19:09:34 2010
New Revision: 211590
URL: http://svn.freebsd.org/changeset/base/211590

Log:
  MFC r210425: dtrace: correctly map sections to addresses in elf object
  modules (amd64)

Modified:
  stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
  stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
Directory Properties:
  stable/7/cddl/contrib/opensolaris/   (props changed)

Modified: stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
==============================================================================
--- stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h	Sat Aug 21 19:02:49 2010	(r211589)
+++ stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h	Sat Aug 21 19:09:34 2010	(r211590)
@@ -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;
 

Modified: stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
==============================================================================
--- stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c	Sat Aug 21 19:02:49 2010	(r211589)
+++ stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c	Sat Aug 21 19:09:34 2010	(r211590)
@@ -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_m
 		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, stru
 	(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, stru
 		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, stru
 		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, stru
 #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


More information about the svn-src-stable-7 mailing list