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