summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLogan Chien <tzuhsiang.chien@gmail.com>2015-07-24 00:16:48 +0000
committerLogan Chien <tzuhsiang.chien@gmail.com>2015-07-24 00:16:48 +0000
commit2d2bf2f2fb58f7114b4ab9b5714472b7884a95bc (patch)
tree2f62ae9246c27e0857e56b5985a45e8082c02643
parent528387511deb1245bc7639ee381b0d8950375c4e (diff)
downloadlibunwind_llvm-2d2bf2f2fb58f7114b4ab9b5714472b7884a95bc.tar.gz
unwind: Fix libc++abi and libgcc build.
To build libc++abi without libunwind, we should make sure that all function calls to _Unwind_{Get,Set}{GR,IP}() are inlined as function calls to _Unwind_VRS_{Get,Set}(). Otherwise, libc++abi.so will fail to link since libgcc does not provide these symbol at all. This commit fixes the problem by providing both the inlined version and exported version. git-svn-id: https://llvm.org/svn/llvm-project/libunwind/trunk@243073 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/unwind.h43
-rw-r--r--src/UnwindLevel1.c42
2 files changed, 50 insertions, 35 deletions
diff --git a/include/unwind.h b/include/unwind.h
index 31fb871..94880bf 100644
--- a/include/unwind.h
+++ b/include/unwind.h
@@ -204,12 +204,55 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
_Unwind_VRS_DataRepresentation representation);
#endif
+#if !_LIBUNWIND_ARM_EHABI
+
extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value);
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
+#else // _LIBUNWIND_ARM_EHABI
+
+#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
+#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
+#else
+#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
+#endif
+
+// These are de facto helper functions for ARM, which delegate the function
+// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI
+// specification, thus these function MUST be inlined. Please don't replace
+// these with the "extern" function declaration; otherwise, the program
+// including this <unwind.h> header won't be ABI compatible and will result in
+// link error when we are linking the program with libgcc.
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
+ uintptr_t value = 0;
+ _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
+ return value;
+}
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+void _Unwind_SetGR(struct _Unwind_Context *context, int index,
+ uintptr_t value) {
+ _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
+}
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
+ // remove the thumb-bit before returning
+ return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1);
+}
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
+ uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
+ _Unwind_SetGR(context, 15, value | thumb_bit);
+}
+#endif // _LIBUNWIND_ARM_EHABI
+
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context);
extern uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
diff --git a/src/UnwindLevel1.c b/src/UnwindLevel1.c
index caef0cf..ce6eb28 100644
--- a/src/UnwindLevel1.c
+++ b/src/UnwindLevel1.c
@@ -12,6 +12,13 @@
//
//===----------------------------------------------------------------------===//
+// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are
+// defining inline functions to delegate the function calls to
+// _Unwind_VRS_{Get,Set}(). However, some applications might declare the
+// function protetype directly (instead of including <unwind.h>), thus we need
+// to export these functions from libunwind.so as well.
+#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
+
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
@@ -496,39 +503,4 @@ _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
unw_set_reg(cursor, UNW_REG_IP, value);
}
-#else
-
-_LIBUNWIND_EXPORT uintptr_t
-_Unwind_GetGR(struct _Unwind_Context *context, int index) {
- uintptr_t value = 0;
- _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
- _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n",
- (void *)context, index, (uint64_t)value);
- return value;
-}
-
-_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
- uintptr_t value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0"PRIx64")\n",
- (void *)context, index, (uint64_t)value);
- _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
-}
-
-_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
- // remove the thumb-bit before returning
- uintptr_t value = _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1);
- _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n",
- (void *)context, (uint64_t)value);
- return value;
-}
-
-_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
- uintptr_t value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n",
- (void *)context, (uint64_t)value);
- uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
- _Unwind_SetGR(context, 15, value | thumb_bit);
-}
-
#endif // !_LIBUNWIND_ARM_EHABI
-