1 // New abi Support -*- C++ -*- 2 3 // Copyright (C) 2000, 2001, 2003, 2004 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 2, 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 // You should have received a copy of the GNU General Public License 18 // along with GCC; see the file COPYING. If not, write to 19 // the Free Software Foundation, 51 Franklin Street, Fifth Floor, 20 // Boston, MA 02110-1301, USA. 21 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 // Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com> 32 33 #include <cxxabi.h> 34 #include <new> 35 #include <exception> 36 #include <exception_defines.h> 37 #include "unwind-cxx.h" 38 39 namespace __cxxabiv1 40 { 41 namespace 42 { 43 struct uncatch_exception 44 { 45 uncatch_exception(); ~uncatch_exception__cxxabiv1::__anoncf5cc0610111::uncatch_exception46 ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); } 47 48 __cxa_exception* p; 49 50 private: 51 uncatch_exception& 52 operator=(const uncatch_exception&); 53 54 uncatch_exception(const uncatch_exception&); 55 }; 56 uncatch_exception()57 uncatch_exception::uncatch_exception() : p(0) 58 { 59 __cxa_eh_globals *globals = __cxa_get_globals_fast (); 60 61 p = globals->caughtExceptions; 62 p->handlerCount -= 1; 63 globals->caughtExceptions = p->nextException; 64 globals->uncaughtExceptions += 1; 65 } 66 } 67 68 // Allocate and construct array. 69 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)70 __cxa_vec_new(std::size_t element_count, 71 std::size_t element_size, 72 std::size_t padding_size, 73 __cxa_cdtor_type constructor, 74 __cxa_cdtor_type destructor) 75 { 76 return __cxa_vec_new2(element_count, element_size, padding_size, 77 constructor, destructor, 78 &operator new[], &operator delete []); 79 } 80 81 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 *))82 __cxa_vec_new2(std::size_t element_count, 83 std::size_t element_size, 84 std::size_t padding_size, 85 __cxa_cdtor_type constructor, 86 __cxa_cdtor_type destructor, 87 void *(*alloc) (std::size_t), 88 void (*dealloc) (void *)) 89 { 90 std::size_t size = element_count * element_size + padding_size; 91 char *base = static_cast <char *> (alloc (size)); 92 if (!base) 93 return base; 94 95 if (padding_size) 96 { 97 base += padding_size; 98 reinterpret_cast <std::size_t *> (base)[-1] = element_count; 99 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 100 reinterpret_cast <std::size_t *> (base)[-2] = element_size; 101 #endif 102 } 103 try 104 { 105 __cxa_vec_ctor(base, element_count, element_size, 106 constructor, destructor); 107 } 108 catch (...) 109 { 110 { 111 uncatch_exception ue; 112 dealloc(base - padding_size); 113 } 114 __throw_exception_again; 115 } 116 return base; 117 } 118 119 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))120 __cxa_vec_new3(std::size_t element_count, 121 std::size_t element_size, 122 std::size_t padding_size, 123 __cxa_cdtor_type constructor, 124 __cxa_cdtor_type destructor, 125 void *(*alloc) (std::size_t), 126 void (*dealloc) (void *, std::size_t)) 127 { 128 std::size_t size = element_count * element_size + padding_size; 129 char *base = static_cast<char *>(alloc (size)); 130 if (!base) 131 return base; 132 133 if (padding_size) 134 { 135 base += padding_size; 136 reinterpret_cast<std::size_t *>(base)[-1] = element_count; 137 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 138 reinterpret_cast <std::size_t *> (base)[-2] = element_size; 139 #endif 140 } 141 try 142 { 143 __cxa_vec_ctor(base, element_count, element_size, 144 constructor, destructor); 145 } 146 catch (...) 147 { 148 { 149 uncatch_exception ue; 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) 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 abi::__cxa_vec_dtor (array_address, 465 reinterpret_cast<std::size_t *>(array_address)[-1], 466 reinterpret_cast<std::size_t *>(array_address)[-2], 467 destructor); 468 return reinterpret_cast<std::size_t*> (array_address) - 2; 469 } 470 471 472 extern "C" void __aeabi_vec_delete(void * array_address,abi::__cxa_cdtor_type destructor)473 __aeabi_vec_delete (void *array_address, 474 abi::__cxa_cdtor_type destructor) 475 { 476 abi::__cxa_vec_delete (array_address, 477 reinterpret_cast<std::size_t *>(array_address)[-2], 478 2 * sizeof (std::size_t), 479 destructor); 480 } 481 482 extern "C" void __aeabi_vec_delete3(void * array_address,abi::__cxa_cdtor_type destructor,void (* dealloc)(void *,std::size_t))483 __aeabi_vec_delete3 (void *array_address, 484 abi::__cxa_cdtor_type destructor, 485 void (*dealloc) (void *, std::size_t)) 486 { 487 abi::__cxa_vec_delete3 (array_address, 488 reinterpret_cast<std::size_t *>(array_address)[-2], 489 2 * sizeof (std::size_t), 490 destructor, dealloc); 491 } 492 493 extern "C" void __aeabi_vec_delete3_nodtor(void * array_address,void (* dealloc)(void *,std::size_t))494 __aeabi_vec_delete3_nodtor (void *array_address, 495 void (*dealloc) (void *, std::size_t)) 496 { 497 abi::__cxa_vec_delete3 (array_address, 498 reinterpret_cast<std::size_t *>(array_address)[-2], 499 2 * sizeof (std::size_t), 500 /*destructor=*/NULL, dealloc); 501 } 502 503 extern "C" int __aeabi_atexit(void * object,void (* destructor)(void *),void * dso_handle)504 __aeabi_atexit (void *object, 505 void (*destructor) (void *), 506 void *dso_handle) 507 { 508 return abi::__cxa_atexit(destructor, object, dso_handle); 509 } 510 } // namespace __aeabiv1 511 512 #endif // defined(__arm__) && defined(__ARM_EABI__) 513