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