summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2020-08-09 10:51:22 +0100
committerTor Lillqvist <tml@collabora.com>2020-11-15 10:42:34 +0100
commit3a36922aa824e3800da08f21bd1acab0cda56d60 (patch)
treec2a8cb913454d348421d24ae91df580fd1500832
parentce8291f5c9cf3742766d5d32e146dbbea7b5c3bc (diff)
Make the C++/UNO bridge work to some extent on macOS on arm64
Use the same code as for Linux on aarch64, with minor additional hacks. But that will not actually work in all cases, as there are slight differences in the ABI. See https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html Thus we can drop the use of the lo_mobile_throwException() hack that was very temporarily used. The run-time code generation requires use of a new API on macOS to work: See the use of pthread_jit_write_protect_np() in bridges/source/cpp_uno/shared/vtablefactory.cxx. For some reason, with the Xcode 12 betas, when compiling for arm64-apple-macos, the symbols for the type_infos for the UNO exception types (_ZTIN3com3sun4star3uno16RuntimeExceptionE etc) end up as "weak private external" in the object file, as displayed by "nm -f darwin". We try to look them up with dlsym(), but that then fails. So use a gross hack: Introduce separate real variables that point to these typeinfos, and look up and dereference them instead. If this hack ends up needing to be permanent, instead of having a manually edited set of such pointer variables, we should teach codemaker to generate corresponding functions, and look up and invoke them to get the std::type_info pointer. When compiling for x86_64-apple-macos, the type_info symbols end up as "weak external" which is fine. With this, LibreOffice starts and seems to work to some extent, and many unit tests succeed. Change-Id: I05f46a122a51ade1ac7dccd57cb90e594547740e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100408 Tested-by: Jenkins Reviewed-by: Tor Lillqvist <tml@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105880 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
-rw-r--r--bridges/Library_cpp_uno.mk16
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx62
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx3
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx2
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx10
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s11
-rw-r--r--bridges/source/cpp_uno/shared/vtablefactory.cxx11
-rw-r--r--sal/osl/unx/salinit.cxx8
8 files changed, 112 insertions, 11 deletions
diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk
index 583a319856f1..d066fa87f4b0 100644
--- a/bridges/Library_cpp_uno.mk
+++ b/bridges/Library_cpp_uno.mk
@@ -23,7 +23,7 @@ endif
else ifeq ($(CPUNAME),AARCH64)
-ifneq ($(filter ANDROID DRAGONFLY FREEBSD LINUX NETBSD OPENBSD,$(OS)),)
+ifneq ($(filter ANDROID DRAGONFLY FREEBSD LINUX MACOSX NETBSD OPENBSD,$(OS)),)
bridges_SELECTED_BRIDGE := gcc3_linux_aarch64
bridge_asm_objects := vtableslotcall
bridge_exception_objects := abi cpp2uno uno2cpp
@@ -32,10 +32,8 @@ $(eval $(call gb_Library_add_exception_objects,$(gb_CPPU_ENV)_uno, \
bridges/source/cpp_uno/$(bridges_SELECTED_BRIDGE)/callvirtualfunction, \
$(if $(HAVE_GCC_STACK_CLASH_PROTECTION),-fno-stack-clash-protection) \
))
-else ifneq ($(filter iOS MACOSX,$(OS)),)
-# For now, use the same bridge for macOS on arm64 as for iOS. But we
-# will eventually obviously want one that does generate code
-# dynamically on macOS.
+
+else ifeq ($(OS),iOS)
bridges_SELECTED_BRIDGE := gcc3_ios
bridge_noopt_objects := cpp2uno except uno2cpp
bridge_asm_objects := ios64_helper
@@ -184,6 +182,14 @@ $(eval $(call gb_Library_use_internal_comprehensive_api,$(gb_CPPU_ENV)_uno,\
udkapi \
))
+ifeq ($(OS),MACOSX)
+ifeq ($(CPUNAME),AARCH64)
+$(eval $(call gb_Library_use_internal_comprehensive_api,$(gb_CPPU_ENV)_uno,\
+ offapi \
+))
+endif
+endif
+
$(eval $(call gb_Library_set_include,$(gb_CPPU_ENV)_uno,\
-I$(SRCDIR)/bridges/inc \
$$(INCLUDE) \
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
index 4a5a1d1b662d..b0a35996784e 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
@@ -1,4 +1,4 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
@@ -31,6 +31,7 @@
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
#include <sal/types.h>
#include <typelib/typeclass.h>
#include <typelib/typedescription.h>
@@ -106,6 +107,31 @@ std::type_info * Rtti::getRtti(typelib_TypeDescription const & type) {
OString sym(b.makeStringAndClear());
std::type_info * rtti = static_cast<std::type_info *>(
dlsym(app_, sym.getStr()));
+#if defined MACOSX
+
+ // Horrible but hopefully temporary hack.
+
+ // For some reason, with the Xcode 12 betas, when compiling for arm64-apple-macos, the
+ // symbols for the typeinfos for the UNO exception types
+ // (_ZTIN3com3sun4star3uno16RuntimeExceptionE etc) end up as "weak private external" in the
+ // object file, as displayed by "nm -f darwin". We try to look them up with dlsym() above,
+ // but that then fails. So use a hackaround... introduce separate real variables (see end of
+ // this file) that point to these typeinfos.
+
+ // When compiling for x86_64-apple-macos, the typeinfo symbols end up as "weak external"
+ // which is fine.
+
+ if (rtti == nullptr)
+ {
+ const OString ptrSym = "ptr" + sym;
+ auto ptr = static_cast<std::type_info **>(dlsym(app_, ptrSym.getStr()));
+ if (ptr != nullptr)
+ rtti = *ptr;
+ else
+ SAL_WARN("bridges.osx", dlerror());
+ }
+#endif
+
if (rtti == 0) {
char const * rttiName = sym.getStr() + std::strlen("_ZTI");
assert(type.eTypeClass == typelib_TypeClass_EXCEPTION);
@@ -152,6 +178,12 @@ extern "C" void _GLIBCXX_CDTOR_CALLABI deleteException(void * exception) {
// 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):
+
+ // Later, libcxxabi, as used at least on macOS on arm64, added a
+ // void *reserve at the start of the __cxa_exception in front of
+ // the referenceCount. See
+ // https://github.com/llvm/llvm-project/commit/f2a436058fcbc11291e73badb44e243f61046183#diff-ba9cda1ceca630ba040b154fe198adbd
+
if (header->exceptionDestructor != &deleteException) {
header = reinterpret_cast<__cxxabiv1::__cxa_exception *>(
reinterpret_cast<char *>(header) - 8);
@@ -283,7 +315,9 @@ ReturnKind getReturnKind(typelib_TypeDescription const * type) {
switch (type->eTypeClass) {
default:
assert(false);
+#ifdef NDEBUG
[[fallthrough]];
+#endif
case typelib_TypeClass_VOID:
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
@@ -327,4 +361,30 @@ ReturnKind getReturnKind(typelib_TypeDescription const * type) {
}
+#ifdef MACOSX
+
+// See the comment about the horrible hack above.
+
+// This set of types are compiled based on what 'make check' needs, but I haven't been able to run
+// it completely yet. And of course as such this hack isn't a viable long-term solution.
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/task/ClassifiedInteractionRequest.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#include <com/sun/star/ucb/NameClashException.hpp>
+#include <com/sun/star/uno/Exception.hpp>
+
+extern "C" {
+ const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star4lang24IllegalArgumentExceptionE = &typeid(css::lang::IllegalArgumentException);
+ const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3uno9ExceptionE = &typeid(css::uno::Exception);
+ const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3uno16RuntimeExceptionE = &typeid(css::uno::RuntimeException);
+ const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3ucb31InteractiveAugmentedIOExceptionE = &typeid(css::ucb::InteractiveAugmentedIOException);
+ const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3ucb22InteractiveIOExceptionE = &typeid(css::ucb::InteractiveIOException);
+ const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3ucb18NameClashExceptionE = &typeid(css::ucb::NameClashException);
+ const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star4task28ClassifiedInteractionRequestE = &typeid(css::task::ClassifiedInteractionRequest);
+}
+
+#endif
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
index e3dc9b5872a7..008d4723e295 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
@@ -71,6 +71,9 @@ namespace __cxxabiv1 {
struct __cxa_exception {
#if defined _LIBCPPABI_VERSION // detect libc++abi
#if defined __LP64__ || LIBCXXABI_ARM_EHABI
+#ifdef MACOSX // on arm64
+ void *reserve;
+#endif
std::size_t referenceCount;
#endif
#endif
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx
index ba5194d6f8c8..b944f31cfd2a 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx
@@ -55,7 +55,7 @@ void callVirtualFunction(
"m" (stackargs) // dummy input to prevent optimizing the alloca away
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
"r11", "r12", "r13", "r14", "r15", "r16", "r17",
-#if !defined ANDROID
+#if !defined ANDROID && !defined MACOSX
"r18"/*TODO?*/,
#endif
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
index f9f26419b381..a67f2ca611ea 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
@@ -357,10 +357,16 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
}
unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
- Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
+ Slot ** slots, unsigned char * code,
+#ifdef USE_DOUBLE_MMAP
+ sal_PtrDiff writetoexecdiff,
+#endif
typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
sal_Int32 functionCount, sal_Int32 vtableOffset)
{
+#ifndef USE_DOUBLE_MMAP
+ constexpr sal_PtrDiff writetoexecdiff = 0;
+#endif
(*slots) -= functionCount;
Slot * s = *slots;
for (sal_Int32 i = 0; i != type->nMembers; ++i) {
@@ -400,7 +406,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
void bridges::cpp_uno::shared::VtableFactory::flushCode(
unsigned char const * begin, unsigned char const * end)
{
-#ifndef ANDROID
+#if !defined ANDROID && !defined MACOSX
static void (*clear_cache)(unsigned char const *, unsigned char const *)
= (void (*)(unsigned char const *, unsigned char const *)) dlsym(
RTLD_DEFAULT, "__clear_cache");
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s b/bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s
index 39873b64d7a6..60bdb4c9cf4e 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s
@@ -20,10 +20,15 @@
.arch armv8-a
.text
.align 2
+#ifndef __APPLE__
.global vtableSlotCall
.hidden vtableSlotCall
.type vtableSlotCall, %function
vtableSlotCall:
+#else
+ .global _vtableSlotCall
+_vtableSlotCall:
+#endif
.cfi_startproc
stp x29, x30, [sp, -192]!
.cfi_def_cfa_offset 192
@@ -53,7 +58,11 @@ vtableSlotCall:
stp d2, d3, [sp, 144]
stp d4, d5, [sp, 160]
stp d6, d7, [sp, 176]
+#ifndef __APPLE__
bl vtableCall
+#else
+ bl _vtableCall
+#endif
ldp x0, x1, [x19]
ldp d0, d1, [x20]
ldp d2, d3, [x20, #16]
@@ -66,7 +75,9 @@ vtableSlotCall:
.cfi_def_cfa_offset 0
ret
.cfi_endproc
+#ifndef __APPLE__
.size vtableSlotCall, .-vtableSlotCall
.section .note.GNU-stack, "", @progbits
+#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab */
diff --git a/bridges/source/cpp_uno/shared/vtablefactory.cxx b/bridges/source/cpp_uno/shared/vtablefactory.cxx
index d17533534e9b..81a8a1228a15 100644
--- a/bridges/source/cpp_uno/shared/vtablefactory.cxx
+++ b/bridges/source/cpp_uno/shared/vtablefactory.cxx
@@ -53,6 +53,10 @@
#include <fcntl.h>
#endif
+#if defined MACOSX && defined __aarch64__
+#include <pthread.h>
+#endif
+
using bridges::cpp_uno::shared::VtableFactory;
namespace {
@@ -322,6 +326,10 @@ sal_Int32 VtableFactory::createVtables(
typelib_InterfaceTypeDescription * type, sal_Int32 vtableNumber,
typelib_InterfaceTypeDescription * mostDerived, bool includePrimary) const
{
+#if defined MACOSX && defined __aarch64__
+ // TODO: Should we handle resetting this in a exception-throwing-safe way?
+ pthread_jit_write_protect_np(0);
+#endif
if (includePrimary) {
sal_Int32 slotCount
= bridges::cpp_uno::shared::getPrimaryFunctions(type);
@@ -361,6 +369,9 @@ sal_Int32 VtableFactory::createVtables(
throw;
}
}
+#if defined MACOSX && defined __aarch64__
+ pthread_jit_write_protect_np(1);
+#endif
for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
vtableNumber = createVtables(
blocks, baseOffset, type->ppBaseTypes[i],
diff --git a/sal/osl/unx/salinit.cxx b/sal/osl/unx/salinit.cxx
index 9424089dbba0..c3ac48c575d1 100644
--- a/sal/osl/unx/salinit.cxx
+++ b/sal/osl/unx/salinit.cxx
@@ -1,3 +1,4 @@
+#include <sal/log.hxx>
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
@@ -22,6 +23,7 @@
#include <sal/config.h>
#if defined MACOSX
+#include <algorithm>
#include <cassert>
#include <limits>
#include <unistd.h>
@@ -71,8 +73,10 @@ void sal_detail_initialize(int argc, char ** argv) {
// Some random value, but hopefully sysconf never returns -1 anyway:
openMax = 1024;
}
- assert(openMax >= 0 && openMax <= std::numeric_limits< int >::max());
- for (int fd = 3; fd < int(openMax); ++fd) {
+ // When LibreOffice restarts itself on macOS 11 beta on arm64, for
+ // some reason sysconf(_SC_OPEN_MAX) returns 0x7FFFFFFFFFFFFFFF,
+ // so use a sanity limit here.
+ for (int fd = 3; fd < std::min(100000l, openMax); ++fd) {
struct stat s;
if (fstat(fd, &s) != -1 && S_ISREG(s.st_mode))
close(fd);