From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- bridges/source/cpp_uno/msvc_win32_arm64/except.cxx | 234 +++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 bridges/source/cpp_uno/msvc_win32_arm64/except.cxx (limited to 'bridges/source/cpp_uno/msvc_win32_arm64/except.cxx') diff --git a/bridges/source/cpp_uno/msvc_win32_arm64/except.cxx b/bridges/source/cpp_uno/msvc_win32_arm64/except.cxx new file mode 100644 index 000000000..8cc380c5d --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_arm64/except.cxx @@ -0,0 +1,234 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#pragma pack(push, 8) + +using namespace ::com::sun::star; + +static void* __cdecl copyConstruct(void* pExcThis, void* pSource, + typelib_TypeDescription* pTD) noexcept +{ + ::uno_copyData(pExcThis, pSource, pTD, uno::cpp_acquire); + return pExcThis; +} + +static void* __cdecl destruct(void* pExcThis, typelib_TypeDescription* pTD) noexcept +{ + ::uno_destructData(pExcThis, pTD, uno::cpp_release); + return pExcThis; +} + +const int nCodeSnippetSize = 28; + +static void GenerateCopyConstructorTrampoline(unsigned char* target, + typelib_TypeDescription* pTD) noexcept +{ + // ldr x2, #12 + // ldr x3, #20 + // br x3 + // pTD + // ©Construct + static const char code[] = "\x62\x00\x00\x58\x83\x00\x00\x58\x60\x00\x1f\xd6"; + static_assert(sizeof(code) == 13); + static const unsigned int code_size = sizeof(code) - 1; + + memcpy(target, code, code_size); + *reinterpret_cast(target + code_size) = pTD; + *reinterpret_cast(target + code_size + 8) = ©Construct; +} + +static void GenerateDestructorTrampoline(unsigned char* target, + typelib_TypeDescription* pTD) noexcept +{ + // ldr x1, #12 + // ldr x2, #20 + // br x2 + // pTD + // &destruct + static const char code[] = "\x61\x00\x00\x58\x82\x00\x00\x58\x40\x00\x1f\xd6"; + static_assert(sizeof(code) == 13); + static const unsigned int code_size = sizeof(code) - 1; + + memcpy(target, code, code_size); + *reinterpret_cast(target + code_size) = pTD; + *reinterpret_cast(target + code_size + 8) = &destruct; +} + +ExceptionType::ExceptionType(unsigned char* pCode, sal_uInt64 pCodeBase, + typelib_TypeDescription* pTD) noexcept + : _n0(0) + , _n1(0) + , _n2(-1) + , _n3(0) + , _n4(pTD->nSize) + , exc_type_info(nullptr, "") +{ + // As _n0 is always initialized to zero, that means the + // hasvirtbase flag (see the ONTL catchabletype struct) is + // off, and thus the copyctor is of the ctor_ptr kind. + + int len; + type_info* pRTTI = RTTInfos::get(pTD->pTypeName, &len); + + memcpy(static_cast(&exc_type_info), static_cast(pRTTI), len); + _pTypeInfo = static_cast(reinterpret_cast(&exc_type_info) - pCodeBase); + GenerateCopyConstructorTrampoline(pCode, pTD); + + assert(pCodeBase <= reinterpret_cast(pCode) + && (reinterpret_cast(pCode) - pCodeBase < 0x100000000)); + _pCopyCtor = static_cast(reinterpret_cast(pCode) - pCodeBase); +} + +/* Rewrite of 32-Bit-Code to work under 64 Bit: +* To use the 32 Bit offset values in the ExceptionType we have to +* allocate a single allocation block and use it for all code and date +* all offsets inside this area are guaranteed to be in 32 bit address range. +* So we have to calc total memory allocation size for D-tor, C-Tors, +* ExceptionType and type_info. ExceptionType is allocated via placement new +* to locate everything inside our mem block. +* There is one caveat: Struct type_info is kept in +* a map and was referenced from class ExceptionType. Therefore type_info now +* is also member of ExceptionType and can be referenced via 32 bit offset. +*/ + +RaiseInfo::RaiseInfo(typelib_TypeDescription* pTD) noexcept + : _n0(0) + , _n2(0) + , _pTD(pTD) +{ + typelib_CompoundTypeDescription* pCompTD; + + // Count how many trampolines we need + int codeSize = nCodeSnippetSize; + + // Info count + int nLen = 0; + for (pCompTD = reinterpret_cast(pTD); pCompTD; + pCompTD = pCompTD->pBaseTypeDescription) + { + ++nLen; + codeSize += nCodeSnippetSize; + } + + // Array with size (4) and all _pTypeInfo (4*nLen) + int typeInfoArraySize = 4 + 4 * nLen; + + // 2.Pass: Get the total needed memory for class ExceptionType + // (with embedded type_info) and keep the sizes for each instance + // is stored in allocated int array + auto exceptionTypeSizeArray = std::make_unique(nLen); + + nLen = 0; + for (pCompTD = reinterpret_cast(pTD); pCompTD; + pCompTD = pCompTD->pBaseTypeDescription) + { + int typeInfoLen; + RTTInfos::get(pCompTD->aBase.pTypeName, &typeInfoLen); + // Mem has to be on 4-byte Boundary + if (typeInfoLen % 4 != 0) + { + int n = typeInfoLen / 4; + n++; + typeInfoLen = n * 4; + } + exceptionTypeSizeArray[nLen++] = typeInfoLen + sizeof(ExceptionType); + } + + // Total ExceptionType related mem + int excTypeAddLen = 0; + for (int i = 0; i < nLen; i++) + { + excTypeAddLen += exceptionTypeSizeArray[i]; + } + + // Allocate mem for code and all dynamic data in one chunk to guarantee + // 32 bit offsets + const int totalSize = codeSize + typeInfoArraySize + excTypeAddLen; + unsigned char* pCode = _code = static_cast(std::malloc(totalSize)); + int pCodeOffset = 0; + + // New base of types array, starts after Trampoline D-Tor / C-Tors + DWORD* types = reinterpret_cast(pCode + codeSize); + + // New base of ExceptionType array, starts after types array + unsigned char* etMem = pCode + codeSize + typeInfoArraySize; + int etMemOffset = 0; + + _codeBase = reinterpret_cast(pCode) + & ~static_cast(ExceptionInfos::allocationGranularity - 1); + + DWORD old_protect; + bool success = VirtualProtect(pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect); + (void)success; + assert(success && "VirtualProtect() failed!"); + + ::typelib_typedescription_acquire(pTD); + + // Fill pCode with D-Tor code + GenerateDestructorTrampoline(pCode, pTD); + _pDtor = static_cast(reinterpret_cast(pCode) - _codeBase); + pCodeOffset += nCodeSnippetSize; + + // Info count accompanied by type info ptrs: type, base type, base base type, ... + // Keep offset of types_array + _types = static_cast(reinterpret_cast(types) - _codeBase); + // Fill types: (nLen, _offset to ExceptionType1, ...ExceptionType2, ...) + types[0] = nLen; + + int nPos = 1; + for (pCompTD = reinterpret_cast(pTD); pCompTD; + pCompTD = pCompTD->pBaseTypeDescription) + { + // Create instance in mem block with placement new + ExceptionType* et = new (etMem + etMemOffset) ExceptionType( + pCode + pCodeOffset, _codeBase, reinterpret_cast(pCompTD)); + + // Next trampoline entry offset + pCodeOffset += nCodeSnippetSize; + // Next ExceptionType placement offset + etMemOffset += exceptionTypeSizeArray[nPos - 1]; + + // Keep offset of addresses of ET for D-Tor call in ~RaiseInfo + types[nPos++] = static_cast(reinterpret_cast(et) - _codeBase); + } + // Final check: end of address calculation must be end of mem + assert(etMem + etMemOffset == pCode + totalSize); +} + +#pragma pack(pop) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3