summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRĂ¼diger Timm <rt@openoffice.org>2006-05-02 11:07:18 +0000
committerRĂ¼diger Timm <rt@openoffice.org>2006-05-02 11:07:18 +0000
commitdca1c17b960e40c824fd396242acbee1eb2e97f5 (patch)
tree99be4cb1f7ed996217139b952ed53630bfa2171c
parentdc8577a12711953efab685123dbf11bc5ca95410 (diff)
INTEGRATION: CWS mhu12 (1.4.38); FILE MERGED
2006/04/28 15:22:21 mhu 1.4.38.5: #i47132# Fixed typo in mprotect() call. 2006/04/28 10:47:52 mhu 1.4.38.4: #i47132# Fedora Core 5 with SELinux enforced needs explicit 'mprotect()', i.e. 'mmap(..PROT_EXEC...)' still fails. 2006/04/19 14:56:18 sb 1.4.38.3: #i47132# One more fix for Solaris. 2006/04/19 14:03:08 sb 1.4.38.2: #i47132# Fix for Solaris. 2006/04/19 12:55:33 sb 1.4.38.1: #i47132# Adapted to new functionality from rtl/alloc.h to obtain executable memory for the raw vtable blocks (which contain code snippets together with the vtables).
-rw-r--r--bridges/source/cpp_uno/shared/vtablefactory.cxx158
1 files changed, 123 insertions, 35 deletions
diff --git a/bridges/source/cpp_uno/shared/vtablefactory.cxx b/bridges/source/cpp_uno/shared/vtablefactory.cxx
index d6b35f885a41..77c085fa7307 100644
--- a/bridges/source/cpp_uno/shared/vtablefactory.cxx
+++ b/bridges/source/cpp_uno/shared/vtablefactory.cxx
@@ -4,9 +4,9 @@
*
* $RCSfile: vtablefactory.cxx,v $
*
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
*
- * last change: $Author: rt $ $Date: 2005-09-07 22:35:41 $
+ * last change: $Author: rt $ $Date: 2006-05-02 12:07:18 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -41,18 +41,81 @@
#include "osl/diagnose.h"
#include "osl/mutex.hxx"
+#include "rtl/alloc.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "typelib/typedescription.hxx"
#include <hash_map>
+#include <new>
#include <vector>
+#if defined SAL_UNX
+#include <unistd.h>
+#include <sys/mman.h>
+#elif defined SAL_W32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#error Unsupported platform
+#endif
+
using bridges::cpp_uno::shared::VtableFactory;
-class VtableFactory::GuardedBlocks: public std::vector< char * > {
+namespace {
+
+extern "C" void * SAL_CALL allocExec(rtl_arena_type *, sal_Size * size) {
+ sal_Size pagesize;
+#if defined SAL_UNX
+#if defined FREEBSD || defined NETBSD
+ pagesize = getpagesize();
+#else
+ pagesize = sysconf(_SC_PAGESIZE);
+#endif
+#elif defined SAL_W32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ pagesize = info.dwPageSize;
+#endif
+ sal_Size n = (*size + (pagesize - 1)) & ~(pagesize - 1);
+ void * p;
+#if defined SAL_UNX
+ p = mmap(
+ 0, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1,
+ 0);
+ if (p == MAP_FAILED) {
+ p = 0;
+ }
+ else if (mprotect (static_cast<char*>(p), n, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
+ {
+ munmap (static_cast<char*>(p), n);
+ p = 0;
+ }
+#elif defined SAL_W32
+ p = VirtualAlloc(0, n, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+#endif
+ if (p != 0) {
+ *size = n;
+ }
+ return p;
+}
+
+extern "C" void SAL_CALL freeExec(
+ rtl_arena_type *, void * address, sal_Size size)
+{
+#if defined SAL_UNX
+ munmap(static_cast< char * >(address), size);
+#elif defined SAL_W32
+ VirtualFree(address, 0, MEM_RELEASE);
+#endif
+}
+
+}
+
+class VtableFactory::GuardedBlocks: public std::vector< Block > {
public:
- GuardedBlocks(): m_guarded(true) {}
+ GuardedBlocks(VtableFactory const & factory):
+ m_factory(factory), m_guarded(true) {}
~GuardedBlocks();
@@ -62,13 +125,14 @@ private:
GuardedBlocks(GuardedBlocks &); // not implemented
void operator =(GuardedBlocks); // not implemented
+ VtableFactory const & m_factory;
bool m_guarded;
};
VtableFactory::GuardedBlocks::~GuardedBlocks() {
if (m_guarded) {
for (iterator i(begin()); i != end(); ++i) {
- delete[] *i;
+ m_factory.freeBlock(*i);
}
}
}
@@ -105,16 +169,28 @@ sal_Int32 VtableFactory::BaseOffset::calculate(
return offset;
}
-VtableFactory::VtableFactory() {}
+VtableFactory::VtableFactory(): m_arena(
+ rtl_arena_create(
+ "bridges::cpp_uno::shared::VtableFactory",
+ sizeof (void *), // to satisfy alignment requirements
+ 0, reinterpret_cast< rtl_arena_type * >(-1), allocExec, freeExec, 0))
+{
+ if (m_arena == 0) {
+ throw std::bad_alloc();
+ }
+}
VtableFactory::~VtableFactory() {
- osl::MutexGuard guard(m_mutex);
- for (Map::iterator i(m_map.begin()); i != m_map.end(); ++i) {
- for (sal_Int32 j = 0; j < i->second.count; ++j) {
- delete[] i->second.blocks[j];
+ {
+ osl::MutexGuard guard(m_mutex);
+ for (Map::iterator i(m_map.begin()); i != m_map.end(); ++i) {
+ for (sal_Int32 j = 0; j < i->second.count; ++j) {
+ freeBlock(i->second.blocks[j]);
+ }
+ delete[] i->second.blocks;
}
- delete[] i->second.blocks;
}
+ rtl_arena_destroy(m_arena);
}
VtableFactory::Vtables VtableFactory::getVtables(
@@ -124,13 +200,13 @@ VtableFactory::Vtables VtableFactory::getVtables(
osl::MutexGuard guard(m_mutex);
Map::iterator i(m_map.find(name));
if (i == m_map.end()) {
- GuardedBlocks blocks;
+ GuardedBlocks blocks(*this);
createVtables(blocks, BaseOffset(type), type, true);
Vtables vtables;
OSL_ASSERT(blocks.size() <= SAL_MAX_INT32);
vtables.count = static_cast< sal_Int32 >(blocks.size());
- bridges::cpp_uno::shared::GuardedArray< char * > guardedBlocks(
- new char *[vtables.count]);
+ bridges::cpp_uno::shared::GuardedArray< Block > guardedBlocks(
+ new Block[vtables.count]);
vtables.blocks = guardedBlocks.get();
for (sal_Int32 j = 0; j < vtables.count; ++j) {
vtables.blocks[j] = blocks[j];
@@ -142,34 +218,46 @@ VtableFactory::Vtables VtableFactory::getVtables(
return i->second;
}
+void VtableFactory::freeBlock(Block const & block) const {
+ rtl_arena_free(m_arena, block.start, block.size);
+}
+
void VtableFactory::createVtables(
GuardedBlocks & blocks, BaseOffset const & baseOffset,
- typelib_InterfaceTypeDescription * type, bool includePrimary)
+ typelib_InterfaceTypeDescription * type, bool includePrimary) const
{
if (includePrimary) {
sal_Int32 slotCount
= bridges::cpp_uno::shared::getPrimaryFunctions(type);
- void ** slots;
- bridges::cpp_uno::shared::GuardedArray< char > block(
- createBlock(slotCount, &slots));
- slots += slotCount;
- unsigned char * codeBegin = reinterpret_cast< unsigned char * >(slots);
- unsigned char * code = codeBegin;
- sal_Int32 vtableOffset = blocks.size() * sizeof (void **);
- for (typelib_InterfaceTypeDescription const * type2 = type; type2 != 0;
- type2 = type2->pBaseTypeDescription)
- {
- sal_Int32 functionCount
- = bridges::cpp_uno::shared::getLocalFunctions(type2);
- slots -= functionCount;
- code = addLocalFunctions(
- slots, code, type2,
- baseOffset.getFunctionOffset(type2->aBase.pTypeName),
- functionCount, vtableOffset);
+ Block block;
+ block.size = getBlockSize(slotCount);
+ block.start = rtl_arena_alloc(m_arena, &block.size);
+ if (block.start == 0) {
+ throw std::bad_alloc();
+ }
+ try {
+ void ** slots = initializeBlock(block.start) + slotCount;
+ unsigned char * codeBegin =
+ reinterpret_cast< unsigned char * >(slots);
+ unsigned char * code = codeBegin;
+ sal_Int32 vtableOffset = blocks.size() * sizeof (void **);
+ for (typelib_InterfaceTypeDescription const * type2 = type;
+ type2 != 0; type2 = type2->pBaseTypeDescription)
+ {
+ sal_Int32 functionCount
+ = bridges::cpp_uno::shared::getLocalFunctions(type2);
+ slots -= functionCount;
+ code = addLocalFunctions(
+ slots, code, type2,
+ baseOffset.getFunctionOffset(type2->aBase.pTypeName),
+ functionCount, vtableOffset);
+ }
+ flushCode(codeBegin, code);
+ blocks.push_back(block);
+ } catch (...) {
+ freeBlock(block);
+ throw;
}
- flushCode(codeBegin, code);
- blocks.push_back(block.get());
- block.release();
}
for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
createVtables(blocks, baseOffset, type->ppBaseTypes[i], i != 0);