diff options
author | ian <ian@FreeBSD.org> | 2014-08-10 22:26:29 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-08-10 22:26:29 +0000 |
commit | a08c00a48a5c0420f98f35d1f33701493c0a3fe8 (patch) | |
tree | 19f035de77ecff371630b14c3582ddd82ed35557 /lib/libc/arm | |
parent | d996016e8763e29196febcff200732accf30a288 (diff) | |
download | FreeBSD-src-a08c00a48a5c0420f98f35d1f33701493c0a3fe8.zip FreeBSD-src-a08c00a48a5c0420f98f35d1f33701493c0a3fe8.tar.gz |
MFC r268993, r268893, r268994, plus partial r264070, r264082
Fix C++ exception handling for ARM EABI.
Just the part of r264070 that creates the FBSD_1.4 namespace in libc
is hand-applied, and then r264082 which creates the Versions.def entry
is MFC'd.
Diffstat (limited to 'lib/libc/arm')
-rw-r--r-- | lib/libc/arm/Symbol.map | 5 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/Makefile.inc | 3 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_unwind_exidx.c | 104 |
3 files changed, 111 insertions, 1 deletions
diff --git a/lib/libc/arm/Symbol.map b/lib/libc/arm/Symbol.map index a58d443..cf65492 100644 --- a/lib/libc/arm/Symbol.map +++ b/lib/libc/arm/Symbol.map @@ -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 --git a/lib/libc/arm/aeabi/Makefile.inc b/lib/libc/arm/aeabi/Makefile.inc index a42831d..b9fd3c0 100644 --- a/lib/libc/arm/aeabi/Makefile.inc +++ b/lib/libc/arm/aeabi/Makefile.inc @@ -5,7 +5,8 @@ SRCS+= aeabi_atexit.c \ aeabi_double.c \ aeabi_float.c \ - aeabi_unwind_cpp.c + aeabi_unwind_cpp.c \ + aeabi_unwind_exidx.c .if ${MACHINE_ARCH:Marmv6*} SRCS+= aeabi_vfp_double.S \ aeabi_vfp_float.S diff --git a/lib/libc/arm/aeabi/aeabi_unwind_exidx.c b/lib/libc/arm/aeabi/aeabi_unwind_exidx.c new file mode 100644 index 0000000..d5af8b3 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_unwind_exidx.c @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2014 Ian Lepore <ian@freebsd.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <machine/elf.h> +#include <link.h> +#include <stddef.h> + +/* + * 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__ */ + |