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:
parent
ace437c3c6
commit
9dba198b0e
@ -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);
|
||||
|
@ -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_*/
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user