From owner-svn-src-head@FreeBSD.ORG Sat Jul 19 22:13:29 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 2EAD3337; Sat, 19 Jul 2014 22:13:29 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1A9A223E8; Sat, 19 Jul 2014 22:13:29 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JMDSqK010195; Sat, 19 Jul 2014 22:13:28 GMT (envelope-from ian@svn.freebsd.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JMDSPu010186; Sat, 19 Jul 2014 22:13:28 GMT (envelope-from ian@svn.freebsd.org) Message-Id: <201407192213.s6JMDSPu010186@svn.freebsd.org> From: Ian Lepore Date: Sat, 19 Jul 2014 22:13:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r268893 - in head: lib/libc/arm lib/libc/arm/aeabi sys/arm/include sys/sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 22:13:29 -0000 Author: ian Date: Sat Jul 19 22:13:27 2014 New Revision: 268893 URL: http://svnweb.freebsd.org/changeset/base/268893 Log: Add dl_unwind_find_exidx() for ARM EABI, required for C++ exception handling. For statically linked apps this uses the __exidx_start/end symbols set up by the linker. For dynamically linked apps it finds the shared object that contains the given address and returns the location and size of the exidx section in that shared object. The dl_unwind_find_exidx() name is used by other BSD projects and Android, and is mentioned in clang 3.5 comments as "the BSD interface" for finding exidx data. GCC (in libgcc_s) expects the exact same API and functionality to be provided by a function named __gnu_Unwind_Find_exidx(), so we provide that with an alias ("strong reference"). Reviewed by: kib@ MFC after: 1 week Added: head/lib/libc/arm/aeabi/aeabi_unwind_exidx.c (contents, props changed) Modified: head/lib/libc/arm/Symbol.map head/lib/libc/arm/aeabi/Makefile.inc head/sys/arm/include/elf.h head/sys/sys/link_elf.h Modified: head/lib/libc/arm/Symbol.map ============================================================================== --- head/lib/libc/arm/Symbol.map Sat Jul 19 22:13:12 2014 (r268892) +++ head/lib/libc/arm/Symbol.map Sat Jul 19 22:13:27 2014 (r268893) @@ -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; Modified: head/lib/libc/arm/aeabi/Makefile.inc ============================================================================== --- head/lib/libc/arm/aeabi/Makefile.inc Sat Jul 19 22:13:12 2014 (r268892) +++ head/lib/libc/arm/aeabi/Makefile.inc Sat Jul 19 22:13:27 2014 (r268893) @@ -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 Added: head/lib/libc/arm/aeabi/aeabi_unwind_exidx.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/lib/libc/arm/aeabi/aeabi_unwind_exidx.c Sat Jul 19 22:13:27 2014 (r268893) @@ -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__ */ + Modified: head/sys/arm/include/elf.h ============================================================================== --- head/sys/arm/include/elf.h Sat Jul 19 22:13:12 2014 (r268892) +++ head/sys/arm/include/elf.h Sat Jul 19 22:13:27 2014 (r268893) @@ -55,6 +55,9 @@ __ElfType(Auxinfo); #define ELF_MACHINE_OK(x) ((x) == EM_ARM) +/* Unwind info section type */ +#define PT_ARM_EXIDX (PT_LOPROC + 1) + /* * Relocation types. */ Modified: head/sys/sys/link_elf.h ============================================================================== --- head/sys/sys/link_elf.h Sat Jul 19 22:13:12 2014 (r268892) +++ head/sys/sys/link_elf.h Sat Jul 19 22:13:27 2014 (r268893) @@ -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_ */