1 //===-------------------------- cxa_vector.cpp ---------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 // 8 // This file implements the "Array Construction and Destruction APIs" 9 // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#array-ctor 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "cxxabi.h" 14 #include "__cxxabi_config.h" 15 16 #include <exception> // for std::terminate 17 #include <new> // for std::bad_array_new_length 18 19 #include "abort_message.h" 20 21 #ifndef __has_builtin 22 #define __has_builtin(x) 0 23 #endif 24 25 namespace __cxxabiv1 { 26 27 // 28 // Helper routines and classes 29 // 30 31 namespace { 32 inline static size_t __get_element_count ( void *p ) { 33 return static_cast <size_t *> (p)[-1]; 34 } 35 36 inline static void __set_element_count ( void *p, size_t element_count ) { 37 static_cast <size_t *> (p)[-1] = element_count; 38 } 39 40 41 // A pair of classes to simplify exception handling and control flow. 42 // They get passed a block of memory in the constructor, and unless the 43 // 'release' method is called, they deallocate the memory in the destructor. 44 // Preferred usage is to allocate some memory, attach it to one of these objects, 45 // and then, when all the operations to set up the memory block have succeeded, 46 // call 'release'. If any of the setup operations fail, or an exception is 47 // thrown, then the block is automatically deallocated. 48 // 49 // The only difference between these two classes is the signature for the 50 // deallocation function (to match new2/new3 and delete2/delete3. 51 class st_heap_block2 { 52 public: 53 typedef void (*dealloc_f)(void *); 54 55 st_heap_block2 ( dealloc_f dealloc, void *ptr ) 56 : dealloc_ ( dealloc ), ptr_ ( ptr ), enabled_ ( true ) {} 57 ~st_heap_block2 () { if ( enabled_ ) dealloc_ ( ptr_ ) ; } 58 void release () { enabled_ = false; } 59 60 private: 61 dealloc_f dealloc_; 62 void *ptr_; 63 bool enabled_; 64 }; 65 66 class st_heap_block3 { 67 public: 68 typedef void (*dealloc_f)(void *, size_t); 69 70 st_heap_block3 ( dealloc_f dealloc, void *ptr, size_t size ) 71 : dealloc_ ( dealloc ), ptr_ ( ptr ), size_ ( size ), enabled_ ( true ) {} 72 ~st_heap_block3 () { if ( enabled_ ) dealloc_ ( ptr_, size_ ) ; } 73 void release () { enabled_ = false; } 74 75 private: 76 dealloc_f dealloc_; 77 void *ptr_; 78 size_t size_; 79 bool enabled_; 80 }; 81 82 class st_cxa_cleanup { 83 public: 84 typedef void (*destruct_f)(void *); 85 86 st_cxa_cleanup ( void *ptr, size_t &idx, size_t element_size, destruct_f destructor ) 87 : ptr_ ( ptr ), idx_ ( idx ), element_size_ ( element_size ), 88 destructor_ ( destructor ), enabled_ ( true ) {} 89 ~st_cxa_cleanup () { 90 if ( enabled_ ) 91 __cxa_vec_cleanup ( ptr_, idx_, element_size_, destructor_ ); 92 } 93 94 void release () { enabled_ = false; } 95 96 private: 97 void *ptr_; 98 size_t &idx_; 99 size_t element_size_; 100 destruct_f destructor_; 101 bool enabled_; 102 }; 103 104 class st_terminate { 105 public: 106 st_terminate ( bool enabled = true ) : enabled_ ( enabled ) {} 107 ~st_terminate () { if ( enabled_ ) std::terminate (); } 108 void release () { enabled_ = false; } 109 private: 110 bool enabled_ ; 111 }; 112 } 113 114 // 115 // Externally visible routines 116 // 117 118 namespace { 119 _LIBCXXABI_NORETURN 120 void throw_bad_array_new_length() { 121 #ifndef _LIBCXXABI_NO_EXCEPTIONS 122 throw std::bad_array_new_length(); 123 #else 124 abort_message("__cxa_vec_new failed to allocate memory"); 125 #endif 126 } 127 128 bool mul_overflow(size_t x, size_t y, size_t *res) { 129 #if (defined(_LIBCXXABI_COMPILER_CLANG) && __has_builtin(__builtin_mul_overflow)) \ 130 || defined(_LIBCXXABI_COMPILER_GCC) 131 return __builtin_mul_overflow(x, y, res); 132 #else 133 *res = x * y; 134 return x && ((*res / x) != y); 135 #endif 136 } 137 138 bool add_overflow(size_t x, size_t y, size_t *res) { 139 #if (defined(_LIBCXXABI_COMPILER_CLANG) && __has_builtin(__builtin_add_overflow)) \ 140 || defined(_LIBCXXABI_COMPILER_GCC) 141 return __builtin_add_overflow(x, y, res); 142 #else 143 *res = x + y; 144 return *res < y; 145 #endif 146 } 147 148 size_t calculate_allocation_size_or_throw(size_t element_count, 149 size_t element_size, 150 size_t padding_size) { 151 size_t element_heap_size; 152 if (mul_overflow(element_count, element_size, &element_heap_size)) 153 throw_bad_array_new_length(); 154 155 size_t allocation_size; 156 if (add_overflow(element_heap_size, padding_size, &allocation_size)) 157 throw_bad_array_new_length(); 158 159 return allocation_size; 160 } 161 162 } // namespace 163 164 extern "C" { 165 166 // Equivalent to 167 // 168 // __cxa_vec_new2(element_count, element_size, padding_size, constructor, 169 // destructor, &::operator new[], &::operator delete[]) 170 _LIBCXXABI_FUNC_VIS void * 171 __cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size, 172 void (*constructor)(void *), void (*destructor)(void *)) { 173 return __cxa_vec_new2 ( element_count, element_size, padding_size, 174 constructor, destructor, &::operator new [], &::operator delete [] ); 175 } 176 177 178 // Given the number and size of elements for an array and the non-negative 179 // size of prefix padding for a cookie, allocate space (using alloc) for 180 // the array preceded by the specified padding, initialize the cookie if 181 // the padding is non-zero, and call the given constructor on each element. 182 // Return the address of the array proper, after the padding. 183 // 184 // If alloc throws an exception, rethrow the exception. If alloc returns 185 // NULL, return NULL. If the constructor throws an exception, call 186 // destructor for any already constructed elements, and rethrow the 187 // exception. If the destructor throws an exception, call std::terminate. 188 // 189 // The constructor may be NULL, in which case it must not be called. If the 190 // padding_size is zero, the destructor may be NULL; in that case it must 191 // not be called. 192 // 193 // Neither alloc nor dealloc may be NULL. 194 _LIBCXXABI_FUNC_VIS void * 195 __cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size, 196 void (*constructor)(void *), void (*destructor)(void *), 197 void *(*alloc)(size_t), void (*dealloc)(void *)) { 198 const size_t heap_size = calculate_allocation_size_or_throw( 199 element_count, element_size, padding_size); 200 char* const heap_block = static_cast<char*>(alloc(heap_size)); 201 char* vec_base = heap_block; 202 203 if (NULL != vec_base) { 204 st_heap_block2 heap(dealloc, heap_block); 205 206 // put the padding before the array elements 207 if ( 0 != padding_size ) { 208 vec_base += padding_size; 209 __set_element_count ( vec_base, element_count ); 210 } 211 212 // Construct the elements 213 __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor ); 214 heap.release (); // We're good! 215 } 216 217 return vec_base; 218 } 219 220 221 // Same as __cxa_vec_new2 except that the deallocation function takes both 222 // the object address and its size. 223 _LIBCXXABI_FUNC_VIS void * 224 __cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size, 225 void (*constructor)(void *), void (*destructor)(void *), 226 void *(*alloc)(size_t), void (*dealloc)(void *, size_t)) { 227 const size_t heap_size = calculate_allocation_size_or_throw( 228 element_count, element_size, padding_size); 229 char* const heap_block = static_cast<char*>(alloc(heap_size)); 230 char* vec_base = heap_block; 231 232 if (NULL != vec_base) { 233 st_heap_block3 heap(dealloc, heap_block, heap_size); 234 235 // put the padding before the array elements 236 if ( 0 != padding_size ) { 237 vec_base += padding_size; 238 __set_element_count ( vec_base, element_count ); 239 } 240 241 // Construct the elements 242 __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor ); 243 heap.release (); // We're good! 244 } 245 246 return vec_base; 247 } 248 249 250 // Given the (data) addresses of a destination and a source array, an 251 // element count and an element size, call the given copy constructor to 252 // copy each element from the source array to the destination array. The 253 // copy constructor's arguments are the destination address and source 254 // address, respectively. If an exception occurs, call the given destructor 255 // (if non-NULL) on each copied element and rethrow. If the destructor 256 // throws an exception, call terminate(). The constructor and or destructor 257 // pointers may be NULL. If either is NULL, no action is taken when it 258 // would have been called. 259 260 _LIBCXXABI_FUNC_VIS void __cxa_vec_cctor(void *dest_array, void *src_array, 261 size_t element_count, 262 size_t element_size, 263 void (*constructor)(void *, void *), 264 void (*destructor)(void *)) { 265 if ( NULL != constructor ) { 266 size_t idx = 0; 267 char *src_ptr = static_cast<char *>(src_array); 268 char *dest_ptr = static_cast<char *>(dest_array); 269 st_cxa_cleanup cleanup ( dest_array, idx, element_size, destructor ); 270 271 for ( idx = 0; idx < element_count; 272 ++idx, src_ptr += element_size, dest_ptr += element_size ) 273 constructor ( dest_ptr, src_ptr ); 274 cleanup.release (); // We're good! 275 } 276 } 277 278 279 // Given the (data) address of an array, not including any cookie padding, 280 // and the number and size of its elements, call the given constructor on 281 // each element. If the constructor throws an exception, call the given 282 // destructor for any already-constructed elements, and rethrow the 283 // exception. If the destructor throws an exception, call terminate(). The 284 // constructor and/or destructor pointers may be NULL. If either is NULL, 285 // no action is taken when it would have been called. 286 _LIBCXXABI_FUNC_VIS void 287 __cxa_vec_ctor(void *array_address, size_t element_count, size_t element_size, 288 void (*constructor)(void *), void (*destructor)(void *)) { 289 if ( NULL != constructor ) { 290 size_t idx; 291 char *ptr = static_cast <char *> ( array_address ); 292 st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor ); 293 294 // Construct the elements 295 for ( idx = 0; idx < element_count; ++idx, ptr += element_size ) 296 constructor ( ptr ); 297 cleanup.release (); // We're good! 298 } 299 } 300 301 // Given the (data) address of an array, the number of elements, and the 302 // size of its elements, call the given destructor on each element. If the 303 // destructor throws an exception, rethrow after destroying the remaining 304 // elements if possible. If the destructor throws a second exception, call 305 // terminate(). The destructor pointer may be NULL, in which case this 306 // routine does nothing. 307 _LIBCXXABI_FUNC_VIS void __cxa_vec_dtor(void *array_address, 308 size_t element_count, 309 size_t element_size, 310 void (*destructor)(void *)) { 311 if ( NULL != destructor ) { 312 char *ptr = static_cast <char *> (array_address); 313 size_t idx = element_count; 314 st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor ); 315 { 316 st_terminate exception_guard (__cxa_uncaught_exception ()); 317 ptr += element_count * element_size; // one past the last element 318 319 while ( idx-- > 0 ) { 320 ptr -= element_size; 321 destructor ( ptr ); 322 } 323 exception_guard.release (); // We're good ! 324 } 325 cleanup.release (); // We're still good! 326 } 327 } 328 329 // Given the (data) address of an array, the number of elements, and the 330 // size of its elements, call the given destructor on each element. If the 331 // destructor throws an exception, call terminate(). The destructor pointer 332 // may be NULL, in which case this routine does nothing. 333 _LIBCXXABI_FUNC_VIS void __cxa_vec_cleanup(void *array_address, 334 size_t element_count, 335 size_t element_size, 336 void (*destructor)(void *)) { 337 if ( NULL != destructor ) { 338 char *ptr = static_cast <char *> (array_address); 339 size_t idx = element_count; 340 st_terminate exception_guard; 341 342 ptr += element_count * element_size; // one past the last element 343 while ( idx-- > 0 ) { 344 ptr -= element_size; 345 destructor ( ptr ); 346 } 347 exception_guard.release (); // We're done! 348 } 349 } 350 351 352 // If the array_address is NULL, return immediately. Otherwise, given the 353 // (data) address of an array, the non-negative size of prefix padding for 354 // the cookie, and the size of its elements, call the given destructor on 355 // each element, using the cookie to determine the number of elements, and 356 // then delete the space by calling ::operator delete[](void *). If the 357 // destructor throws an exception, rethrow after (a) destroying the 358 // remaining elements, and (b) deallocating the storage. If the destructor 359 // throws a second exception, call terminate(). If padding_size is 0, the 360 // destructor pointer must be NULL. If the destructor pointer is NULL, no 361 // destructor call is to be made. 362 // 363 // The intent of this function is to permit an implementation to call this 364 // function when confronted with an expression of the form delete[] p in 365 // the source code, provided that the default deallocation function can be 366 // used. Therefore, the semantics of this function are consistent with 367 // those required by the standard. The requirement that the deallocation 368 // function be called even if the destructor throws an exception derives 369 // from the resolution to DR 353 to the C++ standard, which was adopted in 370 // April, 2003. 371 _LIBCXXABI_FUNC_VIS void __cxa_vec_delete(void *array_address, 372 size_t element_size, 373 size_t padding_size, 374 void (*destructor)(void *)) { 375 __cxa_vec_delete2 ( array_address, element_size, padding_size, 376 destructor, &::operator delete [] ); 377 } 378 379 // Same as __cxa_vec_delete, except that the given function is used for 380 // deallocation instead of the default delete function. If dealloc throws 381 // an exception, the result is undefined. The dealloc pointer may not be 382 // NULL. 383 _LIBCXXABI_FUNC_VIS void 384 __cxa_vec_delete2(void *array_address, size_t element_size, size_t padding_size, 385 void (*destructor)(void *), void (*dealloc)(void *)) { 386 if ( NULL != array_address ) { 387 char *vec_base = static_cast <char *> (array_address); 388 char *heap_block = vec_base - padding_size; 389 st_heap_block2 heap ( dealloc, heap_block ); 390 391 if ( 0 != padding_size && NULL != destructor ) // call the destructors 392 __cxa_vec_dtor ( array_address, __get_element_count ( vec_base ), 393 element_size, destructor ); 394 } 395 } 396 397 398 // Same as __cxa_vec_delete, except that the given function is used for 399 // deallocation instead of the default delete function. The deallocation 400 // function takes both the object address and its size. If dealloc throws 401 // an exception, the result is undefined. The dealloc pointer may not be 402 // NULL. 403 _LIBCXXABI_FUNC_VIS void 404 __cxa_vec_delete3(void *array_address, size_t element_size, size_t padding_size, 405 void (*destructor)(void *), void (*dealloc)(void *, size_t)) { 406 if ( NULL != array_address ) { 407 char *vec_base = static_cast <char *> (array_address); 408 char *heap_block = vec_base - padding_size; 409 const size_t element_count = padding_size ? __get_element_count ( vec_base ) : 0; 410 const size_t heap_block_size = element_size * element_count + padding_size; 411 st_heap_block3 heap ( dealloc, heap_block, heap_block_size ); 412 413 if ( 0 != padding_size && NULL != destructor ) // call the destructors 414 __cxa_vec_dtor ( array_address, element_count, element_size, destructor ); 415 } 416 } 417 418 419 } // extern "C" 420 421 } // abi 422