Commit 1e874273 by Paul Brook Committed by Paul Brook

arm.h (ASM_PREFERRED_EH_DATA_FORMAT): Define.

2011-09-13  Paul Brook  <paul@codesourcery.com>
 
	gcc/
	* config/arm/arm.h (ASM_PREFERRED_EH_DATA_FORMAT): Define.
	(ARM_TARGET2_DWARF_FORMAT): Provide default definition.
	* config/arm/linux-eabi.h (ARM_TARGET2_DWARF_FORMAT): Define.
	* config/arm/symbian.h (ARM_TARGET2_DWARF_FORMAT): Define.
	* config/arm/uclinux-eabi.h(ARM_TARGET2_DWARF_FORMAT): Define.
	* config/arm/t-bpabi (EXTRA_HEADERS): Add unwind-arm-common.h.
	* config/arm/t-symbian (EXTRA_HEADERS): Add unwind-arm-common.h.
	* config/c6x/c6x.c (c6x_output_file_unwind): Don't rely on dwarf2 code
	enabling unwind tables.
	(c6x_debug_unwind_info): New function.
	(TARGET_ARM_EABI_UNWINDER): Define.
	(TARGET_DEBUG_UNWIND_INFO): Define.
	* config/c6x/c6x.h (DWARF_FRAME_RETURN_COLUMN): Define.
	(TARGET_EXTRA_CFI_SECTION): Remove.
	* config/c6x/t-c6x-elf (EXTRA_HEADERS): Set.
	* ginclude/unwind-arm-common.h: New file.

	libgcc/
	* config.host (tic6x-*-*): Add c6x/t-c6x-elf.  Set unwind_header.
	* unwind-c.c (PERSONALITY_FUNCTION): Use UNWIND_POINTER_REG.
	* unwind-arm-common.inc: New file.
	* config/arm/unwind-arm.c: Use unwind-arm-common.inc.
	* config/arm/unwind-arm.h: Use unwind-arm-common.h.
	(_GLIBCXX_OVERRIDE_TTYPE_ENCODING): Define.
	* config/c6x/libunwind.S: New file.
	* config/c6x/pr-support.c: New file.
	* config/c6x/unwind-c6x.c: New file.
	* config/c6x/unwind-c6x.h: New file.
	* config/c6x/t-c6x-elf: New file.


	libstdc++-v3/
	* libsupc++/eh_arm.cc (__cxa_end_cleanup): Add C6X implementation.
	* libsupc++/eh_call.cc (__cxa_call_unexpected): Set rtti_base.
	* libsupc++/eh_personality.cc (NO_SIZE_OF_ENCODED_VALUE): Remove
	__ARM_EABI_UNWINDER__ check.
	(parse_lsda_header): Check _GLIBCXX_OVERRIDE_TTYPE_ENCODING.
	(get_ttype_entry): Use generic implementation on ARM EABI.
	(check_exception_spec): Use _Unwind_decode_typeinfo_ptr and
	UNWIND_STACK_REG.
	(PERSONALITY_FUNCTION): Set ttype_base.

