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 { 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 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.getLength() ) 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 //================================================================================================== 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 110 static OString toRTTImangledname( const OString & rRTTIname ) 111 { 112 if( ! rRTTIname.getLength() ) 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 ); 159 void* getRTTI_UnoName( const OString& rUnoTypename ) 160 { return getRTTI( toRTTIname( rUnoTypename ) ); } 161 162 void* insertRTTI( const OString& rTypename ); 163 void* insertRTTI_UnoName( const OString& rTypename ) 164 { return insertRTTI( toRTTIname( rTypename ) ); } 165 void* generateRTTI( typelib_CompoundTypeDescription* pCompTypeDescr ); 166 }; 167 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 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 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 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 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 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 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