bridges/Library_cpp_uno.mk | 16 +- bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx | 62 +++++++++- bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx | 3 bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx | 2 bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx | 10 + bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s | 11 + bridges/source/cpp_uno/shared/vtablefactory.cxx | 11 + cppuhelper/source/exc_thrower.cxx | 6 sal/osl/unx/salinit.cxx | 8 - 9 files changed, 115 insertions(+), 14 deletions(-)
New commits: commit e2bd5afd726abd5df438b6b821416bd7cf496e4d Author: Tor Lillqvist <t...@collabora.com> AuthorDate: Sun Aug 9 10:51:22 2020 +0100 Commit: Tor Lillqvist <t...@collabora.com> CommitDate: Mon Aug 10 17:51:27 2020 +0200 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 <t...@collabora.com> diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk index cf6fb489c3a1..9adc891f4e3d 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 036b81c4218a..52309c6ec617 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/cppuhelper/source/exc_thrower.cxx b/cppuhelper/source/exc_thrower.cxx index 2963572e4770..7c40d12db16e 100644 --- a/cppuhelper/source/exc_thrower.cxx +++ b/cppuhelper/source/exc_thrower.cxx @@ -173,7 +173,7 @@ ExceptionThrower::ExceptionThrower() class theExceptionThrower : public rtl::Static<ExceptionThrower, theExceptionThrower> {}; -#if defined(IOS) || (defined(__aarch64__) && (defined(ANDROID) || defined(MACOSX))) +#if defined(IOS) || (defined(__aarch64__) && defined(ANDROID)) // In the native iOS / Android app, where we don't have any Java, Python, // BASIC, or other scripting, the only thing that would use the C++/UNO bridge // functionality that invokes codeSnippet() was cppu::throwException(). @@ -211,7 +211,7 @@ void lo_mobile_throwException(css::uno::Any const& aException) assert(false); } -#endif // defined(IOS) || (defined(__aarch64__) && (defined(ANDROID) || defined(MACOSX))) +#endif // defined(IOS) || (defined(__aarch64__) && defined(ANDROID)) } // anonymous namespace @@ -229,7 +229,7 @@ void SAL_CALL throwException( Any const & exc ) "(must be derived from com::sun::star::uno::Exception)!" ); } -#if defined(IOS) || (defined(__aarch64__) && (defined(ANDROID) || defined(MACOSX))) +#if defined(IOS) || (defined(__aarch64__) && defined(ANDROID)) lo_mobile_throwException(exc); #else Mapping uno2cpp(Environment(UNO_LB_UNO), Environment::getCurrent()); 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); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits