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 #include "precompiled_bridges.hxx"
25 #include "sal/config.h"
26
27 #include <cstddef>
28 #include <cstring>
29 #include <map>
30 #include <utility>
31 #include <vector>
32
33 #include "bridges/cpp_uno/shared/arraypointer.hxx"
34 #include "com/sun/star/uno/Reference.hxx"
35 #include "com/sun/star/uno/RuntimeException.hpp"
36 #include "com/sun/star/uno/XInterface.hpp"
37 #include "com/sun/star/uno/genfunc.hxx"
38 #include "osl/diagnose.h"
39 #include "osl/mutex.hxx"
40 #include "rtl/strbuf.hxx"
41 #include "rtl/string.hxx"
42 #include "rtl/textenc.h"
43 #include "rtl/ustring.h"
44 #include "rtl/ustring.hxx"
45 #include "sal/types.h"
46 #include "typelib/typeclass.h"
47 #include "typelib/typedescription.h"
48 #include "uno/any2.h"
49 #include "uno/data.h"
50 #include "uno/mapping.h"
51
52 #include "exceptions.hxx"
53 #include "flushcode.hxx"
54
55 namespace {
56
57 namespace css = com::sun::star;
58
59 typedef void (* Function)(void *);
60
toFunction(void * pointer)61 Function toFunction(void * pointer) {
62 #pragma disable_warn
63 return reinterpret_cast< Function >(pointer);
64 #pragma enable_warn
65 }
66
toUnoName(char const * rttiName,rtl::OUString * unoName)67 bool toUnoName(char const * rttiName, rtl::OUString * unoName) {
68 rtl::OStringBuffer buf;
69 for (;;) {
70 char const * p = std::strchr(rttiName, ':');
71 if (p == NULL) {
72 buf.append(rttiName);
73 break;
74 }
75 if (p - rttiName > SAL_MAX_INT32) {
76 return false;
77 }
78 buf.append(rttiName, sal::static_int_cast< sal_Int32 >(p - rttiName));
79 buf.append(".");
80 while (*p == ':') {
81 ++p;
82 }
83 rttiName = p;
84 }
85 *unoName = rtl::OStringToOUString(
86 buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8);
87 //TODO: check conversion failure
88 return true;
89 }
90
91 class NistHash {
92 public:
93 NistHash(rtl::OString const & text);
94
95 sal_uInt32 hashdata[5];
96
97 private:
f1(sal_uInt32 x,sal_uInt32 y,sal_uInt32 z)98 static sal_uInt32 f1(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z)
99 { return z ^ (x & (y ^ z)); }
100
f2(sal_uInt32 x,sal_uInt32 y,sal_uInt32 z)101 static sal_uInt32 f2(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z)
102 { return x ^ y ^ z; }
103
f3(sal_uInt32 x,sal_uInt32 y,sal_uInt32 z)104 static sal_uInt32 f3(sal_uInt32 x, sal_uInt32 y, sal_uInt32 z)
105 { return (x & y) + (z & (x ^ y)); }
106
rotl(sal_uInt32 value,sal_uInt32 bits)107 static sal_uInt32 rotl(sal_uInt32 value, sal_uInt32 bits)
108 { return (value << bits) | (value >> (32 - bits)); }
109
expand_nostore(sal_uInt32 index)110 sal_uInt32 expand_nostore(sal_uInt32 index) {
111 return data[index & 15] ^ data[(index - 14) & 15] ^
112 data[(index - 8) & 15] ^ data[(index - 3) & 15];
113 }
114
expand_store(sal_uInt32 index)115 sal_uInt32 expand_store(sal_uInt32 index) {
116 return data[index & 15] ^= data[(index - 14) & 15] ^
117 data[(index - 8) & 15] ^ data[(index - 3) & 15];
118 }
119
subRound(sal_uInt32 a,sal_uInt32 & b,sal_uInt32 c,sal_uInt32 d,sal_uInt32 & e,sal_uInt32 constant,sal_uInt32 datum,sal_uInt32 function)120 void subRound(
121 sal_uInt32 a, sal_uInt32 & b, sal_uInt32 c, sal_uInt32 d,
122 sal_uInt32 & e, sal_uInt32 constant, sal_uInt32 datum,
123 sal_uInt32 function)
124 {
125 e += rotl(a, 5);
126 switch (function) {
127 case 1:
128 e += f1(b, c, d);
129 break;
130 case 2:
131 case 4:
132 e += f2(b, c, d);
133 break;
134 case 3:
135 e += f3(b, c, d);
136 break;
137 }
138 e += constant + datum;
139 b = rotl(b, 30);
140 }
141
142 void transform();
143
144 sal_uInt32 data[16];
145 };
146
NistHash(rtl::OString const & text)147 NistHash::NistHash(rtl::OString const & text) {
148 hashdata[0] = 0x67452301;
149 hashdata[1] = 0xefcdab89;
150 hashdata[2] = 0x98badcfe;
151 hashdata[3] = 0x10325476;
152 hashdata[4] = 0xc3d2e1f0;
153 char const * p = text.getStr();
154 sal_Int32 n = text.getLength();
155 while (n >= sizeof data) {
156 std::memcpy(data, p, sizeof data);
157 p += sizeof data;
158 n -= sizeof data;
159 transform();
160 }
161 std::memcpy(data, p, n);
162 reinterpret_cast< unsigned char *>(data)[n++] = 0x80;
163 if (n > sizeof data - 8) {
164 std::memset(reinterpret_cast< char * >(data) + n, 0, sizeof data - n);
165 transform();
166 std::memset(data, 0, sizeof data - 8);
167 } else {
168 std::memset(
169 reinterpret_cast< char * >(data) + n, 0, sizeof data - 8 - n);
170 }
171 data[14] = 0;
172 data[15] = text.getLength() << 3;
173 transform();
174 }
175
transform()176 void NistHash::transform() {
177 sal_uInt32 const K2 = 0x5A827999;
178 sal_uInt32 const K3 = 0x6ED9EBA1;
179 sal_uInt32 const K5 = 0x8F1BBCDC;
180 sal_uInt32 const K10 = 0xCA62C1D6;
181 sal_uInt32 a = hashdata[0];
182 sal_uInt32 b = hashdata[1];
183 sal_uInt32 c = hashdata[2];
184 sal_uInt32 d = hashdata[3];
185 sal_uInt32 e = hashdata[4];
186 subRound(a, b, c, d, e, K2, data[ 0], 1);
187 subRound(e, a, b, c, d, K2, data[ 1], 1);
188 subRound(d, e, a, b, c, K2, data[ 2], 1);
189 subRound(c, d, e, a, b, K2, data[ 3], 1);
190 subRound(b, c, d, e, a, K2, data[ 4], 1);
191 subRound(a, b, c, d, e, K2, data[ 5], 1);
192 subRound(e, a, b, c, d, K2, data[ 6], 1);
193 subRound(d, e, a, b, c, K2, data[ 7], 1);
194 subRound(c, d, e, a, b, K2, data[ 8], 1);
195 subRound(b, c, d, e, a, K2, data[ 9], 1);
196 subRound(a, b, c, d, e, K2, data[10], 1);
197 subRound(e, a, b, c, d, K2, data[11], 1);
198 subRound(d, e, a, b, c, K2, data[12], 1);
199 subRound(c, d, e, a, b, K2, data[13], 1);
200 subRound(b, c, d, e, a, K2, data[14], 1);
201 subRound(a, b, c, d, e, K2, data[15], 1);
202 subRound(e, a, b, c, d, K2, expand_store(16), 1);
203 subRound(d, e, a, b, c, K2, expand_store(17), 1);
204 subRound(c, d, e, a, b, K2, expand_store(18), 1);
205 subRound(b, c, d, e, a, K2, expand_store(19), 1);
206 subRound(a, b, c, d, e, K3, expand_store(20), 2);
207 subRound(e, a, b, c, d, K3, expand_store(21), 2);
208 subRound(d, e, a, b, c, K3, expand_store(22), 2);
209 subRound(c, d, e, a, b, K3, expand_store(23), 2);
210 subRound(b, c, d, e, a, K3, expand_store(24), 2);
211 subRound(a, b, c, d, e, K3, expand_store(25), 2);
212 subRound(e, a, b, c, d, K3, expand_store(26), 2);
213 subRound(d, e, a, b, c, K3, expand_store(27), 2);
214 subRound(c, d, e, a, b, K3, expand_store(28), 2);
215 subRound(b, c, d, e, a, K3, expand_store(29), 2);
216 subRound(a, b, c, d, e, K3, expand_store(30), 2);
217 subRound(e, a, b, c, d, K3, expand_store(31), 2);
218 subRound(d, e, a, b, c, K3, expand_store(32), 2);
219 subRound(c, d, e, a, b, K3, expand_store(33), 2);
220 subRound(b, c, d, e, a, K3, expand_store(34), 2);
221 subRound(a, b, c, d, e, K3, expand_store(35), 2);
222 subRound(e, a, b, c, d, K3, expand_store(36), 2);
223 subRound(d, e, a, b, c, K3, expand_store(37), 2);
224 subRound(c, d, e, a, b, K3, expand_store(38), 2);
225 subRound(b, c, d, e, a, K3, expand_store(39), 2);
226 subRound(a, b, c, d, e, K5, expand_store(40), 3);
227 subRound(e, a, b, c, d, K5, expand_store(41), 3);
228 subRound(d, e, a, b, c, K5, expand_store(42), 3);
229 subRound(c, d, e, a, b, K5, expand_store(43), 3);
230 subRound(b, c, d, e, a, K5, expand_store(44), 3);
231 subRound(a, b, c, d, e, K5, expand_store(45), 3);
232 subRound(e, a, b, c, d, K5, expand_store(46), 3);
233 subRound(d, e, a, b, c, K5, expand_store(47), 3);
234 subRound(c, d, e, a, b, K5, expand_store(48), 3);
235 subRound(b, c, d, e, a, K5, expand_store(49), 3);
236 subRound(a, b, c, d, e, K5, expand_store(50), 3);
237 subRound(e, a, b, c, d, K5, expand_store(51), 3);
238 subRound(d, e, a, b, c, K5, expand_store(52), 3);
239 subRound(c, d, e, a, b, K5, expand_store(53), 3);
240 subRound(b, c, d, e, a, K5, expand_store(54), 3);
241 subRound(a, b, c, d, e, K5, expand_store(55), 3);
242 subRound(e, a, b, c, d, K5, expand_store(56), 3);
243 subRound(d, e, a, b, c, K5, expand_store(57), 3);
244 subRound(c, d, e, a, b, K5, expand_store(58), 3);
245 subRound(b, c, d, e, a, K5, expand_store(59), 3);
246 subRound(a, b, c, d, e, K10, expand_store(60), 4);
247 subRound(e, a, b, c, d, K10, expand_store(61), 4);
248 subRound(d, e, a, b, c, K10, expand_store(62), 4);
249 subRound(c, d, e, a, b, K10, expand_store(63), 4);
250 subRound(b, c, d, e, a, K10, expand_store(64), 4);
251 subRound(a, b, c, d, e, K10, expand_store(65), 4);
252 subRound(e, a, b, c, d, K10, expand_store(66), 4);
253 subRound(d, e, a, b, c, K10, expand_store(67), 4);
254 subRound(c, d, e, a, b, K10, expand_store(68), 4);
255 subRound(b, c, d, e, a, K10, expand_store(69), 4);
256 subRound(a, b, c, d, e, K10, expand_store(70), 4);
257 subRound(e, a, b, c, d, K10, expand_store(71), 4);
258 subRound(d, e, a, b, c, K10, expand_store(72), 4);
259 subRound(c, d, e, a, b, K10, expand_store(73), 4);
260 subRound(b, c, d, e, a, K10, expand_store(74), 4);
261 subRound(a, b, c, d, e, K10, expand_store(75), 4);
262 subRound(e, a, b, c, d, K10, expand_store(76), 4);
263 subRound(d, e, a, b, c, K10, expand_nostore(77), 4);
264 subRound(c, d, e, a, b, K10, expand_nostore(78), 4);
265 subRound(b, c, d, e, a, K10, expand_nostore(79), 4);
266 hashdata[0] += a;
267 hashdata[1] += b;
268 hashdata[2] += c;
269 hashdata[3] += d;
270 hashdata[4] += e;
271 }
272
273 class RttiMap {
274 public:
275 static __Crun::static_type_info const * get(
276 typelib_CompoundTypeDescription const * type);
277
278 private:
279 RttiMap(); // not defined
280 RttiMap(RttiMap &); // not defined
281 ~RttiMap(); // not defined
282 void operator =(RttiMap &); // not defined
283
284 struct Data {
285 __Crun::static_type_info * info;
286 rtl::OString cppName;
287 std::vector< __Crun::class_base_descr > bases;
288 };
289 typedef std::map< rtl::OUString, Data > Map;
290
291 static void toCppNames(
292 rtl::OUString const & unoName, rtl::OString * cppName,
293 rtl::OString * rttiName);
294
295 static Data const & get_(typelib_CompoundTypeDescription const * type);
296
297 static osl::Mutex m_mutex;
298 static Map * m_map;
299 };
300
301 osl::Mutex RttiMap::m_mutex;
302 RttiMap::Map * RttiMap::m_map;
303
get(typelib_CompoundTypeDescription const * type)304 __Crun::static_type_info const * RttiMap::get(
305 typelib_CompoundTypeDescription const * type)
306 {
307 osl::MutexGuard g(m_mutex);
308 if (m_map == NULL) {
309 m_map = new Map; // leaked
310 }
311 return get_(type).info;
312 }
313
toCppNames(rtl::OUString const & unoName,rtl::OString * cppName,rtl::OString * rttiName)314 void RttiMap::toCppNames(
315 rtl::OUString const & unoName, rtl::OString * cppName,
316 rtl::OString * rttiName)
317 {
318 OSL_ASSERT(cppName != NULL && rttiName != NULL);
319 rtl::OStringBuffer bc;
320 rtl::OStringBuffer br;
321 br.append("__1n");
322 for (sal_Int32 i = 0; i != -1;) {
323 rtl::OUString tok(unoName.getToken(0, '.', i));
324 bc.append(rtl::OUStringToOString(tok, RTL_TEXTENCODING_UTF8));
325 // conversion should never fail, as tok should be well-formed ASCII
326 if (i != -1) {
327 bc.append("::");
328 }
329 sal_Int32 len = tok.getLength();
330 sal_Int32 pos = br.getLength();
331 for (sal_Int32 n = len / 26; n > 0; n /= 26) {
332 br.insert(pos, static_cast< char >('a' + (n % 26)));
333 }
334 br.append(static_cast< char >('A' + (len % 26)));
335 for (sal_Int32 j = 0; j < len; ++j) {
336 sal_Unicode c = tok[j];
337 OSL_ASSERT(
338 c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c == '_' ||
339 c >= 'a' && c <= 'z');
340 if (c == 'Q') {
341 br.append("QdD");
342 } else {
343 br.append(static_cast< char >(c));
344 }
345 }
346 }
347 br.append('_');
348 *cppName = bc.makeStringAndClear();
349 *rttiName = br.makeStringAndClear();
350 }
351
get_(typelib_CompoundTypeDescription const * type)352 RttiMap::Data const & RttiMap::get_(
353 typelib_CompoundTypeDescription const * type)
354 {
355 rtl::OUString name(type->aBase.pTypeName);
356 Map::iterator it(m_map->find(name));
357 if (it == m_map->end()) {
358 it = m_map->insert(std::make_pair(name, Data())).first;
359 Data & data = it->second;
360 rtl::OString rttiName;
361 toCppNames(name, &data.cppName, &rttiName);
362 data.info = new __Crun::static_type_info;
363 data.info->ty_name = data.cppName.getStr() -
364 reinterpret_cast< char * >(&data.info->ty_name);
365 data.info->reserved = 0;
366 NistHash hash(rttiName);
367 data.info->type_hash[0] = hash.hashdata[0];
368 data.info->type_hash[1] = hash.hashdata[1];
369 data.info->type_hash[2] = hash.hashdata[2];
370 data.info->type_hash[3] = hash.hashdata[3];
371 data.info->flags = 0;
372 data.info->cv_qualifiers = 0;
373 if (type->pBaseTypeDescription != NULL) {
374 data.bases = get_(type->pBaseTypeDescription).bases;
375 OSL_ASSERT(!data.bases.empty());
376 data.bases.back().offset = 0;
377 }
378 __Crun::class_base_descr last;
379 last.type_hash[0] = data.info->type_hash[0];
380 last.type_hash[1] = data.info->type_hash[1];
381 last.type_hash[2] = data.info->type_hash[2];
382 last.type_hash[3] = data.info->type_hash[3];
383 last.offset = 0x8000000000000000;
384 data.bases.push_back(last);
385 data.info->base_table = reinterpret_cast< char * >(&data.bases[0]) -
386 reinterpret_cast< char * >(&data.info->base_table);
387 }
388 return it->second;
389 }
390
deleteException(void * exception,unsigned int * thunk,typelib_TypeDescription * type)391 void deleteException(
392 void * exception, unsigned int * thunk, typelib_TypeDescription * type)
393 {
394 uno_destructData(
395 exception, type,
396 reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release));
397 typelib_typedescription_release(type);
398 delete[] thunk;
399 }
400
401 }
402
403 namespace bridges { namespace cpp_uno { namespace cc5_solaris_sparc64 {
404
raiseException(uno_Any * exception,uno_Mapping * unoToCpp)405 void raiseException(uno_Any * exception, uno_Mapping * unoToCpp) {
406 bridges::cpp_uno::shared::ArrayPointer< unsigned long > thunkPtr(
407 new unsigned long[4]);
408 typelib_TypeDescription * type = NULL;
409 typelib_typedescriptionreference_getDescription(&type, exception->pType);
410 __Crun::static_type_info const * rtti = RttiMap::get(
411 reinterpret_cast< typelib_CompoundTypeDescription * >(type));
412 void * exc = __Crun::ex_alloc(type->nSize);
413 uno_copyAndConvertData(exc, exception->pData, type, unoToCpp);
414 uno_any_destruct(exception, NULL);
415 unsigned long * thunk = thunkPtr.release();
416 // 0*4: rd %pc, %o1:
417 // 1*4: ldx %o1, (6-0)*4, %o3:
418 thunk[0] = 0x93414000D65A6018;
419 // 2*4: jmpl %o3, %g0, %g0:
420 // 3*4: ldx %o1, (4-0)*4, %o2:
421 thunk[1] = 0x81C2C000D45A6010;
422 // 4*4: .xword type:
423 thunk[2] = reinterpret_cast< unsigned long >(type);
424 // 6*4: .xword deleteException:
425 thunk[3] = reinterpret_cast< unsigned long >(deleteException);
426 flushCode(thunk, thunk + 4);
427 __Crun::ex_throw(exc, rtti, toFunction(thunk));
428 }
429
fillUnoException(void * cppException,char const * cppName,uno_Any * unoException,uno_Mapping * cppToUno)430 void fillUnoException(
431 void * cppException, char const * cppName, uno_Any * unoException,
432 uno_Mapping * cppToUno)
433 {
434 rtl::OUString name;
435 typelib_TypeDescription * type = NULL;
436 if (toUnoName(cppName, &name)) {
437 typelib_typedescription_getByName(&type, name.pData);
438 }
439 if (type == NULL || type->eTypeClass != typelib_TypeClass_EXCEPTION) {
440 css::uno::RuntimeException exc(
441 (rtl::OUString(
442 RTL_CONSTASCII_USTRINGPARAM("Not a UNO exception type: ")) +
443 name),
444 css::uno::Reference< css::uno::XInterface >());
445 uno_type_any_constructAndConvert(
446 unoException, &exc, getCppuType(&exc).getTypeLibType(), cppToUno);
447 } else {
448 uno_any_constructAndConvert(unoException, cppException, type, cppToUno);
449 }
450 if (type != NULL) {
451 typelib_typedescription_release(type);
452 }
453 }
454
455 } } }
456