Fix handling of weak references to undefined symbols on ia64:
o Set st_shndx for sym_zero to SHN_UNDEF instead of SHN_ABS. This gives us something to reliably test against. o For weak references to undefined sysmbols (as indicated by having st_shndx equals SHN_UNDEF) in the context of OPDs, the address of the OPD is to be zero, not the address of the function it contains. o For weak references to undefined symbols in all other cases (only DIR64LSB at this time), the actual relocated value is to be zero, not the value prior to relocating. Roughly speaking, weak references to undefined symbols are no-ops. Tested on: i386, ia64
This commit is contained in:
parent
e64b74e35b
commit
2aba02382e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=95544
@ -123,7 +123,9 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
|
||||
false, cache);
|
||||
if (def == NULL)
|
||||
return -1;
|
||||
target = (Elf_Addr) (defobj->relocbase + def->st_value);
|
||||
|
||||
target = (def->st_shndx != SHN_UNDEF)
|
||||
? (Elf_Addr)(defobj->relocbase + def->st_value) : 0;
|
||||
store64(where, target + rela->r_addend);
|
||||
break;
|
||||
}
|
||||
@ -136,7 +138,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
|
||||
* to ensure this within a single object. If the
|
||||
* caller's alloca failed, we don't even ensure that.
|
||||
*/
|
||||
const Elf_Sym *def, *ref;
|
||||
const Elf_Sym *def;
|
||||
const Obj_Entry *defobj;
|
||||
struct fptr *fptr = 0;
|
||||
Elf_Addr target, gp;
|
||||
@ -146,33 +148,24 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
|
||||
if (def == NULL)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* If this is an undefined weak reference, we need to
|
||||
* have a zero target,gp fptr, not pointing to relocbase.
|
||||
* This isn't quite right. Maybe we should check
|
||||
* explicitly for def == &sym_zero.
|
||||
*/
|
||||
if (def->st_value == 0 &&
|
||||
(ref = obj->symtab + ELF_R_SYM(rela->r_info)) &&
|
||||
ELF_ST_BIND(ref->st_info) == STB_WEAK) {
|
||||
target = 0;
|
||||
gp = 0;
|
||||
} else {
|
||||
target = (Elf_Addr) (defobj->relocbase + def->st_value);
|
||||
gp = (Elf_Addr) defobj->pltgot;
|
||||
}
|
||||
if (def->st_shndx != SHN_UNDEF) {
|
||||
target = (Elf_Addr)(defobj->relocbase + def->st_value);
|
||||
gp = (Elf_Addr)defobj->pltgot;
|
||||
|
||||
/*
|
||||
* Find the @fptr, using fptrs as a helper.
|
||||
*/
|
||||
if (fptrs)
|
||||
fptr = fptrs[ELF_R_SYM(rela->r_info)];
|
||||
if (!fptr) {
|
||||
fptr = alloc_fptr(target, gp);
|
||||
/*
|
||||
* Find the @fptr, using fptrs as a helper.
|
||||
*/
|
||||
if (fptrs)
|
||||
fptrs[ELF_R_SYM(rela->r_info)] = fptr;
|
||||
}
|
||||
store64(where, (Elf_Addr) fptr);
|
||||
fptr = fptrs[ELF_R_SYM(rela->r_info)];
|
||||
if (!fptr) {
|
||||
fptr = alloc_fptr(target, gp);
|
||||
if (fptrs)
|
||||
fptrs[ELF_R_SYM(rela->r_info)] = fptr;
|
||||
}
|
||||
} else
|
||||
fptr = NULL;
|
||||
|
||||
store64(where, (Elf_Addr)fptr);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -327,7 +320,6 @@ reloc_jmpslots(Obj_Entry *obj)
|
||||
const Elf_Sym *def;
|
||||
const Obj_Entry *defobj;
|
||||
|
||||
/* assert(ELF_R_TYPE(rela->r_info) == R_ALPHA_JMP_SLOT); */
|
||||
where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
|
||||
def = find_symdef(ELF_R_SYM(rela->r_info), obj,
|
||||
&defobj, true, NULL);
|
||||
|
@ -357,7 +357,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
|
||||
|
||||
/* Initialize a fake symbol for resolving undefined weak references. */
|
||||
sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
|
||||
sym_zero.st_shndx = SHN_ABS;
|
||||
sym_zero.st_shndx = SHN_UNDEF;
|
||||
|
||||
dbg("loading LD_PRELOAD libraries");
|
||||
if (load_preload_objects() == -1)
|
||||
|
Loading…
Reference in New Issue
Block a user