Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Jul 2014 22:13:28 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
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
Message-ID:  <201407192213.s6JMDSPu010186@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <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__ */
+

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_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407192213.s6JMDSPu010186>