From 189d498f5c0c633f8cd87b3f1b6d57020371a952 Mon Sep 17 00:00:00 2001
From: Stephan Bergmann <sbergman@redhat.com>
Date: Tue, 17 Dec 2019 23:33:28 +0100
Subject: [PATCH] tdf#128671: Rely on unwind.h, declare what's missing from
 cxxabi.h

...for gcc3_linux_aarch64, similar to what
128deeae81a6f802bfb79b8f0fa8c4b10729f7db "cxxabi.h is not specific to GCC" et al
did for gcc3_linux_x86-64

Change-Id: Iee9980842c0e5f6f49642407339a67e865f8be9c
Reviewed-on: https://gerrit.libreoffice.org/85344
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
---
 .../source/cpp_uno/gcc3_linux_aarch64/abi.cxx |   7 +-
 .../source/cpp_uno/gcc3_linux_aarch64/abi.hxx | 117 +++++++++++++-----
 .../cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx    |   4 +-
 3 files changed, 92 insertions(+), 36 deletions(-)

diff --git bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
index 938011a09a2e..892bf6e81963 100644
--- bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
+++ bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
@@ -24,7 +24,6 @@
 #include <cstring>
 #include <typeinfo>
 
-#include <cxxabi.h>
 #include <dlfcn.h>
 
 #include <com/sun/star/uno/RuntimeException.hpp>
