PERFORCE change 96357 for review
John Birrell
jb at FreeBSD.org
Sat Apr 29 11:16:15 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=96357
Change 96357 by jb at 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) */
More information about the p4-projects
mailing list