diff options
author | Logan Chien <tzuhsiang.chien@gmail.com> | 2015-07-24 00:16:48 +0000 |
---|---|---|
committer | Logan Chien <tzuhsiang.chien@gmail.com> | 2015-07-24 00:16:48 +0000 |
commit | 2d2bf2f2fb58f7114b4ab9b5714472b7884a95bc (patch) | |
tree | 2f62ae9246c27e0857e56b5985a45e8082c02643 | |
parent | 528387511deb1245bc7639ee381b0d8950375c4e (diff) | |
download | libunwind_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.h | 43 | ||||
-rw-r--r-- | src/UnwindLevel1.c | 42 |
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 - |