From-SVN: r178808
parent 3e0cef6d
2011-09-13 Paul Brook <paul@codesourcery.com>
* config/arm/arm.h (ASM_PREFERRED_EH_DATA_FORMAT): Define.
(ARM_TARGET2_DWARF_FORMAT): Provide default definition.
* config/arm/linux-eabi.h (ARM_TARGET2_DWARF_FORMAT): Define.
* config/arm/symbian.h (ARM_TARGET2_DWARF_FORMAT): Define.
* config/arm/uclinux-eabi.h(ARM_TARGET2_DWARF_FORMAT): Define.
* config/arm/t-bpabi (EXTRA_HEADERS): Add unwind-arm-common.h.
* config/arm/t-symbian (EXTRA_HEADERS): Add unwind-arm-common.h.
* config/c6x/c6x.c (c6x_output_file_unwind): Don't rely on dwarf2 code
enabling unwind tables.
(c6x_debug_unwind_info): New function.
(TARGET_ARM_EABI_UNWINDER): Define.
(TARGET_DEBUG_UNWIND_INFO): Define.
* config/c6x/c6x.h (DWARF_FRAME_RETURN_COLUMN): Define.
(TARGET_EXTRA_CFI_SECTION): Remove.
* config/c6x/t-c6x-elf (EXTRA_HEADERS): Set.
* ginclude/unwind-arm-common.h: New file.
2011-09-13 Georg-Johann Lay <avr@gjlay.de>
PR target/50358
......@@ -825,6 +825,16 @@ extern int arm_arch_thumb_hwdiv;
#define ARM_EH_STACKADJ_REGNUM 2
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, ARM_EH_STACKADJ_REGNUM)
#ifndef ARM_TARGET2_DWARF_FORMAT
#define ARM_TARGET2_DWARF_FORMAT DW_EH_PE_pcrel
/* ttype entries (the only interesting data references used)
use TARGET2 relocations. */
#define ASM_PREFERRED_EH_DATA_FORMAT(code, data) \
(((code) == 0 && (data) == 1 && ARM_UNWIND_INFO) ? ARM_TARGET2_DWARF_FORMAT \
: DW_EH_PE_absptr)
#endif
/* The native (Norcroft) Pascal compiler for the ARM passes the static chain
as an invisible last argument (possible since varargs don't exist in
Pascal), so the following is not true. */
......
......@@ -101,3 +101,5 @@
is used. */
#undef CLEAR_INSN_CACHE
#define CLEAR_INSN_CACHE(BEG, END) not_used
#define ARM_TARGET2_DWARF_FORMAT (DW_EH_PE_pcrel | DW_EH_PE_indirect)
......@@ -98,3 +98,5 @@
#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P false
#define TARGET_DEFAULT_WORD_RELOCATIONS 1
#define ARM_TARGET2_DWARF_FORMAT DW_EH_PE_absptr
......@@ -28,3 +28,4 @@ LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
# Add the BPABI names.
SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
EXTRA_HEADERS += $(srcdir)/ginclude/unwind-arm-common.h
......@@ -30,6 +30,7 @@ LIB1ASMFUNCS += \
_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
_fixsfsi _fixunssfsi
EXTRA_HEADERS += $(srcdir)/ginclude/unwind-arm-common.h
# Include half-float helpers.
LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
......
......@@ -64,3 +64,4 @@
: "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); \
}
#define ARM_TARGET2_DWARF_FORMAT DW_EH_PE_absptr
......@@ -402,12 +402,19 @@ c6x_output_file_unwind (FILE * f)
if (done_cfi_sections)
return;
/* Output a .cfi_sections directive if we aren't
already doing so for debug info. */
if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
&& dwarf2out_do_frame ())
/* Output a .cfi_sections directive. */
if (dwarf2out_do_frame ())
{
asm_fprintf (f, "\t.cfi_sections .c6xabi.exidx\n");
if (flag_unwind_tables || flag_exceptions)
{
if (write_symbols == DWARF2_DEBUG
|| write_symbols == VMS_AND_DWARF2_DEBUG)
asm_fprintf (f, "\t.cfi_sections .debug_frame, .c6xabi.exidx\n");
else
asm_fprintf (f, "\t.cfi_sections .c6xabi.exidx\n");
}
else
asm_fprintf (f, "\t.cfi_sections .debug_frame\n");
done_cfi_sections = true;
}
}
......@@ -5606,6 +5613,18 @@ c6x_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
/* Target unwind frame info is generated from dwarf CFI directives, so
always output dwarf2 unwind info. */
static enum unwind_info_type
c6x_debug_unwind_info (void)
{
if (flag_unwind_tables || flag_exceptions)
return UI_DWARF2;
return default_debug_unwind_info ();
}
/* Target Structure. */
......@@ -5746,6 +5765,13 @@ c6x_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
#undef TARGET_ASM_TTYPE
#define TARGET_ASM_TTYPE c6x_output_ttype
/* The C6x ABI follows the ARM EABI exception handling rules. */
#undef TARGET_ARM_EABI_UNWINDER
#define TARGET_ARM_EABI_UNWINDER true
#undef TARGET_DEBUG_UNWIND_INFO
#define TARGET_DEBUG_UNWIND_INFO c6x_debug_unwind_info
#undef TARGET_DWARF_REGISTER_SPAN
#define TARGET_DWARF_REGISTER_SPAN c6x_dwarf_register_span
......
......@@ -329,6 +329,7 @@ enum reg_class
/* Before the prologue, the return address is in the B3 register. */
#define RETURN_ADDR_REGNO REG_B3
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, RETURN_ADDR_REGNO)
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (RETURN_ADDR_REGNO)
#define RETURN_ADDR_RTX(COUNT, FRAME) c6x_return_addr_rtx (COUNT)
......@@ -459,8 +460,6 @@ struct GTY(()) machine_function
#define TARG_VEC_PERMUTE_COST 1
#endif
/* Exception handling. */
#define TARGET_EXTRA_CFI_SECTION(unwind) ((unwind) ? ".c6xabi.exidx" : NULL)
/* ttype entries (the only interesting data references used) are
sb-relative got-indirect (aka .ehtype). */
#define ASM_PREFERRED_EH_DATA_FORMAT(code, data) \
......
......@@ -24,6 +24,7 @@ LIB1ASMFUNCS += _strasgi _strasgi_64plus _clzsi2 _clzdi2 _clz
LIB1ASMFUNCS += _push_rts _pop_rts _call_stub
LIB2FUNCS_EXCLUDE = _cmpdi2 _ucmpdi2 _gcc_bcmp _eprintf _clzsi _clzdi
EXTRA_HEADERS += $(srcdir)/ginclude/unwind-arm-common.h
LIB2FUNCS_EXTRA = $(srcdir)/config/c6x/gef.c \
$(srcdir)/config/c6x/gtf.c \
......
/* Header file for the ARM EABI and C6X unwinders
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
Free Software Foundation, Inc.
Contributed by Paul Brook
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* Language-independent unwinder header public defines. This contains both
ABI defined objects, and GNU support routines. */
#ifndef UNWIND_ARM_COMMON_H
#define UNWIND_ARM_COMMON_H
#define __ARM_EABI_UNWINDER__ 1
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
typedef _Unwind_Word _uw;
typedef unsigned _uw64 __attribute__((mode(__DI__)));
typedef unsigned _uw16 __attribute__((mode(__HI__)));
typedef unsigned _uw8 __attribute__((mode(__QI__)));
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 */
}
_Unwind_Reason_Code;
typedef enum
{
_US_VIRTUAL_UNWIND_FRAME = 0,
_US_UNWIND_FRAME_STARTING = 1,
_US_UNWIND_FRAME_RESUME = 2,
_US_ACTION_MASK = 3,
_US_FORCE_UNWIND = 8,
_US_END_OF_STACK = 16
}
_Unwind_State;
/* Provided only for compatibility with existing 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
#define _UA_END_OF_STACK 16
#define _URC_NO_REASON _URC_OK
typedef struct _Unwind_Control_Block _Unwind_Control_Block;
typedef struct _Unwind_Context _Unwind_Context;
typedef _uw _Unwind_EHT_Header;
/* UCB: */
struct _Unwind_Control_Block
{
char exception_class[8];
void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
/* Unwinder cache, private fields for the unwinder's use */
struct
{
_uw reserved1; /* Forced unwind stop fn, 0 if not forced */
_uw reserved2; /* Personality routine address */
_uw reserved3; /* Saved callsite address */
_uw reserved4; /* Forced unwind stop arg */
_uw reserved5;
}
unwinder_cache;
/* Propagation barrier cache (valid after phase 1): */
struct
{
_uw sp;
_uw bitpattern[5];
}
barrier_cache;
/* Cleanup cache (preserved over cleanup): */
struct
{
_uw bitpattern[4];
}
cleanup_cache;
/* Pr cache (for pr's benefit): */
struct
{
_uw fnstart; /* function start address */
_Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
_uw additional; /* additional data */
_uw reserved1;
}
pr_cache;
long long int :0; /* Force alignment to 8-byte boundary */
};
/* Virtual Register Set*/
typedef enum
{
_UVRSC_CORE = 0, /* integer register */
_UVRSC_VFP = 1, /* vfp */
_UVRSC_FPA = 2, /* fpa */
_UVRSC_WMMXD = 3, /* Intel WMMX data register */
_UVRSC_WMMXC = 4 /* Intel WMMX control register */
}
_Unwind_VRS_RegClass;
typedef enum
{
_UVRSD_UINT32 = 0,
_UVRSD_VFPX = 1,
_UVRSD_FPAX = 2,
_UVRSD_UINT64 = 3,
_UVRSD_FLOAT = 4,
_UVRSD_DOUBLE = 5
}
_Unwind_VRS_DataRepresentation;
typedef enum
{
_UVRSR_OK = 0,
_UVRSR_NOT_IMPLEMENTED = 1,
_UVRSR_FAILED = 2
}
_Unwind_VRS_Result;
/* Frame unwinding state. */
typedef struct
{
/* The current word (bytes packed msb first). */
_uw data;
/* Pointer to the next word of data. */
_uw *next;
/* The number of bytes left in this word. */
_uw8 bytes_left;
/* The number of words pointed to by ptr. */
_uw8 words_left;
}
__gnu_unwind_state;
typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
_Unwind_Control_Block *, _Unwind_Context *);
_Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
_uw, _Unwind_VRS_DataRepresentation,
void *);
_Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
_uw, _Unwind_VRS_DataRepresentation,
void *);
_Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
_uw, _Unwind_VRS_DataRepresentation);
/* Support functions for the PR. */
#define _Unwind_Exception _Unwind_Control_Block
typedef char _Unwind_Exception_Class[8];
void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
_Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
_Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
/* This should never be used. */
_Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
/* Interface functions: */
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(int, _Unwind_Action, _Unwind_Exception_Class,
_Unwind_Control_Block *, struct _Unwind_Context *, void *);
_Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
_Unwind_Stop_Fn, void *);
/* @@@ Use unwind data to perform a stack backtrace. The trace callback
is called for every stack frame in the call chain, but no cleanup
actions are performed. */
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *, void *);
_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn,
void*);
_Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
void _Unwind_Complete(_Unwind_Control_Block *ucbp);
void _Unwind_DeleteException (_Unwind_Exception *);
_Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
_Unwind_Context *);
_Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
__gnu_unwind_state *);
static inline _Unwind_Word
_Unwind_GetGR (_Unwind_Context *context, int regno)
{
_uw val;
_Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
return val;
}
#define _Unwind_GetIPInfo(context, ip_before_insn) \
(*ip_before_insn = 0, _Unwind_GetIP (context))
static inline void
_Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
{
_Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
}
_Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
/* leb128 type numbers have a potentially unlimited size.
The target of the following definitions of _sleb128_t and _uleb128_t
is to have efficient data types large enough to hold the leb128 type
numbers used in the unwind code. */
typedef long _sleb128_t;
typedef unsigned long _uleb128_t;
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* defined UNWIND_ARM_COMMON_H */
2011-09-13 Paul Brook <paul@codesourcery.com>
* config.host (tic6x-*-*): Add c6x/t-c6x-elf. Set unwind_header.
* unwind-c.c (PERSONALITY_FUNCTION): Use UNWIND_POINTER_REG.
* unwind-arm-common.inc: New file.
* config/arm/unwind-arm.c: Use unwind-arm-common.inc.
* config/arm/unwind-arm.h: Use unwind-arm-common.h.
(_GLIBCXX_OVERRIDE_TTYPE_ENCODING): Define.
* config/c6x/libunwind.S: New file.
* config/c6x/pr-support.c: New file.
* config/c6x/unwind-c6x.c: New file.
* config/c6x/unwind-c6x.h: New file.
* config/c6x/t-c6x-elf: New file.
2011-08-23 Uros Bizjak <ubizjak@gmail.com>
* config/i386/64/sfp-machine.h (ASM_INVALID): New define.
......
......@@ -790,7 +790,8 @@ spu-*-elf*)
tmake_file="t-fdpbit spu/t-elf"
;;
tic6x-*-*)
tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl t-softfp t-gnu-prefix"
tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl t-softfp t-gnu-prefix c6x/t-c6x-elf"
unwind_header=config/c6x/unwind-c6x.h
;;
v850*-*-*)
tmake_file=t-fdpbit
......
......@@ -28,198 +28,18 @@
#ifndef UNWIND_ARM_H
#define UNWIND_ARM_H
#define __ARM_EABI_UNWINDER__ 1
#include "unwind-arm-common.h"
#define UNWIND_STACK_REG 13
/* Use IP as a scratch register within the personality routine. */
#define UNWIND_POINTER_REG 12
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
typedef _Unwind_Word _uw;
typedef unsigned _uw64 __attribute__((mode(__DI__)));
typedef unsigned _uw16 __attribute__((mode(__HI__)));
typedef unsigned _uw8 __attribute__((mode(__QI__)));
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 */
}
_Unwind_Reason_Code;
typedef enum
{
_US_VIRTUAL_UNWIND_FRAME = 0,
_US_UNWIND_FRAME_STARTING = 1,
_US_UNWIND_FRAME_RESUME = 2,
_US_ACTION_MASK = 3,
_US_FORCE_UNWIND = 8,
_US_END_OF_STACK = 16
}
_Unwind_State;
/* Provided only for compatibility with existing 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
#define _UA_END_OF_STACK 16
#define _URC_NO_REASON _URC_OK
typedef struct _Unwind_Control_Block _Unwind_Control_Block;
typedef struct _Unwind_Context _Unwind_Context;
typedef _uw _Unwind_EHT_Header;
/* UCB: */
struct _Unwind_Control_Block
{
char exception_class[8];
void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
/* Unwinder cache, private fields for the unwinder's use */
struct
{
_uw reserved1; /* Forced unwind stop fn, 0 if not forced */
_uw reserved2; /* Personality routine address */
_uw reserved3; /* Saved callsite address */
_uw reserved4; /* Forced unwind stop arg */
_uw reserved5;
}
unwinder_cache;
/* Propagation barrier cache (valid after phase 1): */
struct
{
_uw sp;
_uw bitpattern[5];
}
barrier_cache;
/* Cleanup cache (preserved over cleanup): */
struct
{
_uw bitpattern[4];
}
cleanup_cache;
/* Pr cache (for pr's benefit): */
struct
{
_uw fnstart; /* function start address */
_Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
_uw additional; /* additional data */
_uw reserved1;
}
pr_cache;
long long int :0; /* Force alignment to 8-byte boundary */
};
/* Virtual Register Set*/
typedef enum
{
_UVRSC_CORE = 0, /* integer register */
_UVRSC_VFP = 1, /* vfp */
_UVRSC_FPA = 2, /* fpa */
_UVRSC_WMMXD = 3, /* Intel WMMX data register */
_UVRSC_WMMXC = 4 /* Intel WMMX control register */
}
_Unwind_VRS_RegClass;
typedef enum
{
_UVRSD_UINT32 = 0,
_UVRSD_VFPX = 1,
_UVRSD_FPAX = 2,
_UVRSD_UINT64 = 3,
_UVRSD_FLOAT = 4,
_UVRSD_DOUBLE = 5
}
_Unwind_VRS_DataRepresentation;
typedef enum
{
_UVRSR_OK = 0,
_UVRSR_NOT_IMPLEMENTED = 1,
_UVRSR_FAILED = 2
}
_Unwind_VRS_Result;
/* Frame unwinding state. */
typedef struct
{
/* The current word (bytes packed msb first). */
_uw data;
/* Pointer to the next word of data. */
_uw *next;
/* The number of bytes left in this word. */
_uw8 bytes_left;
/* The number of words pointed to by ptr. */
_uw8 words_left;
}
__gnu_unwind_state;
typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
_Unwind_Control_Block *, _Unwind_Context *);
_Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
_uw, _Unwind_VRS_DataRepresentation,
void *);
_Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
_uw, _Unwind_VRS_DataRepresentation,
void *);
_Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
_uw, _Unwind_VRS_DataRepresentation);
/* Support functions for the PR. */
#define _Unwind_Exception _Unwind_Control_Block
typedef char _Unwind_Exception_Class[8];
void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
_Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
/* These two should never be used. */
_Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
_Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
/* Interface functions: */
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(int, _Unwind_Action, _Unwind_Exception_Class,
_Unwind_Control_Block *, struct _Unwind_Context *, void *);
_Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
_Unwind_Stop_Fn, void *);
/* @@@ Use unwind data to perform a stack backtrace. The trace callback
is called for every stack frame in the call chain, but no cleanup
actions are performed. */
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *, void *);
_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn,
void*);
_Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
void _Unwind_Complete(_Unwind_Control_Block *ucbp);
void _Unwind_DeleteException (_Unwind_Exception *);
_Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
_Unwind_Context *);
_Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
__gnu_unwind_state *);
/* Decode an R_ARM_TARGET2 relocation. */
static inline _Unwind_Word
_Unwind_decode_target2 (_Unwind_Word ptr)
_Unwind_decode_typeinfo_ptr (_Unwind_Word base, _Unwind_Word ptr)
{
_Unwind_Word tmp;
......@@ -230,50 +50,32 @@ extern "C" {
#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__)
/* Pc-relative indirect. */
#define _GLIBCXX_OVERRIDE_TTYPE_ENCODING (DW_EH_PE_pcrel | DW_EH_PE_indirect)
tmp += ptr;
tmp = *(_Unwind_Word *) tmp;
#elif defined(__symbian__) || defined(__uClinux__)
#define _GLIBCXX_OVERRIDE_TTYPE_ENCODING (DW_EH_PE_absptr)
/* Absolute pointer. Nothing more to do. */
#else
#define _GLIBCXX_OVERRIDE_TTYPE_ENCODING (DW_EH_PE_pcrel)
/* Pc-relative pointer. */
tmp += ptr;
#endif
return tmp;
}
static inline _Unwind_Word
_Unwind_GetGR (_Unwind_Context *context, int regno)
static inline _Unwind_Reason_Code
__gnu_unwind_24bit (_Unwind_Context * context, _uw data, int compact)
{
_uw val;
_Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
return val;
return _URC_FAILURE;
}
/* Return the address of the instruction, not the actual IP value. */
#define _Unwind_GetIP(context) \
(_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
#define _Unwind_GetIPInfo(context, ip_before_insn) \
(*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
static inline void
_Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
{
_Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
}
/* The dwarf unwinder doesn't understand arm/thumb state. We assume the
landing pad uses the same instruction set as the call site. */
#define _Unwind_SetIP(context, val) \
_Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
/* leb128 type numbers have a potentially unlimited size.
The target of the following definitions of _sleb128_t and _uleb128_t
is to have efficient data types large enough to hold the leb128 type
numbers used in the unwind code. */
typedef long _sleb128_t;
typedef unsigned long _uleb128_t;
#ifdef __cplusplus
} /* extern "C" */
#endif
......
.text
.macro do_call fn
#ifdef _TMS320C6400_PLUS
callp .s2 (\fn), B3
#elif defined(_TMS320C6400)
call .s2 (\fn)
addkpc .s2 9f, B3, 0
nop 4
9f:
#else
call .s2 (\fn)
mhkl .s2 9f, B3
mhkh .s2 9f, B3
nop 3
9f:
#endif
.endm
.align 2
.global restore_core_regs
.type restore_core_regs, STT_FUNC
restore_core_regs:
mv .s2x A4, B4
ldw .d1t1 *+A4[0], A0
|| ldw .d2t2 *++B4[16], B0
ldw .d1t1 *+A4[1], A1
|| ldw .d2t2 *+B4[1], B1
ldw .d1t1 *+A4[2], A2
|| ldw .d2t2 *+B4[2], B2
ldw .d1t1 *+A4[3], A3
|| ldw .d2t2 *+B4[3], B3
;; Base registers are loaded later
ldw .d1t1 *+A4[5], A5
|| ldw .d2t2 *+B4[5], B5
ldw .d1t1 *+A4[6], A6
|| ldw .d2t2 *+B4[6], B6
ldw .d1t1 *+A4[7], A7
|| ldw .d2t2 *+B4[7], B7
ldw .d1t1 *+A4[8], A8
|| ldw .d2t2 *+B4[8], B8
ldw .d1t1 *+A4[9], A9
|| ldw .d2t2 *+B4[9], B9
;; load PC into B10 so that it is ready for the branch
ldw .d2t2 *+B4[16], B10
ldw .d1t1 *+A4[11], A11
|| ldw .d2t2 *+B4[11], B11
ldw .d1t1 *+A4[12], A12
|| ldw .d2t2 *+B4[12], B12
ldw .d1t1 *+A4[13], A13
|| ldw .d2t2 *+B4[13], B13
ldw .d1t1 *+A4[14], A14
|| ldw .d2t2 *+B4[14], B14
;; Loads have 4 delay slots. Take advantage of this to restore the
;; scratch registers and stack pointer before the base registers
;; disappear. We also need to make sure no interrupts occur,
;; so put the whole thing in the delay slots of a dummy branch
;; We can not move the ret earlier as that would cause it to occur
;; before the last load completes
b .s1 (1f)
ldw .d1t1 *+A4[4], A4
|| ldw .d2t2 *+B4[4], B4
ldw .d1t1 *+A4[15], A15
|| ldw .d2t2 *+B4[15], B15
ret .s2 B10
ldw .d1t1 *+A4[10], A10
|| ldw .d2t2 *+B4[10], B10
nop 1
1:
nop 3
.size restore_core_regs, . - restore_core_regs
.macro UNWIND_WRAPPER name argreg argside
.global \name
.type \name, STT_FUNC
\name:
# Create saved register state: flags,A0-A15,B0-B15,PC = 136 bytes.
# Plus 4 (rounded to 8) for saving return.
addk .s2 -144, B15
stw .d2t1 A0, *+B15[2]
stw .d2t1 A1, *+B15[3]
stw .d2t1 A2, *+B15[4]
stw .d2t1 A3, *+B15[5]
stw .d2t1 A4, *+B15[6]
stw .d2t1 A5, *+B15[7]
stw .d2t1 A6, *+B15[8]
stw .d2t1 A7, *+B15[9]
stw .d2t1 A8, *+B15[10]
stw .d2t1 A9, *+B15[11]
stw .d2t1 A10, *+B15[12]
stw .d2t1 A11, *+B15[13]
stw .d2t1 A12, *+B15[14]
stw .d2t1 A13, *+B15[15]
stw .d2t1 A14, *+B15[16]
stw .d2t1 A15, *+B15[17]
mv .s1x B15, A0
addk .s1 144, A0
stw .d2t2 B0, *+B15[18]
stw .d2t2 B1, *+B15[19]
stw .d2t2 B2, *+B15[20]
stw .d2t2 B3, *+B15[21]
stw .d2t2 B4, *+B15[22]
stw .d2t2 B5, *+B15[23]
stw .d2t2 B6, *+B15[24]
stw .d2t2 B7, *+B15[25]
stw .d2t2 B8, *+B15[26]
stw .d2t2 B9, *+B15[27]
stw .d2t2 B10, *+B15[28]
stw .d2t2 B11, *+B15[29]
stw .d2t2 B12, *+B15[30]
stw .d2t2 B13, *+B15[31]
stw .d2t2 B14, *+B15[32]
stw .d2t1 A0, *+B15[33]
stw .d2t1 A0, *+B15[34]
# Zero demand saved flags
mvk .s1 0, A0
stw .d2t1 A0, *+B15[1]
# Save return address, setup additional argument and call fucntion
stw .d2t2 B3, *+B15[35]
add .d\argside B15, 4, \argreg
do_call __gnu\name
# Restore stack and return
ldw .d2t2 *+B15[35], B3
addk .s2 144, B15
nop 3
ret .s2 B3
nop 5
.size \name, . - \name
.endm
UNWIND_WRAPPER _Unwind_RaiseException B4 2
UNWIND_WRAPPER _Unwind_Resume B4 2
UNWIND_WRAPPER _Unwind_Resume_or_Rethrow B4 2
UNWIND_WRAPPER _Unwind_ForcedUnwind B6 2
UNWIND_WRAPPER _Unwind_Backtrace A6 1x
LIB2ADDEH = $(srcdir)/config/c6x/unwind-c6x.c \
$(srcdir)/config/c6x/libunwind.S \
$(srcdir)/config/c6x/pr-support.c $(srcdir)/unwind-c.c
/* C6X EABI compliant unwinding routines.
Copyright (C) 2011 Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "unwind.h"
/* Misc constants. */
#define NUM_SAVED_REGS 32
#define R_B0 16
#define R_B3 (R_B0 + 3)
#define R_B15 (R_B0 + 15)
#define R_SP R_B15
#define R_LR R_B3
#define R_PC 33
#define VRS_PC(vrs) ((vrs)->core.pc)
#define VRS_SP(vrs) ((vrs)->core.reg[R_SP])
#define VRS_RETURN(vrs) ((vrs)->core.reg[R_B3])
struct core_regs
{
_uw reg[NUM_SAVED_REGS];
_uw pc;
};
typedef struct
{
/* The first fields must be the same as a phase2_vrs. */
_uw demand_save_flags; /* Currently always zero. */
struct core_regs core;
_uw prev_sp; /* Only valid during forced unwinding. */
} phase1_vrs;
/* This must match the structure created by the assembly wrappers. */
typedef struct
{
_uw demand_save_flags;
struct core_regs core;
} phase2_vrs;
/* Coprocessor register state manipulation functions. */
/* Restore coprocessor state after phase1 unwinding. */
static void
restore_non_core_regs (phase1_vrs * vrs __attribute__((unused)))
{
}
#include "unwind-arm-common.inc"
/* ABI defined personality routines. */
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr0 (_Unwind_State,
_Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr1 (_Unwind_State,
_Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr2 (_Unwind_State,
_Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr3 (_Unwind_State,
_Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
extern _Unwind_Reason_Code __c6xabi_unwind_cpp_pr4 (_Unwind_State,
_Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
/* ABI defined routine to store a virtual register to memory. */
_Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
_Unwind_VRS_RegClass regclass,
_uw regno,
_Unwind_VRS_DataRepresentation representation,
void *valuep)
{
phase1_vrs *vrs = (phase1_vrs *) context;
switch (regclass)
{
case _UVRSC_CORE:
if (representation != _UVRSD_UINT32)
return _UVRSR_FAILED;
if (regno == R_PC)
{
*(_uw *) valuep = vrs->core.pc;
return _UVRSR_OK;
}
if (regno >= NUM_SAVED_REGS)
return _UVRSR_FAILED;
*(_uw *) valuep = vrs->core.reg[regno];
return _UVRSR_OK;
default:
return _UVRSR_FAILED;
}
}
/* ABI defined function to load a virtual register from memory. */
_Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
_Unwind_VRS_RegClass regclass,
_uw regno,
_Unwind_VRS_DataRepresentation representation,
void *valuep)
{
phase1_vrs *vrs = (phase1_vrs *) context;
switch (regclass)
{
case _UVRSC_CORE:
if (representation != _UVRSD_UINT32)
return _UVRSR_FAILED;
if (regno == R_PC)
{
vrs->core.pc = *(_uw *) valuep;
return _UVRSR_OK;
}
if (regno >= NUM_SAVED_REGS)
return _UVRSR_FAILED;
vrs->core.reg[regno] = *(_uw *) valuep;
return _UVRSR_OK;
default:
return _UVRSR_FAILED;
}
}
/* Core unwinding functions. */
/* Calculate the address encoded by a 31-bit self-relative offset at address
P. */
static inline _uw
selfrel_offset31 (const _uw *p)
{
_uw offset;
offset = *p << 1;
return offset + (_uw) p;
}
static _uw
__gnu_unwind_get_pr_addr (int idx)
{
switch (idx)
{
case 0:
return (_uw) &__c6xabi_unwind_cpp_pr0;
case 1:
return (_uw) &__c6xabi_unwind_cpp_pr1;
case 2:
return (_uw) &__c6xabi_unwind_cpp_pr2;
case 3:
return (_uw) &__c6xabi_unwind_cpp_pr3;
case 4:
return (_uw) &__c6xabi_unwind_cpp_pr4;
default:
return 0;
}
}
/* ABI defined personality routine entry points. */
_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr0 (_Unwind_State state,
_Unwind_Control_Block *ucbp,
_Unwind_Context *context)
{
return __gnu_unwind_pr_common (state, ucbp, context, 0);
}
_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr1 (_Unwind_State state,
_Unwind_Control_Block *ucbp,
_Unwind_Context *context)
{
return __gnu_unwind_pr_common (state, ucbp, context, 1);
}
_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr2 (_Unwind_State state,
_Unwind_Control_Block *ucbp,
_Unwind_Context *context)
{
return __gnu_unwind_pr_common (state, ucbp, context, 2);
}
_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr3 (_Unwind_State state,
_Unwind_Control_Block *ucbp,
_Unwind_Context *context)
{
return __gnu_unwind_pr_common (state, ucbp, context, 3);
}
_Unwind_Reason_Code
__c6xabi_unwind_cpp_pr4 (_Unwind_State state,
_Unwind_Control_Block *ucbp,
_Unwind_Context *context)
{
return __gnu_unwind_pr_common (state, ucbp, context, 4);
}
/* Header file for the C6X EABI unwinder
Copyright (C) 2011
Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* Language-independent unwinder header public defines. This contains both
ABI defined objects, and GNU support routines. */
#ifndef UNWIND_C6X_H
#define UNWIND_C6X_H
/* Not really the ARM EABI, but pretty close. */
#include "unwind-arm-common.h"
#define UNWIND_STACK_REG 31
/* Use A0 as a scratch register within the personality routine. */
#define UNWIND_POINTER_REG 0
#ifdef __cplusplus
extern "C" {
#endif
_Unwind_Reason_Code __gnu_unwind_24bit (_Unwind_Context *, _uw, int);
/* Decode an EH table reference to a typeinfo object. */
static inline _Unwind_Word
_Unwind_decode_typeinfo_ptr (_Unwind_Ptr base, _Unwind_Word ptr)
{
_Unwind_Word tmp;
tmp = *(_Unwind_Word *) ptr;
/* Zero values are always NULL. */
if (!tmp)
return 0;
/* SB-relative indirect. Propagate the bottom 2 bits, which can
contain referenceness information in gnu unwinding tables. */
tmp += base;
tmp = *(_Unwind_Word *) (tmp & ~(_Unwind_Word)3) | (tmp & 3);
return tmp;
}
#define _Unwind_GetIP(context) \
(_Unwind_GetGR (context, 33))
#define _Unwind_SetIP(context, val) \
_Unwind_SetGR (context, 33, val)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* defined UNWIND_ARM_H */
......@@ -130,10 +130,10 @@ PERSONALITY_FUNCTION (int version,
/* The dwarf unwinder assumes the context structure holds things like the
function and LSDA pointers. The ARM implementation caches these in
the exception header (UCB). To avoid rewriting everything we make the
virtual IP register point at the UCB. */
the exception header (UCB). To avoid rewriting everything we make a
virtual scratch register point at the UCB. */
ip = (_Unwind_Ptr) ue_header;
_Unwind_SetGR (context, 12, ip);
_Unwind_SetGR (context, UNWIND_POINTER_REG, ip);
#else
if (version != 1)
return _URC_FATAL_PHASE1_ERROR;
......
2011-09-13 Paul Brook <paul@codesourcery.com>
* libsupc++/eh_arm.cc (__cxa_end_cleanup): Add C6X implementation.
* libsupc++/eh_call.cc (__cxa_call_unexpected): Set rtti_base.
* libsupc++/eh_personality.cc (NO_SIZE_OF_ENCODED_VALUE): Remove
__ARM_EABI_UNWINDER__ check.
(parse_lsda_header): Check _GLIBCXX_OVERRIDE_TTYPE_ENCODING.
(get_ttype_entry): Use generic implementation on ARM EABI.
(check_exception_spec): Use _Unwind_decode_typeinfo_ptr and
UNWIND_STACK_REG.
(PERSONALITY_FUNCTION): Set ttype_base.
2011-09-12 Daniel Krugler <daniel.kruegler@googlemail.com>
Paolo Carlini <paolo.carlini@oracle.com>
......
......@@ -155,6 +155,49 @@ __gnu_end_cleanup(void)
return &header->unwindHeader;
}
#ifdef __TMS320C6X__
// Assembly wrapper to call __gnu_end_cleanup without clobbering
// function arguments to _Unwind_Resume.
asm (".global __cxa_end_cleanup\n"
" .type __cxa_end_cleanup, \"function\"\n"
"__cxa_end_cleanup:\n"
" stw .d2t2 B9, *B15--[10]\n"
" stw .d2t2 B8, *+B15[9]\n"
" stw .d2t2 B7, *+B15[8]\n"
" stw .d2t2 B6, *+B15[7]\n"
" stw .d2t2 B5, *+B15[6]\n"
" stw .d2t2 B4, *+B15[5]\n"
" stw .d2t1 A9, *+B15[4]\n"
" stw .d2t1 A8, *+B15[3]\n"
" stw .d2t1 A7, *+B15[2]\n"
" stw .d2t1 A6, *+B15[1]\n"
#ifdef _TMS320C6400_PLUS
" callp .s2 (__gnu_end_cleanup), B3\n"
#elif defined(_TMS320C6400)
" call .s2 (__gnu_end_cleanup)\n"
" addkpc .s2 1f, B3, 0\n"
" nop 4\n"
"1:\n"
#else
" call .s2 (__gnu_end_cleanup)\n"
" mvkl .s2 1f, B3\n"
" mvkh .s2 1f, B3\n"
" nop 3\n"
"1:\n"
#endif
" ldw .d2t1 *+B15[1], A6\n"
" ldw .d2t1 *+B15[2], A7\n"
" ldw .d2t1 *+B15[3], A8\n"
" ldw .d2t1 *+B15[4], A9\n"
" ldw .d2t2 *+B15[5], B4\n"
" ldw .d2t2 *+B15[6], B5\n"
" ldw .d2t2 *+B15[7], B6\n"
" ldw .d2t2 *+B15[8], B7\n"
" ldw .d2t2 *+B15[9], B8\n"
" ldw .d2t2 *++B15[10], B9\n"
" b .s2 _Unwind_Resume\n"
" nop 5\n");
#else
// Assembly wrapper to call __gnu_end_cleanup without clobbering r1-r3.
// Also push r4 to preserve stack alignment.
#ifdef __thumb__
......@@ -179,5 +222,6 @@ asm (" .pushsection .text.__cxa_end_cleanup\n"
" bl\t_Unwind_Resume @ Never returns\n"
" .popsection\n");
#endif
#endif
#endif
......@@ -73,6 +73,7 @@ __cxa_call_unexpected(void* exc_obj_in)
int rtti_count = 0;
_Unwind_Word rtti_stride = 0;
_Unwind_Word* rtti_list = NULL;
_Unwind_Ptr rtti_base = 0;
bool foreign_exception;
std::unexpected_handler unexpectedHandler = NULL;
std::terminate_handler terminateHandler = NULL;
......@@ -84,7 +85,7 @@ __cxa_call_unexpected(void* exc_obj_in)
unexpectedHandler = xh->unexpectedHandler;
terminateHandler = xh->terminateHandler;
rtti_count = exc_obj->barrier_cache.bitpattern[1];
rtti_base = (_Unwind_Ptr) exc_obj->barrier_cache.bitpattern[2];
rtti_stride = exc_obj->barrier_cache.bitpattern[3];
rtti_list = (_Unwind_Word*) exc_obj->barrier_cache.bitpattern[4];
foreign_exception = false;
......@@ -134,7 +135,7 @@ __cxa_call_unexpected(void* exc_obj_in)
_Unwind_Word offset;
offset = (_Unwind_Word) &rtti_list[n * (rtti_stride >> 2)];
offset = _Unwind_decode_target2(offset);
offset = _Unwind_decode_typeinfo_ptr(rtti_base, offset);
catch_type = (const std::type_info*) (offset);
if (__cxa_type_match(&new_xh->unwindHeader, catch_type, false,
......
......@@ -30,11 +30,8 @@
#include <cxxabi.h>
#include "unwind-cxx.h"
using namespace __cxxabiv1;
#ifdef __ARM_EABI_UNWINDER__
#define NO_SIZE_OF_ENCODED_VALUE
#endif
using namespace __cxxabiv1;
#include "unwind-pe.h"
......@@ -70,6 +67,11 @@ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
info->ttype_encoding = *p++;
if (info->ttype_encoding != DW_EH_PE_omit)
{
#if _GLIBCXX_OVERRIDE_TTYPE_ENCODING
/* Older ARM EABI toolchains set this value incorrectly, so use a
hardcoded OS-specific format. */
info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING;
#endif
p = read_uleb128 (p, &tmp);
info->TType = p + tmp;
}
......@@ -85,21 +87,22 @@ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
return p;
}
#ifdef __ARM_EABI_UNWINDER__
// Return an element from a type table.
static const std::type_info*
get_ttype_entry(lsda_header_info* info, _uleb128_t i)
static const std::type_info *
get_ttype_entry (lsda_header_info *info, _uleb128_t i)
{
_Unwind_Ptr ptr;
ptr = (_Unwind_Ptr) (info->TType - (i * 4));
ptr = _Unwind_decode_target2(ptr);
i *= size_of_encoded_value (info->ttype_encoding);
read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
info->TType - i, &ptr);
return reinterpret_cast<const std::type_info *>(ptr);
}
#ifdef __ARM_EABI_UNWINDER__
// The ABI provides a routine for matching exception object types.
typedef _Unwind_Control_Block _throw_typet;
#define get_adjusted_ptr(catch_type, throw_type, thrown_ptr_p) \
......@@ -127,7 +130,7 @@ check_exception_spec(lsda_header_info* info, _throw_typet* throw_type,
if (tmp == 0)
return false;
tmp = _Unwind_decode_target2((_Unwind_Word) e);
tmp = _Unwind_decode_typeinfo_ptr(info->ttype_base, (_Unwind_Word) e);
// Match a ttype entry.
catch_type = reinterpret_cast<const std::type_info*>(tmp);
......@@ -157,7 +160,7 @@ save_caught_exception(struct _Unwind_Exception* ue_header,
const unsigned char* action_record
__attribute__((__unused__)))
{
ue_header->barrier_cache.sp = _Unwind_GetGR(context, 13);
ue_header->barrier_cache.sp = _Unwind_GetGR(context, UNWIND_STACK_REG);
ue_header->barrier_cache.bitpattern[0] = (_uw) thrown_ptr;
ue_header->barrier_cache.bitpattern[1]
= (_uw) handler_switch_value;
......@@ -205,20 +208,6 @@ empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value)
typedef const std::type_info _throw_typet;
// Return an element from a type table.
static const std::type_info *
get_ttype_entry (lsda_header_info *info, _uleb128_t i)
{
_Unwind_Ptr ptr;
i *= size_of_encoded_value (info->ttype_encoding);
read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
info->TType - i, &ptr);
return reinterpret_cast<const std::type_info *>(ptr);
}
// Given the thrown type THROW_TYPE, pointer to a variable containing a
// pointer to the exception object THROWN_PTR_P and a type CATCH_TYPE to
// compare against, return whether or not there is a match and if so,
......@@ -390,7 +379,8 @@ PERSONALITY_FUNCTION (int version,
case _US_UNWIND_FRAME_STARTING:
actions = _UA_CLEANUP_PHASE;
if (!(state & _US_FORCE_UNWIND)
&& ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
&& ue_header->barrier_cache.sp == _Unwind_GetGR(context,
UNWIND_STACK_REG))
actions |= _UA_HANDLER_FRAME;
break;
......@@ -410,10 +400,10 @@ PERSONALITY_FUNCTION (int version,
// The dwarf unwinder assumes the context structure holds things like the
// function and LSDA pointers. The ARM implementation caches these in
// the exception header (UCB). To avoid rewriting everything we make the
// virtual IP register point at the UCB.
// the exception header (UCB). To avoid rewriting everything we make a
// virtual scratch register point at the UCB.
ip = (_Unwind_Ptr) ue_header;
_Unwind_SetGR(context, 12, ip);
_Unwind_SetGR(context, UNWIND_POINTER_REG, ip);
#else
__cxa_exception* xh = __get_exception_header_from_ue(ue_header);
......@@ -679,6 +669,8 @@ PERSONALITY_FUNCTION (int version,
if (handler_switch_value < 0)
{
parse_lsda_header (context, language_specific_data, &info);
info.ttype_base = base_of_encoded_value (info.ttype_encoding,
context);
#ifdef __ARM_EABI_UNWINDER__
const _Unwind_Word* e;
......@@ -692,8 +684,8 @@ PERSONALITY_FUNCTION (int version,
// Count.
ue_header->barrier_cache.bitpattern[1] = n;
// Base (obsolete)
ue_header->barrier_cache.bitpattern[2] = 0;
// Base
ue_header->barrier_cache.bitpattern[2] = info.ttype_base;
// Stride.
ue_header->barrier_cache.bitpattern[3] = 4;
// List head.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment