Make a small revision to the api between the elf linker core and the
elf_reloc() backends for two reasons. First, to support the possibility of there being two elf linkers in the kernel (eg: amd64), and second, to pass the relocbase explicitly (for relocating .o format kld files).
This commit is contained in:
parent
ffb6541b3f
commit
29f2cef3b2
@ -108,9 +108,9 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, int local, elf_lookup_fn lookup)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
@ -152,7 +152,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_ALPHA_REFQUAD:
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
@ -161,7 +161,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_ALPHA_GLOB_DAT:
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
@ -171,7 +171,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
|
||||
case R_ALPHA_JMP_SLOT:
|
||||
/* No point in lazy binding for kernel modules. */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
@ -198,17 +198,19 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
|
||||
elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 0));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 1));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -104,10 +104,11 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, int local, elf_lookup_fn lookup)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf64_Addr *where, val;
|
||||
Elf32_Addr *where32, val32;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
Elf_Word rtype, symidx;
|
||||
@ -133,37 +134,39 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
panic("unknown reloc type %d\n", type);
|
||||
}
|
||||
|
||||
if (local) {
|
||||
if (rtype == R_X86_64_RELATIVE) { /* A + B */
|
||||
addr = relocbase + addend;
|
||||
if (*where != addr)
|
||||
*where = addr;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (rtype) {
|
||||
|
||||
|
||||
case R_X86_64_NONE: /* none */
|
||||
break;
|
||||
|
||||
case R_X86_64_64: /* S + A */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
val = addr + addend;
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
if (*where != addr)
|
||||
*where = addr;
|
||||
if (*where != val)
|
||||
*where = val;
|
||||
break;
|
||||
|
||||
case R_X86_64_PC32: /* S + A - P */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
where32 = (Elf32_Addr *)where;
|
||||
val32 = (Elf32_Addr)(addr + addend - (Elf_Addr)where);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend - (Elf_Addr)where;
|
||||
/* XXX needs to be 32 bit *where, not 64 bit */
|
||||
if (*where != addr)
|
||||
*where = addr;
|
||||
if (*where32 != val32)
|
||||
*where32 = val32;
|
||||
break;
|
||||
|
||||
case R_X86_64_32S: /* S + A sign extend */
|
||||
addr = lookup(lf, symidx, 1);
|
||||
val32 = (Elf32_Addr)(addr + addend);
|
||||
where32 = (Elf32_Addr *)where;
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where32 != val32)
|
||||
*where32 = val32;
|
||||
break;
|
||||
|
||||
case R_X86_64_COPY: /* none */
|
||||
@ -176,7 +179,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_X86_64_GLOB_DAT: /* S */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
@ -184,6 +187,10 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_X86_64_RELATIVE: /* B + A */
|
||||
addr = relocbase + addend;
|
||||
val = addr;
|
||||
if (*where != val)
|
||||
*where = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -195,17 +202,19 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
|
||||
elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 0));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 1));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -104,9 +104,9 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, int local, elf_lookup_fn lookup)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
@ -148,7 +148,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_ARM_PC24: /* S + A - P */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend - (Elf_Addr)where;
|
||||
@ -166,7 +166,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_ARM_GLOB_DAT: /* S */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
@ -185,17 +185,19 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
|
||||
elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 0));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 1));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -104,9 +104,9 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, int local, elf_lookup_fn lookup)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
@ -148,7 +148,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_386_32: /* S + A */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
@ -157,7 +157,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_386_PC32: /* S + A - P */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend - (Elf_Addr)where;
|
||||
@ -175,7 +175,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_386_GLOB_DAT: /* S */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
@ -194,17 +194,19 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
|
||||
elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 0));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 1));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -143,7 +143,7 @@ ia64_coredump(struct thread *td, struct vnode *vp, off_t limit)
|
||||
}
|
||||
|
||||
static Elf_Addr
|
||||
lookup_fdesc(linker_file_t lf, Elf_Word symidx)
|
||||
lookup_fdesc(linker_file_t lf, Elf_Word symidx, elf_lookup_fn lookup)
|
||||
{
|
||||
linker_file_t top;
|
||||
Elf_Addr addr;
|
||||
@ -151,7 +151,7 @@ lookup_fdesc(linker_file_t lf, Elf_Word symidx)
|
||||
int i;
|
||||
static int eot = 0;
|
||||
|
||||
addr = elf_lookup(lf, symidx, 0);
|
||||
addr = lookup(lf, symidx, 0);
|
||||
if (addr == 0) {
|
||||
top = lf;
|
||||
symname = elf_get_symname(top, symidx);
|
||||
@ -191,7 +191,8 @@ lookup_fdesc(linker_file_t lf, Elf_Word symidx)
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, int local, elf_lookup_fn lookup)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr)lf->address;
|
||||
Elf_Addr *where;
|
||||
@ -238,7 +239,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
case R_IA64_NONE:
|
||||
break;
|
||||
case R_IA64_DIR64LSB: /* word64 LSB S + A */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return (-1);
|
||||
*where = addr + addend;
|
||||
@ -248,7 +249,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
printf("%s: addend ignored for OPD relocation\n",
|
||||
__func__);
|
||||
}
|
||||
addr = lookup_fdesc(lf, symidx);
|
||||
addr = lookup_fdesc(lf, symidx, lookup);
|
||||
if (addr == 0)
|
||||
return (-1);
|
||||
*where = addr;
|
||||
@ -256,7 +257,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
case R_IA64_REL64LSB: /* word64 LSB BD + A */
|
||||
break;
|
||||
case R_IA64_IPLTLSB:
|
||||
addr = lookup_fdesc(lf, symidx);
|
||||
addr = lookup_fdesc(lf, symidx, lookup);
|
||||
if (addr == 0)
|
||||
return (-1);
|
||||
where[0] = *((Elf_Addr*)addr) + addend;
|
||||
@ -272,17 +273,19 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
|
||||
elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 0));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 1));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -118,6 +118,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 Elf_Addr elf_lookup(linker_file_t lf, Elf_Word symidx, int deps);
|
||||
|
||||
static kobj_method_t link_elf_methods[] = {
|
||||
KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol),
|
||||
@ -928,7 +929,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rel) {
|
||||
rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
|
||||
while (rel < rellim) {
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
|
||||
if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL,
|
||||
elf_lookup)) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
@ -942,7 +944,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rela) {
|
||||
relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
|
||||
while (rela < relalim) {
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
|
||||
if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA,
|
||||
elf_lookup)) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
@ -956,7 +959,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rel) {
|
||||
rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
|
||||
while (rel < rellim) {
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
|
||||
if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL,
|
||||
elf_lookup)) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
@ -970,7 +974,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rela) {
|
||||
relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
|
||||
while (rela < relalim) {
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
|
||||
if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA,
|
||||
elf_lookup)) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
@ -1244,7 +1249,7 @@ elf_get_symname(linker_file_t lf, Elf_Word symidx)
|
||||
* This is not only more efficient, it's also more correct. It's not always
|
||||
* the case that the symbol can be found through the hash table.
|
||||
*/
|
||||
Elf_Addr
|
||||
static Elf_Addr
|
||||
elf_lookup(linker_file_t lf, Elf_Word symidx, int deps)
|
||||
{
|
||||
elf_file_t ef = (elf_file_t)lf;
|
||||
@ -1297,7 +1302,8 @@ link_elf_reloc_local(linker_file_t lf)
|
||||
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);
|
||||
elf_reloc_local(lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL,
|
||||
elf_lookup);
|
||||
rel++;
|
||||
}
|
||||
}
|
||||
@ -1306,7 +1312,8 @@ link_elf_reloc_local(linker_file_t lf)
|
||||
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);
|
||||
elf_reloc_local(lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA,
|
||||
elf_lookup);
|
||||
rela++;
|
||||
}
|
||||
}
|
||||
|
@ -106,9 +106,9 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
static int
|
||||
elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, int local, elf_lookup_fn lookup)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
@ -141,7 +141,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
break;
|
||||
|
||||
case R_PPC_GLOB_DAT:
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
@ -151,7 +151,7 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
|
||||
case R_PPC_JMP_SLOT:
|
||||
/* No point in lazy binding for kernel modules. */
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
@ -181,17 +181,19 @@ elf_reloc_internal(linker_file_t lf, const void *data, int type, int local)
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
|
||||
elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 0));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, elf_lookup_fn lookup)
|
||||
{
|
||||
|
||||
return (elf_reloc_internal(lf, data, type, 1));
|
||||
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -252,7 +252,8 @@ static long reloc_target_bitmask[] = {
|
||||
#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
|
||||
|
||||
int
|
||||
elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int type, elf_lookup_fn lookup)
|
||||
{
|
||||
const Elf_Rela *rela;
|
||||
Elf_Addr value;
|
||||
@ -275,7 +276,8 @@ elf_reloc_local(linker_file_t lf, const void *data, int type)
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
|
||||
elf_lookup_fn lookup)
|
||||
{
|
||||
const Elf_Rela *rela;
|
||||
Elf_Addr relocbase;
|
||||
@ -289,7 +291,6 @@ elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
if (type != ELF_RELOC_RELA)
|
||||
return (-1);
|
||||
|
||||
relocbase = (Elf_Addr)lf->address;
|
||||
rela = (const Elf_Rela *)data;
|
||||
where = (Elf_Addr *)(relocbase + rela->r_offset);
|
||||
where32 = (Elf_Half *)where;
|
||||
@ -309,7 +310,7 @@ elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
value = rela->r_addend;
|
||||
|
||||
if (RELOC_RESOLVE_SYMBOL(rtype)) {
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
addr = lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return (-1);
|
||||
value += addr;
|
||||
|
@ -241,10 +241,11 @@ extern int kld_debug;
|
||||
|
||||
#endif
|
||||
|
||||
typedef Elf_Addr elf_lookup_fn(linker_file_t, Elf_Word, int);
|
||||
|
||||
/* Support functions */
|
||||
int elf_reloc(linker_file_t _lf, const void *_rel, int _type);
|
||||
int elf_reloc_local(linker_file_t _lf, const void *_rel, int _type);
|
||||
Elf_Addr elf_lookup(linker_file_t, Elf_Word, int);
|
||||
int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu);
|
||||
int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu);
|
||||
const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Word _symidx);
|
||||
const char *elf_get_symname(linker_file_t _lf, Elf_Word _symidx);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user