summaryrefslogtreecommitdiffstats
path: root/usr.sbin/kldxref
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2004-08-28 19:31:10 +0000
committeriedowse <iedowse@FreeBSD.org>2004-08-28 19:31:10 +0000
commitd0d1e68e58c10e5172f1d8f13525f20e9cdc942f (patch)
treedf9e4ff7a3c76c8c08fd9ddaf5e27dba6ee28c29 /usr.sbin/kldxref
parentc409ad7413ce9b5f3bfb661a5d87805c96d093b7 (diff)
downloadFreeBSD-src-d0d1e68e58c10e5172f1d8f13525f20e9cdc942f.zip
FreeBSD-src-d0d1e68e58c10e5172f1d8f13525f20e9cdc942f.tar.gz
Explicitly pass in the relocation base and data offset into ef_reloc()
rather than relying on a trick that happens to work for the current relocation schemes. Also add some comments and improve variable naming.
Diffstat (limited to 'usr.sbin/kldxref')
-rw-r--r--usr.sbin/kldxref/ef.c4
-rw-r--r--usr.sbin/kldxref/ef.h4
-rw-r--r--usr.sbin/kldxref/ef_amd64.c23
-rw-r--r--usr.sbin/kldxref/ef_i386.c23
-rw-r--r--usr.sbin/kldxref/ef_nop.c4
-rw-r--r--usr.sbin/kldxref/ef_obj.c17
-rw-r--r--usr.sbin/kldxref/ef_sparc64.c22
7 files changed, 54 insertions, 43 deletions
diff --git a/usr.sbin/kldxref/ef.c b/usr.sbin/kldxref/ef.c
index 55efb53..c6751c9 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 6a5a627..3843ebe 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 f0acba8..445640a 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 9735900..0fc726a 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 b1a798b..cbbd43c 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 884a1b3..3ed4e40 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 78b40db..e5133f1 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",
OpenPOWER on IntegriCloud