173 lines
4.4 KiB
C
173 lines
4.4 KiB
C
/* Subroutines needed for unwinding stack frames via the libunwind API.
|
||
Copyright (C) 2002, 2003
|
||
Free Software Foundation, Inc.
|
||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||
|
||
This file is part of GCC.
|
||
|
||
GCC 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 2, or (at your option)
|
||
any later version.
|
||
|
||
GCC 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.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GCC; see the file COPYING. If not, write to
|
||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||
Boston, MA 02111-1307, USA. */
|
||
|
||
/* As a special exception, if you link this library with other files,
|
||
some of which are compiled with GCC, to produce an executable,
|
||
this library does not by itself cause the resulting executable
|
||
to be covered by the GNU General Public License.
|
||
This exception does not however invalidate any other reasons why
|
||
the executable file might be covered by the GNU General Public License. */
|
||
|
||
#include "tconfig.h"
|
||
#include "tsystem.h"
|
||
#include "unwind.h"
|
||
|
||
#ifndef __USING_SJLJ_EXCEPTIONS__
|
||
|
||
#define UNW_LOCAL_ONLY
|
||
|
||
#include <libunwind.h>
|
||
|
||
typedef struct {
|
||
_Unwind_Personality_Fn personality;
|
||
} _Unwind_FrameState;
|
||
|
||
struct _Unwind_Context {
|
||
unw_cursor_t cursor;
|
||
};
|
||
|
||
|
||
/* First come the helper-routines that are needed by unwind.inc. */
|
||
|
||
static _Unwind_Reason_Code
|
||
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||
{
|
||
unw_proc_info_t pi;
|
||
|
||
if (unw_step (&context->cursor) <= 0)
|
||
return _URC_END_OF_STACK;
|
||
|
||
unw_get_proc_info(&context->cursor, &pi);
|
||
fs->personality = (_Unwind_Personality_Fn) pi.handler;
|
||
|
||
return _URC_NO_REASON;
|
||
}
|
||
|
||
#define uw_update_context(context,fs) do { ; } while (0)
|
||
|
||
static inline _Unwind_Ptr
|
||
uw_identify_context (struct _Unwind_Context *context)
|
||
{
|
||
unw_word_t ip;
|
||
unw_get_reg (&context->cursor, UNW_REG_IP, &ip);
|
||
return (_Unwind_Ptr) ip;
|
||
}
|
||
|
||
#define uw_init_context(context) \
|
||
do \
|
||
{ \
|
||
unw_context_t uc; \
|
||
unw_getcontext (&uc); \
|
||
unw_init_local (&(context)->cursor, &uc); \
|
||
} \
|
||
while (0)
|
||
|
||
static inline void __attribute__ ((noreturn))
|
||
uw_install_context (struct _Unwind_Context *current __attribute__ ((unused)),
|
||
struct _Unwind_Context *target)
|
||
{
|
||
unw_resume (&(target)->cursor);
|
||
abort ();
|
||
}
|
||
|
||
|
||
/* Now come the helper-routines which may be called from an exception
|
||
handler. The interface for these routines are defined by the C++
|
||
ABI. See: http://www.codesourcery.com/cxx-abi/abi-eh.html */
|
||
|
||
_Unwind_Word
|
||
_Unwind_GetGR (struct _Unwind_Context *context, int index)
|
||
{
|
||
unw_word_t ret;
|
||
|
||
/* Note: here we depend on the fact that general registers are
|
||
expected to start with register number 0! */
|
||
unw_get_reg (&context->cursor, index, &ret);
|
||
return ret;
|
||
}
|
||
|
||
/* Get the value of the CFA as saved in CONTEXT. */
|
||
|
||
_Unwind_Word
|
||
_Unwind_GetCFA (struct _Unwind_Context *context)
|
||
{
|
||
/* ??? Is there any way to get this information? */
|
||
return NULL;
|
||
}
|
||
|
||
/* Overwrite the saved value for register REG in CONTEXT with VAL. */
|
||
|
||
void
|
||
_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
|
||
{
|
||
/* Note: here we depend on the fact that general registers are
|
||
expected to start with register number 0! */
|
||
unw_set_reg (&context->cursor, index, val);
|
||
}
|
||
|
||
/* Retrieve the return address for CONTEXT. */
|
||
|
||
inline _Unwind_Ptr
|
||
_Unwind_GetIP (struct _Unwind_Context *context)
|
||
{
|
||
unw_word_t ret;
|
||
|
||
unw_get_reg (&context->cursor, UNW_REG_IP, &ret);
|
||
return ret;
|
||
}
|
||
|
||
/* Overwrite the return address for CONTEXT with VAL. */
|
||
|
||
inline void
|
||
_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
|
||
{
|
||
unw_set_reg (&context->cursor, UNW_REG_IP, val);
|
||
}
|
||
|
||
void *
|
||
_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
|
||
{
|
||
unw_proc_info_t pi;
|
||
|
||
unw_get_proc_info(&context->cursor, &pi);
|
||
return (void *) pi.lsda;
|
||
}
|
||
|
||
_Unwind_Ptr
|
||
_Unwind_GetRegionStart (struct _Unwind_Context *context)
|
||
{
|
||
unw_proc_info_t pi;
|
||
|
||
unw_get_proc_info(&context->cursor, &pi);
|
||
return (_Unwind_Ptr) pi.start_ip;
|
||
}
|
||
|
||
void *
|
||
_Unwind_FindEnclosingFunction (void *pc)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
#include "unwind.inc"
|
||
|
||
#endif /* !__USING_SJLJ_EXCEPTIONS__ */
|