--- //depot/vendor/freebsd/src/sys/alpha/alpha/elf_machdep.c 2002/10/19 12:20:17 +++ //depot/user/jake/kldxref/src/sys/alpha/alpha/elf_machdep.c 2003/01/03 18:43:59 @@ -89,8 +89,8 @@ &freebsd_brand_info); /* Process one elf relocation with addend. */ -int -elf_reloc(linker_file_t lf, const void *data, int type) +static int +elf_reloc_internal(linker_file_t lf, const void *data, int type, int local) { Elf_Addr relocbase = (Elf_Addr) lf->address; Elf_Addr *where; @@ -119,6 +119,15 @@ panic("elf_reloc: unknown relocation mode %d\n", type); } + if (local) { + if (rtype == R_ALPHA_RELATIVE) { + addr = relocbase + addend; + if (*where != addr) + *where = addr; + } + return (0); + } + switch (rtype) { case R_ALPHA_NONE: @@ -152,9 +161,6 @@ break; case R_ALPHA_RELATIVE: - addr = relocbase + addend; - if (*where != addr) - *where = addr; break; case R_ALPHA_COPY: @@ -174,6 +180,18 @@ } int +elf_reloc(linker_file_t lf, const void *data, int type) +{ + return (elf_reloc_internal(lf, data, type, 0)); +} + +int +elf_reloc_local(linker_file_t lf, const void *data, int type) +{ + return (elf_reloc_internal(lf, data, type, 1)); +} + +int elf_cpu_load_file(linker_file_t lf __unused) { --- //depot/vendor/freebsd/src/sys/boot/common/load_elf.c 2002/05/09 18:25:16 +++ //depot/user/jake/kldxref/src/sys/boot/common/load_elf.c 2003/01/08 17:53:28 @@ -52,6 +52,10 @@ Elf_Hashelt nchains; Elf_Hashelt *buckets; Elf_Hashelt *chains; +#ifdef __sparc__ + Elf_Rela *rela; + size_t relasz; +#endif char *strtab; size_t strsz; int fd; @@ -63,6 +67,10 @@ static int elf_loadimage(struct preloaded_file *mp, elf_file_t ef, vm_offset_t loadaddr); static int elf_lookup_symbol(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym); +#ifdef __sparc__ +static void elf_reloc_ptr(struct preloaded_file *mp, elf_file_t ef, + void *p, void *val, size_t len); +#endif static int elf_parse_modmetadata(struct preloaded_file *mp, elf_file_t ef); static char *fake_modname(const char *name); @@ -491,6 +499,14 @@ case DT_SYMTAB: ef->symtab = (Elf_Sym*)(dp[i].d_un.d_ptr + off); break; +#ifdef __sparc__ + case DT_RELA: + ef->rela = (Elf_Rela *)(dp[i].d_un.d_ptr + off); + break; + case DT_RELASZ: + ef->relasz = dp[i].d_un.d_val; + break; +#endif default: break; } @@ -566,26 +582,47 @@ modcnt = 0; while (p < p_stop) { +#ifdef __sparc__ + COPYOUT(p, &v, sizeof(v)); + elf_reloc_ptr(fp, ef, p, &v, sizeof(v)); + COPYOUT(v, &md, sizeof(md)); + elf_reloc_ptr(fp, ef, v, &md, sizeof(md)); + p++; +#else COPYOUT(p++, &v, sizeof(v)); COPYOUT(v + ef->off, &md, sizeof(md)); +#endif switch(md.md_type) { case MDT_DEPEND: if (ef->kernel) /* kernel must not depend on anything */ break; +#ifdef __sparc__ + s = strdupout((vm_offset_t)md.md_cval); +#else s = strdupout((vm_offset_t)(md.md_cval + ef->off)); +#endif minfolen = sizeof(*mdepend) + strlen(s) + 1; mdepend = malloc(minfolen); if (mdepend == NULL) return ENOMEM; +#ifdef __sparc__ + COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend)); +#else COPYOUT((vm_offset_t)(md.md_data + ef->off), mdepend, sizeof(*mdepend)); +#endif strcpy((char*)(mdepend + 1), s); free(s); file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend); free(mdepend); break; case MDT_VERSION: +#ifdef __sparc__ + s = strdupout((vm_offset_t)md.md_cval); + COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); +#else s = strdupout((vm_offset_t)(md.md_cval + ef->off)); COPYOUT((vm_offset_t)(md.md_data + ef->off), &mver, sizeof(mver)); +#endif file_addmodule(fp, s, mver.mv_version, NULL); free(s); modcnt++; @@ -657,3 +694,30 @@ } return ENOENT; } + +#ifdef __sparc__ +/* + * Apply any intra-module relocations to the value. *p is the load address + * of the value and val/len is the value to be modified. This does NOT modify + * the image in-place, because this is done by kern_linker later on. + */ +static void +elf_reloc_ptr(struct preloaded_file *mp, elf_file_t ef, + void *p, void *val, size_t len) +{ + Elf_Addr off = (Elf_Addr)p - ef->off, word; + size_t n; + Elf_Rela r; + + for (n = 0; n < ef->relasz / sizeof(r); n++) { + COPYOUT(ef->rela + n, &r, sizeof(r)); + + if (r.r_offset >= off && r.r_offset < off + len && + ELF_R_TYPE(r.r_info) == R_SPARC_RELATIVE) { + word = ef->off + r.r_addend; + bcopy(&word, (char *)val + (r.r_offset - off), + sizeof(word)); + } + } +} +#endif --- //depot/vendor/freebsd/src/sys/i386/i386/elf_machdep.c 2002/10/19 12:20:17 +++ //depot/user/jake/kldxref/src/sys/i386/i386/elf_machdep.c 2003/01/03 18:43:59 @@ -86,8 +86,8 @@ &freebsd_brand_info); /* Process one elf relocation with addend. */ -int -elf_reloc(linker_file_t lf, const void *data, int type) +static int +elf_reloc_internal(linker_file_t lf, const void *data, int type, int local) { Elf_Addr relocbase = (Elf_Addr) lf->address; Elf_Addr *where; @@ -116,6 +116,15 @@ panic("unknown reloc type %d\n", type); } + if (local) { + if (rtype == R_386_RELATIVE) { /* A + B */ + addr = relocbase + addend; + if (*where != addr) + *where = addr; + } + return (0); + } + switch (rtype) { case R_386_NONE: /* none */ @@ -156,10 +165,7 @@ *where = addr; break; - case R_386_RELATIVE: /* B + A */ - addr = relocbase + addend; - if (*where != addr) - *where = addr; + case R_386_RELATIVE: break; default: @@ -171,6 +177,18 @@ } int +elf_reloc(linker_file_t lf, const void *data, int type) +{ + return (elf_reloc_internal(lf, data, type, 0)); +} + +int +elf_reloc_local(linker_file_t lf, const void *data, int type) +{ + return (elf_reloc_internal(lf, data, type, 1)); +} + +int elf_cpu_load_file(linker_file_t lf __unused) { --- //depot/vendor/freebsd/src/sys/ia64/ia64/elf_machdep.c 2002/10/19 12:35:16 +++ //depot/user/jake/kldxref/src/sys/ia64/ia64/elf_machdep.c 2003/01/03 18:43:59 @@ -141,8 +141,8 @@ } /* Process one elf relocation with addend. */ -int -elf_reloc(linker_file_t lf, const void *data, int type) +static int +elf_reloc_internal(linker_file_t lf, const void *data, int type, int local) { Elf_Addr relocbase = (Elf_Addr)lf->address; Elf_Addr *where; @@ -179,6 +179,12 @@ panic("%s: invalid ELF relocation (0x%x)\n", __func__, type); } + if (local) { + if (rtype == R_IA64_REL64LSB) + *where = relocbase + addend; + return (0); + } + switch (rtype) { case R_IA64_NONE: break; @@ -199,7 +205,6 @@ *where = addr; break; case R_IA64_REL64LSB: /* word64 LSB BD + A */ - *where = relocbase + addend; break; case R_IA64_IPLTLSB: addr = lookup_fdesc(lf, symidx); @@ -218,6 +223,18 @@ } int +elf_reloc(linker_file_t lf, const void *data, int type) +{ + return (elf_reloc_internal(lf, data, type, 0)); +} + +int +elf_reloc_local(linker_file_t lf, const void *data, int type) +{ + return (elf_reloc_internal(lf, data, type, 1)); +} + +int elf_cpu_load_file(linker_file_t lf) { Elf_Ehdr *hdr; --- //depot/vendor/freebsd/src/sys/kern/kern_linker.c 2002/12/14 00:20:19 +++ //depot/user/jake/kldxref/src/sys/kern/kern_linker.c 2003/01/03 18:43:59 @@ -499,7 +499,7 @@ * Give the module a chance to veto the unload. */ if ((error = module_unload(mod)) != 0) { - KLD_DPF(FILE, ("linker_file_unload: module %x" + KLD_DPF(FILE, ("linker_file_unload: module %p" " vetoes unload\n", mod)); goto out; } else @@ -594,7 +594,7 @@ size_t common_size = 0; int i; - KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n", + KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n", file, name, deps)); if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) { @@ -608,7 +608,7 @@ common_size = symval.size; else { KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol" - ".value=%x\n", symval.value)); + ".value=%p\n", symval.value)); return (symval.value); } } @@ -618,7 +618,7 @@ name, 0); if (address) { KLD_DPF(SYM, ("linker_file_lookup_symbol:" - " deps value=%x\n", address)); + " deps value=%p\n", address)); return (address); } } @@ -634,7 +634,7 @@ STAILQ_FOREACH(cp, &file->common, link) { if (strcmp(cp->name, name) == 0) { KLD_DPF(SYM, ("linker_file_lookup_symbol:" - " old common value=%x\n", cp->address)); + " old common value=%p\n", cp->address)); return (cp->address); } } @@ -656,7 +656,7 @@ STAILQ_INSERT_TAIL(&file->common, cp, link); KLD_DPF(SYM, ("linker_file_lookup_symbol: new common" - " value=%x\n", cp->address)); + " value=%p\n", cp->address)); return (cp->address); } KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); @@ -1106,46 +1106,6 @@ return (mod); } -/* - * This routine is cheap and nasty but will work for data pointers. - */ -static void * -linker_reloc_ptr(linker_file_t lf, const void *offset) -{ - return (lf->address + (uintptr_t)offset); -} - -/* - * Dereference MDT_VERSION metadata into module name and version - */ -static void -linker_mdt_version(linker_file_t lf, struct mod_metadata *mp, - const char **modname, int *version) -{ - struct mod_version *mvp; - - if (modname) - *modname = linker_reloc_ptr(lf, mp->md_cval); - if (version) { - mvp = linker_reloc_ptr(lf, mp->md_data); - *version = mvp->mv_version; - } -} - -/* - * Dereference MDT_DEPEND metadata into module name and mod_depend structure - */ -static void -linker_mdt_depend(linker_file_t lf, struct mod_metadata *mp, - const char **modname, struct mod_depend **verinfo) -{ - - if (modname) - *modname = linker_reloc_ptr(lf, mp->md_cval); - if (verinfo) - *verinfo = linker_reloc_ptr(lf, mp->md_data); -} - static void linker_addmodules(linker_file_t lf, struct mod_metadata **start, struct mod_metadata **stop, int preload) @@ -1155,17 +1115,11 @@ int ver; for (mdp = start; mdp < stop; mdp++) { - if (preload) - mp = *mdp; - else - mp = linker_reloc_ptr(lf, *mdp); + mp = *mdp; if (mp->md_type != MDT_VERSION) continue; - if (preload) { - modname = mp->md_cval; - ver = ((struct mod_version *)mp->md_data)->mv_version; - } else - linker_mdt_version(lf, mp, &modname, &ver); + modname = mp->md_cval; + ver = ((struct mod_version *)mp->md_data)->mv_version; if (modlist_lookup(modname, ver) != NULL) { printf("module %s already present!\n", modname); /* XXX what can we do? this is a build error. :-( */ @@ -1249,18 +1203,16 @@ resolves = 1; /* unless we know otherwise */ if (!error) { for (mdp = start; mdp < stop; mdp++) { - mp = linker_reloc_ptr(lf, *mdp); + mp = *mdp; if (mp->md_type != MDT_DEPEND) continue; - linker_mdt_depend(lf, mp, &modname, &verinfo); + modname = mp->md_cval; + verinfo = mp->md_data; for (nmdp = start; nmdp < stop; nmdp++) { - nmp = linker_reloc_ptr(lf, *nmdp); + nmp = *nmdp; if (nmp->md_type != MDT_VERSION) continue; - linker_mdt_version(lf, nmp, &nmodname, - NULL); - nmodname = linker_reloc_ptr(lf, - nmp->md_cval); + nmodname = nmp->md_cval; if (strcmp(modname, nmodname) == 0) break; } @@ -1283,11 +1235,12 @@ if (resolves) { if (!error) { for (mdp = start; mdp < stop; mdp++) { - mp = linker_reloc_ptr(lf, *mdp); + mp = *mdp; if (mp->md_type != MDT_VERSION) continue; - linker_mdt_version(lf, mp, - &modname, &nver); + modname = mp->md_cval; + nver = ((struct mod_version *) + mp->md_data)->mv_version; if (modlist_lookup(modname, nver) != NULL) { printf("module %s already" @@ -1338,10 +1291,11 @@ &stop, NULL); if (!error) { for (mdp = start; mdp < stop; mdp++) { - mp = linker_reloc_ptr(lf, *mdp); + mp = *mdp; if (mp->md_type != MDT_DEPEND) continue; - linker_mdt_depend(lf, mp, &modname, &verinfo); + modname = mp->md_cval; + verinfo = mp->md_data; mod = modlist_lookup2(modname, verinfo); mod->container->refs++; error = linker_file_add_dependency(lf, @@ -1763,10 +1717,11 @@ &count) != 0) return (0); for (mdp = start; mdp < stop; mdp++) { - mp = linker_reloc_ptr(lf, *mdp); + mp = *mdp; if (mp->md_type != MDT_VERSION) continue; - linker_mdt_version(lf, mp, &modname, &ver); + modname = mp->md_cval; + ver = ((struct mod_version *)mp->md_data)->mv_version; mod = modlist_lookup(modname, ver); if (mod != NULL) { printf("interface %s.%d already present in the KLD" @@ -1777,16 +1732,17 @@ } for (mdp = start; mdp < stop; mdp++) { - mp = linker_reloc_ptr(lf, *mdp); + mp = *mdp; if (mp->md_type != MDT_DEPEND) continue; - linker_mdt_depend(lf, mp, &modname, &verinfo); + modname = mp->md_cval; + verinfo = mp->md_data; nmodname = NULL; for (nmdp = start; nmdp < stop; nmdp++) { - nmp = linker_reloc_ptr(lf, *nmdp); + nmp = *nmdp; if (nmp->md_type != MDT_VERSION) continue; - nmodname = linker_reloc_ptr(lf, nmp->md_cval); + nmodname = nmp->md_cval; if (strcmp(modname, nmodname) == 0) break; } --- //depot/vendor/freebsd/src/sys/kern/link_elf.c 2002/11/19 14:15:18 +++ //depot/user/jake/kldxref/src/sys/kern/link_elf.c 2003/01/03 18:43:59 @@ -116,6 +116,7 @@ static int link_elf_each_function_name(linker_file_t, int (*)(const char *, void *), void *); +static void link_elf_reloc_local(linker_file_t); static kobj_method_t link_elf_methods[] = { KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), @@ -488,6 +489,7 @@ linker_file_unload(lf); return error; } + link_elf_reloc_local(lf); *result = lf; return (0); } @@ -748,6 +750,8 @@ error = parse_dynamic(ef); if (error) goto out; + link_elf_reloc_local(lf); + error = linker_load_dependencies(lf); if (error) goto out; @@ -1266,3 +1270,31 @@ return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); } + +static void +link_elf_reloc_local(linker_file_t lf) +{ + const Elf_Rel *rellim; + const Elf_Rel *rel; + const Elf_Rela *relalim; + const Elf_Rela *rela; + elf_file_t ef = (elf_file_t)lf; + + /* Perform relocations without addend if there are any: */ + if ((rel = ef->rel) != NULL) { + rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize); + while (rel < rellim) { + elf_reloc_local(lf, rel, ELF_RELOC_REL); + rel++; + } + } + + /* Perform relocations with addend if there are any: */ + if ((rela = ef->rela) != NULL) { + relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize); + while (rela < relalim) { + elf_reloc_local(lf, rela, ELF_RELOC_RELA); + rela++; + } + } +} --- //depot/vendor/freebsd/src/sys/sparc64/sparc64/elf_machdep.c 2002/12/02 11:00:17 +++ //depot/user/jake/kldxref/src/sys/sparc64/sparc64/elf_machdep.c 2003/01/03 18:43:59 @@ -235,6 +235,28 @@ }; #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) +int +elf_reloc_local(linker_file_t lf, const void *data, int type) +{ + const Elf_Rela *rela; + Elf_Addr value; + Elf_Addr *where; + + if (type != ELF_RELOC_RELA) + return (-1); + + rela = (const Elf_Rela *)data; + if (ELF_R_TYPE(rela->r_info) != R_SPARC_RELATIVE) + return (-1); + + value = rela->r_addend + (Elf_Addr)lf->address; + where = (Elf_Addr *)((Elf_Addr)lf->address + rela->r_offset); + + *where = value; + + return (0); +} + /* Process one elf relocation with addend. */ int elf_reloc(linker_file_t lf, const void *data, int type) @@ -258,7 +280,7 @@ rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); - if (rtype == R_SPARC_NONE) + if (rtype == R_SPARC_NONE || rtype == R_SPARC_RELATIVE) return (0); if (rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY || --- //depot/vendor/freebsd/src/usr.sbin/kldxref/ef.c 2002/07/17 17:40:48 +++ //depot/user/jake/kldxref/src/usr.sbin/kldxref/ef.c 2003/01/03 18:43:59 @@ -151,7 +151,16 @@ Elf_Hashelt hashhdr[2]; /* int plttype = DT_REL;*/ int error; + Elf_Off rel_off; + Elf_Off rela_off; + int rel_sz; + int rela_sz; + int rel_entry; + int rela_entry; + rel_off = rela_off = 0; + rel_sz = rela_sz = 0; + rel_entry = rela_entry = 0; for (dp = ef->ef_dyn; dp->d_tag != DT_NULL; dp++) { switch (dp->d_tag) { case DT_HASH: @@ -187,6 +196,36 @@ if (dp->d_un.d_val != sizeof(Elf_Sym)) return EFTYPE; break; + case DT_REL: + if (rel_off != 0) + warnx("second DT_REL entry ignored"); + rel_off = dp->d_un.d_ptr; + break; + case DT_RELSZ: + if (rel_sz != 0) + warnx("second DT_RELSZ entry ignored"); + rel_sz = dp->d_un.d_val; + break; + case DT_RELENT: + if (rel_entry != 0) + warnx("second DT_RELENT entry ignored"); + rel_entry = dp->d_un.d_val; + break; + case DT_RELA: + if (rela_off != 0) + warnx("second DT_RELA entry ignored"); + rela_off = dp->d_un.d_ptr; + break; + case DT_RELASZ: + if (rela_sz != 0) + warnx("second DT_RELASZ entry ignored"); + rela_sz = dp->d_un.d_val; + break; + case DT_RELAENT: + if (rela_entry != 0) + warnx("second DT_RELAENT entry ignored"); + rela_entry = dp->d_un.d_val; + break; } } if (ef->ef_symoff == 0) { @@ -210,9 +249,112 @@ warnx("can't load .dynstr section"); return EIO; } + if (rel_off != 0) { + if (rel_entry == 0) { + warnx("%s: no DT_RELENT for DT_REL", ef->ef_name); + return (EFTYPE); + } + if (rel_entry != sizeof(Elf_Rel)) { + warnx("%s: inconsistent DT_RELENT value", + ef->ef_name); + return (EFTYPE); + } + if (rel_sz % rel_entry != 0) { + warnx("%s: inconsistent values for DT_RELSZ and " + "DT_RELENT", ef->ef_name); + return (EFTYPE); + } + if (ef_read_entry(ef, ef_get_offset(ef, rel_off), rel_sz, + (void **)&ef->ef_rel) != 0) { + warnx("%s: cannot load DT_REL section", ef->ef_name); + return (EIO); + } + ef->ef_relsz = rel_sz / rel_entry; + if (ef->ef_verbose) + warnx("%s: %d REL entries", ef->ef_name, + ef->ef_relsz); + } + if (rela_off != 0) { + if (rela_entry == 0) { + warnx("%s: no DT_RELAENT for DT_RELA", ef->ef_name); + return (EFTYPE); + } + if (rela_entry != sizeof(Elf_Rela)) { + warnx("%s: inconsistent DT_RELAENT value", + ef->ef_name); + return (EFTYPE); + } + if (rela_sz % rela_entry != 0) { + warnx("%s: inconsistent values for DT_RELASZ and " + "DT_RELAENT", ef->ef_name); + return (EFTYPE); + } + if (ef_read_entry(ef, ef_get_offset(ef, rela_off), rela_sz, + (void **)&ef->ef_rela) != 0) { + warnx("%s: cannot load DT_RELA section", ef->ef_name); + return (EIO); + } + ef->ef_relasz = rela_sz / rela_entry; + if (ef->ef_verbose) + warnx("%s: %d RELA entries", ef->ef_name, + ef->ef_relasz); + } return 0; } +/* + * Apply relocations to the values we got from the file. + */ +static int +ef_reloc(elf_file_t ef, Elf_Off offset, size_t len, void *dest) +{ + const Elf_Rel *r; + const Elf_Rela *a; +#ifdef R_SPARC_RELATIVE + Elf_Word w; +#endif + + for (r = ef->ef_rel; r < &ef->ef_rel[ef->ef_relsz]; r++) { + if (r->r_offset >= offset && r->r_offset < offset + len) { + switch (ELF_R_TYPE(r->r_info)) { + +#ifdef R_386_RELATIVE + case R_386_RELATIVE: + /* load address is 0 - nothing to do */ + break; +#endif + + default: + warnx("unhandled relocation type %u", + ELF_R_TYPE(r->r_info)); + break; + } + } + } + + for (a = ef->ef_rela; a < &ef->ef_rela[ef->ef_relasz]; a++) { + if (a->r_offset >= offset && a->r_offset < offset + len) { + switch (ELF_R_TYPE(a->r_info)) { + +#ifdef R_SPARC_RELATIVE + case R_SPARC_RELATIVE: + /* load address is 0 */ + w = a->r_addend; + memcpy((u_char *)dest + (a->r_offset - offset), + &w, sizeof(w)); + break; +#endif + + default: + warnx("unhandled relocation type %u", + ELF_R_TYPE(a->r_info)); + break; + } + } + } + return (0); +} + int ef_read(elf_file_t ef, Elf_Off offset, size_t len, void*dest) { @@ -259,6 +401,23 @@ } int +ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void*dest) +{ + u_long ofs = ef_get_offset(ef, offset); + int error; + + if (ofs == 0) { + if (ef->ef_verbose) + warnx("ef_seg_read(%s): zero offset (%lx:%ld)", + ef->ef_name, (long)offset, ofs); + return EFAULT; + } + if ((error = ef_read(ef, ofs, len, dest)) != 0) + return (error); + return (ef_reloc(ef, offset, len, dest)); +} + +int ef_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void**ptr) { int error; @@ -273,6 +432,20 @@ } int +ef_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, void**ptr) +{ + int error; + + *ptr = malloc(len); + if (*ptr == NULL) + return ENOMEM; + error = ef_seg_read_rel(ef, offset, len, *ptr); + if (error) + free(*ptr); + return error; +} + +int ef_open(const char *filename, elf_file_t ef, int verbose) { Elf_Ehdr *hdr; --- //depot/vendor/freebsd/src/usr.sbin/kldxref/ef.h 2002/04/11 02:40:13 +++ //depot/user/jake/kldxref/src/usr.sbin/kldxref/ef.h 2003/01/03 18:43:59 @@ -28,6 +28,10 @@ int ef_nsegs; Elf_Phdr * ef_segs[2]; int ef_verbose; + Elf_Rel * ef_rel; /* relocation table */ + int ef_relsz; /* number of entries */ + Elf_Rela * ef_rela; /* relocation table */ + int ef_relasz; /* number of entries */ } *elf_file_t; __BEGIN_DECLS @@ -36,7 +40,9 @@ int ef_read(elf_file_t ef, Elf_Off offset, size_t len, void* dest); int ef_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void **ptr); int ef_seg_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest); +int ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest); int ef_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len, void**ptr); +int ef_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len, void**ptr); int ef_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym); __END_DECLS --- //depot/vendor/freebsd/src/usr.sbin/kldxref/kldxref.c 2002/04/22 09:44:44 +++ //depot/user/jake/kldxref/src/usr.sbin/kldxref/kldxref.c 2003/01/03 18:43:59 @@ -229,10 +229,11 @@ check(ef_lookup_symbol(&ef, "__stop_set_" MDT_SETNAME, &sym)); finish = sym->st_value; entries = (finish - start) / sizeof(void *); - check(ef_seg_read_entry(&ef, start, sizeof(*p) * entries, (void**)&p)); + check(ef_seg_read_entry_rel(&ef, start, sizeof(*p) * entries, + (void**)&p)); orgp = p; while(entries--) { - check(ef_seg_read(&ef, (Elf_Off)*p, sizeof(md), &md)); + check(ef_seg_read_rel(&ef, (Elf_Off)*p, sizeof(md), &md)); p++; check(ef_seg_read(&ef, (Elf_Off)md.md_cval, sizeof(cval), cval)); cval[MAXMODNAME] = '\0';