[libcxxabi] r228903 - unwind: move exported APIs out of header

Saleem Abdulrasool compnerd at compnerd.org
Tue Mar 17 19:14:51 PDT 2015


On Tue, Mar 17, 2015 at 10:42 AM, Logan Chien <tzuhsiang.chien at gmail.com>
wrote:

> Hi Saleem,
>
> > Why would libc++abi have undefined references, it it doesn't use the
> functions?
>
> Short answer:
>
> The libc++abi library does use these functions (see
> src/cxa_personality.cpp.)  However, it expect that these functions have to
> be replaced with (or inlined as) _Unwind_VRS_{Get,Set}().  After this
> commit, it will simply leave an external function call which will lead to
> an undefined reference.
>

Ah; okay, so as I mentioned in the commit, we really do need to figure out
a way to do the equivalent of __declspec(dllexport) inline, that is, we
need both the inlined verison as well as an external version.


> Long answer:
>
> AFAIK, ARM EHABI [1] and Itanium C++ ABI [2] are independently developed.
> Thus, ARM EHABI is slightly different from Itanium C++ ABI and having
> different language independent unwinder API.  That's the reason why
> _Unwind_{Get,Set}{IP,GR} are not available in the
>

Yes, this is correct.  They were independently designed.  However,
libunwind needs to provider the *libunwind* interfaces.  It can extend that
with the EHABI interfaces as well.  In the case of EHABI, it could use the
EHABI interfaces to reimplement the functionality.


> On the other hand, many developers wish to port their existing code base
> to ARM without wrapping their function calls to _Unwind_{Get,Set}{IP,GR}()
> with sandwich-like #ifdef directives, thus the inline functions are added
> to the <unwind.h> header [3].  Although new functions are added to the
> header, they will be inlined and replaced properly so that the ported
> applications can still be linked with the old libgcc prebuilt binaries.  On
> the contrary, this commit (r228903) will only declare these functions as
> external functions, thus the compiler will simply emit an undefined
> reference to _Unwind_{Get,Set}{IP,GR}().  Consequently, the ported
> application won't link with libgcc anymore.
>

On the other hand, when applications are using the interfaces, expecting
the unwind APIs, I think that they should continue to function.  Providing
both the external as well as the inlined version should achieve that.


> What make the situation even worse is that the <unwind.h> from libc++abi
> will be installed (and overwrite the one from <clang>/lib/Headers/unwind.h)
> if we are running an in-tree build.  The <unwind.h> from libc++abi will be
> chosen when we are compiling source code with clang.  As a result, all of
> _Unwind_{Get,Set}{IP,GR}() will become an external reference.  Even if we
> would like to compile the source code with libstdc++v3 (the GCC STL
> implementation), the external reference will be generated as well.
>
> To wrap up, I think we should bring the inline function back at least.
> Otherwise, the libgcc support will be completely unusable in the
> arm-linux-gnueabi architecture.  Whether should we provide an
> implementation _Unwind_{Get,Set}{IP,GR}() in the libunwind or not is
> another question, although I personally disagree with this idea due to
> other reasons.  Feel free to let me know have any other questions.  Thanks.
>

I think we agree on the fact that we need the inline version as well given
your explanation.  However, I think that we need both the inlined version
as well as the exported version.


