summaryrefslogtreecommitdiffstats
path: root/bridges/inc/vtablefactory.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/inc/vtablefactory.hxx')
-rw-r--r--bridges/inc/vtablefactory.hxx221
1 files changed, 221 insertions, 0 deletions
diff --git a/bridges/inc/vtablefactory.hxx b/bridges/inc/vtablefactory.hxx
new file mode 100644
index 0000000000..9afcb83709
--- /dev/null
+++ b/bridges/inc/vtablefactory.hxx
@@ -0,0 +1,221 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <rtl/alloc.h>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <typelib/typedescription.hxx>
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+
+/*See: http://people.redhat.com/drepper/selinux-mem.html*/
+#if defined(LINUX) || defined(OPENBSD) || defined(FREEBSD) \
+ || defined(NETBSD) || defined(DRAGONFLY) || defined (ANDROID) \
+ || defined(HAIKU)
+#define USE_DOUBLE_MMAP
+#endif
+
+namespace bridges::cpp_uno::shared {
+
+/** Hand out vtable structures for interface type descriptions.
+ */
+class VtableFactory {
+public:
+ // This structure is not defined in the generic part, but instead has to be
+ // defined individually for each CPP--UNO bridge:
+ /** A vtable slot.
+ */
+ struct Slot;
+
+ /** A raw vtable block.
+ */
+ struct Block {
+ /** The start of the raw vtable block.
+
+ It points to the start of the allocated memory block, whereas the
+ vtable pointer typically points some bytes into the block (e.g.,
+ skipping an RTTI pointer, see mapBlockToVtable). Also, the block
+ contains any generated code snippets, after the vtable itself.
+ */
+ void * start;
+
+#ifdef USE_DOUBLE_MMAP
+ /** When separately mmapping the block for writing and executing
+ exec points to the same memory as start, except start is used
+ exclusively for writing and exec for executing
+ */
+ void * exec;
+
+ /** File handle for the underlying anonymous file
+ */
+ int fd;
+#endif
+
+ /** The size of the raw vtable block, in bytes.
+ */
+ sal_Size size;
+ };
+
+ /** The vtable structure corresponding to an interface type.
+ */
+ struct Vtables {
+ /** The number of blocks/vtables.
+ */
+ sal_Int32 count;
+
+ /** An array of blocks, representing the multiple vtables of a
+ (multiple-inheritance) type.
+
+ <p>A block is a raw vtable. It points to the start of the allocated
+ memory block, whereas the vtable pointer typically points some bytes
+ into the block (e.g., skipping an RTTI pointer, see
+ mapBlockToVtable). Also, the block contains any generated code
+ snippets, after the vtable itself.</p>
+ */
+ std::unique_ptr<Block[]> blocks;
+
+ Vtables()
+ : count(0)
+ {
+ }
+ };
+
+ VtableFactory();
+
+ ~VtableFactory();
+
+ /** Given an interface type description, return its corresponding vtable
+ structure.
+ */
+ const Vtables& getVtables(typelib_InterfaceTypeDescription * type);
+
+ // This function is not defined in the generic part, but instead has to be
+ // defined individually for each CPP--UNO bridge:
+ /** Given a pointer to a block, turn it into a vtable pointer.
+ */
+ static Slot * mapBlockToVtable(void * block);
+
+private:
+ class GuardedBlocks;
+ friend class GuardedBlocks;
+
+ class BaseOffset;
+
+ VtableFactory(VtableFactory const &) = delete;
+ VtableFactory& operator =(const VtableFactory&) = delete;
+
+ bool createBlock(Block &block, sal_Int32 slotCount) const;
+
+ void freeBlock(Block const & block) const;
+
+ sal_Int32 createVtables(
+ GuardedBlocks & blocks, BaseOffset const & baseOffset,
+ typelib_InterfaceTypeDescription * type, sal_Int32 vtableNumber,
+ typelib_InterfaceTypeDescription * mostDerived, bool includePrimary)
+ const;
+
+ // This function is not defined in the generic part, but instead has to be
+ // defined individually for each CPP--UNO bridge:
+ /** Calculate the size of a raw vtable block.
+
+ @param slotCount the number of virtual function slots the returned
+ vtable block shall support (if there are any platform-specific slots,
+ like an RTTI pointer, or a pointer to a destructor, they are not covered
+ by slotCount)
+ @return the size of the raw vtable block, in bytes
+ */
+ static std::size_t getBlockSize(sal_Int32 slotCount);
+
+ // This function is not defined in the generic part, but instead has to be
+ // defined individually for each CPP--UNO bridge:
+ /** Initialize a raw vtable block.
+
+ @param block the start address of the raw vtable block
+ @param slotCount the number of slots
+ @param vtableNumber zero-based count across all the most derived type's
+ vtables (for vtable's "offset to top" slot)
+ @param type non-null most derived type (for vtable's "typeinfo pointer"
+ slot)
+ @return a pointer past the last vtable slot
+ */
+ static Slot * initializeBlock(
+ void * block, sal_Int32 slotCount, sal_Int32 vtableNumber,
+ typelib_InterfaceTypeDescription * type);
+
+ // This function is not defined in the generic part, but instead has to be
+ // defined individually for each CPP--UNO bridge:
+ /** Fill the vtable slots corresponding to all local (i.e., not inherited)
+ functions of a given interface type (and generate any necessary code
+ snippets for them).
+
+ @param slots on input, points past the vtable slot to be filled with
+ the last virtual function local to the given type; on output, points to
+ the vtable slot filled with the first virtual function local to the
+ given type
+ @param code points to the start of the area where code snippets can be
+ generated
+ @param writetoexecdiff when the same code area is mapped twice, once for
+ writing for code-generation, and once for code-execution, then this
+ records the offset from a writable address to its executable address
+ @param type the interface type description for which to generate vtable
+ slots
+ @param functionOffset the function offset of the first vtable slot
+ (typically coded into the code snippet for that vtable slot)
+ @param functionCount the number of vtable slots to fill (the number of
+ local functions of the given type, passed in so that it doesn't need to
+ be recomputed)
+ @param vtableOffset the offset of this vtable (needed to adjust the
+ this pointer, typically coded into the code snippets for all the filled
+ vtable slots)
+ @return a pointer to the remaining code snippet area
+ */
+ static unsigned char * addLocalFunctions(
+ Slot ** slots, unsigned char * code,
+#ifdef USE_DOUBLE_MMAP
+ sal_PtrDiff writetoexecdiff,
+#endif
+ typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
+ sal_Int32 functionCount, sal_Int32 vtableOffset);
+
+ // This function is not defined in the generic part, but instead has to be
+ // defined individually for each CPP--UNO bridge:
+ /** Flush all the generated code snippets of a vtable, on platforms that
+ require it.
+
+ @param begin points to the start of the code snippet area
+ @param end points behind the end of the code snippet area
+ */
+ static void flushCode(
+ unsigned char const * begin, unsigned char const * end);
+
+ typedef std::unordered_map< OUString, Vtables > Map;
+
+ std::mutex m_mutex;
+ Map m_map;
+
+ rtl_arena_type * m_arena;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */