/* -*- 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 .
*/
// ONTL, "Open NT Native Template Library", a C++ STL-like library // that can be used even when writing Windows drivers. This is some // quite badass code. The author has done impressive heavy spelunking // of MSVCR structures. http://code.google.com/p/ontl/
// The below is from ONTL's ntl/nt/exception.hxx, cleaned up to keep just the _M_X64 parts:
#if 0
/* This information until the corresponding '#endif // 0' is covered * by ONTL's license, which is said to be the "zlib/libpng license" * below, which as far as I see is permissive enough to allow this * information to be included here in this source file. Note that no * actual code from ONTL below gets compiled into the object file.
*/
/* * Copyright (c) 2011 <copyright holders> (The ONTL main * developer(s) don't tell their real name(s) on the ONTL site.) * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. *
*/
typedef uint32_t rva_t;
///\note the calling convention should not matter since this has no arguments typedefvoid generic_function_t();
struct ptrtomember // _PMD
{ typedef __w64 int32_t mdiff_t;
mdiff_t member_offset;
mdiff_t vbtable_offset; // -1 if not a virtual base
mdiff_t vdisp_offset; // offset to the displacement value inside the vbtable
struct catchabletype
{ /** is simple type */
uint32_t memmoveable : 1; /** catchable as reference only */
uint32_t refonly : 1; /** class with virtual base */
uint32_t hasvirtbase : 1; /** offset to the type descriptor */
rva_t typeinfo;
/** catch type instance location within a thrown object */
ptrtomember thiscast; /** size of the simple type or offset into buffer of \c this pointer for catch object */
uint32_t object_size;
/// This type represents the catch clause struct ehandler
{ // union { uint32_t adjectives; void * ptr; };
uint32_t isconst : 1;
uint32_t isvolatile : 1;
uint32_t isunaligned : 1;// guess it is not used on x86
uint32_t isreference : 1;
uint32_t :27;
uint32_t ishz : 1;
/** offset to the type descriptor of this catch object */ /*0x04*/ rva_t typeinfo; // dispType /*0x08*/ int eobject_bpoffset; // dispCatchObj /** offset to the catch clause funclet */ /*0x0C*/ rva_t handler; // dispOfHandler /*0x10*/ uint32_t frame; // dispFrame
}
// ___BuildCatchObject /// 15.3/16 When the exception-declaration specifies a class type, a copy /// constructor is used to initialize either the object declared /// in the exception-declaration or, /// if the exception-declaration does not specify a name, /// a temporary object of that type. ///\note This is the question may we optimize out the last case. ///\warning If the copy constructor throws an exception, std::unexpected would be called void
constructcatchobject(
cxxregistration * cxxreg, const ehandler * const catchblock,
catchabletype * const convertible, const dispatcher_context* const dispatch
) const
{
_EH_TRACE_ENTER(); // build helper
__try { struct typeinfo_t { void* vtbl; void* spare; char name[1]; }; enum catchable_info { cidefault, cicomplex, civirtual } cinfo = cidefault;
ExceptionType::ExceptionType(unsignedchar* 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);
/* 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.
*/
// Count how many trampolines we need int codeSize = codeSnippetSize;
// Info count int nLen = 0; for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
pCompTD = pCompTD->pBaseTypeDescription)
{
++nLen;
codeSize += codeSnippetSize;
}
// 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<int[]>(nLen);
nLen = 0; for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(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 constint totalSize = codeSize + typeInfoArraySize + excTypeAddLen; unsignedchar* pCode = _code = static_cast<unsignedchar*>(std::malloc(totalSize));
assert(pCode && "Don't handle OOM conditions"); int pCodeOffset = 0;
// New base of types array, starts after Trampoline D-Tor / C-Tors
DWORD* types = reinterpret_cast<DWORD*>(pCode + codeSize);
// New base of ExceptionType array, starts after types array unsignedchar* etMem = pCode + codeSize + typeInfoArraySize; int etMemOffset = 0;
// Fill pCode with D-Tor code
GenerateDestructorTrampoline(pCode, pTD);
_pDtor = static_cast<sal_Int32>(reinterpret_cast<sal_uInt64>(pCode) - _codeBase);
pCodeOffset += codeSnippetSize;
// Info count accompanied by type info ptrs: type, base type, base base type, ... // Keep offset of types_array
_types = static_cast<sal_Int32>(reinterpret_cast<sal_uInt64>(types) - _codeBase); // Fill types: (nLen, _offset to ExceptionType1, ...ExceptionType2, ...)
types[0] = nLen;
int nPos = 1; for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
pCompTD = pCompTD->pBaseTypeDescription)
{ // Create instance in mem block with placement new
ExceptionType* et = new (etMem + etMemOffset) ExceptionType(
pCode + pCodeOffset, _codeBase, reinterpret_cast<typelib_TypeDescription*>(pCompTD));
// Next trampoline entry offset
pCodeOffset += codeSnippetSize; // Next ExceptionType placement offset
etMemOffset += exceptionTypeSizeArray[nPos - 1];
// Keep offset of addresses of ET for D-Tor call in ~RaiseInfo
types[nPos++] = static_cast<DWORD>(reinterpret_cast<sal_uInt64>(et) - _codeBase);
} // Final check: end of address calculation must be end of mem
assert(etMem + etMemOffset == pCode + totalSize);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.