1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_bridges.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #if defined OS2 32*cdf0e10cSrcweir #define INCL_DOS 33*cdf0e10cSrcweir #define INCL_DOSMISC 34*cdf0e10cSrcweir #endif 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir #include "bridges/cpp_uno/shared/vtablefactory.hxx" 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir #include "guardedarray.hxx" 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir #include "bridges/cpp_uno/shared/vtables.hxx" 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir #include "osl/thread.h" 43*cdf0e10cSrcweir #include "osl/security.hxx" 44*cdf0e10cSrcweir #include "osl/file.hxx" 45*cdf0e10cSrcweir #include "osl/diagnose.h" 46*cdf0e10cSrcweir #include "osl/mutex.hxx" 47*cdf0e10cSrcweir #include "rtl/alloc.h" 48*cdf0e10cSrcweir #include "rtl/ustring.hxx" 49*cdf0e10cSrcweir #include "sal/types.h" 50*cdf0e10cSrcweir #include "typelib/typedescription.hxx" 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir #include <hash_map> 53*cdf0e10cSrcweir #include <new> 54*cdf0e10cSrcweir #include <vector> 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir #if defined SAL_UNX 57*cdf0e10cSrcweir #include <unistd.h> 58*cdf0e10cSrcweir #include <string.h> 59*cdf0e10cSrcweir #include <sys/mman.h> 60*cdf0e10cSrcweir #elif defined SAL_W32 61*cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN 62*cdf0e10cSrcweir #ifdef _MSC_VER 63*cdf0e10cSrcweir #pragma warning(push,1) // disable warnings within system headers 64*cdf0e10cSrcweir #endif 65*cdf0e10cSrcweir #include <windows.h> 66*cdf0e10cSrcweir #ifdef _MSC_VER 67*cdf0e10cSrcweir #pragma warning(pop) 68*cdf0e10cSrcweir #endif 69*cdf0e10cSrcweir #elif defined SAL_OS2 70*cdf0e10cSrcweir #define INCL_DOS 71*cdf0e10cSrcweir #define INCL_DOSMISC 72*cdf0e10cSrcweir #include <os2.h> 73*cdf0e10cSrcweir #else 74*cdf0e10cSrcweir #error Unsupported platform 75*cdf0e10cSrcweir #endif 76*cdf0e10cSrcweir 77*cdf0e10cSrcweir using bridges::cpp_uno::shared::VtableFactory; 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir namespace { 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir extern "C" void * SAL_CALL allocExec(rtl_arena_type *, sal_Size * size) { 82*cdf0e10cSrcweir sal_Size pagesize; 83*cdf0e10cSrcweir #if defined SAL_UNX 84*cdf0e10cSrcweir #if defined FREEBSD || defined NETBSD 85*cdf0e10cSrcweir pagesize = getpagesize(); 86*cdf0e10cSrcweir #else 87*cdf0e10cSrcweir pagesize = sysconf(_SC_PAGESIZE); 88*cdf0e10cSrcweir #endif 89*cdf0e10cSrcweir #elif defined SAL_W32 90*cdf0e10cSrcweir SYSTEM_INFO info; 91*cdf0e10cSrcweir GetSystemInfo(&info); 92*cdf0e10cSrcweir pagesize = info.dwPageSize; 93*cdf0e10cSrcweir #elif defined(SAL_OS2) 94*cdf0e10cSrcweir ULONG ulPageSize; 95*cdf0e10cSrcweir DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, &ulPageSize, sizeof(ULONG)); 96*cdf0e10cSrcweir pagesize = (sal_Size)ulPageSize; 97*cdf0e10cSrcweir #else 98*cdf0e10cSrcweir #error Unsupported platform 99*cdf0e10cSrcweir #endif 100*cdf0e10cSrcweir sal_Size n = (*size + (pagesize - 1)) & ~(pagesize - 1); 101*cdf0e10cSrcweir void * p; 102*cdf0e10cSrcweir #if defined SAL_UNX 103*cdf0e10cSrcweir p = mmap( 104*cdf0e10cSrcweir 0, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 105*cdf0e10cSrcweir 0); 106*cdf0e10cSrcweir if (p == MAP_FAILED) { 107*cdf0e10cSrcweir p = 0; 108*cdf0e10cSrcweir } 109*cdf0e10cSrcweir else if (mprotect (static_cast<char*>(p), n, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir munmap (static_cast<char*>(p), n); 112*cdf0e10cSrcweir p = 0; 113*cdf0e10cSrcweir } 114*cdf0e10cSrcweir #elif defined SAL_W32 115*cdf0e10cSrcweir p = VirtualAlloc(0, n, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 116*cdf0e10cSrcweir #elif defined(SAL_OS2) 117*cdf0e10cSrcweir p = 0; 118*cdf0e10cSrcweir DosAllocMem( &p, n, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY); 119*cdf0e10cSrcweir #endif 120*cdf0e10cSrcweir if (p != 0) { 121*cdf0e10cSrcweir *size = n; 122*cdf0e10cSrcweir } 123*cdf0e10cSrcweir return p; 124*cdf0e10cSrcweir } 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir extern "C" void SAL_CALL freeExec( 127*cdf0e10cSrcweir rtl_arena_type *, void * address, sal_Size size) 128*cdf0e10cSrcweir { 129*cdf0e10cSrcweir #if defined SAL_UNX 130*cdf0e10cSrcweir munmap(static_cast< char * >(address), size); 131*cdf0e10cSrcweir #elif defined SAL_W32 132*cdf0e10cSrcweir (void) size; // unused 133*cdf0e10cSrcweir VirtualFree(address, 0, MEM_RELEASE); 134*cdf0e10cSrcweir #elif defined(SAL_OS2) 135*cdf0e10cSrcweir (void) DosFreeMem( address); 136*cdf0e10cSrcweir #endif 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir } 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir class VtableFactory::GuardedBlocks: public std::vector< Block > { 142*cdf0e10cSrcweir public: 143*cdf0e10cSrcweir GuardedBlocks(VtableFactory const & factory): 144*cdf0e10cSrcweir m_factory(factory), m_guarded(true) {} 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir ~GuardedBlocks(); 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir void unguard() { m_guarded = false; } 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir private: 151*cdf0e10cSrcweir GuardedBlocks(GuardedBlocks &); // not implemented 152*cdf0e10cSrcweir void operator =(GuardedBlocks); // not implemented 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir VtableFactory const & m_factory; 155*cdf0e10cSrcweir bool m_guarded; 156*cdf0e10cSrcweir }; 157*cdf0e10cSrcweir 158*cdf0e10cSrcweir VtableFactory::GuardedBlocks::~GuardedBlocks() { 159*cdf0e10cSrcweir if (m_guarded) { 160*cdf0e10cSrcweir for (iterator i(begin()); i != end(); ++i) { 161*cdf0e10cSrcweir m_factory.freeBlock(*i); 162*cdf0e10cSrcweir } 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir } 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir class VtableFactory::BaseOffset { 167*cdf0e10cSrcweir public: 168*cdf0e10cSrcweir BaseOffset(typelib_InterfaceTypeDescription * type) { calculate(type, 0); } 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir sal_Int32 getFunctionOffset(rtl::OUString const & name) const 171*cdf0e10cSrcweir { return m_map.find(name)->second; } 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir private: 174*cdf0e10cSrcweir sal_Int32 calculate( 175*cdf0e10cSrcweir typelib_InterfaceTypeDescription * type, sal_Int32 offset); 176*cdf0e10cSrcweir 177*cdf0e10cSrcweir typedef std::hash_map< rtl::OUString, sal_Int32, rtl::OUStringHash > Map; 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir Map m_map; 180*cdf0e10cSrcweir }; 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir sal_Int32 VtableFactory::BaseOffset::calculate( 183*cdf0e10cSrcweir typelib_InterfaceTypeDescription * type, sal_Int32 offset) 184*cdf0e10cSrcweir { 185*cdf0e10cSrcweir rtl::OUString name(type->aBase.pTypeName); 186*cdf0e10cSrcweir if (m_map.find(name) == m_map.end()) { 187*cdf0e10cSrcweir for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) { 188*cdf0e10cSrcweir offset = calculate(type->ppBaseTypes[i], offset); 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir m_map.insert(Map::value_type(name, offset)); 191*cdf0e10cSrcweir typelib_typedescription_complete( 192*cdf0e10cSrcweir reinterpret_cast< typelib_TypeDescription ** >(&type)); 193*cdf0e10cSrcweir offset += bridges::cpp_uno::shared::getLocalFunctions(type); 194*cdf0e10cSrcweir } 195*cdf0e10cSrcweir return offset; 196*cdf0e10cSrcweir } 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir VtableFactory::VtableFactory(): m_arena( 199*cdf0e10cSrcweir rtl_arena_create( 200*cdf0e10cSrcweir "bridges::cpp_uno::shared::VtableFactory", 201*cdf0e10cSrcweir sizeof (void *), // to satisfy alignment requirements 202*cdf0e10cSrcweir 0, reinterpret_cast< rtl_arena_type * >(-1), allocExec, freeExec, 0)) 203*cdf0e10cSrcweir { 204*cdf0e10cSrcweir if (m_arena == 0) { 205*cdf0e10cSrcweir throw std::bad_alloc(); 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir } 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir VtableFactory::~VtableFactory() { 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir osl::MutexGuard guard(m_mutex); 212*cdf0e10cSrcweir for (Map::iterator i(m_map.begin()); i != m_map.end(); ++i) { 213*cdf0e10cSrcweir for (sal_Int32 j = 0; j < i->second.count; ++j) { 214*cdf0e10cSrcweir freeBlock(i->second.blocks[j]); 215*cdf0e10cSrcweir } 216*cdf0e10cSrcweir delete[] i->second.blocks; 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir } 219*cdf0e10cSrcweir rtl_arena_destroy(m_arena); 220*cdf0e10cSrcweir } 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir VtableFactory::Vtables VtableFactory::getVtables( 223*cdf0e10cSrcweir typelib_InterfaceTypeDescription * type) 224*cdf0e10cSrcweir { 225*cdf0e10cSrcweir rtl::OUString name(type->aBase.pTypeName); 226*cdf0e10cSrcweir osl::MutexGuard guard(m_mutex); 227*cdf0e10cSrcweir Map::iterator i(m_map.find(name)); 228*cdf0e10cSrcweir if (i == m_map.end()) { 229*cdf0e10cSrcweir GuardedBlocks blocks(*this); 230*cdf0e10cSrcweir createVtables(blocks, BaseOffset(type), type, true); 231*cdf0e10cSrcweir Vtables vtables; 232*cdf0e10cSrcweir OSL_ASSERT(blocks.size() <= SAL_MAX_INT32); 233*cdf0e10cSrcweir vtables.count = static_cast< sal_Int32 >(blocks.size()); 234*cdf0e10cSrcweir bridges::cpp_uno::shared::GuardedArray< Block > guardedBlocks( 235*cdf0e10cSrcweir new Block[vtables.count]); 236*cdf0e10cSrcweir vtables.blocks = guardedBlocks.get(); 237*cdf0e10cSrcweir for (sal_Int32 j = 0; j < vtables.count; ++j) { 238*cdf0e10cSrcweir vtables.blocks[j] = blocks[j]; 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir i = m_map.insert(Map::value_type(name, vtables)).first; 241*cdf0e10cSrcweir guardedBlocks.release(); 242*cdf0e10cSrcweir blocks.unguard(); 243*cdf0e10cSrcweir } 244*cdf0e10cSrcweir return i->second; 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir #ifdef USE_DOUBLE_MMAP 248*cdf0e10cSrcweir bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const 249*cdf0e10cSrcweir { 250*cdf0e10cSrcweir sal_Size size = getBlockSize(slotCount); 251*cdf0e10cSrcweir sal_Size pagesize = sysconf(_SC_PAGESIZE); 252*cdf0e10cSrcweir block.size = (size + (pagesize - 1)) & ~(pagesize - 1); 253*cdf0e10cSrcweir block.start = block.exec = NULL; 254*cdf0e10cSrcweir block.fd = -1; 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir osl::Security aSecurity; 257*cdf0e10cSrcweir rtl::OUString strDirectory; 258*cdf0e10cSrcweir rtl::OUString strURLDirectory; 259*cdf0e10cSrcweir if (aSecurity.getHomeDir(strURLDirectory)) 260*cdf0e10cSrcweir osl::File::getSystemPathFromFileURL(strURLDirectory, strDirectory); 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir for (int i = strDirectory.getLength() == 0 ? 1 : 0; i < 2; ++i) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir if (!strDirectory.getLength()) 265*cdf0e10cSrcweir strDirectory = rtl::OUString::createFromAscii("/tmp"); 266*cdf0e10cSrcweir 267*cdf0e10cSrcweir strDirectory += rtl::OUString::createFromAscii("/.execoooXXXXXX"); 268*cdf0e10cSrcweir rtl::OString aTmpName = rtl::OUStringToOString(strDirectory, osl_getThreadTextEncoding()); 269*cdf0e10cSrcweir char *tmpfname = new char[aTmpName.getLength()+1]; 270*cdf0e10cSrcweir strncpy(tmpfname, aTmpName.getStr(), aTmpName.getLength()+1); 271*cdf0e10cSrcweir if ((block.fd = mkstemp(tmpfname)) == -1) 272*cdf0e10cSrcweir perror("creation of executable memory area failed"); 273*cdf0e10cSrcweir if (block.fd == -1) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir delete[] tmpfname; 276*cdf0e10cSrcweir break; 277*cdf0e10cSrcweir } 278*cdf0e10cSrcweir unlink(tmpfname); 279*cdf0e10cSrcweir delete[] tmpfname; 280*cdf0e10cSrcweir if (ftruncate(block.fd, block.size) == -1) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir perror("truncation of executable memory area failed"); 283*cdf0e10cSrcweir close(block.fd); 284*cdf0e10cSrcweir block.fd = -1; 285*cdf0e10cSrcweir break; 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir block.start = mmap(NULL, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, block.fd, 0); 288*cdf0e10cSrcweir if (block.start== MAP_FAILED) { 289*cdf0e10cSrcweir block.start = 0; 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir block.exec = mmap(NULL, block.size, PROT_READ | PROT_EXEC, MAP_SHARED, block.fd, 0); 292*cdf0e10cSrcweir if (block.exec == MAP_FAILED) { 293*cdf0e10cSrcweir block.exec = 0; 294*cdf0e10cSrcweir } 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir //All good 297*cdf0e10cSrcweir if (block.start && block.exec && block.fd != -1) 298*cdf0e10cSrcweir break; 299*cdf0e10cSrcweir 300*cdf0e10cSrcweir freeBlock(block); 301*cdf0e10cSrcweir 302*cdf0e10cSrcweir strDirectory = rtl::OUString(); 303*cdf0e10cSrcweir } 304*cdf0e10cSrcweir if (!block.start || !block.exec || block.fd == -1) 305*cdf0e10cSrcweir { 306*cdf0e10cSrcweir //Fall back to non-doublemmaped allocation 307*cdf0e10cSrcweir block.fd = -1; 308*cdf0e10cSrcweir block.start = block.exec = rtl_arena_alloc(m_arena, &block.size); 309*cdf0e10cSrcweir } 310*cdf0e10cSrcweir return (block.start != 0 && block.exec != 0); 311*cdf0e10cSrcweir } 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir void VtableFactory::freeBlock(Block const & block) const { 314*cdf0e10cSrcweir //if the double-map failed we were allocated on the arena 315*cdf0e10cSrcweir if (block.fd == -1 && block.start == block.exec && block.start != NULL) 316*cdf0e10cSrcweir rtl_arena_free(m_arena, block.start, block.size); 317*cdf0e10cSrcweir else 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir if (block.start) munmap(block.start, block.size); 320*cdf0e10cSrcweir if (block.exec) munmap(block.exec, block.size); 321*cdf0e10cSrcweir if (block.fd != -1) close(block.fd); 322*cdf0e10cSrcweir } 323*cdf0e10cSrcweir } 324*cdf0e10cSrcweir #else 325*cdf0e10cSrcweir bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const 326*cdf0e10cSrcweir { 327*cdf0e10cSrcweir block.size = getBlockSize(slotCount); 328*cdf0e10cSrcweir block.start = rtl_arena_alloc(m_arena, &block.size); 329*cdf0e10cSrcweir return block.start != 0; 330*cdf0e10cSrcweir } 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir void VtableFactory::freeBlock(Block const & block) const { 333*cdf0e10cSrcweir rtl_arena_free(m_arena, block.start, block.size); 334*cdf0e10cSrcweir } 335*cdf0e10cSrcweir #endif 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir void VtableFactory::createVtables( 338*cdf0e10cSrcweir GuardedBlocks & blocks, BaseOffset const & baseOffset, 339*cdf0e10cSrcweir typelib_InterfaceTypeDescription * type, bool includePrimary) const 340*cdf0e10cSrcweir { 341*cdf0e10cSrcweir if (includePrimary) { 342*cdf0e10cSrcweir sal_Int32 slotCount 343*cdf0e10cSrcweir = bridges::cpp_uno::shared::getPrimaryFunctions(type); 344*cdf0e10cSrcweir Block block; 345*cdf0e10cSrcweir if (!createBlock(block, slotCount)) { 346*cdf0e10cSrcweir throw std::bad_alloc(); 347*cdf0e10cSrcweir } 348*cdf0e10cSrcweir try { 349*cdf0e10cSrcweir Slot * slots = initializeBlock(block.start, slotCount); 350*cdf0e10cSrcweir unsigned char * codeBegin = 351*cdf0e10cSrcweir reinterpret_cast< unsigned char * >(slots); 352*cdf0e10cSrcweir unsigned char * code = codeBegin; 353*cdf0e10cSrcweir sal_Int32 vtableOffset = blocks.size() * sizeof (Slot *); 354*cdf0e10cSrcweir for (typelib_InterfaceTypeDescription const * type2 = type; 355*cdf0e10cSrcweir type2 != 0; type2 = type2->pBaseTypeDescription) 356*cdf0e10cSrcweir { 357*cdf0e10cSrcweir code = addLocalFunctions( 358*cdf0e10cSrcweir &slots, code, 359*cdf0e10cSrcweir #ifdef USE_DOUBLE_MMAP 360*cdf0e10cSrcweir sal_IntPtr(block.exec) - sal_IntPtr(block.start), 361*cdf0e10cSrcweir #endif 362*cdf0e10cSrcweir type2, 363*cdf0e10cSrcweir baseOffset.getFunctionOffset(type2->aBase.pTypeName), 364*cdf0e10cSrcweir bridges::cpp_uno::shared::getLocalFunctions(type2), 365*cdf0e10cSrcweir vtableOffset); 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir flushCode(codeBegin, code); 368*cdf0e10cSrcweir #ifdef USE_DOUBLE_MMAP 369*cdf0e10cSrcweir //Finished generating block, swap writable pointer with executable 370*cdf0e10cSrcweir //pointer 371*cdf0e10cSrcweir ::std::swap(block.start, block.exec); 372*cdf0e10cSrcweir #endif 373*cdf0e10cSrcweir blocks.push_back(block); 374*cdf0e10cSrcweir } catch (...) { 375*cdf0e10cSrcweir freeBlock(block); 376*cdf0e10cSrcweir throw; 377*cdf0e10cSrcweir } 378*cdf0e10cSrcweir } 379*cdf0e10cSrcweir for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) { 380*cdf0e10cSrcweir createVtables(blocks, baseOffset, type->ppBaseTypes[i], i != 0); 381*cdf0e10cSrcweir } 382*cdf0e10cSrcweir } 383