From owner-freebsd-hackers@FreeBSD.ORG Fri Jul 18 00:17:45 2014 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 771D7F29 for ; Fri, 18 Jul 2014 00:17:45 +0000 (UTC) Received: from mho-02-ewr.mailhop.org (mho-02-ewr.mailhop.org [204.13.248.72]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 347B22149 for ; Fri, 18 Jul 2014 00:17:44 +0000 (UTC) Received: from c-50-155-136-3.hsd1.co.comcast.net ([50.155.136.3] helo=ilsoft.org) by mho-02-ewr.mailhop.org with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.72) (envelope-from ) id 1X7vrr-0000EI-Fr; Fri, 18 Jul 2014 00:17:43 +0000 Received: from [172.22.42.240] (revolution.hippie.lan [172.22.42.240]) by ilsoft.org (8.14.9/8.14.9) with ESMTP id s6I0HghC019491; Thu, 17 Jul 2014 18:17:42 -0600 (MDT) (envelope-from ian@FreeBSD.org) X-Mail-Handler: Dyn Standard SMTP by Dyn X-Originating-IP: 50.155.136.3 X-Report-Abuse-To: abuse@dyndns.com (see http://www.dyndns.com/services/sendlabs/outbound_abuse.html for abuse reporting information) X-MHO-User: U2FsdGVkX1/TukSHOQwYtUFyfgdlCyhz X-Authentication-Warning: paranoia.hippie.lan: Host revolution.hippie.lan [172.22.42.240] claimed to be [172.22.42.240] Subject: Re: [CFR] Adding a function to rtld-elf.so, how to handle Symbol.map? From: Ian Lepore To: Konstantin Belousov In-Reply-To: <20140717172910.GH93733@kib.kiev.ua> References: <1405545833.1312.84.camel@revolution.hippie.lan> <20140717004537.GE93733@kib.kiev.ua> <1405616990.1312.111.camel@revolution.hippie.lan> <20140717172910.GH93733@kib.kiev.ua> Content-Type: multipart/mixed; boundary="=-9/8rZe+d9rK3teh1VWmm" Date: Thu, 17 Jul 2014 18:17:41 -0600 Message-ID: <1405642661.1312.135.camel@revolution.hippie.lan> Mime-Version: 1.0 X-Mailer: Evolution 2.32.1 FreeBSD GNOME Team Port Cc: hackers@freebsd.org X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Jul 2014 00:17:45 -0000 --=-9/8rZe+d9rK3teh1VWmm Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit On Thu, 2014-07-17 at 20:29 +0300, Konstantin Belousov wrote: > On Thu, Jul 17, 2014 at 11:09:50AM -0600, Ian Lepore wrote: > > On Thu, 2014-07-17 at 03:45 +0300, Konstantin Belousov wrote: > > > On Wed, Jul 16, 2014 at 03:23:53PM -0600, Ian Lepore wrote: > > [snip] > > I did some looking around and Netbsd, Android, and Risc Os all > > implemented this in their dynamic loaders, so that seemed like the way > > to go. Android actually puts a function with this __gnu name in its > > libc, but all that function does is calls dl_unwind_find_exidx() which > > is implemented in their loader. > > > > I've just discovered that the arm unwind support code that will arrive > > as part of clang 3.5 appears to assume the Android way of things unless > > __LINUX__ is defined, so maybe it would be good to follow that model > > ourselves and add a dl_unwind_find_exidx() stub to libc/gen/dlfcn.c and > > name the new implementation in ld-elf to match. > I think that Android/__LINUX__ combination does the right thing, by > providing the symbol in libc. A libc implementation does not need any > additional service from rtld, except already existing _rtld_addr_phdr(). > Android provides a stub of dl_unwind_find_exidx() in libdl and the shared-object implementation in the dynamic linker. What it puts in libc is the __gnu_Unwind_Find_exidx() symbol, which just calls through to the dl_unwind_find_exidx() implementation in the dynamic linker. That aside, I've reworked my code so it all lives in libc instead of rtld, as you suggested. It seems to work fine, and I guess I'm agnostic about whether we're exporting a new function from libc versus rtld. It seems a bit strange to me to have just one dl_something() function with its shared/dynamic implementation in libc, while all the other functions with dl-prefix names are implemented in rtld. But not so weird that it's a big deal. -- Ian --=-9/8rZe+d9rK3teh1VWmm Content-Disposition: inline; filename="find_exidx3.diff" Content-Type: text/x-patch; name="find_exidx3.diff"; charset="us-ascii" Content-Transfer-Encoding: 7bit diff -r 63a383d5fd3e lib/libc/arm/Symbol.map --- lib/libc/arm/Symbol.map Thu May 01 08:14:39 2014 -0600 +++ lib/libc/arm/Symbol.map Thu Jul 17 17:49:52 2014 -0600 @@ -37,6 +37,11 @@ FBSD_1.3 { __flt_rounds; }; +FBSD_1.4 { + __gnu_Unwind_Find_exidx; + dl_unwind_find_exidx; +}; + FBSDprivate_1.0 { /* PSEUDO syscalls */ __sys_getlogin; diff -r 63a383d5fd3e lib/libc/arm/aeabi/Makefile.inc --- lib/libc/arm/aeabi/Makefile.inc Thu May 01 08:14:39 2014 -0600 +++ lib/libc/arm/aeabi/Makefile.inc Thu Jul 17 17:49:52 2014 -0600 @@ -3,7 +3,8 @@ .PATH: ${LIBC_SRCTOP}/arm/aeabi SRCS+= aeabi_atexit.c \ - aeabi_unwind_cpp.c + aeabi_unwind_cpp.c \ + aeabi_unwind_exidx.c .if ${MACHINE_ARCH} != "armv6hf" SRCS+= aeabi_double.c \ aeabi_float.c diff -r 63a383d5fd3e lib/libc/arm/aeabi/aeabi_unwind_exidx.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ lib/libc/arm/aeabi/aeabi_unwind_exidx.c Thu Jul 17 17:49:52 2014 -0600 @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2014 Ian Lepore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +/* + * ARM EABI unwind helper. + * + * This finds the exidx section address and size associated with a given code + * address. There are separate implementations for static and dynamic code. + * + * GCC expects this function to exist as __gnu_Unwind_Find_exidx(), clang and + * BSD tools expect it to be dl_unwind_find_exidx(). Both have the same API, so + * we set up an alias for GCC. + */ +__strong_reference(dl_unwind_find_exidx, __gnu_Unwind_Find_exidx); + +/* + * Each entry in the exidx section is a pair of 32-bit words. We don't + * interpret the contents of the entries here; this typedef is just a local + * convenience for using sizeof() and doing pointer math. + */ +typedef struct exidx_entry { + uint32_t data[2]; +} exidx_entry; + +#ifdef __PIC__ + +/* + * Unwind helper for dynamically linked code. + * + * This finds the shared object that contains the given address, and returns the + * address of the exidx section in that shared object along with the number of + * entries in that section, or NULL if it wasn't found. + */ +void * +dl_unwind_find_exidx(const void *pc, int *pcount) +{ + const Elf_Phdr *hdr; + struct dl_phdr_info info; + int i; + + if (_rtld_addr_phdr(pc, &info)) { + hdr = info.dlpi_phdr; + for (i = 0; i < info.dlpi_phnum; i++, hdr++) { + if (hdr->p_type == PT_ARM_EXIDX) { + *pcount = hdr->p_memsz / (sizeof(exidx_entry)); + return ((void *)(info.dlpi_addr + hdr->p_vaddr)); + } + } + } + return (NULL); +} + +#else /* !__PIC__ */ + +/* + * Unwind helper for statically linked code. + * + * In a statically linked program, the linker populates a pair of symbols with + * the addresses of the start and end of the exidx table, so returning the + * address and count of elements is pretty straighforward. + */ +void * +dl_unwind_find_exidx(const void *pc, int *pcount) +{ + extern struct exidx_entry __exidx_start; + extern struct exidx_entry __exidx_end; + + *pcount = (int)(&__exidx_end - &__exidx_start); + return (&__exidx_start); +} + +#endif /* __PIC__ */ + diff -r 63a383d5fd3e sys/arm/include/elf.h --- sys/arm/include/elf.h Thu May 01 08:14:39 2014 -0600 +++ sys/arm/include/elf.h Thu Jul 17 17:49:52 2014 -0600 @@ -55,6 +55,9 @@ typedef struct { /* Auxiliary vec #define ELF_MACHINE_OK(x) ((x) == EM_ARM) +/* Unwind info section type */ +#define PT_ARM_EXIDX (PT_LOPROC + 1) + /* * Relocation types. */ diff -r 63a383d5fd3e sys/sys/link_elf.h --- sys/sys/link_elf.h Thu May 01 08:14:39 2014 -0600 +++ sys/sys/link_elf.h Thu Jul 17 17:49:52 2014 -0600 @@ -95,6 +95,10 @@ extern int dl_iterate_phdr(__dl_iterate_ int _rtld_addr_phdr(const void *, struct dl_phdr_info *); int _rtld_get_stack_prot(void); +#ifdef __ARM_EABI__ +void * dl_unwind_find_exidx(const void *, int *); +#endif + __END_DECLS #endif /* _SYS_LINK_ELF_H_ */ --=-9/8rZe+d9rK3teh1VWmm--