1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLEFACTORY_HXX
25 #define INCLUDED_BRIDGES_CPP_UNO_SHARED_VTABLEFACTORY_HXX
26 
27 #include "osl/mutex.hxx"
28 #include "rtl/alloc.h"
29 #include "rtl/ustring.hxx"
30 #include "sal/types.h"
31 #include "typelib/typedescription.hxx"
32 
33 #include <hash_map>
34 
35 /*See: http://people.redhat.com/drepper/selinux-mem.html*/
36 #if defined (LINUX) || defined (FREEBSD)
37 #define USE_DOUBLE_MMAP
38 #endif
39 
40 namespace bridges { namespace cpp_uno { namespace shared {
41 
42 /** Hand out vtable structures for interface type descriptions.
43  */
44 class VtableFactory {
45 public:
46     // This structure is not defined in the generic part, but instead has to be
47     // defined individually for each CPP--UNO bridge:
48     /** A vtable slot.
49      */
50     struct Slot;
51 
52     /** A raw vtable block.
53      */
54     struct Block {
55         /** The start of the raw vtable block.
56 
57             It points to the start of the allocated memory block, whereas the
58             vtable pointer typically points some bytes into the block (e.g.,
59             skipping an RTTI pointer, see mapBlockToVtable).  Also, the block
60             contains any generated code snippets, after the vtable itself.
61          */
62         void * start;
63 
64 #ifdef USE_DOUBLE_MMAP
65 	/** When seperately mmapping the block for writing and executing
66             exec points to the same memory as start, except start is used
67             exclusively for writing and exec for executing
68          */
69         void * exec;
70 
71 	/** File handle for the underlying anonymous file
72          */
73         int fd;
74 #endif
75 
76         /** The size of the raw vtable block, in bytes.
77          */
78         sal_Size size;
79     };
80 
81     /** The vtable structure corresponding to an interface type.
82      */
83     struct Vtables {
84         /** The number of blocks/vtables.
85          */
86         sal_Int32 count;
87 
88         /** An array of blocks, representing the multiple vtables of a
89             (multiple-inheritance) type.
90 
91             <p>A block is a raw vtable.  It points to the start of the allocated
92             memory block, whereas the vtable pointer typically points some bytes
93             into the block (e.g., skipping an RTTI pointer, see
94             mapBlockToVtable).  Also, the block contains any generated code
95             snippets, after the vtable itself.</p>
96          */
97         Block * blocks;
98     };
99 
100     VtableFactory();
101 
102     ~VtableFactory();
103 
104     /** Given an interface type description, return its corresponding vtable
105         structure.
106      */
107     Vtables getVtables(typelib_InterfaceTypeDescription * type);
108 
109     // This function is not defined in the generic part, but instead has to be
110     // defined individually for each CPP--UNO bridge:
111     /** Given a pointer to a block, turn it into a vtable pointer.
112      */
113     static Slot * mapBlockToVtable(void * block);
114 
115 private:
116     class GuardedBlocks;
117     friend class GuardedBlocks;
118 
119     class BaseOffset;
120 
121     VtableFactory(VtableFactory &); // not implemented
122     void operator =(VtableFactory); // not implemented
123 
124     bool createBlock(Block &block, sal_Int32 slotCount) const;
125 
126     void freeBlock(Block const & block) const;
127 
128     void createVtables(
129         GuardedBlocks & blocks, BaseOffset const & baseOffset,
130         typelib_InterfaceTypeDescription * type, bool includePrimary) const;
131 
132     // This function is not defined in the generic part, but instead has to be
133     // defined individually for each CPP--UNO bridge:
134     /** Calculate the size of a raw vtable block.
135 
136         @param slotCount  the number of virtual function slots the returned
137         vtable block shall support (if there are any platform-specific slots,
138         like an RTTI pointer, or a pointer to a destructor, they are not covered
139         by slotCount)
140         @return  the size of the raw vtable block, in bytes
141      */
142     static sal_Size getBlockSize(sal_Int32 slotCount);
143 
144     // This function is not defined in the generic part, but instead has to be
145     // defined individually for each CPP--UNO bridge:
146     /** Initialize a raw vtable block.
147 
148         @param block  the start address of the raw vtable block
149         @param slotCount  the number of slots
150         @return  a pointer past the last vtable slot
151      */
152     static Slot * initializeBlock(void * block, sal_Int32 slotCount);
153 
154     // This function is not defined in the generic part, but instead has to be
155     // defined individually for each CPP--UNO bridge:
156     /** Fill the vtable slots corresponding to all local (i.e., not inherited)
157         functions of a given interface type (and generate any necessary code
158         snippets for them).
159 
160         @param slots  on input, points past the vtable slot to be filled with
161         the last virtual function local to the given type; on output, points to
162         the vtable slot filled with the first virtual function local to the
163         given type
164         @param code  points to the start of the area where code snippets can be
165         generated
166         @param writetoexecdiff when the same code area is mmaped twice, once for
167         writing for code-generation, and once for code-execution, then this
168         records the offset from a writable address to its executable address
169         @param type  the interface type description for which to generate vtable
170         slots
171         @param functionOffset  the function offset of the first vtable slot
172         (typically coded into the code snippet for that vtable slot)
173         @param functionCount  the number of vtable slots to fill (the number of
174         local functions of the given type, passed in so that it need not be
175         recomputed)
176         @param vtableOffset  the offset of this vtable (needed to adjust the
177         this pointer, typically coded into the code snippets for all the filled
178         vtable slots)
179         @return  a pointer to the remaining code snippet area
180      */
181     static unsigned char * addLocalFunctions(
182         Slot ** slots, unsigned char * code,
183 #ifdef USE_DOUBLE_MMAP
184         sal_PtrDiff writetoexecdiff,
185 #endif
186         typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
187         sal_Int32 functionCount, sal_Int32 vtableOffset);
188 
189     // This function is not defined in the generic part, but instead has to be
190     // defined individually for each CPP--UNO bridge:
191     /** Flush all the generated code snippets of a vtable, on platforms that
192         require it.
193 
194         @param begin  points to the start of the code snippet area
195         @param end  points behind the end of the code snippet area
196      */
197     static void flushCode(
198         unsigned char const * begin, unsigned char const * end);
199 
200     typedef std::hash_map< rtl::OUString, Vtables, rtl::OUStringHash > Map;
201 
202     osl::Mutex m_mutex;
203     Map m_map;
204 
205     rtl_arena_type * m_arena;
206 };
207 
208 } } }
209 
210 #endif
211