161dff127SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
361dff127SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
461dff127SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
561dff127SAndrew Rist  * distributed with this work for additional information
661dff127SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
761dff127SAndrew Rist  * to you under the Apache License, Version 2.0 (the
861dff127SAndrew Rist  * "License"); you may not use this file except in compliance
961dff127SAndrew Rist  * with the License.  You may obtain a copy of the License at
1061dff127SAndrew Rist  *
1161dff127SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1261dff127SAndrew Rist  *
1361dff127SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1461dff127SAndrew Rist  * software distributed under the License is distributed on an
1561dff127SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1661dff127SAndrew Rist  * KIND, either express or implied.  See the License for the
1761dff127SAndrew Rist  * specific language governing permissions and limitations
1861dff127SAndrew Rist  * under the License.
1961dff127SAndrew Rist  *
2061dff127SAndrew Rist  *************************************************************/
2161dff127SAndrew Rist 
2261dff127SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_bridges.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #if defined OS2
28cdf0e10cSrcweir #define INCL_DOS
29cdf0e10cSrcweir #define INCL_DOSMISC
30cdf0e10cSrcweir #endif
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include "bridges/cpp_uno/shared/vtablefactory.hxx"
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include "guardedarray.hxx"
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include "bridges/cpp_uno/shared/vtables.hxx"
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "osl/thread.h"
39cdf0e10cSrcweir #include "osl/security.hxx"
40cdf0e10cSrcweir #include "osl/file.hxx"
41cdf0e10cSrcweir #include "osl/diagnose.h"
42cdf0e10cSrcweir #include "osl/mutex.hxx"
43cdf0e10cSrcweir #include "rtl/alloc.h"
44cdf0e10cSrcweir #include "rtl/ustring.hxx"
45cdf0e10cSrcweir #include "sal/types.h"
46cdf0e10cSrcweir #include "typelib/typedescription.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include <hash_map>
49cdf0e10cSrcweir #include <new>
50cdf0e10cSrcweir #include <vector>
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #if defined SAL_UNX
53cdf0e10cSrcweir #include <unistd.h>
54cdf0e10cSrcweir #include <string.h>
55cdf0e10cSrcweir #include <sys/mman.h>
56cdf0e10cSrcweir #elif defined SAL_W32
57cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN
58cdf0e10cSrcweir #ifdef _MSC_VER
59cdf0e10cSrcweir #pragma warning(push,1) // disable warnings within system headers
60cdf0e10cSrcweir #endif
61cdf0e10cSrcweir #include <windows.h>
62cdf0e10cSrcweir #ifdef _MSC_VER
63cdf0e10cSrcweir #pragma warning(pop)
64cdf0e10cSrcweir #endif
65cdf0e10cSrcweir #elif defined SAL_OS2
66cdf0e10cSrcweir #define INCL_DOS
67cdf0e10cSrcweir #define INCL_DOSMISC
68cdf0e10cSrcweir #include <os2.h>
69cdf0e10cSrcweir #else
70cdf0e10cSrcweir #error Unsupported platform
71cdf0e10cSrcweir #endif
72cdf0e10cSrcweir 
73cdf0e10cSrcweir using bridges::cpp_uno::shared::VtableFactory;
74cdf0e10cSrcweir 
75cdf0e10cSrcweir namespace {
76cdf0e10cSrcweir 
allocExec(rtl_arena_type *,sal_Size * size)77cdf0e10cSrcweir extern "C" void * SAL_CALL allocExec(rtl_arena_type *, sal_Size * size) {
78cdf0e10cSrcweir     sal_Size pagesize;
79cdf0e10cSrcweir #if defined SAL_UNX
80cdf0e10cSrcweir #if defined FREEBSD || defined NETBSD
81cdf0e10cSrcweir     pagesize = getpagesize();
82cdf0e10cSrcweir #else
83cdf0e10cSrcweir     pagesize = sysconf(_SC_PAGESIZE);
84cdf0e10cSrcweir #endif
85cdf0e10cSrcweir #elif defined SAL_W32
86cdf0e10cSrcweir     SYSTEM_INFO info;
87cdf0e10cSrcweir     GetSystemInfo(&info);
88cdf0e10cSrcweir     pagesize = info.dwPageSize;
89cdf0e10cSrcweir #elif defined(SAL_OS2)
90cdf0e10cSrcweir 	ULONG ulPageSize;
91cdf0e10cSrcweir 	DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, &ulPageSize, sizeof(ULONG));
92cdf0e10cSrcweir 	pagesize = (sal_Size)ulPageSize;
93cdf0e10cSrcweir #else
94cdf0e10cSrcweir #error Unsupported platform
95cdf0e10cSrcweir #endif
96cdf0e10cSrcweir     sal_Size n = (*size + (pagesize - 1)) & ~(pagesize - 1);
97cdf0e10cSrcweir     void * p;
98cdf0e10cSrcweir #if defined SAL_UNX
99cdf0e10cSrcweir     p = mmap(
100cdf0e10cSrcweir         0, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1,
101cdf0e10cSrcweir         0);
102cdf0e10cSrcweir     if (p == MAP_FAILED) {
103cdf0e10cSrcweir         p = 0;
104cdf0e10cSrcweir     }
105cdf0e10cSrcweir 	else if (mprotect (static_cast<char*>(p), n, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
106cdf0e10cSrcweir 	{
107cdf0e10cSrcweir 		munmap (static_cast<char*>(p), n);
108cdf0e10cSrcweir 		p = 0;
109cdf0e10cSrcweir 	}
110cdf0e10cSrcweir #elif defined SAL_W32
111cdf0e10cSrcweir     p = VirtualAlloc(0, n, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
112cdf0e10cSrcweir #elif defined(SAL_OS2)
113cdf0e10cSrcweir     p = 0;
114cdf0e10cSrcweir     DosAllocMem( &p, n, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
115cdf0e10cSrcweir #endif
116cdf0e10cSrcweir     if (p != 0) {
117cdf0e10cSrcweir         *size = n;
118cdf0e10cSrcweir     }
119cdf0e10cSrcweir     return p;
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
freeExec(rtl_arena_type *,void * address,sal_Size size)122cdf0e10cSrcweir extern "C" void SAL_CALL freeExec(
123cdf0e10cSrcweir     rtl_arena_type *, void * address, sal_Size size)
124cdf0e10cSrcweir {
125cdf0e10cSrcweir #if defined SAL_UNX
126cdf0e10cSrcweir     munmap(static_cast< char * >(address), size);
127cdf0e10cSrcweir #elif defined SAL_W32
128cdf0e10cSrcweir     (void) size; // unused
129cdf0e10cSrcweir     VirtualFree(address, 0, MEM_RELEASE);
130cdf0e10cSrcweir #elif defined(SAL_OS2)
131cdf0e10cSrcweir 	(void) DosFreeMem( address);
132cdf0e10cSrcweir #endif
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
137cdf0e10cSrcweir class VtableFactory::GuardedBlocks: public std::vector< Block > {
138cdf0e10cSrcweir public:
GuardedBlocks(VtableFactory const & factory)139cdf0e10cSrcweir     GuardedBlocks(VtableFactory const & factory):
140cdf0e10cSrcweir         m_factory(factory), m_guarded(true) {}
141cdf0e10cSrcweir 
142cdf0e10cSrcweir     ~GuardedBlocks();
143cdf0e10cSrcweir 
unguard()144cdf0e10cSrcweir     void unguard() { m_guarded = false; }
145cdf0e10cSrcweir 
146cdf0e10cSrcweir private:
147cdf0e10cSrcweir     GuardedBlocks(GuardedBlocks &); // not implemented
148cdf0e10cSrcweir     void operator =(GuardedBlocks); // not implemented
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     VtableFactory const & m_factory;
151cdf0e10cSrcweir     bool m_guarded;
152cdf0e10cSrcweir };
153cdf0e10cSrcweir 
~GuardedBlocks()154cdf0e10cSrcweir VtableFactory::GuardedBlocks::~GuardedBlocks() {
155cdf0e10cSrcweir     if (m_guarded) {
156cdf0e10cSrcweir         for (iterator i(begin()); i != end(); ++i) {
157cdf0e10cSrcweir             m_factory.freeBlock(*i);
158cdf0e10cSrcweir         }
159cdf0e10cSrcweir     }
160cdf0e10cSrcweir }
161cdf0e10cSrcweir 
162cdf0e10cSrcweir class VtableFactory::BaseOffset {
163cdf0e10cSrcweir public:
BaseOffset(typelib_InterfaceTypeDescription * type)164cdf0e10cSrcweir     BaseOffset(typelib_InterfaceTypeDescription * type) { calculate(type, 0); }
165cdf0e10cSrcweir 
getFunctionOffset(rtl::OUString const & name) const166cdf0e10cSrcweir     sal_Int32 getFunctionOffset(rtl::OUString const & name) const
167cdf0e10cSrcweir     { return m_map.find(name)->second; }
168cdf0e10cSrcweir 
169cdf0e10cSrcweir private:
170cdf0e10cSrcweir     sal_Int32 calculate(
171cdf0e10cSrcweir         typelib_InterfaceTypeDescription * type, sal_Int32 offset);
172cdf0e10cSrcweir 
173cdf0e10cSrcweir     typedef std::hash_map< rtl::OUString, sal_Int32, rtl::OUStringHash > Map;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     Map m_map;
176cdf0e10cSrcweir };
177cdf0e10cSrcweir 
calculate(typelib_InterfaceTypeDescription * type,sal_Int32 offset)178cdf0e10cSrcweir sal_Int32 VtableFactory::BaseOffset::calculate(
179cdf0e10cSrcweir     typelib_InterfaceTypeDescription * type, sal_Int32 offset)
180cdf0e10cSrcweir {
181cdf0e10cSrcweir     rtl::OUString name(type->aBase.pTypeName);
182cdf0e10cSrcweir     if (m_map.find(name) == m_map.end()) {
183cdf0e10cSrcweir         for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
184cdf0e10cSrcweir             offset = calculate(type->ppBaseTypes[i], offset);
185cdf0e10cSrcweir         }
186cdf0e10cSrcweir         m_map.insert(Map::value_type(name, offset));
187cdf0e10cSrcweir         typelib_typedescription_complete(
188cdf0e10cSrcweir             reinterpret_cast< typelib_TypeDescription ** >(&type));
189cdf0e10cSrcweir         offset += bridges::cpp_uno::shared::getLocalFunctions(type);
190cdf0e10cSrcweir     }
191cdf0e10cSrcweir     return offset;
192cdf0e10cSrcweir }
193cdf0e10cSrcweir 
VtableFactory()194cdf0e10cSrcweir VtableFactory::VtableFactory(): m_arena(
195cdf0e10cSrcweir     rtl_arena_create(
196cdf0e10cSrcweir         "bridges::cpp_uno::shared::VtableFactory",
197cdf0e10cSrcweir         sizeof (void *), // to satisfy alignment requirements
198*37f4cb17SJim Jagielski         0, reinterpret_cast< rtl_arena_type * >( 0 ), allocExec, freeExec, 0))
199cdf0e10cSrcweir {
200cdf0e10cSrcweir     if (m_arena == 0) {
201cdf0e10cSrcweir         throw std::bad_alloc();
202cdf0e10cSrcweir     }
203cdf0e10cSrcweir }
204cdf0e10cSrcweir 
~VtableFactory()205cdf0e10cSrcweir VtableFactory::~VtableFactory() {
206cdf0e10cSrcweir     {
207cdf0e10cSrcweir         osl::MutexGuard guard(m_mutex);
208cdf0e10cSrcweir         for (Map::iterator i(m_map.begin()); i != m_map.end(); ++i) {
209cdf0e10cSrcweir             for (sal_Int32 j = 0; j < i->second.count; ++j) {
210cdf0e10cSrcweir                 freeBlock(i->second.blocks[j]);
211cdf0e10cSrcweir             }
212cdf0e10cSrcweir             delete[] i->second.blocks;
213cdf0e10cSrcweir         }
214cdf0e10cSrcweir     }
215cdf0e10cSrcweir     rtl_arena_destroy(m_arena);
216cdf0e10cSrcweir }
217cdf0e10cSrcweir 
getVtables(typelib_InterfaceTypeDescription * type)218cdf0e10cSrcweir VtableFactory::Vtables VtableFactory::getVtables(
219cdf0e10cSrcweir     typelib_InterfaceTypeDescription * type)
220cdf0e10cSrcweir {
221cdf0e10cSrcweir     rtl::OUString name(type->aBase.pTypeName);
222cdf0e10cSrcweir     osl::MutexGuard guard(m_mutex);
223cdf0e10cSrcweir     Map::iterator i(m_map.find(name));
224cdf0e10cSrcweir     if (i == m_map.end()) {
225cdf0e10cSrcweir         GuardedBlocks blocks(*this);
226cdf0e10cSrcweir         createVtables(blocks, BaseOffset(type), type, true);
227cdf0e10cSrcweir         Vtables vtables;
228cdf0e10cSrcweir         OSL_ASSERT(blocks.size() <= SAL_MAX_INT32);
229cdf0e10cSrcweir         vtables.count = static_cast< sal_Int32 >(blocks.size());
230cdf0e10cSrcweir         bridges::cpp_uno::shared::GuardedArray< Block > guardedBlocks(
231cdf0e10cSrcweir             new Block[vtables.count]);
232cdf0e10cSrcweir         vtables.blocks = guardedBlocks.get();
233cdf0e10cSrcweir         for (sal_Int32 j = 0; j < vtables.count; ++j) {
234cdf0e10cSrcweir             vtables.blocks[j] = blocks[j];
235cdf0e10cSrcweir         }
236cdf0e10cSrcweir         i = m_map.insert(Map::value_type(name, vtables)).first;
237cdf0e10cSrcweir         guardedBlocks.release();
238cdf0e10cSrcweir         blocks.unguard();
239cdf0e10cSrcweir     }
240cdf0e10cSrcweir     return i->second;
241cdf0e10cSrcweir }
242cdf0e10cSrcweir 
243cdf0e10cSrcweir #ifdef USE_DOUBLE_MMAP
createBlock(Block & block,sal_Int32 slotCount) const244cdf0e10cSrcweir bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const
245cdf0e10cSrcweir {
246cdf0e10cSrcweir     sal_Size size = getBlockSize(slotCount);
247cdf0e10cSrcweir     sal_Size pagesize = sysconf(_SC_PAGESIZE);
248cdf0e10cSrcweir     block.size = (size + (pagesize - 1)) & ~(pagesize - 1);
249cdf0e10cSrcweir     block.start = block.exec = NULL;
250cdf0e10cSrcweir     block.fd = -1;
251cdf0e10cSrcweir 
252cdf0e10cSrcweir     osl::Security aSecurity;
253cdf0e10cSrcweir     rtl::OUString strDirectory;
254cdf0e10cSrcweir     rtl::OUString strURLDirectory;
255cdf0e10cSrcweir     if (aSecurity.getHomeDir(strURLDirectory))
256cdf0e10cSrcweir         osl::File::getSystemPathFromFileURL(strURLDirectory, strDirectory);
257cdf0e10cSrcweir 
2580848378bSHerbert Dürr     for (int i = strDirectory.isEmpty() ? 1 : 0; i < 2; ++i)
259cdf0e10cSrcweir     {
2600848378bSHerbert Dürr         if (strDirectory.isEmpty())
261cdf0e10cSrcweir             strDirectory = rtl::OUString::createFromAscii("/tmp");
262cdf0e10cSrcweir 
263cdf0e10cSrcweir         strDirectory += rtl::OUString::createFromAscii("/.execoooXXXXXX");
264cdf0e10cSrcweir         rtl::OString aTmpName = rtl::OUStringToOString(strDirectory, osl_getThreadTextEncoding());
265cdf0e10cSrcweir         char *tmpfname = new char[aTmpName.getLength()+1];
266cdf0e10cSrcweir         strncpy(tmpfname, aTmpName.getStr(), aTmpName.getLength()+1);
267cdf0e10cSrcweir         if ((block.fd = mkstemp(tmpfname)) == -1)
268cdf0e10cSrcweir             perror("creation of executable memory area failed");
269cdf0e10cSrcweir         if (block.fd == -1)
270cdf0e10cSrcweir         {
271cdf0e10cSrcweir             delete[] tmpfname;
272cdf0e10cSrcweir             break;
273cdf0e10cSrcweir         }
274cdf0e10cSrcweir         unlink(tmpfname);
275cdf0e10cSrcweir         delete[] tmpfname;
276cdf0e10cSrcweir         if (ftruncate(block.fd, block.size) == -1)
277cdf0e10cSrcweir         {
278cdf0e10cSrcweir             perror("truncation of executable memory area failed");
279cdf0e10cSrcweir             close(block.fd);
280cdf0e10cSrcweir             block.fd = -1;
281cdf0e10cSrcweir             break;
282cdf0e10cSrcweir         }
283cdf0e10cSrcweir         block.start = mmap(NULL, block.size, PROT_READ | PROT_WRITE, MAP_SHARED, block.fd, 0);
284cdf0e10cSrcweir         if (block.start== MAP_FAILED) {
285cdf0e10cSrcweir             block.start = 0;
286cdf0e10cSrcweir         }
287cdf0e10cSrcweir         block.exec = mmap(NULL, block.size, PROT_READ | PROT_EXEC, MAP_SHARED, block.fd, 0);
288cdf0e10cSrcweir         if (block.exec == MAP_FAILED) {
289cdf0e10cSrcweir            block.exec = 0;
290cdf0e10cSrcweir         }
291cdf0e10cSrcweir 
292cdf0e10cSrcweir         //All good
293cdf0e10cSrcweir         if (block.start && block.exec && block.fd != -1)
294cdf0e10cSrcweir             break;
295cdf0e10cSrcweir 
296cdf0e10cSrcweir         freeBlock(block);
297cdf0e10cSrcweir 
298cdf0e10cSrcweir         strDirectory = rtl::OUString();
299cdf0e10cSrcweir     }
300cdf0e10cSrcweir     if (!block.start || !block.exec || block.fd == -1)
301cdf0e10cSrcweir     {
302cdf0e10cSrcweir        //Fall back to non-doublemmaped allocation
303cdf0e10cSrcweir        block.fd = -1;
304cdf0e10cSrcweir        block.start = block.exec = rtl_arena_alloc(m_arena, &block.size);
305cdf0e10cSrcweir     }
306cdf0e10cSrcweir     return (block.start != 0 && block.exec != 0);
307cdf0e10cSrcweir }
308cdf0e10cSrcweir 
freeBlock(Block const & block) const309cdf0e10cSrcweir void VtableFactory::freeBlock(Block const & block) const {
310cdf0e10cSrcweir     //if the double-map failed we were allocated on the arena
311cdf0e10cSrcweir     if (block.fd == -1 && block.start == block.exec && block.start != NULL)
312cdf0e10cSrcweir         rtl_arena_free(m_arena, block.start, block.size);
313cdf0e10cSrcweir     else
314cdf0e10cSrcweir     {
315cdf0e10cSrcweir         if (block.start) munmap(block.start, block.size);
316cdf0e10cSrcweir         if (block.exec) munmap(block.exec, block.size);
317cdf0e10cSrcweir         if (block.fd != -1) close(block.fd);
318cdf0e10cSrcweir     }
319cdf0e10cSrcweir }
320cdf0e10cSrcweir #else
createBlock(Block & block,sal_Int32 slotCount) const321cdf0e10cSrcweir bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const
322cdf0e10cSrcweir {
323cdf0e10cSrcweir     block.size = getBlockSize(slotCount);
324cdf0e10cSrcweir     block.start = rtl_arena_alloc(m_arena, &block.size);
325cdf0e10cSrcweir     return block.start != 0;
326cdf0e10cSrcweir }
327cdf0e10cSrcweir 
freeBlock(Block const & block) const328cdf0e10cSrcweir void VtableFactory::freeBlock(Block const & block) const {
329cdf0e10cSrcweir     rtl_arena_free(m_arena, block.start, block.size);
330cdf0e10cSrcweir }
331cdf0e10cSrcweir #endif
332cdf0e10cSrcweir 
createVtables(GuardedBlocks & blocks,BaseOffset const & baseOffset,typelib_InterfaceTypeDescription * type,bool includePrimary) const333cdf0e10cSrcweir void VtableFactory::createVtables(
334cdf0e10cSrcweir     GuardedBlocks & blocks, BaseOffset const & baseOffset,
335cdf0e10cSrcweir     typelib_InterfaceTypeDescription * type, bool includePrimary) const
336cdf0e10cSrcweir {
337cdf0e10cSrcweir     if (includePrimary) {
338cdf0e10cSrcweir         sal_Int32 slotCount
339cdf0e10cSrcweir             = bridges::cpp_uno::shared::getPrimaryFunctions(type);
340cdf0e10cSrcweir         Block block;
341cdf0e10cSrcweir         if (!createBlock(block, slotCount)) {
342cdf0e10cSrcweir             throw std::bad_alloc();
343cdf0e10cSrcweir         }
344cdf0e10cSrcweir         try {
345cdf0e10cSrcweir             Slot * slots = initializeBlock(block.start, slotCount);
346cdf0e10cSrcweir             unsigned char * codeBegin =
347cdf0e10cSrcweir                 reinterpret_cast< unsigned char * >(slots);
348cdf0e10cSrcweir             unsigned char * code = codeBegin;
349cdf0e10cSrcweir             sal_Int32 vtableOffset = blocks.size() * sizeof (Slot *);
350cdf0e10cSrcweir             for (typelib_InterfaceTypeDescription const * type2 = type;
351cdf0e10cSrcweir                  type2 != 0; type2 = type2->pBaseTypeDescription)
352cdf0e10cSrcweir             {
353cdf0e10cSrcweir                 code = addLocalFunctions(
354cdf0e10cSrcweir                     &slots, code,
355cdf0e10cSrcweir #ifdef USE_DOUBLE_MMAP
356cdf0e10cSrcweir                     sal_IntPtr(block.exec) - sal_IntPtr(block.start),
357cdf0e10cSrcweir #endif
358cdf0e10cSrcweir                     type2,
359cdf0e10cSrcweir                     baseOffset.getFunctionOffset(type2->aBase.pTypeName),
360cdf0e10cSrcweir                     bridges::cpp_uno::shared::getLocalFunctions(type2),
361cdf0e10cSrcweir                     vtableOffset);
362cdf0e10cSrcweir             }
363cdf0e10cSrcweir             flushCode(codeBegin, code);
364cdf0e10cSrcweir #ifdef USE_DOUBLE_MMAP
365cdf0e10cSrcweir 	    //Finished generating block, swap writable pointer with executable
366cdf0e10cSrcweir 	    //pointer
367cdf0e10cSrcweir             ::std::swap(block.start, block.exec);
368cdf0e10cSrcweir #endif
369cdf0e10cSrcweir             blocks.push_back(block);
370cdf0e10cSrcweir         } catch (...) {
371cdf0e10cSrcweir             freeBlock(block);
372cdf0e10cSrcweir             throw;
373cdf0e10cSrcweir         }
374cdf0e10cSrcweir     }
375cdf0e10cSrcweir     for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
376cdf0e10cSrcweir         createVtables(blocks, baseOffset, type->ppBaseTypes[i], i != 0);
377cdf0e10cSrcweir     }
378cdf0e10cSrcweir }
379