cxa_exception.cpp revision 81b7ea7df48333715c0c57d5418c5383e3f5c950
1//===------------------------- 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
55// pthread_once_t __globals::flag_ = PTHREAD_ONCE_INIT;
56
57extern "C" {
58
59//  Allocate a __cxa_exception object, and zero-fill it.
60//  Reserve "thrown_size" bytes on the end for the user's exception
61//  object. Zero-fill the object. If memory can't be allocated, call
62//  std::terminate. Return a pointer to the memory to be used for the
63//  user's exception object.
64void * __cxa_allocate_exception (size_t thrown_size) throw() {
65    size_t actual_size = object_size_from_exception_size ( thrown_size );
66    void *ptr = do_malloc ( actual_size );
67    if ( NULL == ptr )
68        std::terminate ();
69    std::memset ( ptr, 0, actual_size );
70    return object_from_exception ( ptr );
71    }
72
73
74//  Free a __cxa_exception object allocated with __cxa_allocate_exception.
75void __cxa_free_exception (void * thrown_exception) throw() {
76    do_free ( exception_from_object ( thrown_exception ));
77    }
78
79
80//  This function shall allocate a __cxa_dependent_exception and
81//  return a pointer to it. (Really to the object, not past its' end).
82//  Otherwise, it will work like __cxa_allocate_exception.
83void * __cxa_allocate_dependent_exception () throw() {
84    size_t actual_size = sizeof ( __cxa_dependent_exception );
85    void *ptr = do_malloc ( actual_size );
86    if ( NULL == ptr )
87        std::terminate ();
88    std::memset ( ptr, 0, actual_size );
89//  bookkeeping here ?
90    return ptr;
91    }
92
93
94//  This function shall free a dependent_exception.
95//  It does not affect the reference count of the primary exception.
96void __cxa_free_dependent_exception (void * dependent_exception) throw() {
97//  I'm pretty sure there's no bookkeeping here
98    do_free ( dependent_exception );
99    }
100
101}  // extern "C"
102
103}  // abi
104