diff options
| -rw-r--r-- | cxxabi.h | 14 | ||||
| -rw-r--r-- | dwarf_eh.h | 7 | ||||
| -rw-r--r-- | exception.cc | 170 | ||||
| -rw-r--r-- | guard.cc | 54 | ||||
| -rw-r--r-- | unwind-arm.h | 201 | ||||
| -rw-r--r-- | unwind-itanium.h | 170 | ||||
| -rw-r--r-- | unwind.h | 18 | 
7 files changed, 615 insertions, 19 deletions
@@ -1,7 +1,7 @@  #ifndef __CXXABI_H_  #define __CXXABI_H_  #include <stdint.h> -#include <unwind.h> +#include "unwind.h"  namespace std   {  	class type_info; @@ -87,6 +87,18 @@ struct __cxa_exception  	 * handler count reaches 0 (which it doesn't with the top bit set).  	 */  	int handlerCount; +#ifdef __arm__ +	/** +	 * The ARM EH ABI requires the unwind library to keep track of exceptions +	 * during cleanups.  These support nesting, so we need to keep a list of +	 * them. +	 */ +	_Unwind_Exception *nextCleanup; +	/** +	 * The number of cleanups that are currently being run on this exception.  +	 */ +	int cleanupCount; +#endif  	/**  	 * The selector value to be returned when installing the catch handler.  	 * Used at the call site to determine which catch() block should execute. diff --git a/dwarf_eh.h b/dwarf_eh.h index 09017511177a..52e6369d978d 100644 --- a/dwarf_eh.h +++ b/dwarf_eh.h @@ -16,10 +16,10 @@  // that it doesn't impact the rest of the program.  #ifndef _GNU_SOURCE  #	define _GNU_SOURCE 1 -#	include <unwind.h> +#	include "unwind.h"  #	undef _GNU_SOURCE  #else -#	include <unwind.h> +#	include "unwind.h"  #endif  #include <stdint.h> @@ -340,6 +340,9 @@ static inline struct dwarf_eh_lsda parse_lsda(_Unwind_Context *context,  		lsda.type_table = type_table;  		//lsda.type_table = (uintptr_t*)(data + v);  	} +#if __arm__ +	lsda.type_table_encoding = (DW_EH_PE_pcrel | DW_EH_PE_indirect); +#endif  	lsda.callsite_encoding = (enum dwarf_data_encoding)(*(data++)); diff --git a/exception.cc b/exception.cc index 66e09296f989..abf6a10b3b48 100644 --- a/exception.cc +++ b/exception.cc @@ -2,6 +2,7 @@  #include <dlfcn.h>  #include <stdio.h>  #include <string.h> +#include <stdint.h>  #include <pthread.h>  #include "typeinfo.h"  #include "dwarf_eh.h" @@ -9,6 +10,66 @@  using namespace ABI_NAMESPACE; +/** + * Saves the result of the landing pad that we have found.  For ARM, this is + * stored in the generic unwind structure, while on other platforms it is + * stored in the C++ exception. + */ +static void saveLandingPad(struct _Unwind_Context *context, +                           struct _Unwind_Exception *ucb, +                           struct __cxa_exception *ex, +                           int selector, +                           dw_eh_ptr_t landingPad) +{ +#ifdef __arm__ +	// On ARM, we store the saved exception in the generic part of the structure +	ucb->barrier_cache.sp = _Unwind_GetGR(context, 13); +	ucb->barrier_cache.bitpattern[1] = (uint32_t)selector; +	ucb->barrier_cache.bitpattern[3] = (uint32_t)landingPad; +#endif +	// Cache the results for the phase 2 unwind, if we found a handler +	// and this is not a foreign exception.   +	if (ex) +	{ +		ex->handlerSwitchValue = selector; +		ex->catchTemp = landingPad; +	} +} + +/** + * Loads the saved landing pad.  Returns 1 on success, 0 on failure. + */ +static int loadLandingPad(struct _Unwind_Context *context, +                          struct _Unwind_Exception *ucb, +                          struct __cxa_exception *ex, +                          unsigned long *selector, +                          dw_eh_ptr_t *landingPad) +{ +#ifdef __arm__ +	*selector = ucb->barrier_cache.bitpattern[1]; +	*landingPad = (dw_eh_ptr_t)ucb->barrier_cache.bitpattern[3]; +	return 1; +#else +	if (ex) +	{ +		*selector = ex->handlerSwitchValue; +		*landingPad = (dw_eh_ptr_t)ex->catchTemp; +		return 0; +	} +	return 0; +#endif +} + +static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex, +                                                    struct _Unwind_Context *context) +{ +#ifdef __arm__ +	if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; } +#endif +	return _URC_CONTINUE_UNWIND; +} + +  extern "C" void __cxa_free_exception(void *thrown_exception);  extern "C" void __cxa_free_dependent_exception(void *thrown_exception);  extern "C" void* __dynamic_cast(const void *sub, @@ -59,6 +120,10 @@ struct __cxa_thread_info  	 */  	int emergencyBuffersHeld;  	/** +	 * The exception currently running in a cleanup. +	 */ +	_Unwind_Exception *currentCleanup; +	/**  	 * The public part of this structure, accessible from outside of this  	 * module.  	 */ @@ -78,6 +143,10 @@ struct __cxa_dependent_exception  	terminate_handler terminateHandler;  	__cxa_exception *nextException;  	int handlerCount; +#ifdef __arm__ +	_Unwind_Exception *nextCleanup; +	int cleanupCount; +#endif  	int handlerSwitchValue;  	const char *actionRecord;  	const char *languageSpecificData; @@ -519,9 +588,11 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce  		case _URC_FATAL_PHASE1_ERROR:  			fprintf(stderr, "Fatal error during phase 1 unwinding\n");  			break; +#ifndef __arm__  		case _URC_FATAL_PHASE2_ERROR:  			fprintf(stderr, "Fatal error during phase 2 unwinding\n");  			break; +#endif  		case _URC_END_OF_STACK:  			fprintf(stderr, "Terminating due to uncaught exception %p",   					(void*)thrown_exception); @@ -696,6 +767,7 @@ static std::type_info *get_type_info_entry(_Unwind_Context *context,  	// Get the address of the record in the table.  	dw_eh_ptr_t record = lsda->type_table -   		dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter; +	//record -= 4;  	dw_eh_ptr_t start = record;  	// Read the value, but it's probably an indirect reference...  	int64_t offset = read_value(lsda->type_table_encoding, &record); @@ -709,6 +781,7 @@ static std::type_info *get_type_info_entry(_Unwind_Context *context,  } +  /**   * Checks the type signature found in a handler against the type of the thrown   * object.  If ex is 0 then it is assumed to be a foreign exception and only @@ -829,9 +902,22 @@ static handler_type check_action_record(_Unwind_Context *context,  		}  		else if (filter < 0 && 0 != ex)  		{ -			unsigned char *type_index = ((unsigned char*)lsda->type_table - filter - 1);  			bool matched = false;  			*selector = filter; +#ifdef __arm__ +			filter++; +			std::type_info *handler_type = get_type_info_entry(context, lsda, filter--); +			while (handler_type) +			{ +				if (check_type_signature(ex, handler_type, adjustedPtr)) +				{ +					matched = true; +					break; +				} +				handler_type = get_type_info_entry(context, lsda, filter--); +			} +#else +			unsigned char *type_index = ((unsigned char*)lsda->type_table - filter - 1);  			while (*type_index)  			{  				std::type_info *handler_type = get_type_info_entry(context, lsda, *(type_index++)); @@ -844,6 +930,7 @@ static handler_type check_action_record(_Unwind_Context *context,  					break;  				}  			} +#endif  			if (matched) { continue; }  			// If we don't find an allowed exception spec, we need to install  			// the context for this action.  The landing pad will then call the @@ -859,17 +946,32 @@ static handler_type check_action_record(_Unwind_Context *context,  	return found;  } +static void pushCleanupException(_Unwind_Exception *exceptionObject, +                                 __cxa_exception *ex) +{ +#ifdef __arm__ +	__cxa_thread_info *info = thread_info_fast(); +	if (ex) +	{ +		ex->cleanupCount++; +		if (ex->cleanupCount > 1) +		{ +			assert(exceptionObject == info->currentCleanup); +			return; +		} +		ex->nextCleanup = info->currentCleanup; +	} +	info->currentCleanup = exceptionObject; +#endif +} +  /**   * The exception personality function.  This is referenced in the unwinding   * DWARF metadata and is called by the unwind library for each C++ stack frame   * containing catch or cleanup code.   */ -extern "C" _Unwind_Reason_Code  __gxx_personality_v0(int version, -                                                     _Unwind_Action actions, -                                                     uint64_t exceptionClass, -                                                     struct _Unwind_Exception *exceptionObject, -                                                     struct _Unwind_Context *context) -{ +extern "C" +BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0)  	// This personality function is for version 1 of the ABI.  If you use it  	// with a future version of the ABI, it won't know what to do, so it  	// reports a fatal error and give up before it breaks anything. @@ -896,7 +998,7 @@ extern "C" _Unwind_Reason_Code  __gxx_personality_v0(int version,  		(unsigned char*)_Unwind_GetLanguageSpecificData(context);  	// No LSDA implies no landing pads - try the next frame -	if (0 == lsda_addr) { return _URC_CONTINUE_UNWIND; } +	if (0 == lsda_addr) { return continueUnwinding(exceptionObject, context); }  	// These two variables define how the exception will be handled.  	dwarf_eh_action action = {0}; @@ -941,15 +1043,14 @@ extern "C" _Unwind_Reason_Code  __gxx_personality_v0(int version,  			// and this is not a foreign exception.  			if (ex)  			{ -				ex->handlerSwitchValue = selector; -				ex->actionRecord = (const char*)action.action_record; +				saveLandingPad(context, exceptionObject, ex, selector, action.landing_pad);  				ex->languageSpecificData = (const char*)lsda_addr; -				ex->catchTemp = action.landing_pad; +				ex->actionRecord = (const char*)action.action_record;  				// ex->adjustedPtr is set when finding the action record.  			}  			return _URC_HANDLER_FOUND;  		} -		return _URC_CONTINUE_UNWIND; +		return continueUnwinding(exceptionObject, context);  	} @@ -962,11 +1063,12 @@ extern "C" _Unwind_Reason_Code  __gxx_personality_v0(int version,  		// cleanup  		struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);  		dwarf_eh_find_callsite(context, &lsda, &action); -		if (0 == action.landing_pad) { return _URC_CONTINUE_UNWIND; } +		if (0 == action.landing_pad) { return continueUnwinding(exceptionObject, context); }  		handler_type found_handler = check_action_record(context, &lsda,  				action.action_record, realEx, &selector, ex->adjustedPtr);  		// Ignore handlers this time. -		if (found_handler != handler_cleanup) { return _URC_CONTINUE_UNWIND; } +		if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); } +		pushCleanupException(exceptionObject, ex);  	}  	else if (foreignException)  	{ @@ -983,9 +1085,8 @@ extern "C" _Unwind_Reason_Code  __gxx_personality_v0(int version,  	else  	{  		// Restore the saved info if we saved some last time. -		action.landing_pad = (dw_eh_ptr_t)ex->catchTemp; +		loadLandingPad(context, exceptionObject, ex, &selector, &action.landing_pad);  		ex->catchTemp = 0; -		selector = (unsigned long)ex->handlerSwitchValue;  		ex->handlerSwitchValue = 0;  	} @@ -1063,6 +1164,8 @@ extern "C" void *__cxa_begin_catch(void *e)  	return ((char*)exceptionObject + sizeof(_Unwind_Exception));  } + +  /**   * ABI function called when exiting a catch block.  This will free the current   * exception if it is no longer referenced in other catch blocks. @@ -1281,3 +1384,38 @@ namespace std  		return terminateHandler;  	}  } +#ifdef __arm__ +extern "C" _Unwind_Exception *__cxa_get_cleanup(void) +{ +	__cxa_thread_info *info = thread_info_fast(); +	_Unwind_Exception *exceptionObject = info->currentCleanup; +	if (isCXXException(exceptionObject->exception_class)) +	{ +		__cxa_exception *ex =  exceptionFromPointer(exceptionObject); +		ex->cleanupCount--; +		if (ex->cleanupCount == 0) +		{ +			info->currentCleanup = ex->nextCleanup; +			ex->nextCleanup = 0; +		} +	} +	else +	{ +		info->currentCleanup = 0; +	} +	return exceptionObject; +} + +asm ( +".pushsection .text.__cxa_end_cleanup    \n" +".global __cxa_end_cleanup               \n" +".type __cxa_end_cleanup, \"function\"   \n" +"__cxa_end_cleanup:                      \n" +"	push {r1, r2, r3, r4}                \n" +"	bl __cxa_get_cleanup                 \n" +"	push {r1, r2, r3, r4}                \n" +"	b _Unwind_Resume                     \n" +"	bl abort                             \n" +".popsection                             \n" +); +#endif @@ -16,6 +16,59 @@   */  #include <stdint.h>  #include <pthread.h> +#include <assert.h> + +#ifdef __arm__ +// ARM ABI - 32-bit guards. + +/** + * Acquires a lock on a guard, returning 0 if the object has already been + * initialised, and 1 if it has not.  If the object is already constructed then + * this function just needs to read a byte from memory and return. + */ +extern "C" int __cxa_guard_acquire(volatile int32_t *guard_object) +{ +	if ((1<<31) == *guard_object) { return 0; } +	// If we can atomically move the value from 0 -> 1, then this is +	// uninitialised. +	if (__sync_bool_compare_and_swap(guard_object, 0, 1)) +	{ +		return 1; +	} +	// If the value is not 0, some other thread was initialising this.  Spin +	// until it's finished. +	while (__sync_bool_compare_and_swap(guard_object, (1<<31), (1<<31))) +	{ +		// If the other thread aborted, then we grab the lock +		if (__sync_bool_compare_and_swap(guard_object, 0, 1)) +		{ +			return 1; +		} +		sched_yield(); +	} +	return 0; +} + +/** + * Releases the lock without marking the object as initialised.  This function + * is called if initialising a static causes an exception to be thrown. + */ +extern "C" void __cxa_guard_abort(int32_t *guard_object) +{ +	assert(__sync_bool_compare_and_swap(guard_object, 1, 0)); +} +/** + * Releases the guard and marks the object as initialised.  This function is + * called after successful initialisation of a static. + */ +extern "C" void __cxa_guard_release(int32_t *guard_object) +{ +	assert(__sync_bool_compare_and_swap(guard_object, 1, (1<<31))); +} + + +#else +// Itanium ABI: 64-bit guards  /**   * Returns a pointer to the low 32 bits in a 64-bit value, respecting the @@ -78,3 +131,4 @@ extern "C" void __cxa_guard_release(int64_t *guard_object)  	__cxa_guard_abort(guard_object);  } +#endif diff --git a/unwind-arm.h b/unwind-arm.h new file mode 100644 index 000000000000..f9ed4297603b --- /dev/null +++ b/unwind-arm.h @@ -0,0 +1,201 @@ +/** + * ARM-specific unwind definitions.  These are taken from the ARM EHABI + * specification. + */ + typedef enum +{ +	_URC_OK = 0,                /* operation completed successfully */ +	_URC_FOREIGN_EXCEPTION_CAUGHT = 1, +    _URC_END_OF_STACK = 5, +	_URC_HANDLER_FOUND = 6, +	_URC_INSTALL_CONTEXT = 7, +	_URC_CONTINUE_UNWIND = 8, +	_URC_FAILURE = 9,            /* unspecified failure of some kind */ +	_URC_FATAL_PHASE1_ERROR = _URC_FAILURE +} _Unwind_Reason_Code; + +typedef uint32_t _Unwind_State; +#ifdef __clang__ +static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME  = 0; +static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; +static const _Unwind_State _US_UNWIND_FRAME_RESUME   = 2; +#else // GCC fails at knowing what a constant expression is +#	define _US_VIRTUAL_UNWIND_FRAME  0 +#	define _US_UNWIND_FRAME_STARTING 1 +#	define _US_UNWIND_FRAME_RESUME 2 +#endif + +typedef struct _Unwind_Context _Unwind_Context; + +typedef uint32_t _Unwind_EHT_Header; + +struct _Unwind_Exception +{ +	uint64_t exception_class; +	void (*exception_cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception *); +	/* Unwinder cache, private fields for the unwinder's use */ +	struct +	{ +		uint32_t reserved1; +		uint32_t reserved2; +		uint32_t reserved3; +		uint32_t reserved4; +		uint32_t reserved5; +	/* init reserved1 to 0, then don't touch */ +	} unwinder_cache; +	/* Propagation barrier cache (valid after phase 1): */ +	struct +	{ +		uint32_t sp; +		uint32_t bitpattern[5]; +	} barrier_cache; +	/* Cleanup cache (preserved over cleanup): */ +	struct +	{ +		uint32_t bitpattern[4]; +	} cleanup_cache; +	/* Pr cache (for pr's benefit): */ +	struct +	{ +		/** function start address */ +		uint32_t fnstart; +		/** pointer to EHT entry header word */ +		_Unwind_EHT_Header *ehtp; +		/** additional data */ +		uint32_t additional; +		uint32_t reserved1; +	} pr_cache; +	/** Force alignment of next item to 8-byte boundary */ +	long long int :0; +}; + +/* Unwinding functions */ +_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *ucbp); +void _Unwind_Resume(struct _Unwind_Exception *ucbp); +void _Unwind_Complete(struct _Unwind_Exception *ucbp); +void _Unwind_DeleteException(struct _Unwind_Exception *ucbp); +void *_Unwind_GetLanguageSpecificData(struct _Unwind_Context*); + +typedef enum +{ +	_UVRSR_OK = 0, +	_UVRSR_NOT_IMPLEMENTED = 1, +	_UVRSR_FAILED = 2 +} _Unwind_VRS_Result; +typedef enum +{ +	_UVRSC_CORE = 0, +	_UVRSC_VFP = 1, +	_UVRSC_WMMXD = 3, +	_UVRSC_WMMXC = 4 +} _Unwind_VRS_RegClass; +typedef enum +{ +	_UVRSD_UINT32 = 0, +	_UVRSD_VFPX = 1, +	_UVRSD_UINT64 = 3, +	_UVRSD_FLOAT = 4, +	_UVRSD_DOUBLE = 5 +} _Unwind_VRS_DataRepresentation; + +_Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context, +                                   _Unwind_VRS_RegClass regclass, +                                   uint32_t regno, +                                   _Unwind_VRS_DataRepresentation representation, +                                   void *valuep); +_Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, +                                   _Unwind_VRS_RegClass regclass, +                                   uint32_t regno, +                                   _Unwind_VRS_DataRepresentation representation, +                                   void *valuep); + +/* Return the base-address for data references.  */ +extern unsigned long _Unwind_GetDataRelBase(struct _Unwind_Context *); + +/* Return the base-address for text references.  */ +extern unsigned long _Unwind_GetTextRelBase(struct _Unwind_Context *); +extern unsigned long _Unwind_GetRegionStart(struct _Unwind_Context *); + +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, +						 void *); +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); +extern _Unwind_Reason_Code +	  _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); + +/** + * The next set of functions are compatibility extensions, implementing Itanium + * ABI functions on top of ARM ones. + */ + +#define _UA_SEARCH_PHASE	1 +#define _UA_CLEANUP_PHASE	2 +#define _UA_HANDLER_FRAME	4 +#define _UA_FORCE_UNWIND	8 + +static inline unsigned long _Unwind_GetGR(struct _Unwind_Context *context, int reg) +{ +	unsigned long val; +	_Unwind_VRS_Get(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); +	return val; +} +static inline  void _Unwind_SetGR(struct _Unwind_Context *context, int reg, unsigned long val) +{ +	_Unwind_VRS_Set(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); +} +static inline unsigned long _Unwind_GetIP(_Unwind_Context *context) +{ +	// Low bit store the thumb state - discard it +	return _Unwind_GetGR(context, 15) & ~1; +} +static inline void _Unwind_SetIP(_Unwind_Context *context, unsigned long val) +{ +	// The lowest bit of the instruction pointer indicates whether we're in +	// thumb or ARM mode.  This is assumed to be fixed throughout a function, +	// so must be propagated when setting the program counter. +	unsigned long thumbState = _Unwind_GetGR(context, 15) & 1; +   _Unwind_SetGR(context, 15, (val | thumbState)); +} + +/** GNU API function that unwinds the frame */ +_Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*, struct _Unwind_Context*); + + +#define DECLARE_PERSONALITY_FUNCTION(name) \ +_Unwind_Reason_Code name(_Unwind_State state,\ +                         struct _Unwind_Exception *exceptionObject,\ +                         struct _Unwind_Context *context); + +#define BEGIN_PERSONALITY_FUNCTION(name) \ +_Unwind_Reason_Code name(_Unwind_State state,\ +                         struct _Unwind_Exception *exceptionObject,\ +                         struct _Unwind_Context *context)\ +{\ +	int version = 1;\ +	uint64_t exceptionClass = exceptionObject->exception_class;\ +	int actions;\ +	switch (state)\ +	{\ +		default: return _URC_FAILURE;\ +		case _US_VIRTUAL_UNWIND_FRAME:\ +		{\ +			actions = _UA_SEARCH_PHASE;\ +			break;\ +		}\ +		case _US_UNWIND_FRAME_STARTING:\ +		{\ +			actions = _UA_CLEANUP_PHASE;\ +			if (exceptionObject->barrier_cache.sp == _Unwind_GetGR(context, 13))\ +			{\ +				actions |= _UA_HANDLER_FRAME;\ +			}\ +			break;\ +		}\ +		case _US_UNWIND_FRAME_RESUME:\ +		{\ +			return continueUnwinding(exceptionObject, context);\ +			break;\ +		}\ +	}\ +	_Unwind_SetGR (context, 12, (unsigned long)exceptionObject);\ + +#define CALL_PERSONALITY_FUNCTION(name) name(state,exceptionObject,context) diff --git a/unwind-itanium.h b/unwind-itanium.h new file mode 100644 index 000000000000..16b3eed6d700 --- /dev/null +++ b/unwind-itanium.h @@ -0,0 +1,170 @@ +/* libunwind - a platform-independent unwind library +   Copyright (C) 2003 Hewlett-Packard Co +	Contributed by David Mosberger-Tang <davidm@hpl.hp.com> + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */ + +#ifndef _UNWIND_H +#define _UNWIND_H + +/* For uint64_t */ +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Minimal interface as per C++ ABI draft standard: + +	http://www.codesourcery.com/cxx-abi/abi-eh.html */ + +typedef enum +  { +    _URC_NO_REASON = 0, +    _URC_FOREIGN_EXCEPTION_CAUGHT = 1, +    _URC_FATAL_PHASE2_ERROR = 2, +    _URC_FATAL_PHASE1_ERROR = 3, +    _URC_NORMAL_STOP = 4, +    _URC_END_OF_STACK = 5, +    _URC_HANDLER_FOUND = 6, +    _URC_INSTALL_CONTEXT = 7, +    _URC_CONTINUE_UNWIND = 8 +  } +_Unwind_Reason_Code; + +typedef int _Unwind_Action; + +#define _UA_SEARCH_PHASE	1 +#define _UA_CLEANUP_PHASE	2 +#define _UA_HANDLER_FRAME	4 +#define _UA_FORCE_UNWIND	8 + +struct _Unwind_Context;		/* opaque data-structure */ +struct _Unwind_Exception;	/* forward-declaration */ + +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, +					      struct _Unwind_Exception *); + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action, +						uint64_t, +						struct _Unwind_Exception *, +						struct _Unwind_Context *, +						void *); + +/* The C++ ABI requires exception_class, private_1, and private_2 to +   be of type uint64 and the entire structure to be +   double-word-aligned. Please note that exception_class stays 64-bit  +   even on 32-bit machines for gcc compatibility.  */ +struct _Unwind_Exception +  { +    uint64_t exception_class; +    _Unwind_Exception_Cleanup_Fn exception_cleanup; +    unsigned long private_1; +    unsigned long private_2; +  } __attribute__((__aligned__)); + +extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); +extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, +						 _Unwind_Stop_Fn, void *); +extern void _Unwind_Resume (struct _Unwind_Exception *); +extern void _Unwind_DeleteException (struct _Unwind_Exception *); +extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int); +extern void _Unwind_SetGR (struct _Unwind_Context *, int, unsigned long); +extern unsigned long _Unwind_GetIP (struct _Unwind_Context *); +extern unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *, int *); +extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned long); +extern unsigned long _Unwind_GetLanguageSpecificData (struct _Unwind_Context*); +extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *); + +#ifdef _GNU_SOURCE + +/* Callback for _Unwind_Backtrace().  The backtrace stops immediately +   if the callback returns any value other than _URC_NO_REASON. */ +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, +						 void *); + +/* See http://gcc.gnu.org/ml/gcc-patches/2001-09/msg00082.html for why +   _UA_END_OF_STACK exists.  */ +# define _UA_END_OF_STACK	16 + +/* If the unwind was initiated due to a forced unwind, resume that +   operation, else re-raise the exception.  This is used by +   __cxa_rethrow().  */ +extern _Unwind_Reason_Code +	  _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); + +/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why +   _Unwind_GetBSP() exists.  */ +extern unsigned long _Unwind_GetBSP (struct _Unwind_Context *); + +/* Return the "canonical frame address" for the given context. +   This is used by NPTL... */ +extern unsigned long _Unwind_GetCFA (struct _Unwind_Context *); + +/* Return the base-address for data references.  */ +extern unsigned long _Unwind_GetDataRelBase (struct _Unwind_Context *); + +/* Return the base-address for text references.  */ +extern unsigned long _Unwind_GetTextRelBase (struct _Unwind_Context *); + +/* Call _Unwind_Trace_Fn once for each stack-frame, without doing any +   cleanup.  The first frame for which the callback is invoked is the +   one for the caller of _Unwind_Backtrace().  _Unwind_Backtrace() +   returns _URC_END_OF_STACK when the backtrace stopped due to +   reaching the end of the call-chain or _URC_FATAL_PHASE1_ERROR if it +   stops for any other reason.  */ +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +/* Find the start-address of the procedure containing the specified IP +   or NULL if it cannot be found (e.g., because the function has no +   unwind info).  Note: there is not necessarily a one-to-one +   correspondence between source-level functions and procedures: some +   functions don't have unwind-info and others are split into multiple +   procedures.  */ +extern void *_Unwind_FindEnclosingFunction (void *); + +/* See also Linux Standard Base Spec: +    http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/libgcc-s.html */ + +#endif /* _GNU_SOURCE */ + +#define DECLARE_PERSONALITY_FUNCTION(name) \ +_Unwind_Reason_Code name(int version,\ +                         _Unwind_Action actions,\ +                         uint64_t exceptionClass,\ +                         struct _Unwind_Exception *exceptionObject,\ +                         struct _Unwind_Context *context); +#define BEGIN_PERSONALITY_FUNCTION(name) \ +_Unwind_Reason_Code name(int version,\ +                         _Unwind_Action actions,\ +                         uint64_t exceptionClass,\ +                         struct _Unwind_Exception *exceptionObject,\ +                         struct _Unwind_Context *context)\ +{ + +#define CALL_PERSONALITY_FUNCTION(name) name(version, actions, exceptionClass, exceptionObject, context) + +#ifdef __cplusplus +} +#endif + +#endif /* _UNWIND_H */ diff --git a/unwind.h b/unwind.h new file mode 100644 index 000000000000..50894911fd62 --- /dev/null +++ b/unwind.h @@ -0,0 +1,18 @@ +#ifndef UNWIND_H_INCLUDED +#define UNWIND_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __arm__ +#include "unwind-arm.h" +#else +#include "unwind-itanium.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif  | 
