OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [libgcc/] [config/] [alpha/] [osf5-unwind.h] - Diff between revs 734 and 783

Only display areas with differences | Details | Blame | View Log

Rev 734 Rev 783
/* DWARF2 EH unwinding support for Alpha Tru64.
/* DWARF2 EH unwinding support for Alpha Tru64.
   Copyright (C) 2010 Free Software Foundation, Inc.
   Copyright (C) 2010 Free Software Foundation, Inc.
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
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
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
/* This file implements the MD_FALLBACK_FRAME_STATE_FOR macro, triggered when
/* This file implements the MD_FALLBACK_FRAME_STATE_FOR macro, triggered when
   the GCC table based unwinding process hits a frame for which no unwind info
   the GCC table based unwinding process hits a frame for which no unwind info
   has been registered. This typically occurs when raising an exception from a
   has been registered. This typically occurs when raising an exception from a
   signal handler, because the handler is actually called from the OS kernel.
   signal handler, because the handler is actually called from the OS kernel.
 
 
   The basic idea is to detect that we are indeed trying to unwind past a
   The basic idea is to detect that we are indeed trying to unwind past a
   signal handler and to fill out the GCC internal unwinding structures for
   signal handler and to fill out the GCC internal unwinding structures for
   the OS kernel frame as if it had been directly called from the interrupted
   the OS kernel frame as if it had been directly called from the interrupted
   context.
   context.
 
 
   This is all assuming that the code to set the handler asked the kernel to
   This is all assuming that the code to set the handler asked the kernel to
   pass a pointer to such context information.  */
   pass a pointer to such context information.  */
 
 
