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.
This commit is contained in:
Ian Dowse 2004-08-28 19:31:10 +00:00
parent ace437c3c6
commit 9dba198b0e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=134450
7 changed files with 54 additions and 43 deletions

View File

@ -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);

View File

@ -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_*/

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}

View File

@ -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",