1 // New abi Support -*- C++ -*-
2 
3 // Copyright (C) 2000, 2001, 2003, 2004, 2009, 2011
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of GCC.
7 //
8 // GCC is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3, or (at your option)
11 // any later version.
12 
13 // GCC is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 
18 // Under Section 7 of GPL version 3, you are granted additional
19 // permissions described in the GCC Runtime Library Exception, version
20 // 3.1, as published by the Free Software Foundation.
21 
22 // You should have received a copy of the GNU General Public License and
23 // a copy of the GCC Runtime Library Exception along with this program;
24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 // <http://www.gnu.org/licenses/>.
26 
27 // Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
28 
29 #include <cxxabi.h>
30 #include <new>
31 #include <exception>
32 #include <bits/exception_defines.h>
33 #include "unwind-cxx.h"
34 
35 namespace __cxxabiv1
36 {
37   namespace
38   {
39     struct uncatch_exception
40     {
41       uncatch_exception();
42       ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); }
43 
44       __cxa_exception* p;
45 
46     private:
47       uncatch_exception&
48       operator=(const uncatch_exception&);
49 
50       uncatch_exception(const uncatch_exception&);
51     };
52 
53     uncatch_exception::uncatch_exception() : p(0)
54     {
55       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
56 
57       p = globals->caughtExceptions;
58       p->handlerCount -= 1;
59       globals->caughtExceptions = p->nextException;
60       globals->uncaughtExceptions += 1;
61     }
62   }
63 
64   // Allocate and construct array.
65   extern "C" void *
66   __cxa_vec_new(std::size_t element_count,
67 		std::size_t element_size,
68 		std::size_t padding_size,
69 		__cxa_cdtor_type constructor,
70 		__cxa_cdtor_type destructor)
71   {
72     return __cxa_vec_new2(element_count, element_size, padding_size,
73 			   constructor, destructor,
74 			   &operator new[], &operator delete []);
75   }
76 
77   extern "C" void *
78   __cxa_vec_new2(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 		 void *(*alloc) (std::size_t),
84 		 void (*dealloc) (void *))
85   {
86     std::size_t size = element_count * element_size + padding_size;
87     char *base = static_cast <char *> (alloc (size));
88     if (!base)
89       return base;
90 
91     if (padding_size)
92       {
93 	base += padding_size;
94 	reinterpret_cast <std::size_t *> (base)[-1] = element_count;
95 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
96 	reinterpret_cast <std::size_t *> (base)[-2] = element_size;
97 #endif
98       }
99     __try
100       {
101 	__cxa_vec_ctor(base, element_count, element_size,
102 		       constructor, destructor);
103       }
104     __catch(...)
105       {
106 	{
107 	  uncatch_exception ue;
108 	  // Core issue 901 will probably be resolved such that a
109 	  // deleted operator delete means not freeing memory here.
110 	  if (dealloc)
111 	    dealloc(base - padding_size);
112 	}
113 	__throw_exception_again;
114       }
115     return base;
116   }
117 
118   extern "C" void *
119   __cxa_vec_new3(std::size_t element_count,
120 		 std::size_t element_size,
121 		 std::size_t padding_size,
122 		 __cxa_cdtor_type constructor,
123 		 __cxa_cdtor_type destructor,
124 		 void *(*alloc) (std::size_t),
125 		 void (*dealloc) (void *, std::size_t))
126   {
127     std::size_t size = element_count * element_size + padding_size;
128     char *base = static_cast<char *>(alloc (size));
129     if (!base)
130       return base;
131 
132     if (padding_size)
133       {
134 	base += padding_size;
135 	reinterpret_cast<std::size_t *>(base)[-1] = element_count;
136 #ifdef _GLIBCXX_ELTSIZE_IN_COOKIE
137 	reinterpret_cast <std::size_t *> (base)[-2] = element_size;
138 #endif
139       }
140     __try
141       {
142 	__cxa_vec_ctor(base, element_count, element_size,
143 		       constructor, destructor);
144       }
145     __catch(...)
146       {
147 	{
148 	  uncatch_exception ue;
149 	  if (dealloc)
150 	    dealloc(base - padding_size, size);
151 	}
152 	__throw_exception_again;
153       }
154     return base;
155   }
156 
157   // Construct array.
158   extern "C" __cxa_vec_ctor_return_type
159   __cxa_vec_ctor(void *array_address,
160 		 std::size_t element_count,
161 		 std::size_t element_size,
162 		 __cxa_cdtor_type constructor,
163 		 __cxa_cdtor_type destructor)
164   {
165     std::size_t ix = 0;
166     char *ptr = static_cast<char *>(array_address);
167 
168     __try
169       {
170 	if (constructor)
171 	  for (; ix != element_count; ix++, ptr += element_size)
172 	    constructor(ptr);
173       }
174     __catch(...)
175       {
176 	{
177 	  uncatch_exception ue;
178 	  __cxa_vec_cleanup(array_address, ix, element_size, destructor);
179 	}
180 	__throw_exception_again;
181       }
182     _GLIBCXX_CXA_VEC_CTOR_RETURN (array_address);
183   }
184 
185   // Construct an array by copying.
186   extern "C" __cxa_vec_ctor_return_type
187   __cxa_vec_cctor(void *dest_array,
188 		  void *src_array,
189 		  std::size_t element_count,
190 		  std::size_t element_size,
191 		  __cxa_cdtor_return_type (*constructor) (void *, void *),
192 		  __cxa_cdtor_type destructor)
193   {
194     std::size_t ix = 0;
195     char *dest_ptr = static_cast<char *>(dest_array);
196     char *src_ptr = static_cast<char *>(src_array);
197 
198     __try
199       {
200 	if (constructor)
201 	  for (; ix != element_count;
202 	       ix++, src_ptr += element_size, dest_ptr += element_size)
203 	    constructor(dest_ptr, src_ptr);
204       }
205     __catch(...)
206       {
207 	{
208 	  uncatch_exception ue;
209 	  __cxa_vec_cleanup(dest_array, ix, element_size, destructor);
210 	}
211 	__throw_exception_again;
212       }
213     _GLIBCXX_CXA_VEC_CTOR_RETURN (dest_array);
214   }
215 
216   // Destruct array.
217   extern "C" void
218   __cxa_vec_dtor(void *array_address,
219 		 std::size_t element_count,
220 		 std::size_t element_size,
221 		 __cxa_cdtor_type destructor)
222   {
223     if (destructor)
224       {
225 	char *ptr = static_cast<char *>(array_address);
226 	std::size_t ix = element_count;
227 
228 	ptr += element_count * element_size;
229 
230 	__try
231 	  {
232 	    while (ix--)
233 	      {
234 		ptr -= element_size;
235 		destructor(ptr);
236 	      }
237 	  }
238 	__catch(...)
239 	  {
240 	    {
241 	      uncatch_exception ue;
242 	      __cxa_vec_cleanup(array_address, ix, element_size, destructor);
243 	    }
244 	    __throw_exception_again;
245 	  }
246       }
247   }
248 
249   // Destruct array as a result of throwing an exception.
250   // [except.ctor]/3 If a destructor called during stack unwinding
251   // exits with an exception, terminate is called.
252   extern "C" void
253   __cxa_vec_cleanup(void *array_address,
254 		    std::size_t element_count,
255 		    std::size_t element_size,
256 		    __cxa_cdtor_type destructor) throw()
257   {
258     if (destructor)
259       {
260 	char *ptr = static_cast <char *> (array_address);
261 	std::size_t ix = element_count;
262 
263 	ptr += element_count * element_size;
264 
265 	__try
266 	  {
267 	    while (ix--)
268 	      {
269 		ptr -= element_size;
270 		destructor(ptr);
271 	      }
272 	  }
273 	__catch(...)
274 	  {
275 	    std::terminate();
276 	  }
277       }
278   }
279 
280   // Destruct and release array.
281   extern "C" void
282   __cxa_vec_delete(void *array_address,
283 		   std::size_t element_size,
284 		   std::size_t padding_size,
285 		   __cxa_cdtor_type destructor)
286   {
287     __cxa_vec_delete2(array_address, element_size, padding_size,
288 		       destructor,
289 		       &operator delete []);
290   }
291 
292   extern "C" void
293   __cxa_vec_delete2(void *array_address,
294 		    std::size_t element_size,
295 		    std::size_t padding_size,
296 		    __cxa_cdtor_type destructor,
297 		    void (*dealloc) (void *))
298   {
299     if (!array_address)
300       return;
301 
302     char* base = static_cast<char *>(array_address);
303 
304     if (padding_size)
305       {
306 	std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
307 	base -= padding_size;
308 	__try
309 	  {
310 	    __cxa_vec_dtor(array_address, element_count, element_size,
311 			   destructor);
312 	  }
313 	__catch(...)
314 	  {
315 	    {
316 	      uncatch_exception ue;
317 	      dealloc(base);
318 	    }
319 	    __throw_exception_again;
320 	  }
321       }
322     dealloc(base);
323   }
324 
325   extern "C" void
326   __cxa_vec_delete3(void *array_address,
327 		    std::size_t element_size,
328 		    std::size_t padding_size,
329 		     __cxa_cdtor_type destructor,
330 		    void (*dealloc) (void *, std::size_t))
331   {
332     if (!array_address)
333       return;
334 
335     char* base = static_cast <char *> (array_address);
336     std::size_t size = 0;
337 
338     if (padding_size)
339       {
340 	std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
341 	base -= padding_size;
342 	size = element_count * element_size + padding_size;
343 	__try
344 	  {
345 	    __cxa_vec_dtor(array_address, element_count, element_size,
346 			   destructor);
347 	  }
348 	__catch(...)
349 	  {
350 	    {
351 	      uncatch_exception ue;
352 	      dealloc(base, size);
353 	    }
354 	    __throw_exception_again;
355 	  }
356       }
357     dealloc(base, size);
358   }
359 } // namespace __cxxabiv1
360 
361 #if defined(__arm__) && defined(__ARM_EABI__)
362 
363 // The ARM C++ ABI requires that the library provide these additional
364 // helper functions.  There are placed in this file, despite being
365 // architecture-specifier, so that the compiler can inline the __cxa
366 // functions into these functions as appropriate.
367 
368 namespace __aeabiv1
369 {
370   extern "C" void *
371   __aeabi_vec_ctor_nocookie_nodtor (void *array_address,
372 				    abi::__cxa_cdtor_type constructor,
373 				    std::size_t element_size,
374 				    std::size_t element_count)
375   {
376     return abi::__cxa_vec_ctor (array_address, element_count, element_size,
377 				constructor, /*destructor=*/NULL);
378   }
379 
380   extern "C" void *
381   __aeabi_vec_ctor_cookie_nodtor (void *array_address,
382 				  abi::__cxa_cdtor_type constructor,
383 				  std::size_t element_size,
384 				  std::size_t element_count)
385   {
386     if (array_address == NULL)
387       return NULL;
388 
389     array_address = reinterpret_cast<std::size_t *>(array_address) + 2;
390     reinterpret_cast<std::size_t *>(array_address)[-2] = element_size;
391     reinterpret_cast<std::size_t *>(array_address)[-1] = element_count;
392     return abi::__cxa_vec_ctor (array_address,
393 				element_count, element_size,
394 				constructor, /*destructor=*/NULL);
395   }
396 
397   extern "C" void *
398   __aeabi_vec_cctor_nocookie_nodtor (void *dest_array,
399 				     void *src_array,
400 				     std::size_t element_size,
401 				     std::size_t element_count,
402 				     void *(*constructor) (void *, void *))
403   {
404     return abi::__cxa_vec_cctor (dest_array, src_array,
405 				 element_count, element_size,
406 				 constructor, NULL);
407   }
408 
409   extern "C" void *
410   __aeabi_vec_new_cookie_noctor (std::size_t element_size,
411 				 std::size_t element_count)
412   {
413     return abi::__cxa_vec_new(element_count, element_size,
414 			      2 * sizeof (std::size_t),
415 			      /*constructor=*/NULL, /*destructor=*/NULL);
416   }
417 
418   extern "C" void *
419   __aeabi_vec_new_nocookie (std::size_t element_size,
420 			    std::size_t element_count,
421 			    abi::__cxa_cdtor_type constructor)
422   {
423     return abi::__cxa_vec_new (element_count, element_size, 0, constructor,
424 			       NULL);
425   }
426 
427   extern "C" void *
428   __aeabi_vec_new_cookie_nodtor (std::size_t element_size,
429 				 std::size_t element_count,
430 				 abi::__cxa_cdtor_type constructor)
431   {
432     return abi::__cxa_vec_new(element_count, element_size,
433 			      2 * sizeof (std::size_t),
434 			      constructor, NULL);
435   }
436 
437   extern "C" void *
438   __aeabi_vec_new_cookie(std::size_t element_size,
439 			 std::size_t element_count,
440 			 abi::__cxa_cdtor_type constructor,
441 			 abi::__cxa_cdtor_type destructor)
442   {
443     return abi::__cxa_vec_new (element_count, element_size,
444 			       2 * sizeof (std::size_t),
445 			       constructor, destructor);
446   }
447 
448 
449   extern "C" void *
450   __aeabi_vec_dtor (void *array_address,
451 		    abi::__cxa_cdtor_type destructor,
452 		    std::size_t element_size,
453 		    std::size_t element_count)
454   {
455     abi::__cxa_vec_dtor (array_address, element_count, element_size,
456 			 destructor);
457     return reinterpret_cast<std::size_t*> (array_address) - 2;
458   }
459 
460   extern "C" void *
461   __aeabi_vec_dtor_cookie (void *array_address,
462 			   abi::__cxa_cdtor_type destructor)
463   {
464     if (!array_address)
465       return NULL;
466 
467     abi::__cxa_vec_dtor (array_address,
468 			 reinterpret_cast<std::size_t *>(array_address)[-1],
469 			 reinterpret_cast<std::size_t *>(array_address)[-2],
470 			 destructor);
471     return reinterpret_cast<std::size_t*> (array_address) - 2;
472   }
473 
474 
475   extern "C" void
476   __aeabi_vec_delete (void *array_address,
477 		      abi::__cxa_cdtor_type destructor)
478   {
479     if (!array_address)
480       return;
481 
482     abi::__cxa_vec_delete (array_address,
483 			   reinterpret_cast<std::size_t *>(array_address)[-2],
484 			   2 * sizeof (std::size_t),
485 			   destructor);
486   }
487 
488   extern "C" void
489   __aeabi_vec_delete3 (void *array_address,
490 		       abi::__cxa_cdtor_type destructor,
491 		       void (*dealloc) (void *, std::size_t))
492   {
493     if (!array_address)
494       return;
495 
496     abi::__cxa_vec_delete3 (array_address,
497 			    reinterpret_cast<std::size_t *>(array_address)[-2],
498 			    2 * sizeof (std::size_t),
499 			    destructor, dealloc);
500   }
501 
502   extern "C" void
503   __aeabi_vec_delete3_nodtor (void *array_address,
504 			      void (*dealloc) (void *, std::size_t))
505   {
506     if (!array_address)
507       return;
508 
509     abi::__cxa_vec_delete3 (array_address,
510 			    reinterpret_cast<std::size_t *>(array_address)[-2],
511 			    2 * sizeof (std::size_t),
512 			    /*destructor=*/NULL, dealloc);
513   }
514 } // namespace __aeabiv1
515 
516 #endif // defined(__arm__) && defined(__ARM_EABI__)
517