/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
   -- Basic principles of operation:
   -- Basic principles of operation:
   --------------------------------------------------------------------------
   --------------------------------------------------------------------------
 
 
   1/ We first need a way to detect if we are trying to unwind past a signal
   1/ We first need a way to detect if we are trying to unwind past a signal
      handler.
      handler.
 
 
   The typical method that is used on most platforms is to look at the code
   The typical method that is used on most platforms is to look at the code
   around the return address we have and check if it matches the OS code
   around the return address we have and check if it matches the OS code
   calling a handler.  To determine what this code is expected to be, get a
   calling a handler.  To determine what this code is expected to be, get a
   breakpoint into a real signal handler and look at the code around the
   breakpoint into a real signal handler and look at the code around the
   return address.  Depending on the library versions the pattern of the
   return address.  Depending on the library versions the pattern of the
   signal handler is different; this is the reason why we check against more
   signal handler is different; this is the reason why we check against more
   than one pattern.
   than one pattern.
 
 
   On this target, the return address is right after the call and every
   On this target, the return address is right after the call and every
   instruction is 4 bytes long.  For the simple case of a null dereference in
   instruction is 4 bytes long.  For the simple case of a null dereference in
   a single-threaded app, it went like:
   a single-threaded app, it went like:
 
 
   # Check that we indeed have something we expect: the instruction right
   # Check that we indeed have something we expect: the instruction right
   # before the return address is within a __sigtramp function and is a call.
   # before the return address is within a __sigtramp function and is a call.
 
 
   [... run gdb and break at the signal handler entry ...]
   [... run gdb and break at the signal handler entry ...]
 
 
   (gdb) x /i $ra-4
   (gdb) x /i $ra-4
   <__sigtramp+160>: jsr     ra,(a3),0x3ff800d0ed4 <_fpdata+36468>
   <__sigtramp+160>: jsr     ra,(a3),0x3ff800d0ed4 <_fpdata+36468>
 
 
   # Look at the code around that return address, and eventually observe a
   # Look at the code around that return address, and eventually observe a
   # significantly large chunk of *constant* code right before the call:
   # significantly large chunk of *constant* code right before the call:
 
 
   (gdb) x /10i  $ra-44
   (gdb) x /10i  $ra-44
   <__sigtramp+120>: lda     gp,-27988(gp)
   <__sigtramp+120>: lda     gp,-27988(gp)
   <__sigtramp+124>: ldq     at,-18968(gp)
   <__sigtramp+124>: ldq     at,-18968(gp)
   <__sigtramp+128>: lda     t0,-1
   <__sigtramp+128>: lda     t0,-1
   <__sigtramp+132>: stq     t0,0(at)
   <__sigtramp+132>: stq     t0,0(at)
   <__sigtramp+136>: ldq     at,-18960(gp)
   <__sigtramp+136>: ldq     at,-18960(gp)
   <__sigtramp+140>: ldl     t1,8(at)
   <__sigtramp+140>: ldl     t1,8(at)
   <__sigtramp+144>: ldq     at,-18960(gp)
   <__sigtramp+144>: ldq     at,-18960(gp)
   <__sigtramp+148>: stl     t1,12(at)
   <__sigtramp+148>: stl     t1,12(at)
   <__sigtramp+152>: ldq     at,-18960(gp)
   <__sigtramp+152>: ldq     at,-18960(gp)
   <__sigtramp+156>: stl     t0,8(at)
   <__sigtramp+156>: stl     t0,8(at)
 
 
   # The hexadecimal equivalent that we will have to match is:
   # The hexadecimal equivalent that we will have to match is:
 
 
   (gdb) x /10x  $ra-44
   (gdb) x /10x  $ra-44
   <__sigtramp+120>: 0x23bd92ac    0xa79db5e8    0x203fffff   0xb43c0000
   <__sigtramp+120>: 0x23bd92ac    0xa79db5e8    0x203fffff   0xb43c0000
   <__sigtramp+136>: 0xa79db5f0    0xa05c0008    0xa79db5f0   0xb05c000c
   <__sigtramp+136>: 0xa79db5f0    0xa05c0008    0xa79db5f0   0xb05c000c
   <__sigtramp+152>: 0xa79db5f0    0xb03c0008
   <__sigtramp+152>: 0xa79db5f0    0xb03c0008
 
 
   The problem observed on this target with this approach is that although
   The problem observed on this target with this approach is that although
   we found a constant set of instruction patterns there were some
   we found a constant set of instruction patterns there were some
   gp-related offsets that made the machine code to differ from one
   gp-related offsets that made the machine code to differ from one
   installation to another.  This problem could have been overcome by masking
   installation to another.  This problem could have been overcome by masking
   these offsets, but we found that it would be simpler and more efficient to
   these offsets, but we found that it would be simpler and more efficient to
   check whether the return address was part of a signal handler, by comparing
   check whether the return address was part of a signal handler, by comparing
   it against some expected code offset from __sigtramp.
   it against some expected code offset from __sigtramp.
 
 
   # Check that we indeed have something we expect: the instruction
   # Check that we indeed have something we expect: the instruction
   # right before the return address is within a __sigtramp
   # right before the return address is within a __sigtramp
   # function and is a call. We also need to obtain the offset
   # function and is a call. We also need to obtain the offset
   # between the return address and the start address of __sigtramp.
   # between the return address and the start address of __sigtramp.
 
 
   [... run gdb and break at the signal handler entry ...]
   [... run gdb and break at the signal handler entry ...]
 
 
   (gdb) x /2i $ra-4
   (gdb) x /2i $ra-4
   <__sigtramp+160>: jsr     ra,(a3),0x3ff800d0ed4 <_fpdata+36468>
   <__sigtramp+160>: jsr     ra,(a3),0x3ff800d0ed4 <_fpdata+36468>
   <__sigtramp+164>: ldah    gp,16381(ra)
   <__sigtramp+164>: ldah    gp,16381(ra)
 
 
   (gdb) p (long)$ra - (long)&__sigtramp
   (gdb) p (long)$ra - (long)&__sigtramp
   $2 = 164
   $2 = 164
 
 
   --------------------------------------------------------------------------
   --------------------------------------------------------------------------
 
 
   2/ Once we know we are going through a signal handler, we need a way to
   2/ Once we know we are going through a signal handler, we need a way to
      retrieve information about the interrupted run-time context.
      retrieve information about the interrupted run-time context.
 
 
   On this platform, the third handler's argument is a pointer to a structure
   On this platform, the third handler's argument is a pointer to a structure
   describing this context (struct sigcontext *). We unfortunately have no
   describing this context (struct sigcontext *). We unfortunately have no
   direct way to transfer this value here, so a couple of tricks are required
   direct way to transfer this value here, so a couple of tricks are required
   to compute it.
   to compute it.
 
 
   As documented at least in some header files (e.g. sys/machine/context.h),
   As documented at least in some header files (e.g. sys/machine/context.h),
   the structure the handler gets a pointer to is located on the stack.  As of
   the structure the handler gets a pointer to is located on the stack.  As of
   today, while writing this macro, we have unfortunately not been able to
   today, while writing this macro, we have unfortunately not been able to
   find a detailed description of the full stack layout at handler entry time,
   find a detailed description of the full stack layout at handler entry time,
   so we'll have to resort to empirism :)
   so we'll have to resort to empirism :)
 
 
   When unwinding here, we have the handler's CFA at hand, as part of the
   When unwinding here, we have the handler's CFA at hand, as part of the
   current unwinding context which is one of our arguments.  We presume that
   current unwinding context which is one of our arguments.  We presume that
   for each call to a signal handler by the same kernel routine, the context's
   for each call to a signal handler by the same kernel routine, the context's
   structure location on the stack is always at the same offset from the
   structure location on the stack is always at the same offset from the
   handler's CFA, and we compute that offset from bare observation:
   handler's CFA, and we compute that offset from bare observation:
 
 
   For the simple case of a bare null dereference in a single-threaded app,
   For the simple case of a bare null dereference in a single-threaded app,
   computing the offset was done using GNAT like this:
   computing the offset was done using GNAT like this:
 
 
   # Break on the first handler's instruction, before the prologue to have the
   # Break on the first handler's instruction, before the prologue to have the
   # CFA in $sp, and get there:
   # CFA in $sp, and get there:
 
 
   (gdb) b *&__gnat_error_handler
   (gdb) b *&__gnat_error_handler
   Breakpoint 1 at 0x120016090: file init.c, line 378.
   Breakpoint 1 at 0x120016090: file init.c, line 378.
 
 
   (gdb) r
   (gdb) r
   Program received signal SIGSEGV, Segmentation fault.
   Program received signal SIGSEGV, Segmentation fault.
 
 
   (gdb) c
   (gdb) c
   Breakpoint 1, __gnat_error_handler (sig=..., sip=..., context=...)
   Breakpoint 1, __gnat_error_handler (sig=..., sip=..., context=...)
 
 
   # The displayed argument value are meaningless because we stopped before
   # The displayed argument value are meaningless because we stopped before
   # their final "homing". We know they are passed through $a0, $a1 and $a2
   # their final "homing". We know they are passed through $a0, $a1 and $a2
   # from the ABI, though, so ...
   # from the ABI, though, so ...
 
 
   # Observe that $sp and the context pointer are in the same (stack) area,
   # Observe that $sp and the context pointer are in the same (stack) area,
   # and compute the offset:
   # and compute the offset:
 
 
   (gdb) p /x $sp
   (gdb) p /x $sp
   $2 = 0x11fffbc80
   $2 = 0x11fffbc80
 
 
   (gdb) p /x $a2
   (gdb) p /x $a2
   $3 = 0x11fffbcf8
   $3 = 0x11fffbcf8
 
 
   (gdb) p /x (long)$a2 - (long)$sp
   (gdb) p /x (long)$a2 - (long)$sp
   $4 = 0x78
   $4 = 0x78
 
 
   --------------------------------------------------------------------------
   --------------------------------------------------------------------------
 
 
   3/ Once we know we are unwinding through a signal handler and have the
   3/ Once we know we are unwinding through a signal handler and have the
      address of the structure describing the interrupted context at hand, we
      address of the structure describing the interrupted context at hand, we
      have to fill the internal frame-state/unwind-context structures properly
      have to fill the internal frame-state/unwind-context structures properly
      to allow the unwinding process to proceed.
      to allow the unwinding process to proceed.
 
 
   Roughly, we are provided with an *unwinding* CONTEXT, describing the state
   Roughly, we are provided with an *unwinding* CONTEXT, describing the state
   of some point P in the call chain we are unwinding through.  The macro we
   of some point P in the call chain we are unwinding through.  The macro we
   implement has to fill a "frame state" structure FS that describe the P's
   implement has to fill a "frame state" structure FS that describe the P's
   caller state, by way of *rules* to compute its CFA, return address, and
   caller state, by way of *rules* to compute its CFA, return address, and
   **saved** registers *locations*.
   **saved** registers *locations*.
 
 
   For the case we are going to deal with, the caller is some kernel code
   For the case we are going to deal with, the caller is some kernel code
   calling a signal handler, and:
   calling a signal handler, and:
 
 
   o The saved registers are all in the interrupted run-time context,
   o The saved registers are all in the interrupted run-time context,
 
 
   o The CFA is the stack pointer value when the kernel code is entered, that
   o The CFA is the stack pointer value when the kernel code is entered, that
     is, the stack pointer value at the interruption point, also part of the
     is, the stack pointer value at the interruption point, also part of the
     interrupted run-time context.
     interrupted run-time context.
 
 
   o We want the return address to appear as the address of the active
   o We want the return address to appear as the address of the active
     instruction at the interruption point, so that the unwinder proceeds as
     instruction at the interruption point, so that the unwinder proceeds as
     if the interruption had been a regular call.  This address is also part
     if the interruption had been a regular call.  This address is also part
     of the interrupted run-time context.
     of the interrupted run-time context.
 
 
   --
   --
 
 
   Also, note that there is an important difference between the return address
   Also, note that there is an important difference between the return address
   we need to claim for the kernel frame and the value of the return address
   we need to claim for the kernel frame and the value of the return address
   register at the interruption point.
   register at the interruption point.
 
 
   The latter might be required to be able to unwind past the interrupted
   The latter might be required to be able to unwind past the interrupted
   routine, for instance if it is interrupted before saving the incoming
   routine, for instance if it is interrupted before saving the incoming
   register value in its own frame, which may typically happen during stack
   register value in its own frame, which may typically happen during stack
   probes for stack-checking purposes.
   probes for stack-checking purposes.
 
 
   It is then essential that the rules stated to locate the kernel frame
   It is then essential that the rules stated to locate the kernel frame
   return address don't clobber the rules describing where is saved the return
   return address don't clobber the rules describing where is saved the return
   address register at the interruption point, so some scratch register state
   address register at the interruption point, so some scratch register state
   entry should be used for the former. We have DWARF_ALT_FRAME_RETURN_COLUMN
   entry should be used for the former. We have DWARF_ALT_FRAME_RETURN_COLUMN
   at hand exactly for that purpose.
   at hand exactly for that purpose.
 
 
   --------------------------------------------------------------------------
   --------------------------------------------------------------------------
 
 
   4/ Depending on the context (single-threaded or multi-threaded app, ...),
   4/ Depending on the context (single-threaded or multi-threaded app, ...),
   the code calling the handler and the handler-cfa to interrupted-context
   the code calling the handler and the handler-cfa to interrupted-context
   offset might change, so we use a simple generic data structure to track
   offset might change, so we use a simple generic data structure to track
   the possible variants.  */
   the possible variants.  */
 
 