> Sincerely,
> Logan
>
> [1]
> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
> [2] https://mentorembedded.github.io/cxx-abi/abi-eh.html
> [3] Note that _Unwind_{Get,Set}GR is not a complete replacement for
> _Unwind_VRS_{Get,Set} anyway.  For example, VFP registers can't be accessed
> with _Unwind_{Get,Set}GR().
>
> On Tue, Mar 17, 2015 at 10:34 AM, Saleem Abdulrasool <
> compnerd at compnerd.org> wrote:
>
>> On Sat, Mar 14, 2015 at 8:43 AM, Logan Chien <tzuhsiang.chien at gmail.com>
>> wrote:
>>
>>> Hi Saleem,
>>>
>>> Similar change has been committed and reverted (see r219629 and r226818.)
>>>
>>> This change WILL BREAK the libc++abi + libgcc build.  With this change,
>>> the libc++abi shared library will come with undefined references to
>>> _Unwind_{Get,Set}{IP,GR}, which are not available in libgcc.
>>>
>>> AFAICT, these functions are not a part of public interface of ARM
>>> EHABI.  The only documented public interface is
>>> _Unwind_VRS_Get/_Unwind_VRS_Set.  Even though, most existing
>>> implementations, including the unwind.h shipped with gcc and clang, define
>>> these inline functions.  But none of them will lead to an external
>>> reference to _Unwind_{Get,Set}{IP,GR}.
>>>
>>
>> They aren't part of the EHABI, but are part of the Unwind (public)
>> interfaces.  I do think that they need to be made available, even if in an
>> alternate form.  Why would libc++abi have undefined references, it it
>> doesn't use the functions?
>>
>>
>>> Would you mind to revert this change?  Or, is there any other situation,
>>> which requires this change, that I haven't considered?  Thanks.
>>>
>>> Sincerely,
>>> Logan
>>>
>>>
>>> On Thu, Feb 12, 2015 at 12:25 PM, Saleem Abdulrasool <
>>> compnerd at compnerd.org> wrote:
>>>
>>>> Author: compnerd
>>>> Date: Wed Feb 11 22:25:03 2015
>>>> New Revision: 228903
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=228903&view=rev
>>>> Log:
>>>> unwind: move exported APIs out of header
>>>>
>>>> Ideally, we would do something like inline __declspec(dllexport) to
>>>> ensure that
>>>> the symbol was inlined within libunwind as well as emitted into the
>>>> final DSO.
>>>> This simply moves the definition out of the header to ensure that the
>>>> *public*
>>>> interfaces are defined and exported into the final DSO.
>>>>
>>>> This change also has "gratuitous" code movement so that the EHABI and
>>>> generic
>>>> implementations are co-located making it easier to find them.
>>>>
>>>> The movement from the header has one minor change introduced into the
>>>> code:
>>>> additional tracing to mirror the behaviour of the non-EHABI interfaces.
>>>>
>>>> Modified:
>>>>     libcxxabi/trunk/include/unwind.h
>>>>     libcxxabi/trunk/src/Unwind/UnwindLevel1.c
>>>>
>>>> Modified: libcxxabi/trunk/include/unwind.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/include/unwind.h?rev=228903&r1=228902&r2=228903&view=diff
>>>>
>>>> ==============================================================================
>>>> --- libcxxabi/trunk/include/unwind.h (original)
>>>> +++ libcxxabi/trunk/include/unwind.h Wed Feb 11 22:25:03 2015
>>>> @@ -202,37 +202,13 @@ extern _Unwind_VRS_Result
>>>>  _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass
>>>> regclass,
>>>>                  uint32_t discriminator,
>>>>                  _Unwind_VRS_DataRepresentation representation);
>>>> +#endif
>>>>
>>>> -static inline 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;
>>>> -}
>>>> -
>>>> -static inline void _Unwind_SetGR(struct _Unwind_Context* context, int
>>>> index,
>>>> -                                 uintptr_t new_value) {
>>>> -  _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index,
>>>> -                  _UVRSD_UINT32, &new_value);
>>>> -}
>>>> -
>>>> -static inline uintptr_t _Unwind_GetIP(struct _Unwind_Context* context)
>>>> {
>>>> -  // remove the thumb-bit before returning
>>>> -  return (_Unwind_GetGR(context, 15) & (~(uintptr_t)0x1));
>>>> -}
>>>> -
>>>> -static inline void _Unwind_SetIP(struct _Unwind_Context* context,
>>>> -                                 uintptr_t new_value) {
>>>> -  uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
>>>> -  _Unwind_SetGR(context, 15, new_value | thumb_bit);
>>>> -}
>>>> -#else
>>>>  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);
>>>> -#endif
>>>>
>>>>  extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context
>>>> *context);
>>>>  extern uintptr_t
>>>>
>>>> Modified: libcxxabi/trunk/src/Unwind/UnwindLevel1.c
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/Unwind/UnwindLevel1.c?rev=228903&r1=228902&r2=228903&view=diff
>>>>
>>>> ==============================================================================
>>>> --- libcxxabi/trunk/src/Unwind/UnwindLevel1.c (original)
>>>> +++ libcxxabi/trunk/src/Unwind/UnwindLevel1.c Wed Feb 11 22:25:03 2015
>>>> @@ -422,10 +422,73 @@ _Unwind_GetLanguageSpecificData(struct _
>>>>  }
>>>>
>>>>
>>>> +/// Called by personality handler during phase 2 to find the start of
>>>> the
>>>> +/// function.
>>>> +_LIBUNWIND_EXPORT uintptr_t
>>>> +_Unwind_GetRegionStart(struct _Unwind_Context *context) {
>>>> +  unw_cursor_t *cursor = (unw_cursor_t *)context;
>>>> +  unw_proc_info_t frameInfo;
>>>> +  uintptr_t result = 0;
>>>> +  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
>>>> +    result = (uintptr_t)frameInfo.start_ip;
>>>> +  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%"
>>>> PRIxPTR "\n",
>>>> +                       (void *)context, result);
>>>> +  return result;
>>>> +}
>>>> +
>>>> +
>>>> +/// Called by personality handler during phase 2 if a foreign exception
>>>> +// is caught.
>>>> +_LIBUNWIND_EXPORT void
>>>> +_Unwind_DeleteException(_Unwind_Exception *exception_object) {
>>>> +  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
>>>> +                       (void *)exception_object);
>>>> +  if (exception_object->exception_cleanup != NULL)
>>>> +
>>>> (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
>>>> +                                           exception_object);
>>>> +}
>>>> +
>>>> +#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI
>>>> +
>>>> +#if LIBCXXABI_ARM_EHABI
>>>> +
>>>> +_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);
>>>> +}
>>>> +
>>>> +#else
>>>>
>>>>  /// Called by personality handler during phase 2 to get register
>>>> values.
>>>> -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context
>>>> *context,
>>>> -                                          int index) {
>>>> +_LIBUNWIND_EXPORT uintptr_t
>>>> +_Unwind_GetGR(struct _Unwind_Context *context, int index) {
>>>>    unw_cursor_t *cursor = (unw_cursor_t *)context;
>>>>    unw_word_t result;
>>>>    unw_get_reg(cursor, index, &result);
>>>> @@ -434,20 +497,16 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetG
>>>>    return (uintptr_t)result;
>>>>  }
>>>>
>>>> -
>>>> -
>>>>  /// Called by personality handler during phase 2 to alter register
>>>> values.
>>>>  _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context,
>>>> int index,
>>>> -                                     uintptr_t new_value) {
>>>> +                                     uintptr_t value) {
>>>>    _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0"
>>>> PRIx64
>>>>                         ")\n",
>>>> -                       (void *)context, index, (uint64_t)new_value);
>>>> +                       (void *)context, index, (uint64_t)value);
>>>>    unw_cursor_t *cursor = (unw_cursor_t *)context;
>>>> -  unw_set_reg(cursor, index, new_value);
>>>> +  unw_set_reg(cursor, index, value);
>>>>  }
>>>>
>>>> -
>>>> -
>>>>  /// Called by personality handler during phase 2 to get instruction
>>>> pointer.
>>>>  _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context
>>>> *context) {
>>>>    unw_cursor_t *cursor = (unw_cursor_t *)context;
>>>> @@ -458,44 +517,16 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetI
>>>>    return (uintptr_t)result;
>>>>  }
>>>>
>>>> -
>>>> -
>>>>  /// Called by personality handler during phase 2 to alter instruction
>>>> pointer,
>>>>  /// such as setting where the landing pad is, so _Unwind_Resume() will
>>>>  /// start executing in the landing pad.
>>>>  _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
>>>> -                                     uintptr_t new_value) {
>>>> +                                     uintptr_t value) {
>>>>    _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64
>>>> ")\n",
>>>> -                       (void *)context, (uint64_t)new_value);
>>>> +                       (void *)context, (uint64_t)value);
>>>>    unw_cursor_t *cursor = (unw_cursor_t *)context;
>>>> -  unw_set_reg(cursor, UNW_REG_IP, new_value);
>>>> +  unw_set_reg(cursor, UNW_REG_IP, value);
>>>>  }
>>>>
>>>> +#endif
>>>>
>>>> -/// Called by personality handler during phase 2 to find the start of
>>>> the
>>>> -/// function.
>>>> -_LIBUNWIND_EXPORT uintptr_t
>>>> -_Unwind_GetRegionStart(struct _Unwind_Context *context) {
>>>> -  unw_cursor_t *cursor = (unw_cursor_t *)context;
>>>> -  unw_proc_info_t frameInfo;
>>>> -  uintptr_t result = 0;
>>>> -  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
>>>> -    result = (uintptr_t)frameInfo.start_ip;
>>>> -  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%"
>>>> PRIxPTR "\n",
>>>> -                       (void *)context, result);
>>>> -  return result;
>>>> -}
>>>> -
>>>> -
>>>> -/// Called by personality handler during phase 2 if a foreign exception
>>>> -// is caught.
>>>> -_LIBUNWIND_EXPORT void
>>>> -_Unwind_DeleteException(_Unwind_Exception *exception_object) {
>>>> -  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
>>>> -                       (void *)exception_object);
>>>> -  if (exception_object->exception_cleanup != NULL)
>>>> -
>>>> (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
>>>> -                                           exception_object);
>>>> -}
>>>> -
>>>> -#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI
>>>>
>>>>
>>>> _______________________________________________
>>>> cfe-commits mailing list
>>>> cfe-commits at cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>>>
>>>
>>>
>>
>>
>> --
>> Saleem Abdulrasool
>> compnerd (at) compnerd (dot) org
>>
>
>


-- 
Saleem Abdulrasool
compnerd (at) compnerd (dot) org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150317/1edbfc96/attachment.html>


More information about the cfe-commits mailing list