From patchwork Wed Jul 4 15:55:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Christophe Lyon X-Patchwork-Id: 939450 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=uclibc-ng.org (client-ip=2a00:1828:2000:679::23; helo=helium.openadk.org; envelope-from=devel-bounces@uclibc-ng.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=st.com Received: from helium.openadk.org (helium.openadk.org [IPv6:2a00:1828:2000:679::23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41LQgm19ngz9s4c for ; Thu, 5 Jul 2018 02:00:36 +1000 (AEST) Received: from helium.openadk.org (localhost [IPv6:::1]) by helium.openadk.org (Postfix) with ESMTP id B469710569; Wed, 4 Jul 2018 18:00:33 +0200 (CEST) X-Original-To: devel@uclibc-ng.org Delivered-To: devel@helium.openadk.org Received: from mx07-00178001.pphosted.com (mx08-00178001.pphosted.com [91.207.212.93]) by helium.openadk.org (Postfix) with ESMTPS id BCB4010569 for ; Wed, 4 Jul 2018 18:00:32 +0200 (CEST) Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w64G0Dsq007978; Wed, 4 Jul 2018 18:00:32 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2k0dnwvrem-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 04 Jul 2018 18:00:32 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 857A031; Wed, 4 Jul 2018 16:00:26 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node1.st.com [10.75.127.13]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6E8362C3AB; Wed, 4 Jul 2018 16:00:26 +0000 (GMT) Received: from gnb.st.com (10.75.127.44) by SFHDAG5NODE1.st.com (10.75.127.13) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 4 Jul 2018 18:00:25 +0200 From: Christophe Lyon To: , Date: Wed, 4 Jul 2018 17:55:24 +0200 Message-ID: <20180704155605.1892-12-christophe.lyon@st.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20180704155605.1892-1-christophe.lyon@st.com> References: <20180704155605.1892-1-christophe.lyon@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.44] X-ClientProxiedBy: SFHDAG6NODE2.st.com (10.75.127.17) To SFHDAG5NODE1.st.com (10.75.127.13) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-07-04_06:, , signatures=0 Subject: [uclibc-ng-devel] [PATCH 11/32] [ARM][FDPIC] rtld: Add lazy binding support X-BeenThere: devel@uclibc-ng.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: uClibc-ng Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: devel-bounces@uclibc-ng.org Sender: "devel" Add support for R_ARM_FUNCDESC_VALUE and implement _dl_linux_resolver for FDPIC on ARM. * ldso/ldso/arm/elfinterp.c (_dl_linux_resolver): Support __FDPIC__. (_dl_do_lazy_reloc): Likewise. * ldso/ldso/arm/resolve.S (_dl_linux_resolve): Likewise. Signed-off-by: Mickaël Guêné Signed-off-by: Christophe Lyon Signed-off-by: Mickaël Guêné Signed-off-by: Christophe Lyon diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index 1435c2c..3bcd675 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -34,13 +34,69 @@ extern int _dl_linux_resolve(void); -unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) -{ #if __FDPIC__ - /* FIXME: implement. */ - while(1) ; - return 0; +unsigned long _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_offet) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + struct funcdesc_value funcval; + struct funcdesc_value volatile *got_entry; + char *symname; + struct symbol_ref sym_ref; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_offet); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname= strtab + symtab[symtab_index].st_name; + + /* Address of GOT entry fix up */ + got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset); + + /* Get the address to be used to fill in the GOT entry. */ + new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, 0, &sym_ref); + if (!new_addr) { + new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref); + if (!new_addr) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + } + + funcval.entry_point = new_addr; + funcval.got_value = sym_ref.tpnt->loadaddr.got_value; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n", + got_entry->entry_point, got_entry->got_value, + funcval.entry_point, funcval.got_value, + got_entry); + } + if (1 || !_dl_debug_nofixups) { + *got_entry = funcval; + } +#else + *got_entry = funcval; +#endif + + return got_entry; +} #else +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ ELF_RELOC *this_reloc; char *strtab; char *symname; @@ -93,8 +149,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) #endif return new_addr; -#endif } +#endif static int _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope, @@ -346,7 +402,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, int reloc_type; unsigned long *reloc_addr; - reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); reloc_type = ELF_R_TYPE(rpnt->r_info); #if defined (__SUPPORT_LD_DEBUG__) @@ -356,8 +412,17 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, switch (reloc_type) { case R_ARM_NONE: break; + case R_ARM_JUMP_SLOT: - *reloc_addr += (unsigned long) tpnt->loadaddr; + *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, *reloc_addr); + break; + case R_ARM_FUNCDESC_VALUE: + { + struct funcdesc_value *dst = (struct funcdesc_value *) reloc_addr; + + dst->entry_point = DL_RELOC_ADDR(tpnt->loadaddr, dst->entry_point); + dst->got_value = tpnt->loadaddr.got_value; + } break; default: return -1; /*call _dl_exit(1) */ diff --git a/ldso/ldso/arm/resolve.S b/ldso/ldso/arm/resolve.S index 2a51643..039a6b7 100644 --- a/ldso/ldso/arm/resolve.S +++ b/ldso/ldso/arm/resolve.S @@ -107,6 +107,27 @@ .type _dl_linux_resolve,%function .align 4; +#if __FDPIC__ +/* + * _dl_linux_resolve() FDPIC version receives the following parameters from + * lazy PLT entry: + * R12: GOT address for the resolver GOT + * SP[0]: funcdesc_value_reloc_offset(foo) + * R9: GOT address for the caller GOT + * _dl_linux_resolver() will return a function descriptor address in R0. + */ +_dl_linux_resolve: + push {r0, r1, r2, r3, r14} + ldr r0, [r9, #8] + ldr r1, [sp, #20] + mov r9, r12 + blx _dl_linux_resolver + ldr r9, [r0, #4] + ldr r12, [r0] + pop {r0, r1, r2, r3, r14} + add sp, sp, #4 + bx r12 +#else _dl_linux_resolve: @ _dl_linux_resolver is a standard subroutine call, therefore it @ preserves everything except r0-r3 (a1-a4), ip and lr. This @@ -129,6 +150,7 @@ _dl_linux_resolve: ldmia sp!, {r0, r1, r2, r3, r4, lr} BX(ip) +#endif /* __FDPIC__ */ #else @ In the thumb case _dl_linux_resolver is thumb. If a bl is used @ from arm code the linker will insert a stub call which, with