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.
This commit is contained in:
parent
a037c1293d
commit
4bff590782
@ -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,22 +189,59 @@ 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;
|
||||
|
||||
if (bind_now) { /* Fully resolve the procedure address. */
|
||||
const Elf_Sym *def;
|
||||
const Obj_Entry *defobj;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Fixup the jump slot at "where" to transfer control to "target". */
|
||||
void
|
||||
reloc_jmpslot(Elf_Addr *where, Elf_Addr target)
|
||||
|
@ -203,7 +203,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)
|
||||
{
|
||||
const Elf_Rel *rellim;
|
||||
const Elf_Rel *rel;
|
||||
@ -217,17 +217,32 @@ 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));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Relocate the jump slots in an object. */
|
||||
int
|
||||
reloc_jmpslots(Obj_Entry *obj)
|
||||
{
|
||||
const Elf_Rel *rellim;
|
||||
const Elf_Rel *rel;
|
||||
|
||||
if (obj->jmpslots_done)
|
||||
return 0;
|
||||
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_386_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));
|
||||
}
|
||||
obj->jmpslots_done = true;
|
||||
return 0;
|
||||
}
|
||||
|
@ -203,7 +203,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)
|
||||
{
|
||||
const Elf_Rel *rellim;
|
||||
const Elf_Rel *rel;
|
||||
@ -217,17 +217,32 @@ 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));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Relocate the jump slots in an object. */
|
||||
int
|
||||
reloc_jmpslots(Obj_Entry *obj)
|
||||
{
|
||||
const Elf_Rel *rellim;
|
||||
const Elf_Rel *rel;
|
||||
|
||||
if (obj->jmpslots_done)
|
||||
return 0;
|
||||
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_386_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));
|
||||
}
|
||||
obj->jmpslots_done = true;
|
||||
return 0;
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ static Obj_Entry *obj_from_addr(const void *);
|
||||
static void objlist_add(Objlist *, Obj_Entry *);
|
||||
static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *);
|
||||
static void objlist_remove(Objlist *, Obj_Entry *);
|
||||
static void prebind(void *);
|
||||
static int relocate_objects(Obj_Entry *, bool);
|
||||
static void rtld_exit(void);
|
||||
static char *search_library_path(const char *, const char *);
|
||||
@ -1232,9 +1233,14 @@ relocate_objects(Obj_Entry *first, bool bind_now)
|
||||
}
|
||||
|
||||
/* Process the PLT relocations. */
|
||||
if (reloc_plt(obj, bind_now))
|
||||
if (reloc_plt(obj) == -1)
|
||||
return -1;
|
||||
/* Relocate the jump slots if we are doing immediate binding. */
|
||||
if (bind_now)
|
||||
if (reloc_jmpslots(obj) == -1)
|
||||
return -1;
|
||||
|
||||
|
||||
/*
|
||||
* Set up the magic number and version in the Obj_Entry. These
|
||||
* were checked in the crt1.o from the original ElfKit, so we
|
||||
@ -1361,8 +1367,11 @@ dllockinit(void *context,
|
||||
void (*lock_destroy)(void *lock),
|
||||
void (*context_destroy)(void *context))
|
||||
{
|
||||
bool is_dflt = false;
|
||||
|
||||
/* NULL arguments mean reset to the built-in locks. */
|
||||
if (lock_create == NULL) {
|
||||
is_dflt = true;
|
||||
context = NULL;
|
||||
lock_create = lockdflt_create;
|
||||
rlock_acquire = wlock_acquire = lockdflt_acquire;
|
||||
@ -1383,15 +1392,18 @@ dllockinit(void *context,
|
||||
lockinfo.context_destroy(lockinfo.context);
|
||||
|
||||
/*
|
||||
* Allocate the locks we will need and call all the new locking
|
||||
* methods, to accomplish any needed lazy binding for the methods
|
||||
* themselves.
|
||||
* Make sure the shared objects containing the locking methods are
|
||||
* fully bound, to avoid infinite recursion when they are called
|
||||
* from the lazy binding code.
|
||||
*/
|
||||
if (!is_dflt) {
|
||||
prebind((void *)rlock_acquire);
|
||||
prebind((void *)wlock_acquire);
|
||||
prebind((void *)lock_release);
|
||||
}
|
||||
|
||||
/* Allocate our lock. */
|
||||
lockinfo.thelock = lock_create(lockinfo.context);
|
||||
rlock_acquire(lockinfo.thelock);
|
||||
lock_release(lockinfo.thelock);
|
||||
wlock_acquire(lockinfo.thelock);
|
||||
lock_release(lockinfo.thelock);
|
||||
|
||||
/* Record the new method information. */
|
||||
lockinfo.context = context;
|
||||
@ -1402,6 +1414,23 @@ dllockinit(void *context,
|
||||
lockinfo.context_destroy = context_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
prebind(void *addr)
|
||||
{
|
||||
Obj_Entry *obj;
|
||||
|
||||
if ((obj = obj_from_addr(addr)) == NULL) {
|
||||
_rtld_error("Cannot determine shared object of locking method at %p",
|
||||
addr);
|
||||
die();
|
||||
}
|
||||
if (!obj->rtld && !obj->jmpslots_done) {
|
||||
dbg("Pre-binding %s for locking", obj->path);
|
||||
if (reloc_jmpslots(obj) == -1)
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
dlopen(const char *name, int mode)
|
||||
{
|
||||
|
@ -142,6 +142,7 @@ typedef struct Struct_Obj_Entry {
|
||||
bool textrel; /* True if there are relocations to text seg */
|
||||
bool symbolic; /* True if generated with "-Bsymbolic" */
|
||||
bool traced; /* Already printed in ldd trace output */
|
||||
bool jmpslots_done; /* Already have relocated the jump slots */
|
||||
|
||||
struct link_map linkmap; /* for GDB */
|
||||
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
|
||||
@ -176,7 +177,8 @@ void lockdflt_release(void *);
|
||||
void obj_free(Obj_Entry *);
|
||||
Obj_Entry *obj_new(void);
|
||||
int reloc_non_plt(Obj_Entry *, Obj_Entry *);
|
||||
int reloc_plt(Obj_Entry *, bool);
|
||||
int reloc_plt(Obj_Entry *);
|
||||
int reloc_jmpslots(Obj_Entry *);
|
||||
void _rtld_bind_start(void);
|
||||
const Elf_Sym *symlook_obj(const char *, unsigned long,
|
||||
const Obj_Entry *, bool);
|
||||
|
Loading…
Reference in New Issue
Block a user