| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_bridges.hxx" |
| |
| #include <cstddef> |
| #include <dlfcn.h> |
| #include <new.h> |
| #include <typeinfo> |
| #include <list> |
| #include <map> |
| #include <rtl/alloc.h> |
| #include <osl/diagnose.h> |
| |
| #include <rtl/strbuf.hxx> |
| #include <typelib/typedescription.hxx> |
| #include <com/sun/star/uno/Any.hxx> |
| |
| #include "bridges/cpp_uno/shared/arraypointer.hxx" |
| |
| #include "cc50_solaris_intel.hxx" |
| |
| #include <hash.cxx> |
| |
| // need a += operator for OString and sal_Char |
| namespace rtl |
| { |
| inline OString& operator+=( OString& rString, sal_Char cAdd ) |
| { |
| sal_Char add[2]; |
| add[0] = cAdd; |
| add[1] = 0; |
| return rString += add; |
| } |
| } |
| |
| using namespace std; |
| using namespace osl; |
| using namespace rtl; |
| using namespace com::sun::star::uno; |
| |
| namespace CPPU_CURRENT_NAMESPACE |
| { |
| |
| static OString toUNOname( const OString & rRTTIname ) |
| { |
| OString aRet; |
| |
| const sal_Char* pRTTI = rRTTIname.getStr(); |
| const sal_Char* pOrg = pRTTI; |
| const sal_Char* pLast = pRTTI; |
| |
| while( 1 ) |
| { |
| if( *pRTTI == ':' || ! *pRTTI ) |
| { |
| if( !aRet.isEmpty() ) |
| aRet += "."; |
| aRet += rRTTIname.copy( pLast - pOrg, pRTTI - pLast ); |
| while( *pRTTI == ':' ) |
| pRTTI++; |
| pLast = pRTTI; |
| if( ! *pRTTI ) |
| break; |
| } |
| else |
| pRTTI++; |
| } |
| |
| return aRet; |
| } |
| //================================================================================================== |
| static OString toRTTIname( const OString & rUNOname ) |
| { |
| OStringBuffer aRet( rUNOname.getLength()*2 ); |
| |
| sal_Int32 nIndex = 0; |
| do |
| { |
| if( nIndex > 0 ) |
| aRet.append( "::" ); |
| aRet.append( rUNOname.getToken( 0, '.', nIndex ) ); |
| } while( nIndex != -1 ); |
| |
| return aRet.makeStringAndClear(); |
| } |
| //================================================================================================== |
| |
| static OString toRTTImangledname( const OString & rRTTIname ) |
| { |
| if( rRTTIname.isEmpty() ) |
| return OString(); |
| |
| OStringBuffer aRet( rRTTIname.getLength()*2 ); |
| |
| aRet.append( "__1n" ); |
| sal_Int32 nIndex = 0; |
| do |
| { |
| OString aToken( rRTTIname.getToken( 0, ':', nIndex ) ); |
| int nBytes = aToken.getLength(); |
| if( nBytes ) |
| { |
| if( nBytes > 25 ) |
| { |
| aRet.append( (sal_Char)( nBytes/26 + 'a' ) ); |
| aRet.append( (sal_Char)( nBytes%26 + 'A' ) ); |
| } |
| else |
| aRet.append( (sal_Char)( nBytes + 'A' ) ); |
| for (sal_Int32 i = 0; i < aToken.getLength(); ++i) { |
| char c = aToken[i]; |
| if (c == 'Q') { |
| aRet.append("QdD"); |
| } else { |
| aRet.append(c); |
| } |
| } |
| } |
| } while( nIndex != -1 ); |
| |
| aRet.append( '_' ); |
| |
| return aRet.makeStringAndClear(); |
| } |
| |
| //################################################################################################## |
| //#### RTTI simulation ############################################################################# |
| //################################################################################################## |
| |
| class RTTIHolder |
| { |
| std::map< OString, void* > aAllRTTI; |
| public: |
| ~RTTIHolder(); |
| |
| void* getRTTI( const OString& rTypename ); |
| void* getRTTI_UnoName( const OString& rUnoTypename ) |
| { return getRTTI( toRTTIname( rUnoTypename ) ); } |
| |
| void* insertRTTI( const OString& rTypename ); |
| void* insertRTTI_UnoName( const OString& rTypename ) |
| { return insertRTTI( toRTTIname( rTypename ) ); } |
| void* generateRTTI( typelib_CompoundTypeDescription* pCompTypeDescr ); |
| }; |
| |
| RTTIHolder::~RTTIHolder() |
| { |
| for ( std::map< OString, void* >::const_iterator iPos( aAllRTTI.begin() ); |
| iPos != aAllRTTI.end(); ++iPos ) |
| { |
| delete[] static_cast< char * >(iPos->second); |
| } |
| } |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| #include <stdio.h> |
| #endif |
| |
| void* RTTIHolder::getRTTI( const OString& rTypename ) |
| { |
| std::map< OString, void* >::iterator element; |
| |
| element = aAllRTTI.find( rTypename ); |
| if( element != aAllRTTI.end() ) |
| return (*element).second; |
| |
| // create rtti structure |
| element = aAllRTTI.find( rTypename ); |
| if( element != aAllRTTI.end() ) |
| return (*element).second; |
| |
| return NULL; |
| } |
| |
| static long nMagicId = 1; |
| |
| void* RTTIHolder::insertRTTI( const OString& rTypename ) |
| { |
| OString aMangledName( toRTTImangledname( rTypename ) ); |
| NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() ); |
| |
| |
| // rSuperTypename MUST exist !!! |
| std::size_t const RTTI_SIZE = 19; // 14??? |
| void** pRTTI = reinterpret_cast< void ** >( |
| new char[RTTI_SIZE * sizeof (void *) + strlen(rTypename.getStr()) + 1]); |
| pRTTI[ 0 ] = reinterpret_cast< void * >(RTTI_SIZE * sizeof (void *)); |
| pRTTI[ 1 ] = NULL; |
| pRTTI[ 2 ] = (void*)(7*sizeof(void*)); |
| pRTTI[ 3 ] = (void*)aHash.getHash()[0]; |
| pRTTI[ 4 ] = (void*)aHash.getHash()[1]; |
| pRTTI[ 5 ] = (void*)aHash.getHash()[2]; |
| pRTTI[ 6 ] = (void*)aHash.getHash()[3]; |
| pRTTI[ 7 ] = NULL; |
| pRTTI[ 8 ] = NULL; |
| |
| pRTTI[ 9 ] = pRTTI[ 3 ]; |
| pRTTI[ 10 ] = pRTTI[ 4 ]; |
| pRTTI[ 11 ] = pRTTI[ 5 ]; |
| pRTTI[ 12 ] = pRTTI[ 6 ]; |
| pRTTI[ 13 ] = (void*)0x80000000; |
| strcpy(reinterpret_cast< char * >(pRTTI + RTTI_SIZE), rTypename.getStr()); |
| |
| aAllRTTI[ rTypename ] = (void*)pRTTI; |
| #if OSL_DEBUG_LEVEL > 1 |
| fprintf( stderr, |
| "generating base RTTI for type %s:\n" |
| " mangled: %s\n" |
| " hash: %.8x %.8x %.8x %.8x\n", |
| rTypename.getStr(), |
| aMangledName.getStr(), |
| pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ] |
| ); |
| #endif |
| return pRTTI; |
| } |
| |
| void* RTTIHolder::generateRTTI( typelib_CompoundTypeDescription * pCompTypeDescr ) |
| { |
| OString aUNOCompTypeName( OUStringToOString( pCompTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US ) ); |
| OString aRTTICompTypeName( toRTTIname( aUNOCompTypeName ) ); |
| |
| void* pHaveRTTI = getRTTI( aRTTICompTypeName ); |
| if( pHaveRTTI ) |
| return pHaveRTTI; |
| |
| if( ! pCompTypeDescr->pBaseTypeDescription ) |
| // this is a base type |
| return insertRTTI( aRTTICompTypeName ); |
| |
| // get base class RTTI |
| void* pSuperRTTI = generateRTTI( pCompTypeDescr->pBaseTypeDescription ); |
| OSL_ENSURE( pSuperRTTI, "could not generate RTTI for supertype !" ); |
| |
| // find out the size to allocate for RTTI |
| void** pInherit = (void**)((sal_uInt32)pSuperRTTI + ((sal_uInt32*)pSuperRTTI)[2] + 8); |
| int nInherit; |
| for( nInherit = 1; pInherit[ nInherit*5-1 ] != (void*)0x80000000; nInherit++ ) |
| ; |
| |
| OString aMangledName( toRTTImangledname( aRTTICompTypeName ) ); |
| NIST_Hash aHash( aMangledName.getStr(), aMangledName.getLength() ); |
| |
| std::size_t const rttiSize = 14 + nInherit * 5; |
| void** pRTTI = reinterpret_cast< void ** >( |
| new char[ |
| rttiSize * sizeof (void *) |
| + strlen(aRTTICompTypeName.getStr()) + 1]); |
| pRTTI[ 0 ] = reinterpret_cast< void * >(rttiSize * sizeof (void *)); |
| pRTTI[ 1 ] = NULL; |
| pRTTI[ 2 ] = (void*)(7*sizeof(void*)); |
| pRTTI[ 3 ] = (void*)aHash.getHash()[0]; |
| pRTTI[ 4 ] = (void*)aHash.getHash()[1]; |
| pRTTI[ 5 ] = (void*)aHash.getHash()[2]; |
| pRTTI[ 6 ] = (void*)aHash.getHash()[3]; |
| pRTTI[ 7 ] = NULL; |
| pRTTI[ 8 ] = NULL; |
| |
| memcpy( pRTTI+9, pInherit, 4*nInherit*5 ); |
| pRTTI[ 8 +nInherit*5 ] = NULL; |
| pRTTI[ 9 +nInherit*5 ] = pRTTI[ 3 ]; |
| pRTTI[ 10+nInherit*5 ] = pRTTI[ 4 ]; |
| pRTTI[ 11+nInherit*5 ] = pRTTI[ 5 ]; |
| pRTTI[ 12+nInherit*5 ] = pRTTI[ 6 ]; |
| pRTTI[ 13+nInherit*5 ] = (void*)0x80000000; |
| strcpy( |
| reinterpret_cast< char * >(pRTTI + rttiSize), |
| aRTTICompTypeName.getStr()); |
| |
| aAllRTTI[ aRTTICompTypeName ] = (void*)pRTTI; |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| fprintf( stderr, |
| "generating struct RTTI for type %s:\n" |
| " mangled: %s\n" |
| " hash: %.8x %.8x %.8X %.8x\n", |
| aRTTICompTypeName.getStr(), |
| aMangledName.getStr(), |
| pRTTI[ 3 ], pRTTI[ 4 ], pRTTI[ 5 ], pRTTI[ 6 ] |
| ); |
| #endif |
| |
| return pRTTI; |
| } |
| |
| //__________________________________________________________________________________________________ |
| |
| static void deleteException( |
| void* pExc, unsigned char* thunk, typelib_TypeDescription* pType ) |
| { |
| uno_destructData( |
| pExc, pType, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); |
| typelib_typedescription_release( pType ); |
| delete[] thunk; |
| } |
| |
| //__________________________________________________________________________________________________ |
| |
| //################################################################################################## |
| //#### exported #################################################################################### |
| //################################################################################################## |
| |
| void cc50_solaris_intel_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) |
| { |
| #if OSL_DEBUG_LEVEL > 1 |
| OString cstr( |
| OUStringToOString( |
| *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ), |
| RTL_TEXTENCODING_ASCII_US ) ); |
| fprintf( stderr, "> uno exception occured: %s\n", cstr.getStr() ); |
| #endif |
| bridges::cpp_uno::shared::ArrayPointer< unsigned char > thunkPtr( |
| new unsigned char[24]); |
| typelib_TypeDescription * pTypeDescr = 0; |
| // will be released by deleteException |
| typelib_typedescriptionreference_getDescription( &pTypeDescr, pUnoExc->pType ); |
| |
| void* pRTTI; |
| { |
| static ::osl::Mutex aMutex; |
| ::osl::Guard< ::osl::Mutex > guard( aMutex ); |
| |
| static RTTIHolder * s_pRTTI = 0; |
| if (! s_pRTTI) |
| { |
| #ifdef LEAK_STATIC_DATA |
| s_pRTTI = new RTTIHolder(); |
| #else |
| static RTTIHolder s_aRTTI; |
| s_pRTTI = &s_aRTTI; |
| #endif |
| } |
| |
| pRTTI = s_pRTTI->generateRTTI( (typelib_CompoundTypeDescription *)pTypeDescr ); |
| } |
| |
| // a must be |
| OSL_ENSURE( sizeof(sal_Int32) == sizeof(void *), "### pointer size differs from sal_Int32!" ); |
| |
| void * pCppExc = __Crun::ex_alloc( pTypeDescr->nSize ); |
| uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); |
| |
| // destruct uno exception |
| uno_any_destruct( pUnoExc, 0 ); |
| |
| unsigned char * thunk = thunkPtr.release(); |
| // movl %esp, %ecx: |
| thunk[0] = 0x8B; |
| thunk[1] = 0xCC; |
| // pushl pTypeDescr: |
| thunk[2] = 0x68; |
| *reinterpret_cast< void ** >(thunk + 3) = pTypeDescr; |
| // pushl thunk: |
| thunk[7] = 0x68; |
| *reinterpret_cast< void ** >(thunk + 8) = thunk; |
| // pushl 4(%ecx): |
| thunk[12] = 0xFF; |
| thunk[13] = 0x71; |
| thunk[14] = 0x04; |
| // call deleteException: |
| thunk[15] = 0xE8; |
| #pragma disable_warn |
| void * d = reinterpret_cast< void * >(deleteException); |
| #pragma enable_warn |
| *reinterpret_cast< std::ptrdiff_t * >(thunk + 16) = |
| static_cast< unsigned char * >(d) - (thunk + 20); |
| // addl $12, %esp: |
| thunk[20] = 0x83; |
| thunk[21] = 0xC4; |
| thunk[22] = 0x0C; |
| // ret: |
| thunk[23] = 0xC3; |
| |
| #pragma disable_warn |
| void (* f)(void *) = reinterpret_cast< void (*)(void *) >(thunk); |
| #pragma enable_warn |
| __Crun::ex_throw(pCppExc, (const __Crun::static_type_info*)pRTTI, f); |
| } |
| |
| void cc50_solaris_intel_fillUnoException( |
| void* pCppExc, |
| const char* pInfo, |
| uno_Any* pUnoExc, |
| uno_Mapping * pCpp2Uno ) |
| { |
| OSL_ASSERT( pInfo != 0 ); |
| OString uno_name( toUNOname( pInfo ) ); |
| OUString aName( OStringToOUString( |
| uno_name, RTL_TEXTENCODING_ASCII_US ) ); |
| typelib_TypeDescription * pExcTypeDescr = 0; |
| typelib_typedescription_getByName( &pExcTypeDescr, aName.pData ); |
| |
| if (pExcTypeDescr == 0) // the thing that should not be |
| { |
| RuntimeException aRE( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "exception type not found: ") ) + aName, |
| Reference< XInterface >() ); |
| Type const & rType = ::getCppuType( &aRE ); |
| uno_type_any_constructAndConvert( |
| pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); |
| #if OSL_DEBUG_LEVEL > 0 |
| OString cstr( OUStringToOString( |
| aRE.Message, RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_ENSURE( 0, cstr.getStr() ); |
| #endif |
| return; |
| } |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| fprintf( stderr, "> c++ exception occured: %s\n", |
| ::rtl::OUStringToOString( |
| pExcTypeDescr->pTypeName, |
| RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| #endif |
| // construct uno exception any |
| uno_any_constructAndConvert( |
| pUnoExc, pCppExc, pExcTypeDescr, pCpp2Uno ); |
| typelib_typedescription_release( pExcTypeDescr ); |
| } |
| |
| } |
| |