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