libcxxrt version snapshot created.

Approved by:	dim (mentor)
This commit is contained in:
theraven 2011-11-25 15:48:30 +00:00
parent 8020e408d3
commit 7fa781e37c
7 changed files with 615 additions and 19 deletions

View File

@ -1,7 +1,7 @@
#ifndef __CXXABI_H_ #ifndef __CXXABI_H_
#define __CXXABI_H_ #define __CXXABI_H_
#include <stdint.h> #include <stdint.h>
#include <unwind.h> #include "unwind.h"
namespace std namespace std
{ {
class type_info; class type_info;
@ -87,6 +87,18 @@ struct __cxa_exception
* handler count reaches 0 (which it doesn't with the top bit set). * handler count reaches 0 (which it doesn't with the top bit set).
*/ */
int handlerCount; 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. * The selector value to be returned when installing the catch handler.
* Used at the call site to determine which catch() block should execute. * Used at the call site to determine which catch() block should execute.

View File

@ -16,10 +16,10 @@
// that it doesn't impact the rest of the program. // that it doesn't impact the rest of the program.
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
# define _GNU_SOURCE 1 # define _GNU_SOURCE 1
# include <unwind.h> # include "unwind.h"
# undef _GNU_SOURCE # undef _GNU_SOURCE
#else #else
# include <unwind.h> # include "unwind.h"
#endif #endif
#include <stdint.h> #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 = type_table;
//lsda.type_table = (uintptr_t*)(data + v); //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++)); lsda.callsite_encoding = (enum dwarf_data_encoding)(*(data++));

View File

@ -2,6 +2,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include <pthread.h> #include <pthread.h>
#include "typeinfo.h" #include "typeinfo.h"
#include "dwarf_eh.h" #include "dwarf_eh.h"
@ -9,6 +10,66 @@
using namespace ABI_NAMESPACE; 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_exception(void *thrown_exception);
extern "C" void __cxa_free_dependent_exception(void *thrown_exception); extern "C" void __cxa_free_dependent_exception(void *thrown_exception);
extern "C" void* __dynamic_cast(const void *sub, extern "C" void* __dynamic_cast(const void *sub,
@ -58,6 +119,10 @@ struct __cxa_thread_info
* in ABI spec [3.3.1]). * in ABI spec [3.3.1]).
*/ */
int emergencyBuffersHeld; int emergencyBuffersHeld;
/**
* The exception currently running in a cleanup.
*/
_Unwind_Exception *currentCleanup;
/** /**
* The public part of this structure, accessible from outside of this * The public part of this structure, accessible from outside of this
* module. * module.
@ -78,6 +143,10 @@ struct __cxa_dependent_exception
terminate_handler terminateHandler; terminate_handler terminateHandler;
__cxa_exception *nextException; __cxa_exception *nextException;
int handlerCount; int handlerCount;
#ifdef __arm__
_Unwind_Exception *nextCleanup;
int cleanupCount;
#endif
int handlerSwitchValue; int handlerSwitchValue;
const char *actionRecord; const char *actionRecord;
const char *languageSpecificData; const char *languageSpecificData;
@ -519,9 +588,11 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce
case _URC_FATAL_PHASE1_ERROR: case _URC_FATAL_PHASE1_ERROR:
fprintf(stderr, "Fatal error during phase 1 unwinding\n"); fprintf(stderr, "Fatal error during phase 1 unwinding\n");
break; break;
#ifndef __arm__
case _URC_FATAL_PHASE2_ERROR: case _URC_FATAL_PHASE2_ERROR:
fprintf(stderr, "Fatal error during phase 2 unwinding\n"); fprintf(stderr, "Fatal error during phase 2 unwinding\n");
break; break;
#endif
case _URC_END_OF_STACK: case _URC_END_OF_STACK:
fprintf(stderr, "Terminating due to uncaught exception %p", fprintf(stderr, "Terminating due to uncaught exception %p",
(void*)thrown_exception); (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. // Get the address of the record in the table.
dw_eh_ptr_t record = lsda->type_table - dw_eh_ptr_t record = lsda->type_table -
dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter; dwarf_size_of_fixed_size_field(lsda->type_table_encoding)*filter;
//record -= 4;
dw_eh_ptr_t start = record; dw_eh_ptr_t start = record;
// Read the value, but it's probably an indirect reference... // Read the value, but it's probably an indirect reference...
int64_t offset = read_value(lsda->type_table_encoding, &record); 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 * 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 * 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) else if (filter < 0 && 0 != ex)
{ {
unsigned char *type_index = ((unsigned char*)lsda->type_table - filter - 1);
bool matched = false; bool matched = false;
*selector = filter; *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) while (*type_index)
{ {
std::type_info *handler_type = get_type_info_entry(context, lsda, *(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; break;
} }
} }
#endif
if (matched) { continue; } if (matched) { continue; }
// If we don't find an allowed exception spec, we need to install // 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 // 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; 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 * The exception personality function. This is referenced in the unwinding
* DWARF metadata and is called by the unwind library for each C++ stack frame * DWARF metadata and is called by the unwind library for each C++ stack frame
* containing catch or cleanup code. * containing catch or cleanup code.
*/ */
extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, extern "C"
_Unwind_Action actions, BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0)
uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject,
struct _Unwind_Context *context)
{
// This personality function is for version 1 of the ABI. If you use it // 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 // 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. // 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); (unsigned char*)_Unwind_GetLanguageSpecificData(context);
// No LSDA implies no landing pads - try the next frame // 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. // These two variables define how the exception will be handled.
dwarf_eh_action action = {0}; 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. // and this is not a foreign exception.
if (ex) if (ex)
{ {
ex->handlerSwitchValue = selector; saveLandingPad(context, exceptionObject, ex, selector, action.landing_pad);
ex->actionRecord = (const char*)action.action_record;
ex->languageSpecificData = (const char*)lsda_addr; 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. // ex->adjustedPtr is set when finding the action record.
} }
return _URC_HANDLER_FOUND; 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 // cleanup
struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr);
dwarf_eh_find_callsite(context, &lsda, &action); 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, handler_type found_handler = check_action_record(context, &lsda,
action.action_record, realEx, &selector, ex->adjustedPtr); action.action_record, realEx, &selector, ex->adjustedPtr);
// Ignore handlers this time. // 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) else if (foreignException)
{ {
@ -983,9 +1085,8 @@ extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version,
else else
{ {
// Restore the saved info if we saved some last time. // 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; ex->catchTemp = 0;
selector = (unsigned long)ex->handlerSwitchValue;
ex->handlerSwitchValue = 0; ex->handlerSwitchValue = 0;
} }
@ -1063,6 +1164,8 @@ extern "C" void *__cxa_begin_catch(void *e)
return ((char*)exceptionObject + sizeof(_Unwind_Exception)); return ((char*)exceptionObject + sizeof(_Unwind_Exception));
} }
/** /**
* ABI function called when exiting a catch block. This will free the current * ABI function called when exiting a catch block. This will free the current
* exception if it is no longer referenced in other catch blocks. * exception if it is no longer referenced in other catch blocks.
@ -1281,3 +1384,38 @@ namespace std
return terminateHandler; 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

View File

@ -16,6 +16,59 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include <pthread.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 * 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); __cxa_guard_abort(guard_object);
} }
#endif

201
unwind-arm.h Normal file
View File

@ -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)

170
unwind-itanium.h Normal file
View File

@ -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 */

18
unwind.h Normal file
View File

@ -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