1 // New abi Support -*- C++ -*- 2 3 // Copyright (C) 2000, 2001, 2003, 2004, 2009 Free Software Foundation, Inc. 4 // 5 // This file is part of GCC. 6 // 7 // GCC is free software; you can redistribute it and/or modify 8 // it under the terms of the GNU General Public License as published by 9 // the Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 12 // GCC is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 // Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com> 27 28 #include <cxxabi.h> 29 #include <new> 30 #include <exception> 31 #include <exception_defines.h> 32 #include "unwind-cxx.h" 33 34 namespace __cxxabiv1 35 { 36 namespace 37 { 38 struct uncatch_exception 39 { 40 uncatch_exception(); 41 ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); } 42 43 __cxa_exception* p; 44 45 private: 46 uncatch_exception& 47 operator=(const uncatch_exception&); 48 49 uncatch_exception(const uncatch_exception&); 50 }; 51 52 uncatch_exception::uncatch_exception() : p(0) 53 { 54 __cxa_eh_globals *globals = __cxa_get_globals_fast (); 55 56 p = globals->caughtExceptions; 57 p->handlerCount -= 1; 58 globals->caughtExceptions = p->nextException; 59 globals->uncaughtExceptions += 1; 60 } 61 } 62 63 // Allocate and construct array. 64 extern "C" void * 65 __cxa_vec_new(std::size_t element_count, 66 std::size_t element_size, 67 std::size_t padding_size, 68 __cxa_cdtor_type constructor, 69 __cxa_cdtor_type destructor) 70 { 71 return __cxa_vec_new2(element_count, element_size, padding_size, 72 constructor, destructor, 73 &operator new[], &operator delete []); 74 } 75 76 extern "C" void * 77 __cxa_vec_new2(std::size_t element_count, 78 std::size_t element_size, 79 std::size_t padding_size, 80 __cxa_cdtor_type constructor, 81 __cxa_cdtor_type destructor, 82 void *(*alloc) (std::size_t), 83 void (*dealloc) (void *)) 84 { 85 std::size_t size = element_count * element_size + padding_size; 86 char *base = static_cast <char *> (alloc (size)); 87 if (!base) 88 return base; 89 90 if (padding_size) 91 { 92 base += padding_size; 93 reinterpret_cast <std::size_t *> (base)[-1] = element_count; 94 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 95 reinterpret_cast <std::size_t *> (base)[-2] = element_size; 96 #endif 97 } 98 __try 99 { 100 __cxa_vec_ctor(base, element_count, element_size, 101 constructor, destructor); 102 } 103 __catch(...) 104 { 105 { 106 uncatch_exception ue; 107 // Core issue 901 will probably be resolved such that a 108 // deleted operator delete means not freeing memory here. 109 if (dealloc) 110 dealloc(base - padding_size); 111 } 112 __throw_exception_again; 113 } 114 return base; 115 } 116 117 extern "C" void * 118 __cxa_vec_new3(std::size_t element_count, 119 std::size_t element_size, 120 std::size_t padding_size, 121 __cxa_cdtor_type constructor, 122 __cxa_cdtor_type destructor, 123 void *(*alloc) (std::size_t), 124 void (*dealloc) (void *, std::size_t)) 125 { 126 std::size_t size = element_count * element_size + padding_size; 127 char *base = static_cast<char *>(alloc (size)); 128 if (!base) 129 return base; 130 131 if (padding_size) 132 { 133 base += padding_size; 134 reinterpret_cast<std::size_t *>(base)[-1] = element_count; 135 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 136 reinterpret_cast <std::size_t *> (base)[-2] = element_size; 137 #endif 138 } 139 __try 140 { 141 __cxa_vec_ctor(base, element_count, element_size, 142 constructor, destructor); 143 } 144 __catch(...) 145 { 146 { 147 uncatch_exception ue; 148 if (dealloc) 149 dealloc(base - padding_size, size); 150 } 151 __throw_exception_again; 152 } 153 return base; 154 } 155 156 // Construct array. 157 extern "C" __cxa_vec_ctor_return_type 158 __cxa_vec_ctor(void *array_address, 159 std::size_t element_count, 160 std::size_t element_size, 161 __cxa_cdtor_type constructor, 162 __cxa_cdtor_type destructor) 163 { 164 std::size_t ix = 0; 165 char *ptr = static_cast<char *>(array_address); 166 167 __try 168 { 169 if (constructor) 170 for (; ix != element_count; ix++, ptr += element_size) 171 constructor(ptr); 172 } 173 __catch(...) 174 { 175 { 176 uncatch_exception ue; 177 __cxa_vec_cleanup(array_address, ix, element_size, destructor); 178 } 179 __throw_exception_again; 180 } 181 _GLIBCXX_CXA_VEC_CTOR_RETURN (array_address); 182 } 183 184 // Construct an array by copying. 185 extern "C" __cxa_vec_ctor_return_type 186 __cxa_vec_cctor(void *dest_array, 187 void *src_array, 188 std::size_t element_count, 189 std::size_t element_size, 190 __cxa_cdtor_return_type (*constructor) (void *, void *), 191 __cxa_cdtor_type destructor) 192 { 193 std::size_t ix = 0; 194 char *dest_ptr = static_cast<char *>(dest_array); 195 char *src_ptr = static_cast<char *>(src_array); 196 197 __try 198 { 199 if (constructor) 200 for (; ix != element_count; 201 ix++, src_ptr += element_size, dest_ptr += element_size) 202 constructor(dest_ptr, src_ptr); 203 } 204 __catch(...) 205 { 206 { 207 uncatch_exception ue; 208 __cxa_vec_cleanup(dest_array, ix, element_size, destructor); 209 } 210 __throw_exception_again; 211 } 212 _GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array); 213 } 214 215 // Destruct array. 216 extern "C" void 217 __cxa_vec_dtor(void *array_address, 218 std::size_t element_count, 219 std::size_t element_size, 220 __cxa_cdtor_type destructor) 221 { 222 if (destructor) 223 { 224 char *ptr = static_cast<char *>(array_address); 225 std::size_t ix = element_count; 226 227 ptr += element_count * element_size; 228 229 __try 230 { 231 while (ix--) 232 { 233 ptr -= element_size; 234 destructor(ptr); 235 } 236 } 237 __catch(...) 238 { 239 { 240 uncatch_exception ue; 241 __cxa_vec_cleanup(array_address, ix, element_size, destructor); 242 } 243 __throw_exception_again; 244 } 245 } 246 } 247 248 // Destruct array as a result of throwing an exception. 249 // [except.ctor]/3 If a destructor called during stack unwinding 250 // exits with an exception, terminate is called. 251 extern "C" void 252 __cxa_vec_cleanup(void *array_address, 253 std::size_t element_count, 254 std::size_t element_size, 255 __cxa_cdtor_type destructor) throw() 256 { 257 if (destructor) 258 { 259 char *ptr = static_cast <char *> (array_address); 260 std::size_t ix = element_count; 261 262 ptr += element_count * element_size; 263 264 __try 265 { 266 while (ix--) 267 { 268 ptr -= element_size; 269 destructor(ptr); 270 } 271 } 272 __catch(...) 273 { 274 std::terminate(); 275 } 276 } 277 } 278 279 // Destruct and release array. 280 extern "C" void 281 __cxa_vec_delete(void *array_address, 282 std::size_t element_size, 283 std::size_t padding_size, 284 __cxa_cdtor_type destructor) 285 { 286 __cxa_vec_delete2(array_address, element_size, padding_size, 287 destructor, 288 &operator delete []); 289 } 290 291 extern "C" void 292 __cxa_vec_delete2(void *array_address, 293 std::size_t element_size, 294 std::size_t padding_size, 295 __cxa_cdtor_type destructor, 296 void (*dealloc) (void *)) 297 { 298 if (!array_address) 299 return; 300 301 char* base = static_cast<char *>(array_address); 302 303 if (padding_size) 304 { 305 std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1]; 306 base -= padding_size; 307 __try 308 { 309 __cxa_vec_dtor(array_address, element_count, element_size, 310 destructor); 311 } 312 __catch(...) 313 { 314 { 315 uncatch_exception ue; 316 dealloc(base); 317 } 318 __throw_exception_again; 319 } 320 } 321 dealloc(base); 322 } 323 324 extern "C" void 325 __cxa_vec_delete3(void *array_address, 326 std::size_t element_size, 327 std::size_t padding_size, 328 __cxa_cdtor_type destructor, 329 void (*dealloc) (void *, std::size_t)) 330 { 331 if (!array_address) 332 return; 333 334 char* base = static_cast <char *> (array_address); 335 std::size_t size = 0; 336 337 if (padding_size) 338 { 339 std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1]; 340 base -= padding_size; 341 size = element_count * element_size + padding_size; 342 __try 343 { 344 __cxa_vec_dtor(array_address, element_count, element_size, 345 destructor); 346 } 347 __catch(...) 348 { 349 { 350 uncatch_exception ue; 351 dealloc(base, size); 352 } 353 __throw_exception_again; 354 } 355 } 356 dealloc(base, size); 357 } 358 } // namespace __cxxabiv1 359 360 #if defined(__arm__) && defined(__ARM_EABI__) 361 362 // The ARM C++ ABI requires that the library provide these additional 363 // helper functions. There are placed in this file, despite being 364 // architecture-specifier, so that the compiler can inline the __cxa 365 // functions into these functions as appropriate. 366 367 namespace __aeabiv1 368 { 369 extern "C" void * 370 __aeabi_vec_ctor_nocookie_nodtor (void *array_address, 371 abi::__cxa_cdtor_type constructor, 372 std::size_t element_size, 373 std::size_t element_count) 374 { 375 return abi::__cxa_vec_ctor (array_address, element_count, element_size, 376 constructor, /*destructor=*/NULL); 377 } 378 379 extern "C" void * 380 __aeabi_vec_ctor_cookie_nodtor (void *array_address, 381 abi::__cxa_cdtor_type constructor, 382 std::size_t element_size, 383 std::size_t element_count) 384 { 385 if (array_address == NULL) 386 return NULL; 387 388 array_address = reinterpret_cast<std::size_t *>(array_address) + 2; 389 reinterpret_cast<std::size_t *>(array_address)[-2] = element_size; 390 reinterpret_cast<std::size_t *>(array_address)[-1] = element_count; 391 return abi::__cxa_vec_ctor (array_address, 392 element_count, element_size, 393 constructor, /*destructor=*/NULL); 394 } 395 396 extern "C" void * 397 __aeabi_vec_cctor_nocookie_nodtor (void *dest_array, 398 void *src_array, 399 std::size_t element_size, 400 std::size_t element_count, 401 void *(*constructor) (void *, void *)) 402 { 403 return abi::__cxa_vec_cctor (dest_array, src_array, 404 element_count, element_size, 405 constructor, NULL); 406 } 407 408 extern "C" void * 409 __aeabi_vec_new_cookie_noctor (std::size_t element_size, 410 std::size_t element_count) 411 { 412 return abi::__cxa_vec_new(element_count, element_size, 413 2 * sizeof (std::size_t), 414 /*constructor=*/NULL, /*destructor=*/NULL); 415 } 416 417 extern "C" void * 418 __aeabi_vec_new_nocookie (std::size_t element_size, 419 std::size_t element_count, 420 abi::__cxa_cdtor_type constructor) 421 { 422 return abi::__cxa_vec_new (element_count, element_size, 0, constructor, 423 NULL); 424 } 425 426 extern "C" void * 427 __aeabi_vec_new_cookie_nodtor (std::size_t element_size, 428 std::size_t element_count, 429 abi::__cxa_cdtor_type constructor) 430 { 431 return abi::__cxa_vec_new(element_count, element_size, 432 2 * sizeof (std::size_t), 433 constructor, NULL); 434 } 435 436 extern "C" void * 437 __aeabi_vec_new_cookie(std::size_t element_size, 438 std::size_t element_count, 439 abi::__cxa_cdtor_type constructor, 440 abi::__cxa_cdtor_type destructor) 441 { 442 return abi::__cxa_vec_new (element_count, element_size, 443 2 * sizeof (std::size_t), 444 constructor, destructor); 445 } 446 447 448 extern "C" void * 449 __aeabi_vec_dtor (void *array_address, 450 abi::__cxa_cdtor_type destructor, 451 std::size_t element_size, 452 std::size_t element_count) 453 { 454 abi::__cxa_vec_dtor (array_address, element_count, element_size, 455 destructor); 456 return reinterpret_cast<std::size_t*> (array_address) - 2; 457 } 458 459 extern "C" void * 460 __aeabi_vec_dtor_cookie (void *array_address, 461 abi::__cxa_cdtor_type destructor) 462 { 463 if (!array_address) 464 return NULL; 465 466 abi::__cxa_vec_dtor (array_address, 467 reinterpret_cast<std::size_t *>(array_address)[-1], 468 reinterpret_cast<std::size_t *>(array_address)[-2], 469 destructor); 470 return reinterpret_cast<std::size_t*> (array_address) - 2; 471 } 472 473 474 extern "C" void 475 __aeabi_vec_delete (void *array_address, 476 abi::__cxa_cdtor_type destructor) 477 { 478 if (!array_address) 479 return; 480 481 abi::__cxa_vec_delete (array_address, 482 reinterpret_cast<std::size_t *>(array_address)[-2], 483 2 * sizeof (std::size_t), 484 destructor); 485 } 486 487 extern "C" void 488 __aeabi_vec_delete3 (void *array_address, 489 abi::__cxa_cdtor_type destructor, 490 void (*dealloc) (void *, std::size_t)) 491 { 492 if (!array_address) 493 return; 494 495 abi::__cxa_vec_delete3 (array_address, 496 reinterpret_cast<std::size_t *>(array_address)[-2], 497 2 * sizeof (std::size_t), 498 destructor, dealloc); 499 } 500 501 extern "C" void 502 __aeabi_vec_delete3_nodtor (void *array_address, 503 void (*dealloc) (void *, std::size_t)) 504 { 505 if (!array_address) 506 return; 507 508 abi::__cxa_vec_delete3 (array_address, 509 reinterpret_cast<std::size_t *>(array_address)[-2], 510 2 * sizeof (std::size_t), 511 /*destructor=*/NULL, dealloc); 512 } 513 } // namespace __aeabiv1 514 515 #endif // defined(__arm__) && defined(__ARM_EABI__) 516