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