Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Apr 2006 11:16:14 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 96357 for review
Message-ID:  <200604291116.k3TBGEbg067328@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=96357

Change 96357 by jb@jb_freebsd2 on 2006/04/29 11:15:15

	FreeBSD's kernel modules are linked to vaddr 0x0 and then relocated on load.
	Sun's libelf code assumes that the ELF file it is 'loading' (actually mmap'ing
	read-only) has all the symbol values exactly as they are in the kernel.
	On FreeBSD, pass the kld_file_stat structure to the module loader function
	so that it has access to the address that the module was loaded at. Then look
	for the first PT_LOAD header record and compute the relocation offset required.
	If the module is actually the kernel, the relocation value will be zero.
	
	To get around the problem of mmap'ed sections, malloc and copy them on
	FreeBSD so that the symbol values can be updated.
	
	This brings us to another milestone.
	
	$dtrace -n 'BEGIN{trace(`metadelay); exit(0)}'
	
	CPU     ID                    FUNCTION:NAME
	  0      1                           :BEGIN        28
	
	And if you look in sys/kern/vfs_subr.c, you'll see that 'metadelay' is a
	static integer. Surprised?

Affected files ...

.. //depot/projects/dtrace/src/contrib/opensolaris/lib/libdtrace/common/dt_impl.h#6 edit
.. //depot/projects/dtrace/src/contrib/opensolaris/lib/libdtrace/common/dt_module.c#6 edit
.. //depot/projects/dtrace/src/sys/contrib/opensolaris/uts/common/sys/ctf_api.h#5 edit

Differences ...

==== //depot/projects/dtrace/src/contrib/opensolaris/lib/libdtrace/common/dt_impl.h#6 (text) ====

@@ -139,6 +139,9 @@
 	GElf_Addr dm_bss_va;	/* virtual address of BSS */
 	GElf_Xword dm_bss_size;	/* size in bytes of BSS */
 	dt_idhash_t *dm_extern;	/* external symbol definitions */
+#if !defined(sun)
+	caddr_t dm_reloc_offset;	/* Symbol relocation offset. */
+#endif
 } dt_module_t;
 
 #define	DT_DM_LOADED	0x1	/* module symbol and type data is loaded */

==== //depot/projects/dtrace/src/contrib/opensolaris/lib/libdtrace/common/dt_module.c#6 (text) ====

@@ -79,7 +79,7 @@
 static uint_t
 dt_module_syminit32(dt_module_t *dmp)
 {
-	const Elf32_Sym *sym = dmp->dm_symtab.cts_data;
+	Elf32_Sym *sym = dmp->dm_symtab.cts_data;
 	const char *base = dmp->dm_strtab.cts_data;
 	size_t ss_size = dmp->dm_strtab.cts_size;
 	uint_t i, n = dmp->dm_nsymelems;
@@ -96,9 +96,14 @@
 			continue; /* skip null or invalid names */
 
 		if (sym->st_value != 0 &&
-		    (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
+		    (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
 			asrsv++; /* reserve space in the address map */
 
+#if !defined(sun)
+			sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
+#endif
+		}
+
 		dt_module_symhash_insert(dmp, name, i);
 	}
 
@@ -108,7 +113,7 @@
 static uint_t
 dt_module_syminit64(dt_module_t *dmp)
 {
-	const Elf64_Sym *sym = dmp->dm_symtab.cts_data;
+	Elf64_Sym *sym = dmp->dm_symtab.cts_data;
 	const char *base = dmp->dm_strtab.cts_data;
 	size_t ss_size = dmp->dm_strtab.cts_size;
 	uint_t i, n = dmp->dm_nsymelems;
@@ -125,9 +130,14 @@
 			continue; /* skip null or invalid names */
 
 		if (sym->st_value != 0 &&
-		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
+		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
 			asrsv++; /* reserve space in the address map */
 
+#if !defined(sun)
+			sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
+#endif
+		}
+
 		dt_module_symhash_insert(dmp, name, i);
 	}
 
@@ -502,7 +512,13 @@
 	if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL)
 		return (0);
 
+#if defined(sun)
 	ctsp->cts_data = dp->d_buf;
+#else
+	if ((ctsp->cts_data = malloc(dp->d_size)) == NULL)
+		return (0);
+	memcpy(ctsp->cts_data, dp->d_buf, dp->d_size);
+#endif
 	ctsp->cts_size = dp->d_size;
 
 	dt_dprintf("loaded %s [%s] (%lu bytes)\n",
@@ -678,6 +694,18 @@
 	ctf_close(dmp->dm_ctfp);
 	dmp->dm_ctfp = NULL;
 
+#if !defined(sun)
+	if (dmp->dm_ctdata.cts_data != NULL) {
+		free(dmp->dm_ctdata.cts_data);
+	}
+	if (dmp->dm_symtab.cts_data != NULL) {
+		free(dmp->dm_symtab.cts_data);
+	}
+	if (dmp->dm_strtab.cts_data != NULL) {
+		free(dmp->dm_strtab.cts_data);
+	}
+#endif
+
 	bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
 	bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
 	bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
@@ -799,7 +827,11 @@
  * including the path.
  */
 static void
+#if defined(sun)
 dt_module_update(dtrace_hdl_t *dtp, const char *name)
+#else
+dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
+#endif
 {
 	char fname[MAXPATHLEN];
 	struct stat64 st;
@@ -816,7 +848,10 @@
 	(void) snprintf(fname, sizeof (fname),
 	    "%s/%s/object", OBJFS_ROOT, name);
 #else
-	(void) strlcpy(fname, name, sizeof(fname));
+	GElf_Phdr ph;
+	char *name = fname;
+	int i = 0;
+	(void) strlcpy(fname, k_stat->pathname, sizeof(fname));
 #endif
 
 	if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 ||
@@ -893,11 +928,16 @@
 	dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
 #else
 	/*
-	 * On FreeBSD we probably should map this to the 'fileid' that
-	 * kldstat(2) reports. Unfortunately we discarded that info before
-	 * this function was called.
+	 * Find the first load section and figure out the relocation
+	 * offset for the symbols. The kernel module will not need
+	 * relocation, but the kernel linker modules will.
 	 */
-	dmp->dm_modid = 0;
+	for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) {
+		if (ph.p_type == PT_LOAD) {
+			dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr;
+			break;
+		}
+	}
 #endif
 
 	if (dmp->dm_info.objfs_info_primary)
@@ -949,7 +989,7 @@
 		struct kld_file_stat k_stat;
 		k_stat.version = sizeof(k_stat);
 		if (kldstat(fileid, &k_stat) == 0)
-			dt_module_update(dtp, k_stat.pathname);
+			dt_module_update(dtp, &k_stat);
 	}
 #endif
 

==== //depot/projects/dtrace/src/sys/contrib/opensolaris/uts/common/sys/ctf_api.h#5 (text) ====

@@ -78,7 +78,11 @@
 	const char *cts_name;	/* section name (if any) */
 	ulong_t cts_type;	/* section type (ELF SHT_... value) */
 	ulong_t cts_flags;	/* section flags (ELF SHF_... value) */
+#if defined(sun)
 	const void *cts_data;	/* pointer to section data */
+#else
+	void *cts_data;		/* pointer to section data */
+#endif
 	size_t cts_size;	/* size of data in bytes */
 	size_t cts_entsize;	/* size of each section entry (symtab only) */
 	off64_t cts_offset;	/* file offset of this section (if any) */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604291116.k3TBGEbg067328>