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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26
27 #include <cstddef>
28 #include <dlfcn.h>
29 #include <new.h>
30 #include <typeinfo>
31 #include <list>
32 #include <map>
33 #include <rtl/alloc.h>
34 #include <osl/diagnose.h>
35
36 #include <rtl/strbuf.hxx>
37 #include <typelib/typedescription.hxx>
38 #include <com/sun/star/uno/Any.hxx>
39
40 #include "bridges/cpp_uno/shared/arraypointer.hxx"
41
42 #include "cc50_solaris_intel.hxx"
43
44 #include <hash.cxx>
45
46 // need a += operator for OString and sal_Char
47 namespace rtl
48 {
operator +=(OString & rString,sal_Char cAdd)49 inline OString& operator+=( OString& rString, sal_Char cAdd )
50 {
51 sal_Char add[2];
52 add[0] = cAdd;
53 add[1] = 0;
54 return rString += add;
55 }
56 }
57
58 using namespace std;
59 using namespace osl;
60 using namespace rtl;
61 using namespace com::sun::star::uno;
62
63 namespace CPPU_CURRENT_NAMESPACE
64 {
65
toUNOname(const OString & rRTTIname)66 static OString toUNOname( const OString & rRTTIname )
67 {
68 OString aRet;
69
70 const sal_Char* pRTTI = rRTTIname.getStr();
71 const sal_Char* pOrg = pRTTI;
72 const sal_Char* pLast = pRTTI;
73
74 while( 1 )
75 {
76 if( *pRTTI == ':' || ! *pRTTI )
77 {
78 if( !aRet.isEmpty() )
79 aRet += ".";
80 aRet += rRTTIname.copy( pLast - pOrg, pRTTI - pLast );
81 while( *pRTTI == ':' )
82 pRTTI++;
83 pLast = pRTTI;
84 if( ! *pRTTI )
85 break;
86 }
87 else
88 pRTTI++;
89 }
90
91 return aRet;
92 }
93 //==================================================================================================
toRTTIname(const OString & rUNOname)94 static OString toRTTIname( const OString & rUNOname )
95 {
96 OStringBuffer aRet( rUNOname.getLength()*2 );
97
98 sal_Int32 nIndex = 0;
99 do
100 {
101 if( nIndex > 0 )
102 aRet.append( "::" );
103 aRet.append( rUNOname.getToken( 0, '.', nIndex ) );
104 } while( nIndex != -1 );
105
106 return aRet.makeStringAndClear();
107 }
108 //==================================================================================================
109
toRTTImangledname(const OString & rRTTIname)110 static OString toRTTImangledname( const OString & rRTTIname )
111 {
112 if( rRTTIname.isEmpty() )
113 return OString();
114
115 OStringBuffer aRet( rRTTIname.getLength()*2 );
116
117 aRet.append( "__1n" );
118 sal_Int32 nIndex = 0;
119 do
120 {
121 OString aToken( rRTTIname.getToken( 0, ':', nIndex ) );
122 int nBytes = aToken.getLength();
123 if( nBytes )
124 {
125 if( nBytes > 25 )
126 {
127 aRet.append( (sal_Char)( nBytes/26 + 'a' ) );
128 aRet.append( (sal_Char)( nBytes%26 + 'A' ) );
129 }
130 else
131 aRet.append( (sal_Char)( nBytes + 'A' ) );
132 for (sal_Int32 i = 0; i < aToken.getLength(); ++i) {
133 char c = aToken[i];
134 if (c == 'Q') {
135 aRet.append("QdD");
136 } else {
137 aRet.append(c);
138 }
139 }
140 }
141 } while( nIndex != -1 );
142
143 aRet.append( '_' );
144
145 return aRet.makeStringAndClear();
146 }
147
148 //##################################################################################################
149 //#### RTTI simulation #############################################################################
150 //##################################################################################################
151
152 class RTTIHolder
153 {
154 std::map< OString, void* > aAllRTTI;
155 public:
156 ~RTTIHolder();
157
158 void* getRTTI( const OString& rTypename );
getRTTI_UnoName(const OString & rUnoTypename)159 void* getRTTI_UnoName( const OString& rUnoTypename )
160 { return getRTTI( toRTTIname( rUnoTypename ) ); }
161
162 void* insertRTTI( const OString& rTypename );
insertRTTI_UnoName(const OString & rTypename)163 void* insertRTTI_UnoName( const OString& rTypename )
164 { return insertRTTI( toRTTIname( rTypename ) ); }
165 void* generateRTTI( typelib_CompoundTypeDescription* pCompTypeDescr );
166 };
167
~RTTIHolder()168 RTTIHolder::~RTTIHolder()
169 {
170 for ( std::map< OString, void* >::const_iterator iPos( aAllRTTI.begin() );
171 iPos != aAllRTTI.end(); ++iPos )
172 {
173 delete[] static_cast< char * >(iPos->second);
174 }
175 }
176
177 #if OSL_DEBUG_LEVEL > 1
178 #include <stdio.h>
179 #endif
180
getRTTI(const OString & rTypename)181 void* RTTIHolder::getRTTI( const OString& rTypename )
182 {
183 std::map< OString, void* >::iterator element;
184
185 element = aAllRTTI.find( rTypename );
186 if( element != aAllRTTI.end() )
187 return (*element).second;
188
189 // create rtti structure
190 element = aAllRTTI.find( rTypename );
191 if( element != aAllRTTI.end() )
192 return (*element).second;
193
194 return NULL;
195 }
196
197 static long nMagicId = 1;
198
insertRTTI(const OString & rTypename)199 void* RTTIHolder::insertRTTI( const OString& rTypename )
200 {
201 OString aMangledName( toRTTImangledname( rTypename ) );
202 NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() );
203
204
205 // rSuperTypename MUST exist !!!
206 std::size_t const RTTI_SIZE = 19; // 14???
207 void** pRTTI = reinterpret_cast< void ** >(
208 new char[RTTI_SIZE * sizeof (void *) + strlen(rTypename.getStr()) + 1]);
209 pRTTI[ 0 ] = reinterpret_cast< void * >(RTTI_SIZE * sizeof (void *));
210 pRTTI[ 1 ] = NULL;
211 pRTTI[ 2 ] = (void*)(7*sizeof(void*));
212 pRTTI[ 3 ] = (void*)aHash.getHash()[0];
213 pRTTI[ 4 ] = (void*)aHash.getHash()[1];
214 pRTTI[ 5 ] = (void*)aHash.getHash()[2];
215 pRTTI[ 6 ] = (void*)aHash.getHash()[3];
216 pRTTI[ 7 ] = NULL;
217 pRTTI[ 8 ] = NULL;
218
219 pRTTI[ 9 ] = pRTTI[ 3 ];
220 pRTTI[ 10 ] = pRTTI[ 4 ];
221 pRTTI[ 11 ] = pRTTI[ 5 ];
222 pRTTI[ 12 ] = pRTTI[ 6 ];
223 pRTTI[ 13 ] = (void*)0x80000000;
224 strcpy(reinterpret_cast< char * >(pRTTI + RTTI_SIZE), rTypename.getStr());
225
226 aAllRTTI[ rTypename ] = (void*)pRTTI;
227 #if OSL_DEBUG_LEVEL > 1
228 fprintf( stderr,
229 "generating base RTTI for type %s:\n"
230 " mangled: %s\n"
231 " hash: %.8x %.8x %.8x %.8x\n",
232 rTypename.getStr(),
233 aMangledName.getStr(),
234 pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ]
235 );
236 #endif
237 return pRTTI;
238 }
239
generateRTTI(typelib_CompoundTypeDescription * pCompTypeDescr)240 void* RTTIHolder::generateRTTI( typelib_CompoundTypeDescription * pCompTypeDescr )
241 {
242 OString aUNOCompTypeName( OUStringToOString( pCompTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US ) );
243 OString aRTTICompTypeName( toRTTIname( aUNOCompTypeName ) );
244
245 void* pHaveRTTI = getRTTI( aRTTICompTypeName );
246 if( pHaveRTTI )
247 return pHaveRTTI;
248
249 if( ! pCompTypeDescr->pBaseTypeDescription )
250 // this is a base type
251 return insertRTTI( aRTTICompTypeName );
252
253 // get base class RTTI
254 void* pSuperRTTI = generateRTTI( pCompTypeDescr->pBaseTypeDescription );
255 OSL_ENSURE( pSuperRTTI, "could not generate RTTI for supertype !" );
256
257 // find out the size to allocate for RTTI
258 void** pInherit = (void**)((sal_uInt32)pSuperRTTI + ((sal_uInt32*)pSuperRTTI)[2] + 8);
259 int nInherit;
260 for( nInherit = 1; pInherit[ nInherit*5-1 ] != (void*)0x80000000; nInherit++ )
261 ;
262
263 OString aMangledName( toRTTImangledname( aRTTICompTypeName ) );
264 NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() );
265
266 std::size_t const rttiSize = 14 + nInherit * 5;
267 void** pRTTI = reinterpret_cast< void ** >(
268 new char[
269 rttiSize * sizeof (void *)
270 + strlen(aRTTICompTypeName.getStr()) + 1]);
271 pRTTI[ 0 ] = reinterpret_cast< void * >(rttiSize * sizeof (void *));
272 pRTTI[ 1 ] = NULL;
273 pRTTI[ 2 ] = (void*)(7*sizeof(void*));
274 pRTTI[ 3 ] = (void*)aHash.getHash()[0];
275 pRTTI[ 4 ] = (void*)aHash.getHash()[1];
276 pRTTI[ 5 ] = (void*)aHash.getHash()[2];
277 pRTTI[ 6 ] = (void*)aHash.getHash()[3];
278 pRTTI[ 7 ] = NULL;
279 pRTTI[ 8 ] = NULL;
280
281 memcpy( pRTTI+9, pInherit, 4*nInherit*5 );
282 pRTTI[ 8 +nInherit*5 ] = NULL;
283 pRTTI[ 9 +nInherit*5 ] = pRTTI[ 3 ];
284 pRTTI[ 10+nInherit*5 ] = pRTTI[ 4 ];
285 pRTTI[ 11+nInherit*5 ] = pRTTI[ 5 ];
286 pRTTI[ 12+nInherit*5 ] = pRTTI[ 6 ];
287 pRTTI[ 13+nInherit*5 ] = (void*)0x80000000;
288 strcpy(
289 reinterpret_cast< char * >(pRTTI + rttiSize),
290 aRTTICompTypeName.getStr());
291
292 aAllRTTI[ aRTTICompTypeName ] = (void*)pRTTI;
293
294 #if OSL_DEBUG_LEVEL > 1
295 fprintf( stderr,
296 "generating struct RTTI for type %s:\n"
297 " mangled: %s\n"
298 " hash: %.8x %.8x %.8X %.8x\n",
299 aRTTICompTypeName.getStr(),
300 aMangledName.getStr(),
301 pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ]
302 );
303 #endif
304
305 return pRTTI;
306 }
307
308 //__________________________________________________________________________________________________
309
deleteException(void * pExc,unsigned char * thunk,typelib_TypeDescription * pType)310 static void deleteException(
311 void* pExc, unsigned char* thunk, typelib_TypeDescription* pType )
312 {
313 uno_destructData(
314 pExc, pType, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
315 typelib_typedescription_release( pType );
316 delete[] thunk;
317 }
318
319 //__________________________________________________________________________________________________
320
321 //##################################################################################################
322 //#### exported ####################################################################################
323 //##################################################################################################
324
cc50_solaris_intel_raiseException(uno_Any * pUnoExc,uno_Mapping * pUno2Cpp)325 void cc50_solaris_intel_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
326 {
327 #if OSL_DEBUG_LEVEL > 1
328 OString cstr(
329 OUStringToOString(
330 *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
331 RTL_TEXTENCODING_ASCII_US ) );
332 fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() );
333 #endif
334 bridges::cpp_uno::shared::ArrayPointer< unsigned char > thunkPtr(
335 new unsigned char[24]);
336 typelib_TypeDescription * pTypeDescr = 0;
337 // will be released by deleteException
338 typelib_typedescriptionreference_getDescription( &pTypeDescr, pUnoExc->pType );
339
340 void* pRTTI;
341 {
342 static ::osl::Mutex aMutex;
343 ::osl::Guard< ::osl::Mutex > guard( aMutex );
344
345 static RTTIHolder * s_pRTTI = 0;
346 if (! s_pRTTI)
347 {
348 #ifdef LEAK_STATIC_DATA
349 s_pRTTI = new RTTIHolder();
350 #else
351 static RTTIHolder s_aRTTI;
352 s_pRTTI = &s_aRTTI;
353 #endif
354 }
355
356 pRTTI = s_pRTTI->generateRTTI( (typelib_CompoundTypeDescription *)pTypeDescr );
357 }
358
359 // a must be
360 OSL_ENSURE( sizeof(sal_Int32) == sizeof(void *), "### pointer size differs from sal_Int32!" );
361
362 void * pCppExc = __Crun::ex_alloc( pTypeDescr->nSize );
363 uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
364
365 // destruct uno exception
366 uno_any_destruct( pUnoExc, 0 );
367
368 unsigned char * thunk = thunkPtr.release();
369 // movl %esp, %ecx:
370 thunk[0] = 0x8B;
371 thunk[1] = 0xCC;
372 // pushl pTypeDescr:
373 thunk[2] = 0x68;
374 *reinterpret_cast< void ** >(thunk + 3) = pTypeDescr;
375 // pushl thunk:
376 thunk[7] = 0x68;
377 *reinterpret_cast< void ** >(thunk + 8) = thunk;
378 // pushl 4(%ecx):
379 thunk[12] = 0xFF;
380 thunk[13] = 0x71;
381 thunk[14] = 0x04;
382 // call deleteException:
383 thunk[15] = 0xE8;
384 #pragma disable_warn
385 void * d = reinterpret_cast< void * >(deleteException);
386 #pragma enable_warn
387 *reinterpret_cast< std::ptrdiff_t * >(thunk + 16) =
388 static_cast< unsigned char * >(d) - (thunk + 20);
389 // addl $12, %esp:
390 thunk[20] = 0x83;
391 thunk[21] = 0xC4;
392 thunk[22] = 0x0C;
393 // ret:
394 thunk[23] = 0xC3;
395
396 #pragma disable_warn
397 void (* f)(void *) = reinterpret_cast< void (*)(void *) >(thunk);
398 #pragma enable_warn
399 __Crun::ex_throw(pCppExc, (const __Crun::static_type_info*)pRTTI, f);
400 }
401
cc50_solaris_intel_fillUnoException(void * pCppExc,const char * pInfo,uno_Any * pUnoExc,uno_Mapping * pCpp2Uno)402 void cc50_solaris_intel_fillUnoException(
403 void* pCppExc,
404 const char* pInfo,
405 uno_Any* pUnoExc,
406 uno_Mapping * pCpp2Uno )
407 {
408 OSL_ASSERT( pInfo != 0 );
409 OString uno_name( toUNOname( pInfo ) );
410 OUString aName( OStringToOUString(
411 uno_name, RTL_TEXTENCODING_ASCII_US ) );
412 typelib_TypeDescription * pExcTypeDescr = 0;
413 typelib_typedescription_getByName( &pExcTypeDescr, aName.pData );
414
415 if (pExcTypeDescr == 0) // the thing that should not be
416 {
417 RuntimeException aRE(
418 OUString( RTL_CONSTASCII_USTRINGPARAM(
419 "exception type not found: ") ) + aName,
420 Reference< XInterface >() );
421 Type const & rType = ::getCppuType( &aRE );
422 uno_type_any_constructAndConvert(
423 pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
424 #if OSL_DEBUG_LEVEL > 0
425 OString cstr( OUStringToOString(
426 aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
427 OSL_ENSURE( 0, cstr.getStr() );
428 #endif
429 return;
430 }
431
432 #if OSL_DEBUG_LEVEL > 1
433 fprintf( stderr, "> c++ exception occurred: %s\n",
434 ::rtl::OUStringToOString(
435 pExcTypeDescr->pTypeName,
436 RTL_TEXTENCODING_ASCII_US ).getStr() );
437 #endif
438 // construct uno exception any
439 uno_any_constructAndConvert(
440 pUnoExc, pCppExc, pExcTypeDescr, pCpp2Uno );
441 typelib_typedescription_release( pExcTypeDescr );
442 }
443
444 }
445
446