diff options
author | jdp <jdp@FreeBSD.org> | 2000-01-29 01:27:04 +0000 |
---|---|---|
committer | jdp <jdp@FreeBSD.org> | 2000-01-29 01:27:04 +0000 |
commit | 4bff590782e7100c86fb3cb5c40e46fb5c813b42 (patch) | |
tree | 15bb6f7a1a22644cfbb8a3a3b6db5834e253c62b /libexec/rtld-elf/alpha | |
parent | a037c1293d958b92212a5b2d4a23307eea11f46d (diff) | |
download | FreeBSD-src-4bff590782e7100c86fb3cb5c40e46fb5c813b42.zip FreeBSD-src-4bff590782e7100c86fb3cb5c40e46fb5c813b42.tar.gz |
When a threads package registers locking methods with dllockinit(),
figure out which shared object(s) contain the the locking methods
and fully bind those objects as if they had been loaded with
LD_BIND_NOW=1. The goal is to keep the locking methods from
requiring any lazy binding. Otherwise infinite recursion occurs
in _rtld_bind.
This fixes the infinite recursion problem in the linuxthreads port.
Diffstat (limited to 'libexec/rtld-elf/alpha')
-rw-r--r-- | libexec/rtld-elf/alpha/reloc.c | 68 |
1 files changed, 47 insertions, 21 deletions
diff --git a/libexec/rtld-elf/alpha/reloc.c b/libexec/rtld-elf/alpha/reloc.c index 114f3ae..8763be4 100644 --- a/libexec/rtld-elf/alpha/reloc.c +++ b/libexec/rtld-elf/alpha/reloc.c @@ -159,7 +159,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) /* Process the PLT relocations. */ int -reloc_plt(Obj_Entry *obj, bool bind_now) +reloc_plt(Obj_Entry *obj) { /* All PLT relocations are the same kind: either Elf_Rel or Elf_Rela. */ if (obj->pltrelsize != 0) { @@ -175,17 +175,6 @@ reloc_plt(Obj_Entry *obj, bool bind_now) /* Relocate the GOT slot pointing into the PLT. */ where = (Elf_Addr *)(obj->relocbase + rel->r_offset); *where += (Elf_Addr)obj->relocbase; - - if (bind_now) { /* Fully resolve the procedure address. */ - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true); - if (def == NULL) - return -1; - reloc_jmpslot(where, - (Elf_Addr)(defobj->relocbase + def->st_value)); - } } } else { const Elf_Rela *relalim; @@ -200,19 +189,56 @@ reloc_plt(Obj_Entry *obj, bool bind_now) /* Relocate the GOT slot pointing into the PLT. */ where = (Elf_Addr *)(obj->relocbase + rela->r_offset); *where += (Elf_Addr)obj->relocbase; + } + } + return 0; +} - if (bind_now) { /* Fully resolve the procedure address. */ - const Elf_Sym *def; - const Obj_Entry *defobj; +/* Relocate the jump slots in an object. */ +int +reloc_jmpslots(Obj_Entry *obj) +{ + if (obj->jmpslots_done) + return 0; + /* All PLT relocations are the same kind: either Elf_Rel or Elf_Rela. */ + if (obj->pltrelsize != 0) { + const Elf_Rel *rellim; + const Elf_Rel *rel; - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); - if (def == NULL) - return -1; - reloc_jmpslot(where, - (Elf_Addr)(defobj->relocbase + def->st_value)); - } + rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); + for (rel = obj->pltrel; rel < rellim; rel++) { + Elf_Addr *where; + const Elf_Sym *def; + const Obj_Entry *defobj; + + assert(ELF_R_TYPE(rel->r_info) == R_ALPHA_JMP_SLOT); + where = (Elf_Addr *)(obj->relocbase + rel->r_offset); + def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true); + if (def == NULL) + return -1; + reloc_jmpslot(where, + (Elf_Addr)(defobj->relocbase + def->st_value)); + } + } else { + const Elf_Rela *relalim; + const Elf_Rela *rela; + + relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); + for (rela = obj->pltrela; rela < relalim; rela++) { + Elf_Addr *where; + 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); + if (def == NULL) + return -1; + reloc_jmpslot(where, + (Elf_Addr)(defobj->relocbase + def->st_value)); } } + obj->jmpslots_done = true; return 0; } |