Don't use the symbol name to lookup the symbol value when we can use
the symbol index defined by the relocation. The elf_lookup() support function is to be used by elf_reloc() when symbol lookups need to be done. The elf_lookup() function operates on the symbol index and will do a symbol name based lookup when such is required, otherwise it uses the symbol index directly. This solves the problem seen on ia64 where the symbol hash table does not contain local symbols and a symbol name based lookup would fail for those symbols. Don't pass the symbol name to elf_reloc(), as it isn't used any more.
This commit is contained in:
parent
12a8faa64a
commit
56d625090e
@ -38,13 +38,13 @@
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
Elf_Word rtype;
|
||||
Elf_Word rtype, symidx;
|
||||
const Elf_Rel *rel;
|
||||
const Elf_Rela *rela;
|
||||
|
||||
@ -54,12 +54,14 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
where = (Elf_Addr *) (relocbase + rel->r_offset);
|
||||
addend = *where;
|
||||
rtype = ELF_R_TYPE(rel->r_info);
|
||||
symidx = ELF_R_SYM(rel->r_info);
|
||||
break;
|
||||
case ELF_RELOC_RELA:
|
||||
rela = (const Elf_Rela *)data;
|
||||
where = (Elf_Addr *) (relocbase + rela->r_offset);
|
||||
addend = rela->r_addend;
|
||||
rtype = ELF_R_TYPE(rela->r_info);
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
break;
|
||||
default:
|
||||
panic("elf_reloc: unknown relocation mode %d\n", type);
|
||||
@ -71,9 +73,8 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_ALPHA_REFQUAD:
|
||||
addr = (Elf_Addr)
|
||||
linker_file_lookup_symbol(lf, sym, 1);
|
||||
if (addr == NULL)
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
if (*where != addr)
|
||||
@ -81,9 +82,8 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_ALPHA_GLOB_DAT:
|
||||
addr = (Elf_Addr)
|
||||
linker_file_lookup_symbol(lf, sym, 1);
|
||||
if (addr == NULL)
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
if (*where != addr)
|
||||
@ -92,9 +92,8 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
|
||||
case R_ALPHA_JMP_SLOT:
|
||||
/* No point in lazy binding for kernel modules. */
|
||||
addr = (Elf_Addr)
|
||||
linker_file_lookup_symbol(lf, sym, 1);
|
||||
if (addr == NULL)
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
*where = addr;
|
||||
|
@ -32,13 +32,13 @@
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
Elf_Word rtype;
|
||||
Elf_Word rtype, symidx;
|
||||
const Elf_Rel *rel;
|
||||
const Elf_Rela *rela;
|
||||
|
||||
@ -48,12 +48,14 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
where = (Elf_Addr *) (relocbase + rel->r_offset);
|
||||
addend = *where;
|
||||
rtype = ELF_R_TYPE(rel->r_info);
|
||||
symidx = ELF_R_SYM(rel->r_info);
|
||||
break;
|
||||
case ELF_RELOC_RELA:
|
||||
rela = (const Elf_Rela *)data;
|
||||
where = (Elf_Addr *) (relocbase + rela->r_offset);
|
||||
addend = rela->r_addend;
|
||||
rtype = ELF_R_TYPE(rela->r_info);
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
break;
|
||||
default:
|
||||
panic("unknown reloc type %d\n", type);
|
||||
@ -65,9 +67,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_386_32: /* S + A */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
@ -76,9 +76,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_386_PC32: /* S + A - P */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend - (Elf_Addr)where;
|
||||
@ -96,9 +94,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_386_GLOB_DAT: /* S */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
|
@ -32,13 +32,13 @@
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
Elf_Word rtype;
|
||||
Elf_Word rtype, symidx;
|
||||
const Elf_Rel *rel;
|
||||
const Elf_Rela *rela;
|
||||
|
||||
@ -48,12 +48,14 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
where = (Elf_Addr *) (relocbase + rel->r_offset);
|
||||
addend = *where;
|
||||
rtype = ELF_R_TYPE(rel->r_info);
|
||||
symidx = ELF_R_SYM(rel->r_info);
|
||||
break;
|
||||
case ELF_RELOC_RELA:
|
||||
rela = (const Elf_Rela *)data;
|
||||
where = (Elf_Addr *) (relocbase + rela->r_offset);
|
||||
addend = rela->r_addend;
|
||||
rtype = ELF_R_TYPE(rela->r_info);
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
break;
|
||||
default:
|
||||
panic("unknown reloc type %d\n", type);
|
||||
@ -65,9 +67,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_386_32: /* S + A */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
@ -76,9 +76,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_386_PC32: /* S + A - P */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend - (Elf_Addr)where;
|
||||
@ -96,9 +94,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_386_GLOB_DAT: /* S */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
|
@ -41,24 +41,24 @@ Elf_Addr link_elf_get_gp(linker_file_t);
|
||||
extern Elf_Addr fptr_storage[];
|
||||
|
||||
static Elf_Addr
|
||||
lookup_fdesc(linker_file_t lf, const char *sym)
|
||||
lookup_fdesc(linker_file_t lf, Elf_Word symidx)
|
||||
{
|
||||
Elf_Addr addr;
|
||||
int i;
|
||||
static int eot = 0;
|
||||
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 0);
|
||||
if (addr == NULL) {
|
||||
addr = elf_lookup(lf, symidx, 0);
|
||||
if (addr == 0) {
|
||||
for (i = 0; i < lf->ndeps; i++) {
|
||||
addr = lookup_fdesc(lf->deps[i], sym);
|
||||
if (addr != NULL)
|
||||
addr = lookup_fdesc(lf->deps[i], symidx);
|
||||
if (addr != 0)
|
||||
return (addr);
|
||||
}
|
||||
return (NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (eot)
|
||||
return (NULL);
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Lookup and/or construct OPD
|
||||
@ -77,17 +77,17 @@ lookup_fdesc(linker_file_t lf, const char *sym)
|
||||
printf("%s: fptr table full\n", __func__);
|
||||
eot = 1;
|
||||
|
||||
return (NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr)lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addend, addr;
|
||||
Elf_Word rtype;
|
||||
Elf_Word rtype, symidx;
|
||||
const Elf_Rel *rel;
|
||||
const Elf_Rela *rela;
|
||||
|
||||
@ -96,6 +96,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
rel = (const Elf_Rel *)data;
|
||||
where = (Elf_Addr *)(relocbase + rel->r_offset);
|
||||
rtype = ELF_R_TYPE(rel->r_info);
|
||||
symidx = ELF_R_SYM(rel->r_info);
|
||||
switch (rtype) {
|
||||
case R_IA64_DIR64LSB:
|
||||
case R_IA64_FPTR64LSB:
|
||||
@ -111,6 +112,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
rela = (const Elf_Rela *)data;
|
||||
where = (Elf_Addr *)(relocbase + rela->r_offset);
|
||||
rtype = ELF_R_TYPE(rela->r_info);
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
addend = rela->r_addend;
|
||||
break;
|
||||
default:
|
||||
@ -121,35 +123,28 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
case R_IA64_NONE:
|
||||
break;
|
||||
case R_IA64_DIR64LSB: /* word64 LSB S + A */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
return (-1);
|
||||
*where = addr + addend;
|
||||
break;
|
||||
case R_IA64_FPTR64LSB: /* word64 LSB @fptr(S + A) */
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
if (addend != 0) {
|
||||
printf("%s: addend ignored for OPD relocation\n",
|
||||
__func__);
|
||||
}
|
||||
addr = lookup_fdesc(lf, sym);
|
||||
addr = lookup_fdesc(lf, symidx);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
return (-1);
|
||||
*where = addr;
|
||||
break;
|
||||
case R_IA64_REL64LSB: /* word64 LSB BD + A */
|
||||
*where = relocbase + addend;
|
||||
break;
|
||||
case R_IA64_IPLTLSB:
|
||||
if (sym == NULL)
|
||||
return -1;
|
||||
/* lookup_fdesc() returns the address of the OPD. */
|
||||
addr = lookup_fdesc(lf, sym);
|
||||
addr = lookup_fdesc(lf, symidx);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
return (-1);
|
||||
where[0] = *((Elf_Addr*)addr) + addend;
|
||||
where[1] = *((Elf_Addr*)addr + 1);
|
||||
break;
|
||||
@ -159,5 +154,5 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
@ -904,8 +904,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rel) {
|
||||
rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
|
||||
while (rel < rellim) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -918,8 +918,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rela) {
|
||||
relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
|
||||
while (rela < relalim) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -932,8 +932,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rel) {
|
||||
rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
|
||||
while (rel < rellim) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -946,8 +946,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rela) {
|
||||
relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
|
||||
while (rela < relalim) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -1190,3 +1190,50 @@ link_elf_get_gp(linker_file_t lf)
|
||||
return (Elf_Addr)ef->got;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Symbol lookup function that can be used when the symbol index is known (ie
|
||||
* in relocations). It uses the symbol index instead of doing a fully fledged
|
||||
* hash table based lookup when such is valid. For example for local symbols.
|
||||
* 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
|
||||
elf_lookup(linker_file_t lf, Elf_Word symidx, int deps)
|
||||
{
|
||||
elf_file_t ef = (elf_file_t)lf;
|
||||
const Elf_Sym *sym;
|
||||
const char *symbol;
|
||||
|
||||
/* Don't even try to lookup the symbol if the index is bogus. */
|
||||
if (symidx >= ef->nchains)
|
||||
return (0);
|
||||
|
||||
sym = ef->symtab + symidx;
|
||||
|
||||
/*
|
||||
* Don't do a full lookup when the symbol is local. It may even
|
||||
* fail because it may not be found through the hash table.
|
||||
*/
|
||||
if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
|
||||
/* Force lookup failure when we have an insanity. */
|
||||
if (sym->st_shndx == SHN_UNDEF || sym->st_value == 0)
|
||||
return (0);
|
||||
return ((Elf_Addr)ef->address + sym->st_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX we can avoid doing a hash table based lookup for global
|
||||
* symbols as well. This however is not always valid, so we'll
|
||||
* just do it the hard way for now. Performance tweaks can
|
||||
* always be added.
|
||||
*/
|
||||
|
||||
symbol = ef->strtab + sym->st_name;
|
||||
|
||||
/* Force a lookup failure if the symbol name is bogus. */
|
||||
if (*symbol == 0)
|
||||
return (0);
|
||||
|
||||
return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
|
||||
}
|
||||
|
@ -904,8 +904,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rel) {
|
||||
rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
|
||||
while (rel < rellim) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -918,8 +918,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rela) {
|
||||
relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
|
||||
while (rela < relalim) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -932,8 +932,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rel) {
|
||||
rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
|
||||
while (rel < rellim) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
|
||||
if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) {
|
||||
symname = symbol_name(ef, rel->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -946,8 +946,8 @@ relocate_file(elf_file_t ef)
|
||||
if (rela) {
|
||||
relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
|
||||
while (rela < relalim) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
|
||||
if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) {
|
||||
symname = symbol_name(ef, rela->r_info);
|
||||
printf("link_elf: symbol %s undefined\n", symname);
|
||||
return ENOENT;
|
||||
}
|
||||
@ -1190,3 +1190,50 @@ link_elf_get_gp(linker_file_t lf)
|
||||
return (Elf_Addr)ef->got;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Symbol lookup function that can be used when the symbol index is known (ie
|
||||
* in relocations). It uses the symbol index instead of doing a fully fledged
|
||||
* hash table based lookup when such is valid. For example for local symbols.
|
||||
* 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
|
||||
elf_lookup(linker_file_t lf, Elf_Word symidx, int deps)
|
||||
{
|
||||
elf_file_t ef = (elf_file_t)lf;
|
||||
const Elf_Sym *sym;
|
||||
const char *symbol;
|
||||
|
||||
/* Don't even try to lookup the symbol if the index is bogus. */
|
||||
if (symidx >= ef->nchains)
|
||||
return (0);
|
||||
|
||||
sym = ef->symtab + symidx;
|
||||
|
||||
/*
|
||||
* Don't do a full lookup when the symbol is local. It may even
|
||||
* fail because it may not be found through the hash table.
|
||||
*/
|
||||
if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
|
||||
/* Force lookup failure when we have an insanity. */
|
||||
if (sym->st_shndx == SHN_UNDEF || sym->st_value == 0)
|
||||
return (0);
|
||||
return ((Elf_Addr)ef->address + sym->st_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX we can avoid doing a hash table based lookup for global
|
||||
* symbols as well. This however is not always valid, so we'll
|
||||
* just do it the hard way for now. Performance tweaks can
|
||||
* always be added.
|
||||
*/
|
||||
|
||||
symbol = ef->strtab + sym->st_name;
|
||||
|
||||
/* Force a lookup failure if the symbol name is bogus. */
|
||||
if (*symbol == 0)
|
||||
return (0);
|
||||
|
||||
return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
|
||||
}
|
||||
|
@ -38,13 +38,13 @@
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
{
|
||||
Elf_Addr relocbase = (Elf_Addr) lf->address;
|
||||
Elf_Addr *where;
|
||||
Elf_Addr addr;
|
||||
Elf_Addr addend;
|
||||
Elf_Word rtype;
|
||||
Elf_Word rtype, symidx;
|
||||
const Elf_Rel *rel;
|
||||
const Elf_Rela *rela;
|
||||
|
||||
@ -54,12 +54,14 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
where = (Elf_Addr *) (relocbase + rel->r_offset);
|
||||
addend = *where;
|
||||
rtype = ELF_R_TYPE(rel->r_info);
|
||||
symidx = ELF_R_SYM(rel->r_info);
|
||||
break;
|
||||
case ELF_RELOC_RELA:
|
||||
rela = (const Elf_Rela *)data;
|
||||
where = (Elf_Addr *) (relocbase + rela->r_offset);
|
||||
addend = rela->r_addend;
|
||||
rtype = ELF_R_TYPE(rela->r_info);
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
break;
|
||||
default:
|
||||
panic("elf_reloc: unknown relocation mode %d\n", type);
|
||||
@ -71,9 +73,8 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
break;
|
||||
|
||||
case R_PPC_GLOB_DAT:
|
||||
addr = (Elf_Addr)
|
||||
linker_file_lookup_symbol(lf, sym, 1);
|
||||
if (addr == NULL)
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
addr += addend;
|
||||
if (*where != addr)
|
||||
@ -82,9 +83,8 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym)
|
||||
|
||||
case R_PPC_JMP_SLOT:
|
||||
/* No point in lazy binding for kernel modules. */
|
||||
addr = (Elf_Addr)
|
||||
linker_file_lookup_symbol(lf, sym, 1);
|
||||
if (addr == NULL)
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return -1;
|
||||
if (*where != addr)
|
||||
*where = addr;
|
||||
|
@ -168,13 +168,13 @@ static long reloc_target_bitmask[] = {
|
||||
|
||||
/* Process one elf relocation with addend. */
|
||||
int
|
||||
elf_reloc(linker_file_t lf, const void *data, int type, const char *symname)
|
||||
elf_reloc(linker_file_t lf, const void *data, int type)
|
||||
{
|
||||
const Elf_Rela *rela;
|
||||
Elf_Addr relocbase;
|
||||
Elf_Half *where32;
|
||||
Elf_Addr *where;
|
||||
Elf_Word rtype;
|
||||
Elf_Word rtype, symidx;
|
||||
Elf_Addr value;
|
||||
Elf_Addr mask;
|
||||
caddr_t addr;
|
||||
@ -187,6 +187,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *symname)
|
||||
where = (Elf_Addr *)(relocbase + rela->r_offset);
|
||||
where32 = (Elf_Half *)where;
|
||||
rtype = ELF_R_TYPE(rela->r_info);
|
||||
symidx = ELF_R_SYM(rela->r_info);
|
||||
|
||||
if (rtype == R_SPARC_NONE)
|
||||
return (0);
|
||||
@ -201,7 +202,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *symname)
|
||||
value = rela->r_addend;
|
||||
|
||||
if (RELOC_RESOLVE_SYMBOL(rtype)) {
|
||||
addr = linker_file_lookup_symbol(lf, symname, 1);
|
||||
addr = elf_lookup(lf, symidx, 1);
|
||||
if (addr == 0)
|
||||
return (-1);
|
||||
value += (Elf_Addr)addr;
|
||||
|
@ -226,8 +226,9 @@ extern int kld_debug;
|
||||
#endif
|
||||
|
||||
/* Support functions */
|
||||
int elf_reloc(linker_file_t _lf, const void *_rel, int _type,
|
||||
const char *_sym);
|
||||
int elf_reloc(linker_file_t _lf, const void *_rel, int _type);
|
||||
Elf_Addr elf_lookup(linker_file_t, Elf_Word, int);
|
||||
|
||||
/* values for type */
|
||||
#define ELF_RELOC_REL 1
|
||||
#define ELF_RELOC_RELA 2
|
||||
|
Loading…
x
Reference in New Issue
Block a user