blob: e616d6aef4f5c329cfe6a62a0f340c4cb0ffc3e5 [file] [log] [blame]
/**************************************************************
*
* 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 );
}
}