@@ -135,8 +134,8 @@ std::type_info * getRtti(typelib_TypeDescription const & type) {
 }
 
 extern "C" void _GLIBCXX_CDTOR_CALLABI deleteException(void * exception) {
-    abi_aarch64::__cxa_exception * header =
-        static_cast<abi_aarch64::__cxa_exception *>(exception) - 1;
+    __cxxabiv1::__cxa_exception * header =
+        static_cast<__cxxabiv1::__cxa_exception *>(exception) - 1;
     OUString unoName(toUnoName(header->exceptionType->name()));
     typelib_TypeDescription * td = 0;
     typelib_typedescription_getByName(&td, unoName.pData);
@@ -224,7 +223,7 @@ StructKind getStructKind(typelib_CompoundTypeDescription const * type) {
 namespace abi_aarch64 {
 
 void mapException(
-    __cxa_exception * exception, std::type_info const * type, uno_Any * any, uno_Mapping * mapping)
+    __cxxabiv1::__cxa_exception * exception, std::type_info const * type, uno_Any * any, uno_Mapping * mapping)
 {
     assert(exception != 0);
     assert(type != nullptr);
diff --git bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
index 50c5f1f21a37..e3dc9b5872a7 100644
--- bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
+++ bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
@@ -22,55 +22,114 @@
 
 #include <sal/config.h>
 
+#include <cstddef>
 #include <exception>
 #include <typeinfo>
 
+#include <cxxabi.h>
+#ifndef _GLIBCXX_CDTOR_CALLABI // new in GCC 4.7 cxxabi.h
+#define _GLIBCXX_CDTOR_CALLABI
+#endif
+#include <unwind.h>
+
+#include <config_cxxabi.h>
 #include <typelib/typedescription.h>
 #include <uno/any2.h>
 #include <uno/mapping.h>
 
-namespace abi_aarch64 {
-
-// Following declarations from libstdc++-v3/libsupc++/unwind-cxx.h and
-// lib/gcc/*-*-*/*/include/unwind.h:
-
-struct _Unwind_Exception
-{
-    unsigned exception_class __attribute__((__mode__(__DI__)));
-    void * exception_cleanup;
-    unsigned private_1 __attribute__((__mode__(__word__)));
-    unsigned private_2 __attribute__((__mode__(__word__)));
-} __attribute__((__aligned__));
+#if !HAVE_CXXABI_H_CLASS_TYPE_INFO
+// <https://mentorembedded.github.io/cxx-abi/abi.html>,
+// libstdc++-v3/libsupc++/cxxabi.h:
+namespace __cxxabiv1 {
+class __class_type_info: public std::type_info {
+public:
+    explicit __class_type_info(char const * n): type_info(n) {}
+    ~__class_type_info() override;
+};
+}
+#endif
 
-struct __cxa_exception
-{
-    std::type_info *exceptionType;
-    void (*exceptionDestructor)(void *);
+#if !HAVE_CXXABI_H_SI_CLASS_TYPE_INFO
+// <https://mentorembedded.github.io/cxx-abi/abi.html>,
+// libstdc++-v3/libsupc++/cxxabi.h:
+namespace __cxxabiv1 {
+class __si_class_type_info: public __class_type_info {
+public:
+    __class_type_info const * __base_type;
+    explicit __si_class_type_info(
+        char const * n, __class_type_info const *base):
+        __class_type_info(n), __base_type(base) {}
+    ~__si_class_type_info() override;
+};
+}
+#endif
 
+#if !HAVE_CXXABI_H_CXA_EXCEPTION
+// <https://mentorembedded.github.io/cxx-abi/abi-eh.html>,
+// libcxxabi/src/cxa_exception.hpp:
+namespace __cxxabiv1 {
+struct __cxa_exception {
+#if defined _LIBCPPABI_VERSION // detect libc++abi
+#if defined __LP64__ || LIBCXXABI_ARM_EHABI
+    std::size_t referenceCount;
+#endif
+#endif
+    std::type_info * exceptionType;
+    void (* exceptionDestructor)(void *);
     void (*unexpectedHandler)(); // std::unexpected_handler dropped from C++17
     std::terminate_handler terminateHandler;
-
-    __cxa_exception *nextException;
-
+    __cxa_exception * nextException;
     int handlerCount;
-
     int handlerSwitchValue;
-    const unsigned char *actionRecord;
-    const unsigned char *languageSpecificData;
-    void *catchTemp;
-    void *adjustedPtr;
-
+    char const * actionRecord;
+    char const * languageSpecificData;
+    void * catchTemp;
+    void * adjustedPtr;
     _Unwind_Exception unwindHeader;
 };
+}
+#endif
 
-struct __cxa_eh_globals
-{
-    __cxa_exception *caughtExceptions;
+#if !HAVE_CXXABI_H_CXA_EH_GLOBALS
+// <https://mentorembedded.github.io/cxx-abi/abi-eh.html>:
+namespace __cxxabiv1 {
+struct __cxa_eh_globals {
+    __cxa_exception * caughtExceptions;
     unsigned int uncaughtExceptions;
 };
+}
+#endif
+
+#if !HAVE_CXXABI_H_CXA_GET_GLOBALS
+namespace __cxxabiv1 {
+extern "C" __cxa_eh_globals * __cxa_get_globals() throw();
+}
+#endif
+
+#if !HAVE_CXXABI_H_CXA_CURRENT_EXCEPTION_TYPE
+namespace __cxxabiv1 {
+extern "C" std::type_info *__cxa_current_exception_type() throw();
+}
+#endif
+
+#if !HAVE_CXXABI_H_CXA_ALLOCATE_EXCEPTION
+namespace __cxxabiv1 {
+extern "C" void * __cxa_allocate_exception(std::size_t thrown_size) throw();
+}
+#endif
+
+#if !HAVE_CXXABI_H_CXA_THROW
+namespace __cxxabiv1 {
+extern "C" void __cxa_throw(
+    void * thrown_exception, void * tinfo, void (* dest)(void *))
+    __attribute__((noreturn));
+}
+#endif
+
+namespace abi_aarch64 {
 
 void mapException(
-    __cxa_exception * exception, std::type_info const * type, uno_Any * any, uno_Mapping * mapping);
+    __cxxabiv1::__cxa_exception * exception, std::type_info const * type, uno_Any * any, uno_Mapping * mapping);
 
 void raiseException(uno_Any * any, uno_Mapping * mapping);
 
diff --git bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
index f03d848521cc..0847dfc76db5 100644
--- bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
+++ bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
@@ -24,8 +24,6 @@
 #include <exception>
 #include <typeinfo>
 
-#include <cxxabi.h>
-
 #include <bridge.hxx>
 #include <types.hxx>
 #include <unointerfaceproxy.hxx>
@@ -190,7 +188,7 @@ void call(
         }
     } catch (css::uno::Exception &) {
         abi_aarch64::mapException(
-            reinterpret_cast<abi_aarch64::__cxa_eh_globals *>(
+            reinterpret_cast<__cxxabiv1::__cxa_eh_globals *>(
                 __cxxabiv1::__cxa_get_globals())->caughtExceptions,
             __cxxabiv1::__cxa_current_exception_type(), *exception,
             proxy->getBridge()->getCpp2Uno());
From a7d1fed24557b203acb5016a98af26f4ef24d27a Mon Sep 17 00:00:00 2001
From: Stephan Bergmann <sbergman@redhat.com>
Date: Tue, 11 Feb 2020 15:46:45 +0100
Subject: [PATCH] Hack to dynamically adapt to __cxa_exceptiom in LLVM 5.0
 libcxxabi

...for Linux aarch64, similar to 7a9dd3d482deeeb3ed1d50074e56adbd3f928296 "Hack
to dynamically adapt to __cxa_exceptiom in LLVM 5.0 libcxxabi" for macOS x86-64.
But unlike on macOS (which is known to always use libcxxabi), be careful to only
execute the hack in builds targeting libcxxabi.

Change-Id: I5417fde425d2d6bac9400592193a9fe5d2bfe175
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88458
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
---
 .../source/cpp_uno/gcc3_linux_aarch64/abi.cxx | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
index 892bf6e81963..611442a31e31 100644
--- bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
+++ bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
@@ -136,6 +136,28 @@ std::type_info * getRtti(typelib_TypeDescription const & type) {
 extern "C" void _GLIBCXX_CDTOR_CALLABI deleteException(void * exception) {
     __cxxabiv1::__cxa_exception * header =
         static_cast<__cxxabiv1::__cxa_exception *>(exception) - 1;
+#if defined _LIBCPPABI_VERSION // detect libc++abi
+    // The libcxxabi commit
+    // <http://llvm.org/viewvc/llvm-project?view=revision&revision=303175>
+    // "[libcxxabi] Align unwindHeader on a double-word boundary" towards
+    // LLVM 5.0 changed the size of __cxa_exception by adding
+    //
+    //   __attribute__((aligned))
+    //
+    // to the final member unwindHeader, on x86-64 effectively adding a hole of
+    // size 8 in front of that member (changing its offset from 88 to 96,
+    // sizeof(__cxa_exception) from 120 to 128, and alignof(__cxa_exception)
+    // from 8 to 16); a hack to dynamically determine whether we run against a
+    // new libcxxabi is to look at the exceptionDestructor member, which must
+    // point to this function (the use of __cxa_exception in fillUnoException is
+    // unaffected, as it only accesses members towards the start of the struct,
+    // through a pointer known to actually point at the start):
+    if (header->exceptionDestructor != &deleteException) {
+        header = reinterpret_cast<__cxa_exception const *>(
+            reinterpret_cast<char const *>(header) - 8);
+        assert(header->exceptionDestructor == &deleteException);
+    }
+#endif
     OUString unoName(toUnoName(header->exceptionType->name()));
     typelib_TypeDescription * td = 0;
     typelib_typedescription_getByName(&td, unoName.pData);
