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