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:
jdp 2000-01-29 01:27:04 +00:00
parent a037c1293d
commit 4bff590782
5 changed files with 143 additions and 56 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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);