From owner-p4-projects@FreeBSD.ORG Sat Apr 29 11:16:15 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 38B5B16A406; Sat, 29 Apr 2006 11:16:15 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 08D5D16A402 for ; Sat, 29 Apr 2006 11:16:15 +0000 (UTC) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id B511F43D49 for ; Sat, 29 Apr 2006 11:16:14 +0000 (GMT) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k3TBGE11067331 for ; Sat, 29 Apr 2006 11:16:14 GMT (envelope-from jb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k3TBGEbg067328 for perforce@freebsd.org; Sat, 29 Apr 2006 11:16:14 GMT (envelope-from jb@freebsd.org) Date: Sat, 29 Apr 2006 11:16:14 GMT Message-Id: <200604291116.k3TBGEbg067328@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jb@freebsd.org using -f From: John Birrell To: Perforce Change Reviews Cc: Subject: PERFORCE change 96357 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Apr 2006 11:16:15 -0000 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) */