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/arm | |
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/arm')
-rw-r--r-- | libexec/rtld-elf/arm/reloc.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c index 6ad80fd..8f83a8e 100644 --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -36,31 +36,39 @@ do_copy_relocations(Obj_Entry *dstobj) void *dstaddr; const Elf_Sym *dstsym; const char *name; - unsigned long hash; size_t size; const void *srcaddr; const Elf_Sym *srcsym; - Obj_Entry *srcobj; - const Ver_Entry *ve; + const Obj_Entry *srcobj, *defobj; + SymLook req; + int res; dstaddr = (void *) (dstobj->relocbase + rel->r_offset); dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info); name = dstobj->strtab + dstsym->st_name; - hash = elf_hash(name); size = dstsym->st_size; - ve = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info)); - - for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) - if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL) + + symlook_init(&req, name); + req.ventry = fetch_ventry(dstobj, + ELF_R_SYM(rel->r_info)); + for (srcobj = dstobj->next; srcobj != 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 in %s", name, dstobj->path); - return -1; + _rtld_error( +"Undefined symbol \"%s\" referenced from COPY relocation in %s", + name, dstobj->path); + return (-1); } - srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); + srcaddr = (const void *)(defobj->relocbase + + srcsym->st_value); memcpy(dstaddr, srcaddr, size); } } @@ -123,7 +131,8 @@ store_ptr(void *where, Elf_Addr val) } static int -reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache) +reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache, + RtldLockState *lockstate) { Elf_Addr *where; const Elf_Sym *def; @@ -149,7 +158,8 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache) if (addend & 0x00800000) addend |= 0xff000000; - def = find_symdef(symnum, obj, &defobj, false, cache); + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); if (def == NULL) return -1; tmp = (Elf_Addr)obj->relocbase + def->st_value @@ -175,7 +185,8 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache) case R_ARM_ABS32: /* word32 B + S + A */ case R_ARM_GLOB_DAT: /* word32 B + S */ - def = find_symdef(symnum, obj, &defobj, false, cache); + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); if (def == NULL) return -1; if (__predict_true(RELOC_ALIGNED_P(where))) { @@ -240,7 +251,7 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache) * * Process non-PLT relocations * */ 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_Rel *rellim; const Elf_Rel *rel; @@ -259,7 +270,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize); for (rel = obj->rel; rel < rellim; rel++) { - if (reloc_nonplt_object(obj, rel, cache) < 0) + if (reloc_nonplt_object(obj, rel, cache, lockstate) < 0) goto done; } r = 0; @@ -296,7 +307,7 @@ reloc_plt(Obj_Entry *obj) * * LD_BIND_NOW was set - force relocation for all jump slots * */ int -reloc_jmpslots(Obj_Entry *obj) +reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate) { const Obj_Entry *defobj; const Elf_Rel *rellim; @@ -310,7 +321,7 @@ reloc_jmpslots(Obj_Entry *obj) assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT); where = (Elf_Addr *)(obj->relocbase + rel->r_offset); def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - true, NULL); + true, NULL, lockstate); if (def == NULL) { dbg("reloc_jmpslots: sym not found"); return (-1); |