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