/* This is the structure to wrap information about each possible sighandler
/* This is the structure to wrap information about each possible sighandler
   caller we may have to identify.  */
   caller we may have to identify.  */
 
 
typedef struct {
typedef struct {
  /* Expected return address when being called from a sighandler.  */
  /* Expected return address when being called from a sighandler.  */
  void *ra_value;
  void *ra_value;
 
 
  /* Offset to get to the sigcontext structure from the handler's CFA
  /* Offset to get to the sigcontext structure from the handler's CFA
     when the pattern matches.  */
     when the pattern matches.  */
  int cfa_to_context_offset;
  int cfa_to_context_offset;
 
 
} sighandler_call_t;
} sighandler_call_t;
 
 
/* Helper macro for MD_FALLBACK_FRAME_STATE_FOR below.
/* Helper macro for MD_FALLBACK_FRAME_STATE_FOR below.
 
 
   Look at RA to see if it matches within a sighandler caller.
   Look at RA to see if it matches within a sighandler caller.
   Set SIGCTX to the corresponding sigcontext structure (computed from
   Set SIGCTX to the corresponding sigcontext structure (computed from
   CFA) if it does, or to 0 otherwise.  */
   CFA) if it does, or to 0 otherwise.  */
 
 
#define COMPUTE_SIGCONTEXT_FOR(RA,CFA,SIGCTX)                               \
#define COMPUTE_SIGCONTEXT_FOR(RA,CFA,SIGCTX)                               \
do {                                                                        \
do {                                                                        \
  /* Define and register the applicable patterns.  */                       \
  /* Define and register the applicable patterns.  */                       \
  extern void __sigtramp (void);                                            \
  extern void __sigtramp (void);                                            \
                                                                            \
                                                                            \
  sighandler_call_t sighandler_calls [] = {                                 \
  sighandler_call_t sighandler_calls [] = {                                 \
    {__sigtramp + 164, 0x78}                                                \
    {__sigtramp + 164, 0x78}                                                \
  };                                                                        \
  };                                                                        \
                                                                            \
                                                                            \
  int n_patterns_to_match                                                   \
  int n_patterns_to_match                                                   \
    = sizeof (sighandler_calls) / sizeof (sighandler_call_t);               \
    = sizeof (sighandler_calls) / sizeof (sighandler_call_t);               \
                                                                            \
                                                                            \
  int pn;  /* pattern number  */                                            \
  int pn;  /* pattern number  */                                            \
                                                                            \
                                                                            \
  int match = 0;  /* Did last pattern match ?  */                            \
  int match = 0;  /* Did last pattern match ?  */                            \
                                                                            \
                                                                            \
  /* Try to match each pattern in turn.  */                                 \
  /* Try to match each pattern in turn.  */                                 \
  for (pn = 0; !match && pn < n_patterns_to_match; pn ++)                    \
  for (pn = 0; !match && pn < n_patterns_to_match; pn ++)                    \
    match = ((RA) == sighandler_calls[pn].ra_value);                        \
    match = ((RA) == sighandler_calls[pn].ra_value);                        \
                                                                            \
                                                                            \
  (SIGCTX) = (struct sigcontext *)                                          \
  (SIGCTX) = (struct sigcontext *)                                          \
    (match ? ((CFA) + sighandler_calls[pn - 1].cfa_to_context_offset) : 0); \
    (match ? ((CFA) + sighandler_calls[pn - 1].cfa_to_context_offset) : 0); \
} while (0);
} while (0);
 
 
#include <sys/context_t.h>
#include <sys/context_t.h>
 
 
#define REG_SP  30  /* hard reg for stack pointer */
#define REG_SP  30  /* hard reg for stack pointer */
#define REG_RA  26  /* hard reg for return address */
#define REG_RA  26  /* hard reg for return address */
 
 
#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state
#define MD_FALLBACK_FRAME_STATE_FOR alpha_fallback_frame_state
 
 
static _Unwind_Reason_Code
static _Unwind_Reason_Code
alpha_fallback_frame_state (struct _Unwind_Context *context,
alpha_fallback_frame_state (struct _Unwind_Context *context,
                            _Unwind_FrameState *fs)
                            _Unwind_FrameState *fs)
{
{
  /* Return address and CFA of the frame we're attempting to unwind through,
  /* Return address and CFA of the frame we're attempting to unwind through,
     possibly a signal handler.  */
     possibly a signal handler.  */
  void *ctx_ra  = (void *)context->ra;
  void *ctx_ra  = (void *)context->ra;
  void *ctx_cfa = (void *)context->cfa;
  void *ctx_cfa = (void *)context->cfa;
 
 
  /* CFA of the intermediate abstract kernel frame between the interrupted
  /* CFA of the intermediate abstract kernel frame between the interrupted
     code and the signal handler, if we're indeed unwinding through a signal
     code and the signal handler, if we're indeed unwinding through a signal
     handler.  */
     handler.  */
  void *k_cfa;
  void *k_cfa;
 
 
  /* Pointer to the sigcontext structure pushed by the kernel when we're
  /* Pointer to the sigcontext structure pushed by the kernel when we're
     unwinding through a signal handler.  */
     unwinding through a signal handler.  */
  struct sigcontext *sigctx;
  struct sigcontext *sigctx;
  int i;
  int i;
 
 
  COMPUTE_SIGCONTEXT_FOR (ctx_ra, ctx_cfa, sigctx);
  COMPUTE_SIGCONTEXT_FOR (ctx_ra, ctx_cfa, sigctx);
 
 
  if (sigctx == 0)
  if (sigctx == 0)
    return _URC_END_OF_STACK;
    return _URC_END_OF_STACK;
 
 
  /* The kernel frame's CFA is exactly the stack pointer value at the
  /* The kernel frame's CFA is exactly the stack pointer value at the
     interruption point.  */
     interruption point.  */
  k_cfa = (void *) sigctx->sc_regs [REG_SP];
  k_cfa = (void *) sigctx->sc_regs [REG_SP];
 
 
  /* State the rules to compute the CFA we have the value of: use the
  /* State the rules to compute the CFA we have the value of: use the
     previous CFA and offset by the difference between the two.  See
     previous CFA and offset by the difference between the two.  See
     uw_update_context_1 for the supporting details.  */
     uw_update_context_1 for the supporting details.  */
  fs->regs.cfa_how = CFA_REG_OFFSET;
  fs->regs.cfa_how = CFA_REG_OFFSET;
  fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
  fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
  fs->regs.cfa_offset = k_cfa - ctx_cfa;
  fs->regs.cfa_offset = k_cfa - ctx_cfa;
 
 
  /* Fill the internal frame_state structure with information stating
  /* Fill the internal frame_state structure with information stating
     where each register of interest in the saved context can be found
     where each register of interest in the saved context can be found
     from the CFA.  */
     from the CFA.  */
 
 
  /* The general registers are in sigctx->sc_regs.  Leave out r31, which
  /* The general registers are in sigctx->sc_regs.  Leave out r31, which
     is read-as-zero. It makes no sense restoring it, and we are going to
     is read-as-zero. It makes no sense restoring it, and we are going to
     use the state entry for the kernel return address rule below.
     use the state entry for the kernel return address rule below.
 
 
     This loop must cover at least all the callee-saved registers, and
     This loop must cover at least all the callee-saved registers, and
     we just don't bother specializing the set here.  */
     we just don't bother specializing the set here.  */
  for (i = 0; i <= 30; i ++)
  for (i = 0; i <= 30; i ++)
    {
    {
      fs->regs.reg[i].how = REG_SAVED_OFFSET;
      fs->regs.reg[i].how = REG_SAVED_OFFSET;
      fs->regs.reg[i].loc.offset
      fs->regs.reg[i].loc.offset
        = (void *) &sigctx->sc_regs[i] - (void *) k_cfa;
        = (void *) &sigctx->sc_regs[i] - (void *) k_cfa;
    }
    }
 
 
  /* Ditto for the floating point registers in sigctx->sc_fpregs.  */
  /* Ditto for the floating point registers in sigctx->sc_fpregs.  */
  for (i = 0; i <= 31; i ++)
  for (i = 0; i <= 31; i ++)
    {
    {
      fs->regs.reg[32+i].how = REG_SAVED_OFFSET;
      fs->regs.reg[32+i].how = REG_SAVED_OFFSET;
      fs->regs.reg[32+i].loc.offset
      fs->regs.reg[32+i].loc.offset
        = (void *) &sigctx->sc_fpregs[i] - (void *) k_cfa;
        = (void *) &sigctx->sc_fpregs[i] - (void *) k_cfa;
    }
    }
 
 
  /* State the rules to find the kernel's code "return address", which
  /* State the rules to find the kernel's code "return address", which
     is the address of the active instruction when the signal was caught,
     is the address of the active instruction when the signal was caught,
     in sigctx->sc_pc. Use DWARF_ALT_FRAME_RETURN_COLUMN since the return
     in sigctx->sc_pc. Use DWARF_ALT_FRAME_RETURN_COLUMN since the return
     address register is a general register and should be left alone.  */
     address register is a general register and should be left alone.  */
  fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
  fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
  fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET;
  fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET;
  fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset
  fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset
    = (void *) &sigctx->sc_pc - (void *) k_cfa;
    = (void *) &sigctx->sc_pc - (void *) k_cfa;
  fs->signal_frame = 1;
  fs->signal_frame = 1;
 
 
  return _URC_NO_REASON;
  return _URC_NO_REASON;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.