Home | History | Annotate | Download | only in src
      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