xref: /AOO41X/main/bridges/source/cpp_uno/cc50_solaris_intel/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 
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 occured: %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 occured: %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