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:
scoped_block(void * ptr,size_t size,dealloc2_func dealloc)50   scoped_block(void* ptr, size_t size, dealloc2_func dealloc)
51     : ptr_(ptr), size_(size), dealloc_(dealloc) {}
52 
~scoped_block()53   ~scoped_block() {
54     if (dealloc_)
55       dealloc_(ptr_, size_);
56   }
57 
release()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:
scoped_cleanup(void * array,size_t & index,size_t element_size,destructor_func destructor)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 
~scoped_cleanup()77   ~scoped_cleanup() {
78     if (destructor_)
79       __cxxabiv1::__cxa_vec_cleanup(array_,
80                                     index_,
81                                     element_size_,
82                                     destructor_);
83   }
84 
release()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:
scoped_catcher(const char * message)99   scoped_catcher(const char* message) : message_(message) {}
100 
~scoped_catcher()101   ~scoped_catcher() {
102     if (message_)
103       __gabixx::__fatal_error(message_);
104   }
105 
release()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 
__cxa_vec_new(size_t element_count,size_t element_size,size_t padding_size,constructor_func constructor,destructor_func destructor)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 
__cxa_vec_new2(size_t element_count,size_t element_size,size_t padding_size,constructor_func constructor,destructor_func destructor,alloc_func alloc,dealloc_func dealloc)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 
__cxa_vec_new3(size_t element_count,size_t element_size,size_t padding_size,constructor_func constructor,destructor_func destructor,alloc_func alloc,dealloc2_func dealloc)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
__cxa_vec_ctor(void * array_address,size_t element_count,size_t element_size,constructor_func constructor,destructor_func destructor)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.
__cxa_vec_dtor(void * array_address,size_t element_count,size_t element_size,destructor_func destructor)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.
__cxa_vec_cleanup(void * array_address,size_t element_count,size_t element_size,destructor_func destructor)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.
__cxa_vec_delete(void * array_address,size_t element_size,size_t padding_size,destructor_func destructor)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.
__cxa_vec_delete2(void * array_address,size_t element_size,size_t padding_size,destructor_func destructor,dealloc_func dealloc)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.
__cxa_vec_delete3(void * array_address,size_t element_size,size_t padding_size,destructor_func destructor,dealloc2_func dealloc)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
__cxa_vec_cctor(void * dst_array,void * src_array,size_t element_count,size_t element_size,copy_constructor_func copy_constructor,destructor_func destructor)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 
__aeabi_vec_ctor_nocookie_nodtor(void * array_address,constructor_func constructor,size_t element_size,size_t element_count)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 
__aeabi_vec_ctor_cookie_nodtor(void * array_address,constructor_func constructor,size_t element_size,size_t element_count)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 
__aeabi_vec_cctor_nocookie_nodtor(void * dst_array,void * src_array,size_t element_size,size_t element_count,copy_constructor_func copy_constructor)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 
__aeabi_vec_new_cookie_noctor(size_t element_size,size_t element_count)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 
__aeabi_vec_new_nocookie(size_t element_size,size_t element_count,constructor_func constructor)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 
__aeabi_vec_new_cookie_nodtor(size_t element_size,size_t element_count,constructor_func constructor)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 
__aeabi_vec_new_cookie(size_t element_size,size_t element_count,constructor_func constructor,destructor_func destructor)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 
__aeabi_vec_dtor(void * array_address,destructor_func destructor,size_t element_size,size_t element_count)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 
__aeabi_vec_dtor_cookie(void * array_address,destructor_func destructor)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 
__aeabi_vec_delete(void * array_address,destructor_func destructor)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 
__aeabi_vec_delete3(void * array_address,destructor_func destructor,dealloc2_func dealloc)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 
__aeabi_vec_delete3_nodtor(void * array_address,dealloc2_func dealloc)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