blob: 93a4bd41df08826e79ae7aaff78f0f0a02bddaa0 [file] [log] [blame]
Marshall Clowe0252022011-07-20 15:04:39 +00001//===------------------------- cxa_exception.cpp --------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// This file implements the "Exception Handling APIs"
10// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
11//
12//===----------------------------------------------------------------------===//
13
14#include "cxxabi.h"
15
16#include <exception> // for std::terminate
17#include <cstdlib> // for malloc, free
18#include <string> // for memset
19#include <pthread.h>
20
21#include "cxa_exception.hpp"
22#include "cxa_exception_storage.hpp"
23
24namespace __cxxabiv1 {
25
26// Utility routines
27static __cxa_exception *exception_from_object ( void *p ) {
28 return ((__cxa_exception *) p ) - 1;
29 }
30
31void * object_from_exception ( void *p ) {
32 return (void *) (((__cxa_exception *) p ) + 1 );
33 }
34
35static size_t object_size_from_exception_size ( size_t size ) {
36 return size + sizeof (__cxa_exception);
37 }
38
39#include "fallback_malloc.cpp"
40
41// Allocate some memory from _somewhere_
42static void *do_malloc ( size_t size ) throw () {
43 void *ptr = std::malloc ( size );
44 if ( NULL == ptr ) // if malloc fails, fall back to emergency stash
45 ptr = fallback_malloc ( size );
46 return ptr;
47 }
48
49// Didn't know you could "return <expression>" from a void function, did you?
50// Well, you can, if the type of the expression is "void" also.
51static void do_free ( void *ptr ) throw () {
52 return is_fallback_ptr ( ptr ) ? fallback_free ( ptr ) : std::free ( ptr );
53 }
54
55static thread_local_storage<__cxa_eh_globals> __globals;
56// pthread_once_t __globals::flag_ = PTHREAD_ONCE_INIT;
57
58extern "C" {
59
60// Allocate a __cxa_exception object, and zero-fill it.
61// Reserve "thrown_size" bytes on the end for the user's exception
62// object. Zero-fill the object. If memory can't be allocated, call
63// std::terminate. Return a pointer to the memory to be used for the
64// user's exception object.
65void * __cxa_allocate_exception (size_t thrown_size) throw() {
66 size_t actual_size = object_size_from_exception_size ( thrown_size );
67 void *ptr = do_malloc ( actual_size );
68 if ( NULL == ptr )
69 std::terminate ();
70 std::memset ( ptr, 0, actual_size );
71 return object_from_exception ( ptr );
72 }
73
74
75// Free a __cxa_exception object allocated with __cxa_allocate_exception.
76void __cxa_free_exception (void * thrown_exception) throw() {
77 do_free ( exception_from_object ( thrown_exception ));
78 }
79
80
81// This function shall allocate a __cxa_dependent_exception and
82// return a pointer to it. (Really to the object, not past its' end).
83// Otherwise, it will work like __cxa_allocate_exception.
84void * __cxa_allocate_dependent_exception () throw() {
85 size_t actual_size = sizeof ( __cxa_dependent_exception );
86 void *ptr = do_malloc ( actual_size );
87 if ( NULL == ptr )
88 std::terminate ();
89 std::memset ( ptr, 0, actual_size );
90// bookkeeping here ?
91 return ptr;
92 }
93
94
95// This function shall free a dependent_exception.
96// It does not affect the reference count of the primary exception.
97void __cxa_free_dependent_exception (void * dependent_exception) throw() {
98// I'm pretty sure there's no bookkeeping here
99 do_free ( dependent_exception );
100 }
101
102__cxa_eh_globals * __cxa_get_globals () throw() { return __globals.get_tls (); }
103__cxa_eh_globals * __cxa_get_globals_fast () throw() { return __globals.get_tls_fast (); }
104
105} // extern "C"
106
107} // abi