diff --git a/usr.sbin/kldxref/ef.c b/usr.sbin/kldxref/ef.c index 55efb535a8fa..c6751c9d7a19 100644 --- a/usr.sbin/kldxref/ef.c +++ b/usr.sbin/kldxref/ef.c @@ -481,13 +481,13 @@ ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void*dest) return (error); for (r = ef->ef_rel; r < &ef->ef_rel[ef->ef_relsz]; r++) { - error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, offset, len, + error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, 0, offset, len, dest); if (error != 0) return (error); } for (a = ef->ef_rela; a < &ef->ef_rela[ef->ef_relasz]; a++) { - error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, offset, len, + error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, 0, offset, len, dest); if (error != 0) return (error); diff --git a/usr.sbin/kldxref/ef.h b/usr.sbin/kldxref/ef.h index 6a5a62788ee2..3843ebebbaef 100644 --- a/usr.sbin/kldxref/ef.h +++ b/usr.sbin/kldxref/ef.h @@ -62,8 +62,8 @@ struct elf_file { __BEGIN_DECLS int ef_open(const char *filename, struct elf_file *ef, int verbose); int ef_obj_open(const char *filename, struct elf_file *ef, int verbose); -int ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, - size_t len, void *dest); +int ef_reloc(struct elf_file *ef, const void *reldata, int reltype, + Elf_Off relbase, Elf_Off dataoff, size_t len, void *dest); __END_DECLS #endif /* _EF_H_*/ diff --git a/usr.sbin/kldxref/ef_amd64.c b/usr.sbin/kldxref/ef_amd64.c index f0acba87caee..445640ae27af 100644 --- a/usr.sbin/kldxref/ef_amd64.c +++ b/usr.sbin/kldxref/ef_amd64.c @@ -37,11 +37,13 @@ #include "ef.h" /* - * Apply relocations to the values we got from the file. + * Apply relocations to the values we got from the file. `relbase' is the + * target relocation address of the section, and `dataoff' is the target + * relocation address of the data in `dest'. */ int -ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, - size_t len, void *dest) +ef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase, + Elf_Off dataoff, size_t len, void *dest) { Elf64_Addr *where, val; Elf32_Addr *where32, val32; @@ -50,16 +52,17 @@ ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, const Elf_Rel *rel; const Elf_Rela *rela; - switch (type) { + switch (reltype) { case EF_RELOC_REL: - rel = (const Elf_Rel *)data; - where = (Elf_Addr *)(dest + rel->r_offset - offset); + rel = (const Elf_Rel *)reldata; + where = (Elf_Addr *)(dest + relbase + rel->r_offset - dataoff); + addend = 0; rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; case EF_RELOC_RELA: - rela = (const Elf_Rela *)data; - where = (Elf_Addr *)(dest + rela->r_offset - offset); + rela = (const Elf_Rela *)reldata; + where = (Elf_Addr *)(dest + relbase + rela->r_offset - dataoff); addend = rela->r_addend; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); @@ -71,7 +74,7 @@ ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len) return (0); - if (type == EF_RELOC_REL) { + if (reltype == EF_RELOC_REL) { /* Addend is 32 bit on 32 bit relocs */ switch (rtype) { case R_X86_64_PC32: @@ -103,7 +106,7 @@ ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, *where = addr; break; case R_X86_64_RELATIVE: /* B + A */ - addr = (Elf_Addr)addend; + addr = (Elf_Addr)addend + relbase; val = addr; *where = val; break; diff --git a/usr.sbin/kldxref/ef_i386.c b/usr.sbin/kldxref/ef_i386.c index 973590049a91..0fc726af7ca6 100644 --- a/usr.sbin/kldxref/ef_i386.c +++ b/usr.sbin/kldxref/ef_i386.c @@ -37,27 +37,30 @@ #include "ef.h" /* - * Apply relocations to the values we got from the file. + * Apply relocations to the values we got from the file. `relbase' is the + * target relocation address of the section, and `dataoff' is the target + * relocation address of the data in `dest'. */ int -ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, - size_t len, void *dest) +ef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase, + Elf_Off dataoff, size_t len, void *dest) { Elf_Addr *where, addr, addend; Elf_Word rtype, symidx; const Elf_Rel *rel; const Elf_Rela *rela; - switch (type) { + switch (reltype) { case EF_RELOC_REL: - rel = (const Elf_Rel *)data; - where = (Elf_Addr *)(dest + rel->r_offset - offset); + rel = (const Elf_Rel *)reldata; + where = (Elf_Addr *)(dest + relbase + rel->r_offset - dataoff); + addend = 0; rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); break; case EF_RELOC_RELA: - rela = (const Elf_Rela *)data; - where = (Elf_Addr *)(dest + rela->r_offset - offset); + rela = (const Elf_Rela *)reldata; + where = (Elf_Addr *)(dest + relbase + rela->r_offset - dataoff); addend = rela->r_addend; rtype = ELF_R_TYPE(rela->r_info); symidx = ELF_R_SYM(rela->r_info); @@ -69,12 +72,12 @@ ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len) return (0); - if (type == EF_RELOC_REL) + if (reltype == EF_RELOC_REL) addend = *where; switch (rtype) { case R_386_RELATIVE: /* A + B */ - addr = (Elf_Addr)addend; + addr = (Elf_Addr)addend + relbase; *where = addr; break; case R_386_32: /* S + A - P */ diff --git a/usr.sbin/kldxref/ef_nop.c b/usr.sbin/kldxref/ef_nop.c index b1a798b378ca..cbbd43cc23c9 100644 --- a/usr.sbin/kldxref/ef_nop.c +++ b/usr.sbin/kldxref/ef_nop.c @@ -32,8 +32,8 @@ #include "ef.h" int -ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, - size_t len, void *dest) +ef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase, + Elf_Off dataoff, size_t len, void *dest) { return (0); diff --git a/usr.sbin/kldxref/ef_obj.c b/usr.sbin/kldxref/ef_obj.c index 884a1b31b05f..3ed4e40561b6 100644 --- a/usr.sbin/kldxref/ef_obj.c +++ b/usr.sbin/kldxref/ef_obj.c @@ -240,9 +240,9 @@ ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) char *memaddr; Elf_Rel *r; Elf_Rela *a; - Elf_Off secoff; + Elf_Off secbase, dataoff; int error, i, sec; - + if (offset + len > ef->size) { if (ef->ef_verbose) warnx("ef_seg_read_rel(%s): bad offset/len (%lx:%ld)", @@ -254,6 +254,7 @@ ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) /* Find out which section contains the data. */ memaddr = ef->address + offset; sec = -1; + secbase = dataoff = 0; for (i = 0; i < ef->nprogtab; i++) { if (ef->progtab[i].addr == NULL) continue; @@ -261,7 +262,9 @@ ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) (char *)ef->progtab[i].addr + ef->progtab[i].size) continue; sec = ef->progtab[i].sec; - secoff = memaddr - (char *)ef->progtab[i].addr; + /* We relocate to address 0. */ + secbase = (char *)ef->progtab[i].addr - ef->address; + dataoff = memaddr - ef->address; break; } @@ -274,8 +277,8 @@ ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) continue; for (r = ef->reltab[i].rel; r < &ef->reltab[i].rel[ef->reltab[i].nrel]; r++) { - error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, secoff, - len, dest); + error = ef_reloc(ef->ef_efile, r, EF_RELOC_REL, secbase, + dataoff, len, dest); if (error != 0) return (error); } @@ -285,8 +288,8 @@ ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len, void *dest) continue; for (a = ef->relatab[i].rela; a < &ef->relatab[i].rela[ef->relatab[i].nrela]; a++) { - error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, secoff, - len, dest); + error = ef_reloc(ef->ef_efile, a, EF_RELOC_RELA, + secbase, dataoff, len, dest); if (error != 0) return (error); } diff --git a/usr.sbin/kldxref/ef_sparc64.c b/usr.sbin/kldxref/ef_sparc64.c index 78b40db93b82..e5133f1d3996 100644 --- a/usr.sbin/kldxref/ef_sparc64.c +++ b/usr.sbin/kldxref/ef_sparc64.c @@ -35,25 +35,27 @@ #include "ef.h" /* - * Apply relocations to the values we got from the file. + * Apply relocations to the values we got from the file. `relbase' is the + * target relocation address of the section, and `dataoff' is the target + * relocation address of the data in `dest'. */ int -ef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, - size_t len, void *dest) +ef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase, + Elf_Off dataoff, size_t len, void *dest) { const Elf_Rela *a; Elf_Word w; - switch (type) { + switch (reltype) { case EF_RELOC_RELA: - a = data; - if (a->r_offset >= offset && a->r_offset < offset + len) { + a = reldata; + if (relbase + a->r_offset >= dataoff && relbase + a->r_offset < + dataoff + len) { switch (ELF_R_TYPE(a->r_info)) { case R_SPARC_RELATIVE: - /* load address is 0 */ - w = a->r_addend; - memcpy((u_char *)dest + (a->r_offset - offset), - &w, sizeof(w)); + w = a->r_addend + relbase; + memcpy((u_char *)dest + (relbase + a->r_offset - + dataoff), &w, sizeof(w)); break; default: warnx("unhandled relocation type %u",