diff options
author | kib <kib@FreeBSD.org> | 2010-12-25 08:51:20 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2010-12-25 08:51:20 +0000 |
commit | cefd8b2a41e4b4bf7a16e2dea1e0c719a30d56a3 (patch) | |
tree | 487c080e0cb090d960945a4f112301253d4a6e9f /libexec/rtld-elf/sparc64/reloc.c | |
parent | 377233e6cca2d48c8ecba755aa46304a8ae7731b (diff) | |
download | FreeBSD-src-cefd8b2a41e4b4bf7a16e2dea1e0c719a30d56a3.zip FreeBSD-src-cefd8b2a41e4b4bf7a16e2dea1e0c719a30d56a3.tar.gz |
Implement support for ELF filters in rtld. Both normal and auxillary
filters are implemented.
Filtees are loaded on demand, unless LD_LOADFLTR environment variable
is set or -z loadfltr was specified during the linking. This forces
rtld to upgrade read-locked rtld_bind_lock to write lock when it
encounters an object with filter during symbol lookup.
Consolidate common arguments of the symbol lookup functions in the
SymLook structure. Track the state of the rtld locks in the
RtldLockState structure. Pass local RtldLockState through the rtld
symbol lookup calls to allow lock upgrades.
Reviewed by: kan
Tested by: Mykola Dzham <i levsha me>, nwhitehorn (powerpc)
Diffstat (limited to 'libexec/rtld-elf/sparc64/reloc.c')
-rw-r--r-- | libexec/rtld-elf/sparc64/reloc.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c index 1b8f1fd..c8d657c 100644 --- a/libexec/rtld-elf/sparc64/reloc.c +++ b/libexec/rtld-elf/sparc64/reloc.c @@ -193,7 +193,7 @@ static const long reloc_target_bitmask[] = { __asm __volatile("flush %0 + %1" : : "r" (va), "I" (offs)); static int reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, - SymCache *cache); + SymCache *cache, RtldLockState *lockstate); static void install_plt(Elf_Word *pltgot, Elf_Addr proc); extern char _rtld_bind_start_0[]; @@ -206,13 +206,13 @@ do_copy_relocations(Obj_Entry *dstobj) const Elf_Rela *rela; const Elf_Sym *dstsym; const Elf_Sym *srcsym; - const Ver_Entry *ve; void *dstaddr; const void *srcaddr; - Obj_Entry *srcobj; - unsigned long hash; + const Obj_Entry *srcobj, *defobj; + SymLook req; const char *name; size_t size; + int res; assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ @@ -222,16 +222,20 @@ do_copy_relocations(Obj_Entry *dstobj) dstaddr = (void *)(dstobj->relocbase + rela->r_offset); dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); name = dstobj->strtab + dstsym->st_name; - hash = elf_hash(name); size = dstsym->st_size; - ve = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); + symlook_init(&req, name); + req.ventry = fetch_ventry(dstobj, + ELF_R_SYM(rela->r_info)); for (srcobj = dstobj->next; srcobj != NULL; - srcobj = srcobj->next) - if ((srcsym = symlook_obj(name, hash, srcobj, - ve, 0)) != NULL) + srcobj = srcobj->next) { + res = symlook_obj(&req, srcobj); + if (res == 0) { + srcsym = req.sym_out; + defobj = req.defobj_out; break; - + } + } if (srcobj == NULL) { _rtld_error("Undefined symbol \"%s\"" "referenced from COPY relocation" @@ -239,7 +243,7 @@ do_copy_relocations(Obj_Entry *dstobj) return (-1); } - srcaddr = (const void *)(srcobj->relocbase + + srcaddr = (const void *)(defobj->relocbase + srcsym->st_value); memcpy(dstaddr, srcaddr, size); } @@ -249,7 +253,7 @@ do_copy_relocations(Obj_Entry *dstobj) } int -reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) +reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) { const Elf_Rela *relalim; const Elf_Rela *rela; @@ -268,7 +272,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize); for (rela = obj->rela; rela < relalim; rela++) { - if (reloc_nonplt_object(obj, rela, cache) < 0) + if (reloc_nonplt_object(obj, rela, cache, lockstate) < 0) goto done; } r = 0; @@ -279,7 +283,8 @@ done: } static int -reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, SymCache *cache) +reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, SymCache *cache, + RtldLockState *lockstate) { const Obj_Entry *defobj; const Elf_Sym *def; @@ -333,7 +338,7 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, SymCache *cache) /* Find the symbol */ def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return (-1); @@ -416,7 +421,7 @@ reloc_plt(Obj_Entry *obj) assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT); where = (Elf_Addr *)(obj->relocbase + rela->r_offset); def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - true, NULL); + true, NULL, lockstate); value = (Elf_Addr)(defobj->relocbase + def->st_value); *where = value; } @@ -446,7 +451,7 @@ reloc_plt(Obj_Entry *obj) #define LOVAL(v) ((v) & 0x000003ff) int -reloc_jmpslots(Obj_Entry *obj) +reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate) { const Obj_Entry *defobj; const Elf_Rela *relalim; @@ -460,7 +465,7 @@ reloc_jmpslots(Obj_Entry *obj) assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT); where = (Elf_Addr *)(obj->relocbase + rela->r_offset); def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - true, NULL); + true, NULL, lockstate); if (def == NULL) return -1; target = (Elf_Addr)(defobj->relocbase + def->st_value); |