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