xref: /AOO41X/main/bridges/source/cpp_uno/cc50_solaris_sparc/except.cxx (revision 0848378beb0d0fcd9a9bf3cafa6204dbc20d39f7)
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