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