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