1 // New abi Support -*- C++ -*- 2 3 // Copyright (C) 2000-2020 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 <bits/exception_defines.h> 32 #include "unwind-cxx.h" 33 34 namespace __cxxabiv1 35 { 36 namespace 37 { 38 struct uncatch_exception 39 { 40 uncatch_exception(); ~uncatch_exception__cxxabiv1::__anon5959f4220111::uncatch_exception41 ~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 uncatch_exception()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 // Compute the total size with overflow checking. compute_size(std::size_t element_count,std::size_t element_size,std::size_t padding_size)63 std::size_t compute_size(std::size_t element_count, 64 std::size_t element_size, 65 std::size_t padding_size) 66 { 67 if (element_size && element_count > std::size_t(-1) / element_size) 68 _GLIBCXX_THROW_OR_ABORT(std::bad_alloc()); 69 std::size_t size = element_count * element_size; 70 if (size + padding_size < size) 71 _GLIBCXX_THROW_OR_ABORT(std::bad_alloc()); 72 return size + padding_size; 73 } 74 } 75 76 // Allocate and construct array. 77 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)78 __cxa_vec_new(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 { 84 return __cxa_vec_new2(element_count, element_size, padding_size, 85 constructor, destructor, 86 &operator new[], &operator delete []); 87 } 88 89 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 *))90 __cxa_vec_new2(std::size_t element_count, 91 std::size_t element_size, 92 std::size_t padding_size, 93 __cxa_cdtor_type constructor, 94 __cxa_cdtor_type destructor, 95 void *(*alloc) (std::size_t), 96 void (*dealloc) (void *)) 97 { 98 std::size_t size 99 = compute_size(element_count, element_size, padding_size); 100 char *base = static_cast <char *> (alloc (size)); 101 if (!base) 102 return base; 103 104 if (padding_size) 105 { 106 base += padding_size; 107 reinterpret_cast <std::size_t *> (base)[-1] = element_count; 108 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 109 reinterpret_cast <std::size_t *> (base)[-2] = element_size; 110 #endif 111 } 112 __try 113 { 114 __cxa_vec_ctor(base, element_count, element_size, 115 constructor, destructor); 116 } 117 __catch(...) 118 { 119 { 120 uncatch_exception ue; 121 // Core issue 901 will probably be resolved such that a 122 // deleted operator delete means not freeing memory here. 123 if (dealloc) 124 dealloc(base - padding_size); 125 } 126 __throw_exception_again; 127 } 128 return base; 129 } 130 131 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))132 __cxa_vec_new3(std::size_t element_count, 133 std::size_t element_size, 134 std::size_t padding_size, 135 __cxa_cdtor_type constructor, 136 __cxa_cdtor_type destructor, 137 void *(*alloc) (std::size_t), 138 void (*dealloc) (void *, std::size_t)) 139 { 140 std::size_t size 141 = compute_size(element_count, element_size, padding_size); 142 char *base = static_cast<char *>(alloc (size)); 143 if (!base) 144 return base; 145 146 if (padding_size) 147 { 148 base += padding_size; 149 reinterpret_cast<std::size_t *>(base)[-1] = element_count; 150 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE 151 reinterpret_cast <std::size_t *> (base)[-2] = element_size; 152 #endif 153 } 154 __try 155 { 156 __cxa_vec_ctor(base, element_count, element_size, 157 constructor, destructor); 158 } 159 __catch(...) 160 { 161 { 162 uncatch_exception ue; 163 if (dealloc) 164 dealloc(base - padding_size, size); 165 } 166 __throw_exception_again; 167 } 168 return base; 169 } 170 171 // Construct array. 172 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)173 __cxa_vec_ctor(void *array_address, 174 std::size_t element_count, 175 std::size_t element_size, 176 __cxa_cdtor_type constructor, 177 __cxa_cdtor_type destructor) 178 { 179 std::size_t ix = 0; 180 char *ptr = static_cast<char *>(array_address); 181 182 __try 183 { 184 if (constructor) 185 for (; ix != element_count; ix++, ptr += element_size) 186 constructor(ptr); 187 } 188 __catch(...) 189 { 190 { 191 uncatch_exception ue; 192 __cxa_vec_cleanup(array_address, ix, element_size, destructor); 193 } 194 __throw_exception_again; 195 } 196 _GLIBCXX_CXA_VEC_CTOR_RETURN (array_address); 197 } 198 199 // Construct an array by copying. 200 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)201 __cxa_vec_cctor(void *dest_array, 202 void *src_array, 203 std::size_t element_count, 204 std::size_t element_size, 205 __cxa_cdtor_return_type (*constructor) (void *, void *), 206 __cxa_cdtor_type destructor) 207 { 208 std::size_t ix = 0; 209 char *dest_ptr = static_cast<char *>(dest_array); 210 char *src_ptr = static_cast<char *>(src_array); 211 212 __try 213 { 214 if (constructor) 215 for (; ix != element_count; 216 ix++, src_ptr += element_size, dest_ptr += element_size) 217 constructor(dest_ptr, src_ptr); 218 } 219 __catch(...) 220 { 221 { 222 uncatch_exception ue; 223 __cxa_vec_cleanup(dest_array, ix, element_size, destructor); 224 } 225 __throw_exception_again; 226 } 227 _GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array); 228 } 229 230 // Destruct array. 231 extern "C" void __cxa_vec_dtor(void * array_address,std::size_t element_count,std::size_t element_size,__cxa_cdtor_type destructor)232 __cxa_vec_dtor(void *array_address, 233 std::size_t element_count, 234 std::size_t element_size, 235 __cxa_cdtor_type destructor) 236 { 237 if (destructor) 238 { 239 char *ptr = static_cast<char *>(array_address); 240 std::size_t ix = element_count; 241 242 ptr += element_count * element_size; 243 244 __try 245 { 246 while (ix--) 247 { 248 ptr -= element_size; 249 destructor(ptr); 250 } 251 } 252 __catch(...) 253 { 254 { 255 uncatch_exception ue; 256 __cxa_vec_cleanup(array_address, ix, element_size, destructor); 257 } 258 __throw_exception_again; 259 } 260 } 261 } 262 263 // Destruct array as a result of throwing an exception. 264 // [except.ctor]/3 If a destructor called during stack unwinding 265 // exits with an exception, terminate is called. 266 extern "C" void __cxa_vec_cleanup(void * array_address,std::size_t element_count,std::size_t element_size,__cxa_cdtor_type destructor)267 __cxa_vec_cleanup(void *array_address, 268 std::size_t element_count, 269 std::size_t element_size, 270 __cxa_cdtor_type destructor) throw() 271 { 272 if (destructor) 273 { 274 char *ptr = static_cast <char *> (array_address); 275 std::size_t ix = element_count; 276 277 ptr += element_count * element_size; 278 279 __try 280 { 281 while (ix--) 282 { 283 ptr -= element_size; 284 destructor(ptr); 285 } 286 } 287 __catch(...) 288 { 289 std::terminate(); 290 } 291 } 292 } 293 294 // Destruct and release array. 295 extern "C" void __cxa_vec_delete(void * array_address,std::size_t element_size,std::size_t padding_size,__cxa_cdtor_type destructor)296 __cxa_vec_delete(void *array_address, 297 std::size_t element_size, 298 std::size_t padding_size, 299 __cxa_cdtor_type destructor) 300 { 301 __cxa_vec_delete2(array_address, element_size, padding_size, 302 destructor, 303 &operator delete []); 304 } 305 306 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 *))307 __cxa_vec_delete2(void *array_address, 308 std::size_t element_size, 309 std::size_t padding_size, 310 __cxa_cdtor_type destructor, 311 void (*dealloc) (void *)) 312 { 313 if (!array_address) 314 return; 315 316 char* base = static_cast<char *>(array_address); 317 318 if (padding_size) 319 { 320 std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1]; 321 base -= padding_size; 322 __try 323 { 324 __cxa_vec_dtor(array_address, element_count, element_size, 325 destructor); 326 } 327 __catch(...) 328 { 329 { 330 uncatch_exception ue; 331 dealloc(base); 332 } 333 __throw_exception_again; 334 } 335 } 336 dealloc(base); 337 } 338 339 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))340 __cxa_vec_delete3(void *array_address, 341 std::size_t element_size, 342 std::size_t padding_size, 343 __cxa_cdtor_type destructor, 344 void (*dealloc) (void *, std::size_t)) 345 { 346 if (!array_address) 347 return; 348 349 char* base = static_cast <char *> (array_address); 350 std::size_t size = 0; 351 352 if (padding_size) 353 { 354 std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1]; 355 base -= padding_size; 356 size = element_count * element_size + padding_size; 357 __try 358 { 359 __cxa_vec_dtor(array_address, element_count, element_size, 360 destructor); 361 } 362 __catch(...) 363 { 364 { 365 uncatch_exception ue; 366 dealloc(base, size); 367 } 368 __throw_exception_again; 369 } 370 } 371 dealloc(base, size); 372 } 373 } // namespace __cxxabiv1 374 375 #if defined(__arm__) && defined(__ARM_EABI__) 376 377 // The ARM C++ ABI requires that the library provide these additional 378 // helper functions. There are placed in this file, despite being 379 // architecture-specifier, so that the compiler can inline the __cxa 380 // functions into these functions as appropriate. 381 382 namespace __aeabiv1 383 { 384 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)385 __aeabi_vec_ctor_nocookie_nodtor (void *array_address, 386 abi::__cxa_cdtor_type constructor, 387 std::size_t element_size, 388 std::size_t element_count) 389 { 390 return abi::__cxa_vec_ctor (array_address, element_count, element_size, 391 constructor, /*destructor=*/NULL); 392 } 393 394 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)395 __aeabi_vec_ctor_cookie_nodtor (void *array_address, 396 abi::__cxa_cdtor_type constructor, 397 std::size_t element_size, 398 std::size_t element_count) 399 { 400 if (array_address == NULL) 401 return NULL; 402 403 array_address = reinterpret_cast<std::size_t *>(array_address) + 2; 404 reinterpret_cast<std::size_t *>(array_address)[-2] = element_size; 405 reinterpret_cast<std::size_t *>(array_address)[-1] = element_count; 406 return abi::__cxa_vec_ctor (array_address, 407 element_count, element_size, 408 constructor, /*destructor=*/NULL); 409 } 410 411 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 *))412 __aeabi_vec_cctor_nocookie_nodtor (void *dest_array, 413 void *src_array, 414 std::size_t element_size, 415 std::size_t element_count, 416 void *(*constructor) (void *, void *)) 417 { 418 return abi::__cxa_vec_cctor (dest_array, src_array, 419 element_count, element_size, 420 constructor, NULL); 421 } 422 423 extern "C" void * __aeabi_vec_new_cookie_noctor(std::size_t element_size,std::size_t element_count)424 __aeabi_vec_new_cookie_noctor (std::size_t element_size, 425 std::size_t element_count) 426 { 427 return abi::__cxa_vec_new(element_count, element_size, 428 2 * sizeof (std::size_t), 429 /*constructor=*/NULL, /*destructor=*/NULL); 430 } 431 432 extern "C" void * __aeabi_vec_new_nocookie(std::size_t element_size,std::size_t element_count,abi::__cxa_cdtor_type constructor)433 __aeabi_vec_new_nocookie (std::size_t element_size, 434 std::size_t element_count, 435 abi::__cxa_cdtor_type constructor) 436 { 437 return abi::__cxa_vec_new (element_count, element_size, 0, constructor, 438 NULL); 439 } 440 441 extern "C" void * __aeabi_vec_new_cookie_nodtor(std::size_t element_size,std::size_t element_count,abi::__cxa_cdtor_type constructor)442 __aeabi_vec_new_cookie_nodtor (std::size_t element_size, 443 std::size_t element_count, 444 abi::__cxa_cdtor_type constructor) 445 { 446 return abi::__cxa_vec_new(element_count, element_size, 447 2 * sizeof (std::size_t), 448 constructor, NULL); 449 } 450 451 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)452 __aeabi_vec_new_cookie(std::size_t element_size, 453 std::size_t element_count, 454 abi::__cxa_cdtor_type constructor, 455 abi::__cxa_cdtor_type destructor) 456 { 457 return abi::__cxa_vec_new (element_count, element_size, 458 2 * sizeof (std::size_t), 459 constructor, destructor); 460 } 461 462 463 extern "C" void * __aeabi_vec_dtor(void * array_address,abi::__cxa_cdtor_type destructor,std::size_t element_size,std::size_t element_count)464 __aeabi_vec_dtor (void *array_address, 465 abi::__cxa_cdtor_type destructor, 466 std::size_t element_size, 467 std::size_t element_count) 468 { 469 abi::__cxa_vec_dtor (array_address, element_count, element_size, 470 destructor); 471 return reinterpret_cast<std::size_t*> (array_address) - 2; 472 } 473 474 extern "C" void * __aeabi_vec_dtor_cookie(void * array_address,abi::__cxa_cdtor_type destructor)475 __aeabi_vec_dtor_cookie (void *array_address, 476 abi::__cxa_cdtor_type destructor) 477 { 478 if (!array_address) 479 return NULL; 480 481 abi::__cxa_vec_dtor (array_address, 482 reinterpret_cast<std::size_t *>(array_address)[-1], 483 reinterpret_cast<std::size_t *>(array_address)[-2], 484 destructor); 485 return reinterpret_cast<std::size_t*> (array_address) - 2; 486 } 487 488 489 extern "C" void __aeabi_vec_delete(void * array_address,abi::__cxa_cdtor_type destructor)490 __aeabi_vec_delete (void *array_address, 491 abi::__cxa_cdtor_type destructor) 492 { 493 if (!array_address) 494 return; 495 496 abi::__cxa_vec_delete (array_address, 497 reinterpret_cast<std::size_t *>(array_address)[-2], 498 2 * sizeof (std::size_t), 499 destructor); 500 } 501 502 extern "C" void __aeabi_vec_delete3(void * array_address,abi::__cxa_cdtor_type destructor,void (* dealloc)(void *,std::size_t))503 __aeabi_vec_delete3 (void *array_address, 504 abi::__cxa_cdtor_type destructor, 505 void (*dealloc) (void *, std::size_t)) 506 { 507 if (!array_address) 508 return; 509 510 abi::__cxa_vec_delete3 (array_address, 511 reinterpret_cast<std::size_t *>(array_address)[-2], 512 2 * sizeof (std::size_t), 513 destructor, dealloc); 514 } 515 516 extern "C" void __aeabi_vec_delete3_nodtor(void * array_address,void (* dealloc)(void *,std::size_t))517 __aeabi_vec_delete3_nodtor (void *array_address, 518 void (*dealloc) (void *, std::size_t)) 519 { 520 if (!array_address) 521 return; 522 523 abi::__cxa_vec_delete3 (array_address, 524 reinterpret_cast<std::size_t *>(array_address)[-2], 525 2 * sizeof (std::size_t), 526 /*destructor=*/NULL, dealloc); 527 } 528 } // namespace __aeabiv1 529 530 #endif // defined(__arm__) && defined(__ARM_EABI__) 531