LibreOffice Module bridges (master) 1
msvc_win32_arm64/except.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <memory>
23
24#include <malloc.h>
25#include <new.h>
26#include <typeinfo>
27#include <signal.h>
28
29#include <rtl/alloc.h>
30#include <rtl/strbuf.hxx>
31#include <rtl/ustrbuf.hxx>
32#include <sal/log.hxx>
33
34#include <com/sun/star/uno/Any.hxx>
35#include <msvc/arm64.hxx>
36#include <except.hxx>
37
38#pragma pack(push, 8)
39
40using namespace ::com::sun::star;
41
42static void* __cdecl copyConstruct(void* pExcThis, void* pSource,
43 typelib_TypeDescription* pTD) noexcept
44{
45 ::uno_copyData(pExcThis, pSource, pTD, uno::cpp_acquire);
46 return pExcThis;
47}
48
49static void* __cdecl destruct(void* pExcThis, typelib_TypeDescription* pTD) noexcept
50{
51 ::uno_destructData(pExcThis, pTD, uno::cpp_release);
52 return pExcThis;
53}
54
55const int nCodeSnippetSize = 28;
56
57static void GenerateCopyConstructorTrampoline(unsigned char* target,
58 typelib_TypeDescription* pTD) noexcept
59{
60 // ldr x2, #12
61 // ldr x3, #20
62 // br x3
63 // pTD
64 // &copyConstruct
65 static const char code[] = "\x62\x00\x00\x58\x83\x00\x00\x58\x60\x00\x1f\xd6";
66 static_assert(sizeof(code) == 13);
67 static const unsigned int code_size = sizeof(code) - 1;
68
69 memcpy(target, code, code_size);
70 *reinterpret_cast<void**>(target + code_size) = pTD;
71 *reinterpret_cast<void**>(target + code_size + 8) = &copyConstruct;
72}
73
74static void GenerateDestructorTrampoline(unsigned char* target,
75 typelib_TypeDescription* pTD) noexcept
76{
77 // ldr x1, #12
78 // ldr x2, #20
79 // br x2
80 // pTD
81 // &destruct
82 static const char code[] = "\x61\x00\x00\x58\x82\x00\x00\x58\x40\x00\x1f\xd6";
83 static_assert(sizeof(code) == 13);
84 static const unsigned int code_size = sizeof(code) - 1;
85
86 memcpy(target, code, code_size);
87 *reinterpret_cast<void**>(target + code_size) = pTD;
88 *reinterpret_cast<void**>(target + code_size + 8) = &destruct;
89}
90
91ExceptionType::ExceptionType(unsigned char* pCode, sal_uInt64 pCodeBase,
92 typelib_TypeDescription* pTD) noexcept
93 : _n0(0)
94 , _n1(0)
95 , _n2(-1)
96 , _n3(0)
97 , _n4(pTD->nSize)
98 , exc_type_info(nullptr, "")
99{
100 // As _n0 is always initialized to zero, that means the
101 // hasvirtbase flag (see the ONTL catchabletype struct) is
102 // off, and thus the copyctor is of the ctor_ptr kind.
103
104 int len;
105 type_info* pRTTI = RTTInfos::get(pTD->pTypeName, &len);
106
107 memcpy(static_cast<void*>(&exc_type_info), static_cast<void*>(pRTTI), len);
108 _pTypeInfo = static_cast<sal_uInt32>(reinterpret_cast<sal_uInt64>(&exc_type_info) - pCodeBase);
110
111 assert(pCodeBase <= reinterpret_cast<sal_uInt64>(pCode)
112 && (reinterpret_cast<sal_uInt64>(pCode) - pCodeBase < 0x100000000));
113 _pCopyCtor = static_cast<sal_uInt32>(reinterpret_cast<sal_uInt64>(pCode) - pCodeBase);
114}
115
116/* Rewrite of 32-Bit-Code to work under 64 Bit:
117* To use the 32 Bit offset values in the ExceptionType we have to
118* allocate a single allocation block and use it for all code and date
119* all offsets inside this area are guaranteed to be in 32 bit address range.
120* So we have to calc total memory allocation size for D-tor, C-Tors,
121* ExceptionType and type_info. ExceptionType is allocated via placement new
122* to locate everything inside our mem block.
123* There is one caveat: Struct type_info is kept in
124* a map and was referenced from class ExceptionType. Therefore type_info now
125* is also member of ExceptionType and can be referenced via 32 bit offset.
126*/
127
129 : _n0(0)
130 , _n2(0)
131 , _pTD(pTD)
132{
133 typelib_CompoundTypeDescription* pCompTD;
134
135 // Count how many trampolines we need
136 int codeSize = nCodeSnippetSize;
137
138 // Info count
139 int nLen = 0;
140 for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
141 pCompTD = pCompTD->pBaseTypeDescription)
142 {
143 ++nLen;
144 codeSize += nCodeSnippetSize;
145 }
146
147 // Array with size (4) and all _pTypeInfo (4*nLen)
148 int typeInfoArraySize = 4 + 4 * nLen;
149
150 // 2.Pass: Get the total needed memory for class ExceptionType
151 // (with embedded type_info) and keep the sizes for each instance
152 // is stored in allocated int array
153 auto exceptionTypeSizeArray = std::make_unique<int[]>(nLen);
154
155 nLen = 0;
156 for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
157 pCompTD = pCompTD->pBaseTypeDescription)
158 {
159 int typeInfoLen;
160 RTTInfos::get(pCompTD->aBase.pTypeName, &typeInfoLen);
161 // Mem has to be on 4-byte Boundary
162 if (typeInfoLen % 4 != 0)
163 {
164 int n = typeInfoLen / 4;
165 n++;
166 typeInfoLen = n * 4;
167 }
168 exceptionTypeSizeArray[nLen++] = typeInfoLen + sizeof(ExceptionType);
169 }
170
171 // Total ExceptionType related mem
172 int excTypeAddLen = 0;
173 for (int i = 0; i < nLen; i++)
174 {
175 excTypeAddLen += exceptionTypeSizeArray[i];
176 }
177
178 // Allocate mem for code and all dynamic data in one chunk to guarantee
179 // 32 bit offsets
180 const int totalSize = codeSize + typeInfoArraySize + excTypeAddLen;
181 unsigned char* pCode = _code = static_cast<unsigned char*>(std::malloc(totalSize));
182 int pCodeOffset = 0;
183
184 // New base of types array, starts after Trampoline D-Tor / C-Tors
185 DWORD* types = reinterpret_cast<DWORD*>(pCode + codeSize);
186
187 // New base of ExceptionType array, starts after types array
188 unsigned char* etMem = pCode + codeSize + typeInfoArraySize;
189 int etMemOffset = 0;
190
191 _codeBase = reinterpret_cast<sal_uInt64>(pCode)
192 & ~static_cast<sal_uInt64>(ExceptionInfos::allocationGranularity - 1);
193
194 DWORD old_protect;
195 bool success = VirtualProtect(pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect);
196 (void)success;
197 assert(success && "VirtualProtect() failed!");
198
199 ::typelib_typedescription_acquire(pTD);
200
201 // Fill pCode with D-Tor code
203 _pDtor = static_cast<sal_Int32>(reinterpret_cast<sal_uInt64>(pCode) - _codeBase);
204 pCodeOffset += nCodeSnippetSize;
205
206 // Info count accompanied by type info ptrs: type, base type, base base type, ...
207 // Keep offset of types_array
208 _types = static_cast<sal_Int32>(reinterpret_cast<sal_uInt64>(types) - _codeBase);
209 // Fill types: (nLen, _offset to ExceptionType1, ...ExceptionType2, ...)
210 types[0] = nLen;
211
212 int nPos = 1;
213 for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
214 pCompTD = pCompTD->pBaseTypeDescription)
215 {
216 // Create instance in mem block with placement new
217 ExceptionType* et = new (etMem + etMemOffset) ExceptionType(
218 pCode + pCodeOffset, _codeBase, reinterpret_cast<typelib_TypeDescription*>(pCompTD));
219
220 // Next trampoline entry offset
221 pCodeOffset += nCodeSnippetSize;
222 // Next ExceptionType placement offset
223 etMemOffset += exceptionTypeSizeArray[nPos - 1];
224
225 // Keep offset of addresses of ET for D-Tor call in ~RaiseInfo
226 types[nPos++] = static_cast<DWORD>(reinterpret_cast<sal_uInt64>(et) - _codeBase);
227 }
228 // Final check: end of address calculation must be end of mem
229 assert(etMem + etMemOffset == pCode + totalSize);
230}
231
232#pragma pack(pop)
233
234/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static DWORD allocationGranularity
static type_info * get(OUString const &rUNOname, int *len=nullptr) noexcept
sal_Int64 n
sal_uInt16 nPos
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
static void GenerateDestructorTrampoline(unsigned char *target, typelib_TypeDescription *pTD) noexcept
static void *__cdecl destruct(void *pExcThis, typelib_TypeDescription *pTD) noexcept
static void GenerateCopyConstructorTrampoline(unsigned char *target, typelib_TypeDescription *pTD) noexcept
const int nCodeSnippetSize
static void *__cdecl copyConstruct(void *pExcThis, void *pSource, typelib_TypeDescription *pTD) noexcept
int i
sal_Unicode code
ExceptionType(unsigned char *pCode, sal_uInt64 pCodeBase, typelib_TypeDescription *pTD) noexcept
RaiseInfo(typelib_TypeDescription *pTD) noexcept