PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/bridges/source/cpp_uno/cc50_solaris_intel/except.cxx

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