diff options
author | aph <aph@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-09-04 15:05:01 +0000 |
---|---|---|
committer | aph <aph@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-09-04 15:05:01 +0000 |
commit | 4a90ac8840bbb250b9dfb05e2d969d435de9fbac (patch) | |
tree | 5a319de7534ebec38fb5f1ac5caf21f1c810bbce /gcc/config/arm/unwind-arm.c | |
parent | ed59fd36a64db0ed51d6014744ff7f4893d2d5a9 (diff) | |
download | gcc-4a90ac8840bbb250b9dfb05e2d969d435de9fbac.tar.gz |
2007-08-08 Andrew Haley <aph@redhat.com>
* config/arm/libunwind.S (UNWIND_WRAPPER _Unwind_Backtrace): New.
* config/arm/unwind-arm.h (__gnu_Unwind_Backtrace): New.
* config/arm/unwind-arm.c (__gnu_Unwind_Backtrace): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128087 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm/unwind-arm.c')
-rw-r--r-- | gcc/config/arm/unwind-arm.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/gcc/config/arm/unwind-arm.c b/gcc/config/arm/unwind-arm.c index 60f61d526f4..d9f8a855925 100644 --- a/gcc/config/arm/unwind-arm.c +++ b/gcc/config/arm/unwind-arm.c @@ -950,6 +950,66 @@ _Unwind_DeleteException (_Unwind_Exception * exc) } +/* Perform stack backtrace through unwind data. */ +_Unwind_Reason_Code +__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument, + phase2_vrs * entry_vrs); +_Unwind_Reason_Code +__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument, + phase2_vrs * entry_vrs) +{ + phase1_vrs saved_vrs; + _Unwind_Reason_Code code; + + _Unwind_Control_Block ucb; + _Unwind_Control_Block *ucbp = &ucb; + + /* Set the pc to the call site. */ + entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR]; + + /* Save the core registers. */ + saved_vrs.core = entry_vrs->core; + /* Set demand-save flags. */ + saved_vrs.demand_save_flags = ~(_uw) 0; + + do + { + /* Find the entry for this routine. */ + if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK) + { + code = _URC_FAILURE; + break; + } + + /* 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. */ + _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp); + + /* Call trace function. */ + if ((*trace) ((_Unwind_Context *) &saved_vrs, trace_argument) + != _URC_NO_REASON) + { + code = _URC_FAILURE; + break; + } + + /* Call the pr to decide what to do. */ + code = ((personality_routine) UCB_PR_ADDR (ucbp)) + (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, + ucbp, (void *) &saved_vrs); + } + while (code != _URC_END_OF_STACK + && code != _URC_FAILURE); + + finish: + restore_non_core_regs (&saved_vrs); + return code; +} + + /* Common implementation for ARM ABI defined personality routines. ID is the index of the personality routine, other arguments are as defined by __aeabi_unwind_cpp_pr{0,1,2}. */ |