From owner-svn-src-all@FreeBSD.ORG Sat Dec 25 08:51:21 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 47703106564A; Sat, 25 Dec 2010 08:51:21 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 347C78FC0A; Sat, 25 Dec 2010 08:51:21 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oBP8pLCI017025; Sat, 25 Dec 2010 08:51:21 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oBP8pLLm017014; Sat, 25 Dec 2010 08:51:21 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201012250851.oBP8pLLm017014@svn.freebsd.org> From: Konstantin Belousov Date: Sat, 25 Dec 2010 08:51:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r216695 - in head/libexec/rtld-elf: . amd64 arm i386 ia64 mips powerpc powerpc64 sparc64 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Dec 2010 08:51:21 -0000 Author: kib Date: Sat Dec 25 08:51:20 2010 New Revision: 216695 URL: http://svn.freebsd.org/changeset/base/216695 Log: 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 , nwhitehorn (powerpc) Modified: head/libexec/rtld-elf/amd64/reloc.c head/libexec/rtld-elf/arm/reloc.c head/libexec/rtld-elf/i386/reloc.c head/libexec/rtld-elf/ia64/reloc.c head/libexec/rtld-elf/mips/reloc.c head/libexec/rtld-elf/powerpc/reloc.c head/libexec/rtld-elf/powerpc64/reloc.c head/libexec/rtld-elf/rtld.1 head/libexec/rtld-elf/rtld.c head/libexec/rtld-elf/rtld.h head/libexec/rtld-elf/rtld_lock.c head/libexec/rtld-elf/rtld_lock.h head/libexec/rtld-elf/sparc64/reloc.c Modified: head/libexec/rtld-elf/amd64/reloc.c ============================================================================== --- head/libexec/rtld-elf/amd64/reloc.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/amd64/reloc.c Sat Dec 25 08:51:20 2010 (r216695) @@ -69,23 +69,28 @@ 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 + 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) + 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" @@ -93,7 +98,7 @@ do_copy_relocations(Obj_Entry *dstobj) return -1; } - srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); + srcaddr = (const void *) (defobj->relocbase + srcsym->st_value); memcpy(dstaddr, srcaddr, size); } } @@ -113,7 +118,7 @@ init_pltgot(Obj_Entry *obj) /* Process the 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_Rela *relalim; const Elf_Rela *rela; @@ -146,7 +151,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -165,7 +170,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -195,7 +200,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -209,7 +214,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -240,7 +245,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -272,7 +277,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -286,7 +291,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -300,7 +305,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -350,7 +355,7 @@ reloc_plt(Obj_Entry *obj) /* Relocate the jump slots in an object. */ int -reloc_jmpslots(Obj_Entry *obj) +reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate) { const Elf_Rela *relalim; const Elf_Rela *rela; @@ -365,7 +370,8 @@ reloc_jmpslots(Obj_Entry *obj) assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT); where = (Elf_Addr *)(obj->relocbase + rela->r_offset); - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL); + def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL, + lockstate); if (def == NULL) return -1; target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend); Modified: head/libexec/rtld-elf/arm/reloc.c ============================================================================== --- head/libexec/rtld-elf/arm/reloc.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/arm/reloc.c Sat Dec 25 08:51:20 2010 (r216695) @@ -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, cons 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, cons 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, cons * * 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 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); Modified: head/libexec/rtld-elf/i386/reloc.c ============================================================================== --- head/libexec/rtld-elf/i386/reloc.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/i386/reloc.c Sat Dec 25 08:51:20 2010 (r216695) @@ -70,23 +70,28 @@ 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; - const Ver_Entry *ve; - Obj_Entry *srcobj; + 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)); + symlook_init(&req, name); + req.ventry = 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) + 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" @@ -94,7 +99,7 @@ do_copy_relocations(Obj_Entry *dstobj) return -1; } - srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); + srcaddr = (const void *) (defobj->relocbase + srcsym->st_value); memcpy(dstaddr, srcaddr, size); } } @@ -114,7 +119,7 @@ init_pltgot(Obj_Entry *obj) /* Process the 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; @@ -146,7 +151,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -165,7 +170,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -195,7 +200,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -213,7 +218,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -243,7 +248,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -257,7 +262,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) goto done; @@ -301,7 +306,7 @@ reloc_plt(Obj_Entry *obj) /* Relocate the jump slots in an object. */ int -reloc_jmpslots(Obj_Entry *obj) +reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate) { const Elf_Rel *rellim; const Elf_Rel *rel; @@ -316,7 +321,8 @@ reloc_jmpslots(Obj_Entry *obj) 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, NULL); + def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL, + lockstate); if (def == NULL) return -1; target = (Elf_Addr)(defobj->relocbase + def->st_value); Modified: head/libexec/rtld-elf/ia64/reloc.c ============================================================================== --- head/libexec/rtld-elf/ia64/reloc.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/ia64/reloc.c Sat Dec 25 08:51:20 2010 (r216695) @@ -151,7 +151,7 @@ free_fptrs(Obj_Entry *obj, bool mapped) /* Relocate a non-PLT object with addend. */ static int reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela, - SymCache *cache) + SymCache *cache, RtldLockState *lockstate) { struct fptr **fptrs; Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset); @@ -172,7 +172,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, O Elf_Addr target; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return -1; @@ -195,7 +195,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, O int sym_index; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - true, cache); + true, cache, lockstate); if (def == NULL) { /* * XXX r_debug_state is problematic and find_symdef() @@ -254,7 +254,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, O Elf_Addr target, gp; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return -1; @@ -277,7 +277,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, O const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return -1; @@ -290,7 +290,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, O const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return -1; @@ -303,7 +303,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, O const Obj_Entry *defobj; def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return -1; @@ -342,7 +342,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, O /* Process the 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; @@ -368,14 +368,15 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry locrela.r_info = rel->r_info; locrela.r_offset = rel->r_offset; locrela.r_addend = 0; - if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache)) + if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache, + lockstate)) goto done; } /* Perform relocations with addend if there are any: */ relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize); for (rela = obj->rela; obj->rela != NULL && rela < relalim; rela++) { - if (reloc_non_plt_obj(obj_rtld, obj, rela, cache)) + if (reloc_non_plt_obj(obj_rtld, obj, rela, cache, lockstate)) goto done; } @@ -436,7 +437,7 @@ reloc_plt(Obj_Entry *obj) /* Relocate the jump slots in an object. */ int -reloc_jmpslots(Obj_Entry *obj) +reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate) { if (obj->jmpslots_done) return 0; @@ -455,7 +456,7 @@ reloc_jmpslots(Obj_Entry *obj) assert(ELF_R_TYPE(rel->r_info) == R_IA_64_IPLTLSB); where = (Elf_Addr *)(obj->relocbase + rel->r_offset); def = find_symdef(ELF_R_SYM(rel->r_info), obj, - &defobj, true, NULL); + &defobj, true, NULL, lockstate); if (def == NULL) return -1; reloc_jmpslot(where, @@ -476,7 +477,7 @@ reloc_jmpslots(Obj_Entry *obj) where = (Elf_Addr *)(obj->relocbase + rela->r_offset); def = find_symdef(ELF_R_SYM(rela->r_info), obj, - &defobj, true, NULL); + &defobj, true, NULL, lockstate); if (def == NULL) return -1; reloc_jmpslot(where, Modified: head/libexec/rtld-elf/mips/reloc.c ============================================================================== --- head/libexec/rtld-elf/mips/reloc.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/mips/reloc.c Sat Dec 25 08:51:20 2010 (r216695) @@ -238,7 +238,8 @@ _mips_rtld_bind(Obj_Entry *obj, Elf_Size const Obj_Entry *defobj; Elf_Addr target; - def = find_symdef(reloff, obj, &defobj, SYMLOOK_IN_PLT, NULL); + def = find_symdef(reloff, obj, &defobj, SYMLOOK_IN_PLT, NULL, + NULL); if (def == NULL) _rtld_error("bind failed no symbol"); @@ -253,7 +254,7 @@ _mips_rtld_bind(Obj_Entry *obj, Elf_Size } 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 *rel; const Elf_Rel *rellim; @@ -312,7 +313,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry * to 0 if there are non-PLT references, but older * versions of GNU ld do not do this. */ - def = find_symdef(i, obj, &defobj, false, NULL); + def = find_symdef(i, obj, &defobj, false, NULL, + lockstate); if (def == NULL) return -1; *got = def->st_value + (Elf_Addr)defobj->relocbase; @@ -353,7 +355,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry } } else { /* TODO: add cache here */ - def = find_symdef(i, obj, &defobj, false, NULL); + def = find_symdef(i, obj, &defobj, false, NULL, + lockstate); if (def == NULL) { dbg("Warning4, cant find symbole %d", i); return -1; @@ -487,7 +490,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) { /* Do nothing */ obj->jmpslots_done = true; Modified: head/libexec/rtld-elf/powerpc/reloc.c ============================================================================== --- head/libexec/rtld-elf/powerpc/reloc.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/powerpc/reloc.c Sat Dec 25 08:51:20 2010 (r216695) @@ -75,12 +75,12 @@ 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 = NULL; - Obj_Entry *srcobj; - const Ver_Entry *ve; + const Obj_Entry *srcobj, *defobj; + SymLook req; + int res; if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) { continue; @@ -89,14 +89,16 @@ 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) { + res = symlook_obj(&req, srcobj); + if (res == 0) { + srcsym = req.sym_out; + defobj = req.defobj_out; break; } } @@ -108,7 +110,7 @@ do_copy_relocations(Obj_Entry *dstobj) return (-1); } - srcaddr = (const void *) (srcobj->relocbase+srcsym->st_value); + srcaddr = (const void *) (defobj->relocbase+srcsym->st_value); memcpy(dstaddr, srcaddr, size); dbg("copy_reloc: src=%p,dst=%p,size=%d\n",srcaddr,dstaddr,size); } @@ -157,7 +159,7 @@ reloc_non_plt_self(Elf_Dyn *dynp, Elf_Ad */ static int reloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela, - SymCache *cache) + SymCache *cache, RtldLockState *lockstate) { Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); const Elf_Sym *def; @@ -172,7 +174,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC_ADDR32: /* word32 S + A */ case R_PPC_GLOB_DAT: /* word32 S + A */ def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) { return (-1); } @@ -219,7 +221,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC_DTPMOD32: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return (-1); @@ -230,7 +232,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC_TPREL32: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return (-1); @@ -259,7 +261,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC_DTPREL32: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return (-1); @@ -283,7 +285,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, * 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_Rela *relalim; const Elf_Rela *rela; @@ -307,7 +309,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry */ relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize); for (rela = obj->rela; rela < relalim; rela++) { - if (reloc_nonplt_object(obj_rtld, obj, rela, cache) < 0) + if (reloc_nonplt_object(obj_rtld, obj, rela, cache, lockstate) + < 0) goto done; } r = 0; @@ -401,7 +404,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_Rela *relalim; @@ -415,7 +418,7 @@ reloc_jmpslots(Obj_Entry *obj) assert(ELF_R_TYPE(rela->r_info) == R_PPC_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) { dbg("reloc_jmpslots: sym not found"); return (-1); Modified: head/libexec/rtld-elf/powerpc64/reloc.c ============================================================================== --- head/libexec/rtld-elf/powerpc64/reloc.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/powerpc64/reloc.c Sat Dec 25 08:51:20 2010 (r216695) @@ -69,12 +69,12 @@ 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 = NULL; - Obj_Entry *srcobj; - const Ver_Entry *ve; + const Obj_Entry *srcobj, *defobj; + SymLook req; + int res; if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) { continue; @@ -83,14 +83,16 @@ 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) { + res = symlook_obj(&req, srcobj); + if (res == 0) { + srcsym = req.sym_out; + defobj = req.defobj_out; break; } } @@ -102,7 +104,7 @@ do_copy_relocations(Obj_Entry *dstobj) return (-1); } - srcaddr = (const void *) (srcobj->relocbase+srcsym->st_value); + srcaddr = (const void *) (defobj->relocbase+srcsym->st_value); memcpy(dstaddr, srcaddr, size); dbg("copy_reloc: src=%p,dst=%p,size=%zd\n",srcaddr,dstaddr,size); } @@ -151,7 +153,7 @@ reloc_non_plt_self(Elf_Dyn *dynp, Elf_Ad */ static int reloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela, - SymCache *cache) + SymCache *cache, RtldLockState *lockstate) { Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); const Elf_Sym *def; @@ -166,7 +168,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC64_ADDR64: /* doubleword64 S + A */ case R_PPC_GLOB_DAT: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) { return (-1); } @@ -213,7 +215,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC64_DTPMOD64: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return (-1); @@ -224,7 +226,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC64_TPREL64: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return (-1); @@ -253,7 +255,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, case R_PPC64_DTPREL64: def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); + false, cache, lockstate); if (def == NULL) return (-1); @@ -277,7 +279,7 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, * 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_Rela *relalim; const Elf_Rela *rela; @@ -304,7 +306,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry */ relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize); for (rela = obj->rela; rela < relalim; rela++) { - if (reloc_nonplt_object(obj_rtld, obj, rela, cache) < 0) + if (reloc_nonplt_object(obj_rtld, obj, rela, cache, lockstate) + < 0) goto done; } r = 0; @@ -376,7 +379,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_Rela *relalim; @@ -390,7 +393,7 @@ reloc_jmpslots(Obj_Entry *obj) assert(ELF_R_TYPE(rela->r_info) == R_PPC_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) { dbg("reloc_jmpslots: sym not found"); return (-1); Modified: head/libexec/rtld-elf/rtld.1 ============================================================================== --- head/libexec/rtld-elf/rtld.1 Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/rtld.1 Sat Dec 25 08:51:20 2010 (r216695) @@ -221,6 +221,14 @@ If set, .Nm will log events such as the loading and unloading of shared objects via .Xr utrace 2 . +.Pp +.It Ev LD_LOADFLTR +If set, +.Nm +will process the filtee dependencies of the loaded objects immediately, +instead of postponing it until required. +Normally, the filtees are opened at the time of the first symbol resolution +from the filter object. .El .Sh FILES .Bl -tag -width ".Pa /var/run/ld-elf32.so.hints" -compact Modified: head/libexec/rtld-elf/rtld.c ============================================================================== --- head/libexec/rtld-elf/rtld.c Sat Dec 25 08:42:38 2010 (r216694) +++ head/libexec/rtld-elf/rtld.c Sat Dec 25 08:51:20 2010 (r216695) @@ -71,16 +71,6 @@ typedef void (*func_ptr_type)(); typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); /* - * This structure provides a reentrant way to keep a list of objects and - * check which ones have already been processed in some way. - */ -typedef struct Struct_DoneList { - const Obj_Entry **objs; /* Array of object pointers */ - unsigned int num_alloc; /* Allocated size of the array */ - unsigned int num_used; /* Number of array slots used */ -} DoneList; - -/* * Function declarations. */ static const char *basename(const char *); @@ -91,6 +81,8 @@ static void digest_dynamic2(Obj_Entry *, static void digest_dynamic(Obj_Entry *, int); static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); static Obj_Entry *dlcheck(void *); +static Obj_Entry *dlopen_object(const char *name, Obj_Entry *refobj, + int lo_flags, int mode); static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); static bool donelist_check(DoneList *, const Obj_Entry *); @@ -106,12 +98,14 @@ static void initlist_add_neededs(Needed_ static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); static void linkmap_add(Obj_Entry *); static void linkmap_delete(Obj_Entry *); +static void load_filtees(Obj_Entry *, int flags, RtldLockState *); +static void unload_filtees(Obj_Entry *); static int load_needed_objects(Obj_Entry *, int); static int load_preload_objects(void); static Obj_Entry *load_object(const char *, const Obj_Entry *, int); static Obj_Entry *obj_from_addr(const void *); -static void objlist_call_fini(Objlist *, Obj_Entry *, int *); -static void objlist_call_init(Objlist *, int *); +static void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *); +static void objlist_call_init(Objlist *, RtldLockState *); static void objlist_clear(Objlist *); static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); static void objlist_init(Objlist *); @@ -119,20 +113,18 @@ static void objlist_push_head(Objlist *, static void objlist_push_tail(Objlist *, Obj_Entry *); static void objlist_remove(Objlist *, Obj_Entry *); static void *path_enumerate(const char *, path_enum_proc, void *); -static int relocate_objects(Obj_Entry *, bool, Obj_Entry *); +static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, RtldLockState *); static int rtld_dirname(const char *, char *); static int rtld_dirname_abs(const char *, char *); static void rtld_exit(void); static char *search_library_path(const char *, const char *); static const void **get_program_var_addr(const char *); static void set_program_var(const char *, const void *); -static const Elf_Sym *symlook_default(const char *, unsigned long, - const Obj_Entry *, const Obj_Entry **, const Ver_Entry *, int); -static const Elf_Sym *symlook_list(const char *, unsigned long, const Objlist *, - const Obj_Entry **, const Ver_Entry *, int, DoneList *); -static const Elf_Sym *symlook_needed(const char *, unsigned long, - const Needed_Entry *, const Obj_Entry **, const Ver_Entry *, - int, DoneList *); +static int symlook_default(SymLook *, const Obj_Entry *refobj); +static void symlook_init_from_req(SymLook *, const SymLook *); +static int symlook_list(SymLook *, const Objlist *, DoneList *); +static int symlook_needed(SymLook *, const Needed_Entry *, DoneList *); +static int symlook_obj1(SymLook *, const Obj_Entry *); static void trace_loaded_objects(Obj_Entry *); static void unlink_object(Obj_Entry *); static void unload_object(Obj_Entry *); @@ -157,6 +149,7 @@ void r_debug_state(struct r_debug *, str static char *error_message; /* Message for dlerror(), or NULL */ struct r_debug r_debug; /* for GDB; */ static bool libmap_disable; /* Disable libmap */ +static bool ld_loadfltr; /* Immediate filters processing */ static char *libmap_override; /* Maps to use in addition to libmap.conf */ static bool trust; /* False for setuid and setgid programs */ static bool dangerous_ld_env; /* True if environment variables have been @@ -300,7 +293,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ Obj_Entry *obj; Obj_Entry **preload_tail; Objlist initlist; - int lockstate; + RtldLockState lockstate; /* * On entry, the dynamic linker itself has not been relocated yet. @@ -346,7 +339,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ if (!trust) { if (unsetenv(LD_ "PRELOAD") || unsetenv(LD_ "LIBMAP") || unsetenv(LD_ "LIBRARY_PATH") || unsetenv(LD_ "LIBMAP_DISABLE") || - unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH")) { + unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH") || + unsetenv(LD_ "LOADFLTR")) { _rtld_error("environment corrupt; aborting"); die(); } @@ -357,9 +351,10 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ ld_library_path = getenv(LD_ "LIBRARY_PATH"); ld_preload = getenv(LD_ "PRELOAD"); ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH"); + ld_loadfltr = getenv(LD_ "LOADFLTR") != NULL; dangerous_ld_env = libmap_disable || (libmap_override != NULL) || (ld_library_path != NULL) || (ld_preload != NULL) || - (ld_elf_hints_path != NULL); + (ld_elf_hints_path != NULL) || ld_loadfltr; ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); ld_utrace = getenv(LD_ "UTRACE"); @@ -373,6 +368,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ dbg("RTLD dynamic = %p", obj_rtld.dynamic); dbg("RTLD pltgot = %p", obj_rtld.pltgot); + dbg("initializing thread locks"); + lockdflt_init(); + /* * Load the main program, or process its program header if it is * already loaded. @@ -498,7 +496,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ allocate_initial_tls(obj_list); if (relocate_objects(obj_main, - ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld) == -1) + ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld, NULL) == -1) die(); dbg("doing copy relocations"); @@ -515,19 +513,21 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ set_program_var("environ", env); set_program_var("__elf_aux_vector", aux); - dbg("initializing thread locks"); - lockdflt_init(); - /* Make a list of init functions to call. */ objlist_init(&initlist); initlist_add_objects(obj_list, preload_tail, &initlist); r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ - lockstate = wlock_acquire(rtld_bind_lock); + wlock_acquire(rtld_bind_lock, &lockstate); objlist_call_init(&initlist, &lockstate); objlist_clear(&initlist); - wlock_release(rtld_bind_lock, lockstate); + dbg("loading filtees"); + for (obj = obj_list->next; obj != NULL; obj = obj->next) { + if (ld_loadfltr || obj->z_loadfltr) + load_filtees(obj, 0, &lockstate); + } + lock_release(rtld_bind_lock, &lockstate); dbg("transferring control to program entry point = %p", obj_main->entry); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***