1 // Copyright (C) 2013 The Android Open Source Project 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 1. Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // 2. Redistributions in binary form must reproduce the above copyright 10 // notice, this list of conditions and the following disclaimer in the 11 // documentation and/or other materials provided with the distribution. 12 // 3. Neither the name of the project nor the names of its contributors 13 // may be used to endorse or promote products derived from this software 14 // without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 // ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 // SUCH DAMAGE. 27 28 #include <cstddef> 29 #include <new> 30 31 #include "cxxabi_defines.h" 32 33 using std::size_t; 34 35 namespace { 36 37 using namespace __cxxabiv1; 38 39 typedef __cxa_vec_constructor constructor_func; 40 typedef __cxa_vec_copy_constructor copy_constructor_func; 41 typedef __cxa_vec_destructor destructor_func; 42 typedef void* (*alloc_func)(size_t); 43 typedef void (*dealloc_func)(void*); 44 typedef void (*dealloc2_func)(void*, size_t); 45 46 // Helper class to ensure a ptr is deallocated on scope exit unless 47 // the release() method has been called. 48 class scoped_block { 49 public: 50 scoped_block(void* ptr, size_t size, dealloc2_func dealloc) 51 : ptr_(ptr), size_(size), dealloc_(dealloc) {} 52 53 ~scoped_block() { 54 if (dealloc_) 55 dealloc_(ptr_, size_); 56 } 57 58 void release() { 59 dealloc_ = 0; 60 } 61 62 private: 63 void* ptr_; 64 size_t size_; 65 dealloc2_func dealloc_; 66 }; 67 68 // Helper class to ensure a vector is cleaned up on scope exit 69 // unless the release() method has been called. 70 class scoped_cleanup { 71 public: 72 scoped_cleanup(void* array, size_t& index, size_t element_size, 73 destructor_func destructor) 74 : array_(array), index_(index), element_size_(element_size), 75 destructor_(destructor) {} 76 77 ~scoped_cleanup() { 78 if (destructor_) 79 __cxxabiv1::__cxa_vec_cleanup(array_, 80 index_, 81 element_size_, 82 destructor_); 83 } 84 85 void release() { 86 destructor_ = 0; 87 } 88 private: 89 void* array_; 90 size_t& index_; 91 size_t element_size_; 92 destructor_func destructor_; 93 }; 94 95 // Helper class that calls __fatal_error() with a given message if 96 // it exits a scope without a previous call to release(). 97 class scoped_catcher { 98 public: 99 scoped_catcher(const char* message) : message_(message) {} 100 101 ~scoped_catcher() { 102 if (message_) 103 __gabixx::__fatal_error(message_); 104 } 105 106 void release() { 107 message_ = 0; 108 } 109 110 private: 111 const char* message_; 112 }; 113 114 } // namespace 115 116 namespace __cxxabiv1 { 117 extern "C" { 118 119 void* __cxa_vec_new(size_t element_count, 120 size_t element_size, 121 size_t padding_size, 122 constructor_func constructor, 123 destructor_func destructor) { 124 return __cxa_vec_new2(element_count, element_size, padding_size, 125 constructor, destructor, 126 &operator new[], &operator delete []); 127 } 128 129 void* __cxa_vec_new2(size_t element_count, 130 size_t element_size, 131 size_t padding_size, 132 constructor_func constructor, 133 destructor_func destructor, 134 alloc_func alloc, 135 dealloc_func dealloc) { 136 // The only difference with __cxa_vec_new3 is the type of the 137 // dealloc parameter. force a cast because on all supported 138 // platforms, it is possible to call the dealloc function here 139 // with two parameters. The second one will simply be ignored. 140 return __cxa_vec_new3(element_count, element_size, padding_size, 141 constructor, destructor, alloc, 142 reinterpret_cast<dealloc2_func>(dealloc)); 143 } 144 145 void* __cxa_vec_new3(size_t element_count, 146 size_t element_size, 147 size_t padding_size, 148 constructor_func constructor, 149 destructor_func destructor, 150 alloc_func alloc, 151 dealloc2_func dealloc) { 152 // Compute the size of the needed memory block, and throw 153 // std::bad_alloc() on overflow. 154 bool overflow = false; 155 size_t size = 0; 156 if (element_size > 0 && element_count > size_t(-1) / element_size) 157 overflow = true; 158 else { 159 size = element_count * element_size; 160 if (size + padding_size < size) 161 overflow = true; 162 } 163 if (overflow) 164 throw std::bad_alloc(); 165 166 // Allocate memory. Do not throw if NULL is returned. 167 char* base = static_cast<char*>(alloc(size)); 168 if (!base) 169 return base; 170 171 // Ensure the block is freed if construction throws. 172 scoped_block block(base, size, dealloc); 173 174 if (padding_size) { 175 base += padding_size; 176 reinterpret_cast<size_t*>(base)[-1] = element_count; 177 #ifdef __arm__ 178 // Required by the ARM C++ ABI. 179 reinterpret_cast<size_t*>(base)[-2] = element_size; 180 #endif 181 } 182 183 __cxa_vec_ctor(base, element_count, element_size, 184 constructor, destructor); 185 186 // Construction succeeded, no need to release the block. 187 block.release(); 188 return base; 189 } 190 191 #ifdef __arm__ 192 // On ARM, __cxa_vec_ctor and __cxa_vec_cctor must return 193 // their first parameter. Handle this here. 194 #define _CXA_VEC_CTOR_RETURN(x) return x 195 #else 196 #define _CXA_VEC_CTOR_RETURN(x) return 197 #endif 198 199 __cxa_vec_ctor_return_type 200 __cxa_vec_ctor(void* array_address, 201 size_t element_count, 202 size_t element_size, 203 constructor_func constructor, 204 destructor_func destructor) { 205 if (constructor) { 206 size_t n = 0; 207 char* base = static_cast<char*>(array_address); 208 209 scoped_cleanup cleanup(array_address, n, element_size, destructor); 210 for (; n != element_count; ++n) { 211 constructor(base); 212 base += element_size; 213 } 214 cleanup.release(); 215 } 216 _CXA_VEC_CTOR_RETURN(array_address); 217 } 218 219 // Given the (data) address of an array, the number of elements, 220 // and the size of its elements, call the given destructor on each 221 // element. If the destructor throws an exception, rethrow after 222 // destroying the remaining elements if possible. If the destructor 223 // throws a second exception, call terminate(). The destructor 224 // pointer may be NULL, in which case this routine does nothing. 225 void __cxa_vec_dtor(void* array_address, 226 size_t element_count, 227 size_t element_size, 228 destructor_func destructor) { 229 if (!destructor) 230 return; 231 232 char* base = static_cast<char*>(array_address); 233 size_t n = element_count; 234 scoped_cleanup cleanup(array_address, n, element_size, destructor); 235 base += element_count * element_size; 236 // Note: n must be decremented before the destructor call 237 // to avoid cleaning up one extra unwanted item. 238 while (n--) { 239 base -= element_size; 240 destructor(base); 241 } 242 cleanup.release(); 243 } 244 245 // Given the (data) address of an array, the number of elements, 246 // and the size of its elements, call the given destructor on each 247 // element. If the destructor throws an exception, call terminate(). 248 // The destructor pointer may be NULL, in which case this routine 249 // does nothing. 250 void __cxa_vec_cleanup(void* array_address, 251 size_t element_count, 252 size_t element_size, 253 destructor_func destructor) { 254 if (!destructor) 255 return; 256 257 char* base = static_cast<char*>(array_address); 258 size_t n = element_count; 259 base += n * element_size; 260 261 scoped_catcher catcher("exception raised in vector destructor!"); 262 while (n--) { 263 base -= element_size; 264 destructor(base); 265 } 266 catcher.release(); 267 } 268 269 // If the array_address is NULL, return immediately. Otherwise, 270 // given the (data) address of an array, the non-negative size 271 // of prefix padding for the cookie, and the size of its elements, 272 // call the given destructor on each element, using the cookie to 273 // determine the number of elements, and then delete the space by 274 // calling ::operator delete[](void *). If the destructor throws an 275 // exception, rethrow after (a) destroying the remaining elements, 276 // and (b) deallocating the storage. If the destructor throws a 277 // second exception, call terminate(). If padding_size is 0, the 278 // destructor pointer must be NULL. If the destructor pointer is NULL, 279 // no destructor call is to be made. 280 void __cxa_vec_delete(void* array_address, 281 size_t element_size, 282 size_t padding_size, 283 destructor_func destructor) { 284 __cxa_vec_delete2(array_address, element_size, padding_size, 285 destructor, &operator delete []); 286 } 287 288 // Same as __cxa_vec_delete, except that the given function is used 289 // for deallocation instead of the default delete function. If dealloc 290 // throws an exception, the result is undefined. The dealloc pointer 291 // may not be NULL. 292 void __cxa_vec_delete2(void* array_address, 293 size_t element_size, 294 size_t padding_size, 295 destructor_func destructor, 296 dealloc_func dealloc) { 297 // Same trick than the one used on __cxa_vec_new2. 298 __cxa_vec_delete3(array_address, element_size, padding_size, 299 destructor, 300 reinterpret_cast<dealloc2_func>(dealloc)); 301 } 302 303 // Same as __cxa_vec_delete, except that the given function is used 304 // for deallocation instead of the default delete function. The 305 // deallocation function takes both the object address and its size. 306 // If dealloc throws an exception, the result is undefined. The dealloc 307 // pointer may not be NULL. 308 void __cxa_vec_delete3(void* array_address, 309 size_t element_size, 310 size_t padding_size, 311 destructor_func destructor, 312 dealloc2_func dealloc) { 313 if (!array_address) 314 return; 315 316 char* base = static_cast<char*>(array_address); 317 318 if (!padding_size) { 319 // If here is no padding size, asume the deallocator knows 320 // how to handle this. Useful when called from __cxa_vec_delete2. 321 dealloc(base, 0); 322 return; 323 } 324 325 size_t element_count = reinterpret_cast<size_t*>(base)[-1]; 326 base -= padding_size; 327 size_t size = element_count * element_size + padding_size; 328 329 // Always deallocate base on exit. 330 scoped_block block(base, size, dealloc); 331 332 if (padding_size > 0 && destructor != 0) 333 __cxa_vec_dtor(array_address, element_count, element_size, destructor); 334 } 335 336 __cxa_vec_ctor_return_type 337 __cxa_vec_cctor(void* dst_array, 338 void* src_array, 339 size_t element_count, 340 size_t element_size, 341 copy_constructor_func copy_constructor, 342 destructor_func destructor) { 343 if (copy_constructor) { 344 size_t n = 0; 345 char* dst = static_cast<char*>(dst_array); 346 char* src = static_cast<char*>(src_array); 347 348 scoped_cleanup cleanup(dst_array, n, element_size, destructor); 349 350 for ( ; n != element_count; ++n) { 351 copy_constructor(dst, src); 352 dst += element_size; 353 src += element_size; 354 } 355 356 cleanup.release(); 357 } 358 _CXA_VEC_CTOR_RETURN(dst_array); 359 } 360 361 } // extern "C" 362 } // namespace __cxxabiv1 363 364 #if _GABIXX_ARM_ABI 365 // The following functions are required by the ARM ABI, even 366 // though neither GCC nor LLVM generate any code that uses it. 367 // This may be important for machine code generated by other 368 // compilers though (e.g. RCVT), which may depend on them. 369 // They're supposed to simplify calling code. 370 namespace __aeabiv1 { 371 372 extern "C" { 373 374 using namespace __cxxabiv1; 375 376 void* __aeabi_vec_ctor_nocookie_nodtor(void* array_address, 377 constructor_func constructor, 378 size_t element_size, 379 size_t element_count) { 380 return __cxa_vec_ctor(array_address, 381 element_count, 382 element_size, 383 constructor, 384 /* destructor */ NULL); 385 } 386 387 void* __aeabi_vec_ctor_cookie_nodtor(void* array_address, 388 constructor_func constructor, 389 size_t element_size, 390 size_t element_count) { 391 if (!array_address) 392 return array_address; 393 394 size_t* base = reinterpret_cast<size_t*>(array_address) + 2; 395 base[-2] = element_size; 396 base[-1] = element_count; 397 return __cxa_vec_ctor(base, 398 element_count, 399 element_size, 400 constructor, 401 /* destructor */ NULL); 402 } 403 404 void* __aeabi_vec_cctor_nocookie_nodtor( 405 void* dst_array, 406 void* src_array, 407 size_t element_size, 408 size_t element_count, 409 copy_constructor_func copy_constructor) { 410 return __cxa_vec_cctor(dst_array, src_array, element_count, 411 element_size, copy_constructor, NULL); 412 } 413 414 void* __aeabi_vec_new_cookie_noctor(size_t element_size, 415 size_t element_count) { 416 return __cxa_vec_new(element_count, element_size, 417 /* padding */ 2 * sizeof(size_t), 418 /* constructor */ NULL, 419 /* destructor */ NULL); 420 } 421 422 void* __aeabi_vec_new_nocookie(size_t element_size, 423 size_t element_count, 424 constructor_func constructor) { 425 return __cxa_vec_new(element_count, 426 element_size, 427 /* padding */ 0, 428 constructor, 429 /* destructor */ NULL); 430 } 431 432 void* __aeabi_vec_new_cookie_nodtor(size_t element_size, 433 size_t element_count, 434 constructor_func constructor) { 435 return __cxa_vec_new(element_count, 436 element_size, 437 /* padding */ 2 * sizeof(size_t), 438 constructor, 439 /* destructor */ NULL); 440 } 441 442 void* __aeabi_vec_new_cookie(size_t element_size, 443 size_t element_count, 444 constructor_func constructor, 445 destructor_func destructor) { 446 return __cxa_vec_new(element_count, 447 element_size, 448 /* padding */ 2 * sizeof(size_t), 449 constructor, 450 destructor); 451 } 452 453 void* __aeabi_vec_dtor(void* array_address, 454 destructor_func destructor, 455 size_t element_size, 456 size_t element_count) { 457 __cxa_vec_dtor(array_address, element_count, element_size, 458 destructor); 459 return reinterpret_cast<size_t*>(array_address) - 2; 460 } 461 462 void* __aeabi_vec_dtor_cookie(void* array_address, 463 destructor_func destructor) { 464 if (!array_address) 465 return NULL; 466 467 size_t* base = reinterpret_cast<size_t*>(array_address); 468 __cxa_vec_dtor(array_address, 469 /* element_count */ base[-1], 470 /* element_size */ base[-2], 471 destructor); 472 return base - 2; 473 } 474 475 void __aeabi_vec_delete(void* array_address, 476 destructor_func destructor) { 477 if (array_address) { 478 size_t* base = reinterpret_cast<size_t*>(array_address); 479 480 __cxa_vec_delete(array_address, 481 /* element_size */ base[-2], 482 /* padding */ 2 * sizeof(size_t), 483 destructor); 484 } 485 } 486 487 void __aeabi_vec_delete3(void* array_address, 488 destructor_func destructor, 489 dealloc2_func dealloc) { 490 if (array_address) { 491 size_t* base = reinterpret_cast<size_t*>(array_address); 492 493 __cxa_vec_delete3(array_address, 494 /* element_size */ base[-2], 495 /* padding */ 2 * sizeof(size_t), 496 destructor, 497 dealloc); 498 } 499 } 500 501 void __aeabi_vec_delete3_nodtor(void* array_address, 502 dealloc2_func dealloc) { 503 if (array_address) { 504 size_t* base = reinterpret_cast<size_t*>(array_address); 505 506 __cxa_vec_delete3(array_address, 507 /* element_size */ base[-2], 508 /* padding */ 2 * sizeof(size_t), 509 /* destructor */ NULL, 510 dealloc); 511 } 512 } 513 514 } // extern "C" 515 } // namespace __aeabiv1 516 517 #endif // _GABIXX_ARM_ABI 518