Beispiel #1
0
PROTECTED int
unw_step (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret;

  Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n",
         c, c->dwarf.ip, c->dwarf.cfa);

  /* Special handling the singal frame. */
  if (unw_is_signal_frame (cursor))
    return unw_handle_signal_frame (cursor);

  /* Try DWARF-based unwinding... */
  ret = dwarf_step (&c->dwarf);

  if (unlikely (ret == -UNW_ESTOPUNWIND))
    return ret;

  /* Dwarf unwinding didn't work, stop.  */
  if (unlikely (ret < 0))
    return 0;

  return (c->dwarf.ip == 0) ? 0 : 1;
}
Beispiel #2
0
PROTECTED unsigned long
_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
{
  unw_word_t val;

  unw_get_reg (&context->cursor, UNW_REG_IP, &val);
  *ip_before_insn = unw_is_signal_frame (&context->cursor);
  return val;
}
Beispiel #3
0
static void
sighandler (int signal)
{
  unw_cursor_t cursor, cursor2;
  unw_word_t ip;
  unw_context_t uc;

  if (verbose)
    printf ("caught signal %d\n", signal);

  unw_getcontext (&uc);
  if (unw_init_local (&cursor, &uc) < 0)
    panic ("unw_init() failed!\n");

  /* get cursor for caller of sighandler: */
  if (unw_step (&cursor) < 0)
    panic ("unw_step() failed!\n");

  cursor2 = cursor;
  while (!unw_is_signal_frame (&cursor2))
    if (unw_step (&cursor2) < 0)
      panic ("failed to find signal frame!\n");

  if (unw_step (&cursor2) < 0)
    panic ("unw_step() failed!\n");

  if (unw_get_reg (&cursor2, UNW_REG_IP, &ip) < 0)
    panic ("failed to get IP!\n");

  /* skip faulting instruction (doesn't handle MLX template) */
  ++ip;
  if ((ip & 0x3) == 0x3)
    ip += 13;

  if (unw_set_reg (&cursor2, UNW_REG_IP, ip) < 0)
    panic ("failed to set IP!\n");

  unw_resume (&cursor);	/* update context & return to caller of sighandler() */

  panic ("unexpected return from unw_resume()!\n");
}
Beispiel #4
0
PROTECTED int
unw_step (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret;

  Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n",
	 c, c->dwarf.ip, c->dwarf.cfa);

  /* Check if this is a signal frame. */
  if (unw_is_signal_frame (cursor))
    return unw_handle_signal_frame (cursor);

  ret = dwarf_step (&c->dwarf);
  Debug(1, "dwarf_step()=%d\n", ret);

  if (unlikely (ret == -UNW_ESTOPUNWIND))
    return ret;

  if (unlikely (ret < 0))
    return 0;

  return (c->dwarf.ip == 0) ? 0 : 1;
}
Beispiel #5
0
BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers)
{
    int st;
    unw_context_t unwContext;
    unw_cursor_t cursor;

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_ARM64_)
    DWORD64 curPc;
#endif

    if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0)
    {
        // The current frame is a source of hardware exception. Due to the fact that
        // we use the low level unwinder to unwind just one frame a time, the
        // unwinder doesn't have the signal_frame flag set. So it doesn't
        // know that it should not decrement the PC before looking up the unwind info.
        // So we compensate it by incrementing the PC before passing it to the unwinder.
        // Without it, the unwinder would not find unwind info if the hardware exception
        // happened in the first instruction of a function.
        SetPc(context, GetPc(context) + 1);
    }

#if UNWIND_CONTEXT_IS_UCONTEXT_T
    WinContextToUnwindContext(context, &unwContext);
#else
    st = unw_getcontext(&unwContext);
    if (st < 0)
    {
        return FALSE;
    }
#endif
    st = unw_init_local(&cursor, &unwContext);
    if (st < 0)
    {
        return FALSE;
    }

#if !UNWIND_CONTEXT_IS_UCONTEXT_T
    // Set the unwind context to the specified windows context
    WinContextToUnwindCursor(context, &cursor);
#endif

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_ARM64_)
    // OSX and FreeBSD appear to do two different things when unwinding
    // 1: If it reaches where it cannot unwind anymore, say a 
    // managed frame.  It wil return 0, but also update the $pc
    // 2: If it unwinds all the way to _start it will return
    // 0 from the step, but $pc will stay the same.
    // The behaviour of libunwind from nongnu.org is to null the PC
    // So we bank the original PC here, so we can compare it after
    // the step
    curPc = GetPc(context);
#endif

    st = unw_step(&cursor);
    if (st < 0)
    {
        return FALSE;
    }

    // Check if the frame we have unwound to is a frame that caused
    // synchronous signal, like a hardware exception and record it
    // in the context flags.
    st = unw_is_signal_frame(&cursor); 
    if (st > 0)
    {
        context->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
    }
    else
    {
        context->ContextFlags &= ~CONTEXT_EXCEPTION_ACTIVE;
    }

    // Update the passed in windows context to reflect the unwind
    //
    UnwindContextToWinContext(&cursor, context);
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_ARM64_)
    if (st == 0 && GetPc(context) == curPc)
    {
        SetPc(context, 0);
    }
#endif

    if (contextPointers != NULL)
    {
        GetContextPointers(&cursor, &unwContext, contextPointers);
    }
    return TRUE;
}
Beispiel #6
0
bool IsSignalFrameCallback::execute_real()
{
  ret = unw_is_signal_frame(cp_);
  return true;
}
Beispiel #7
0
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret;
  unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
  struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);

  if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
    return -UNW_EUNSPEC;

  /* Obtain signal frame type (non-RT or RT). */
  ret = unw_is_signal_frame (cursor);

  /* Save the SP and PC to be able to return execution at this point
     later in time (unw_resume).  */
  c->sigcontext_sp = c->dwarf.cfa;
  c->sigcontext_pc = c->dwarf.ip;

  /* Since kernel version 2.6.18 the non-RT signal frame starts with a
     ucontext while the RT signal frame starts with a siginfo, followed
     by a sigframe whose first element is an ucontext.
     Prior 2.6.18 the non-RT signal frame starts with a sigcontext while
     the RT signal frame starts with two pointers followed by a siginfo
     and an ucontext. The first pointer points to the start of the siginfo
     structure and the second one to the ucontext structure.  */

  if (ret == 1)
    {
      /* Handle non-RT signal frames. Check if the first word on the stack
	 is the magic number.  */
      if (sp == 0x5ac3c35a)
	{
	  c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME;
	  sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
	}
      else
	{
	  c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME;
	  sc_addr = sp_addr;
	}
      c->sigcontext_addr = sp_addr;
    }
  else if (ret == 2)
    {
      /* Handle RT signal frames. Check if the first word on the stack is a
	 pointer to the siginfo structure.  */
      if (sp == sp_addr + 8)
	{
	  c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME;
	  c->sigcontext_addr = sp_addr + 8 + sizeof (siginfo_t); 
	}
      else
	{
	  c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME;
	  c->sigcontext_addr = sp_addr + sizeof (siginfo_t);
	}
      sc_addr = c->sigcontext_addr + LINUX_UC_MCONTEXT_OFF;
    }
  else
    return -UNW_EUNSPEC;

  /* Update the dwarf cursor.
     Set the location of the registers to the corresponding addresses of the
     uc_mcontext / sigcontext structure contents.  */
  c->dwarf.loc[UNW_ARM_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0);
  c->dwarf.loc[UNW_ARM_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0);
  c->dwarf.loc[UNW_ARM_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0);
  c->dwarf.loc[UNW_ARM_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0);
  c->dwarf.loc[UNW_ARM_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0);
  c->dwarf.loc[UNW_ARM_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0);
  c->dwarf.loc[UNW_ARM_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0);
  c->dwarf.loc[UNW_ARM_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0);
  c->dwarf.loc[UNW_ARM_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0);
  c->dwarf.loc[UNW_ARM_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0);
  c->dwarf.loc[UNW_ARM_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0);
  c->dwarf.loc[UNW_ARM_R11] = DWARF_LOC (sc_addr + LINUX_SC_FP_OFF, 0);
  c->dwarf.loc[UNW_ARM_R12] = DWARF_LOC (sc_addr + LINUX_SC_IP_OFF, 0);
  c->dwarf.loc[UNW_ARM_R13] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0);
  c->dwarf.loc[UNW_ARM_R14] = DWARF_LOC (sc_addr + LINUX_SC_LR_OFF, 0);
  c->dwarf.loc[UNW_ARM_R15] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);

  /* Set SP/CFA and PC/IP.  */
  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa);
  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip);

  return 1;
}
Beispiel #8
0
PROTECTED int
unw_step (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret = -UNW_EUNSPEC;

  Debug (1, "(cursor=%p)\n", c);

  /* Check if this is a signal frame. */
  if (unw_is_signal_frame (cursor))
     return unw_handle_signal_frame (cursor);

#ifdef CONFIG_DEBUG_FRAME
  /* First, try DWARF-based unwinding. */
  if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
    {
      ret = dwarf_step (&c->dwarf);
      Debug(1, "dwarf_step()=%d\n", ret);

      if (likely (ret > 0))
	return 1;
      else if (unlikely (ret == -UNW_ESTOPUNWIND))
	return ret;

    if (ret < 0 && ret != -UNW_ENOINFO)
      {
        Debug (2, "returning %d\n", ret);
        return ret;
      }
    }
#endif /* CONFIG_DEBUG_FRAME */

  /* Next, try extbl-based unwinding. */
  if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
    {
      ret = arm_exidx_step (c);
      if (ret > 0)
	return 1;
      if (ret == -UNW_ESTOPUNWIND || ret == 0)
	return ret;
    }

  /* Fall back on APCS frame parsing.
     Note: This won't work in case the ARM EABI is used. */
  if (unlikely (ret < 0))
    {
      if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME))
        {
          ret = UNW_ESUCCESS;
          /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */
          unw_word_t instr, i;
          Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
          dwarf_loc_t ip_loc, fp_loc;
          unw_word_t frame;
          /* Mark all registers unsaved, since we don't know where
             they are saved (if at all), except for the EBP and
             EIP.  */
          if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_ARM_R11], &frame) < 0)
            {
              return 0;
            }
          for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) {
            c->dwarf.loc[i] = DWARF_NULL_LOC;
          }
          if (frame)
            {
              if (dwarf_get(&c->dwarf, DWARF_LOC(frame, 0), &instr) < 0)
                {
                  return 0;
                }
              instr -= 8;
              if (dwarf_get(&c->dwarf, DWARF_LOC(instr, 0), &instr) < 0)
                {
                  return 0;
                }
              if ((instr & 0xFFFFD800) == 0xE92DD800)
                {
                  /* Standard APCS frame. */
                  ip_loc = DWARF_LOC(frame - 4, 0);
                  fp_loc = DWARF_LOC(frame - 12, 0);
                }
              else
                {
                  /* Codesourcery optimized normal frame. */
                  ip_loc = DWARF_LOC(frame, 0);
                  fp_loc = DWARF_LOC(frame - 4, 0);
                }
              if (dwarf_get(&c->dwarf, ip_loc, &c->dwarf.ip) < 0)
                {
                  return 0;
                }
              c->dwarf.loc[UNW_ARM_R12] = ip_loc;
              c->dwarf.loc[UNW_ARM_R11] = fp_loc;
              Debug(15, "ip=%lx\n", c->dwarf.ip);
            }
          else
            {
              ret = -UNW_ENOINFO;
            }
        }
    }
  return ret == -UNW_ENOINFO ? 0 : 1;
}
Beispiel #9
0
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret;
  unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa;
  struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0);

  if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0)
    return -UNW_EUNSPEC;

  ret = unw_is_signal_frame (cursor);
  Debug(1, "unw_is_signal_frame()=%d\n", ret);

  /* Save the SP and PC to be able to return execution at this point
     later in time (unw_resume).  */
  c->sigcontext_sp = c->dwarf.cfa;
  c->sigcontext_pc = c->dwarf.ip;

  if (ret)
    {
      c->sigcontext_format = AARCH64_SCF_LINUX_RT_SIGFRAME;
      sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF;
    }
  else
    return -UNW_EUNSPEC;

  c->sigcontext_addr = sc_addr;

  /* Update the dwarf cursor.
     Set the location of the registers to the corresponding addresses of the
     uc_mcontext / sigcontext structure contents.  */
  c->dwarf.loc[UNW_AARCH64_X0]  = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X1]  = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X2]  = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X3]  = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X4]  = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X5]  = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X6]  = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X7]  = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X8]  = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X9]  = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_SP]  = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_PC]  = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);
  c->dwarf.loc[UNW_AARCH64_PSTATE]  = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0);

  /* Set SP/CFA and PC/IP.  */
  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa);
  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);

  c->dwarf.pi_valid = 0;

  return 1;
}
Beispiel #10
0
PROTECTED int
unw_step (unw_cursor_t * cursor)
{
    struct cursor *c = (struct cursor *) cursor;
    stack_frame_t dummy;
    unw_word_t back_chain_offset, lr_save_offset, v_regs_ptr;
    struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc, v_regs_loc;
    int ret;

    Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip);

    if (c->dwarf.ip == 0)
    {
        /* Unless the cursor or stack is corrupt or uninitialized,
           we've most likely hit the top of the stack */
        return 0;
    }

    /* Try DWARF-based unwinding... */

    ret = dwarf_step (&c->dwarf);

    if (ret < 0 && ret != -UNW_ENOINFO)
    {
        Debug (2, "returning %d\n", ret);
        return ret;
    }

    if (unlikely (ret < 0))
    {
        if (likely (!unw_is_signal_frame (cursor)))
        {
            /* DWARF unwinding failed.  As of 09/26/2006, gcc in 64-bit mode
               produces the mandatory level of traceback record in the code, but
               I get the impression that this is transitory, that eventually gcc
               will not produce any traceback records at all.  So, for now, we
               won't bother to try to find and use these records.

               We can, however, attempt to unwind the frame by using the callback
               chain.  This is very crude, however, and won't be able to unwind
               any registers besides the IP, SP, and LR . */

            back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy);
            lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy);

            back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0);

            if ((ret =
                        dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0)
            {
                Debug
                ("Unable to retrieve CFA from back chain in stack frame - %d\n",
                 ret);
                return ret;
            }
            if (c->dwarf.cfa == 0)
                /* Unless the cursor or stack is corrupt or uninitialized we've most
                   likely hit the top of the stack */
                return 0;

            lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0);

            if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0)
            {
                Debug
                ("Unable to retrieve IP from lr save in stack frame - %d\n",
                 ret);
                return ret;
            }
            ret = 1;
        }
        else
        {
            /* Find the sigcontext record by taking the CFA and adjusting by
               the dummy signal frame size.

               Note that there isn't any way to determined if SA_SIGINFO was
               set in the sa_flags parameter to sigaction when the signal
               handler was established.  If it was not set, the ucontext
               record is not required to be on the stack, in which case the
               following code will likely cause a seg fault or other crash
               condition.  */

            unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE;

            Debug (1, "signal frame, skip over trampoline\n");

            c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME;
            c->sigcontext_addr = ucontext;

            sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
            ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0);

            ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa);
            if (ret < 0)
            {
                Debug (2, "returning %d\n", ret);
                return ret;
            }
            ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip);
            if (ret < 0)
            {
                Debug (2, "returning %d\n", ret);
                return ret;
            }

            /* Instead of just restoring the non-volatile registers, do all
               of the registers for now.  This will incur a performance hit,
               but it's rare enough not to cause too much of a problem, and
               might be useful in some cases.  */
            c->dwarf.loc[UNW_PPC64_R0] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0);
            c->dwarf.loc[UNW_PPC64_R1] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
            c->dwarf.loc[UNW_PPC64_R2] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0);
            c->dwarf.loc[UNW_PPC64_R3] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0);
            c->dwarf.loc[UNW_PPC64_R4] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0);
            c->dwarf.loc[UNW_PPC64_R5] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0);
            c->dwarf.loc[UNW_PPC64_R6] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0);
            c->dwarf.loc[UNW_PPC64_R7] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0);
            c->dwarf.loc[UNW_PPC64_R8] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
            c->dwarf.loc[UNW_PPC64_R9] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
            c->dwarf.loc[UNW_PPC64_R10] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
            c->dwarf.loc[UNW_PPC64_R11] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
            c->dwarf.loc[UNW_PPC64_R12] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
            c->dwarf.loc[UNW_PPC64_R13] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
            c->dwarf.loc[UNW_PPC64_R14] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
            c->dwarf.loc[UNW_PPC64_R15] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
            c->dwarf.loc[UNW_PPC64_R16] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0);
            c->dwarf.loc[UNW_PPC64_R17] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0);
            c->dwarf.loc[UNW_PPC64_R18] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0);
            c->dwarf.loc[UNW_PPC64_R19] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0);
            c->dwarf.loc[UNW_PPC64_R20] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0);
            c->dwarf.loc[UNW_PPC64_R21] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0);
            c->dwarf.loc[UNW_PPC64_R22] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0);
            c->dwarf.loc[UNW_PPC64_R23] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0);
            c->dwarf.loc[UNW_PPC64_R24] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0);
            c->dwarf.loc[UNW_PPC64_R25] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0);
            c->dwarf.loc[UNW_PPC64_R26] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0);
            c->dwarf.loc[UNW_PPC64_R27] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0);
            c->dwarf.loc[UNW_PPC64_R28] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0);
            c->dwarf.loc[UNW_PPC64_R29] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0);
            c->dwarf.loc[UNW_PPC64_R30] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0);
            c->dwarf.loc[UNW_PPC64_R31] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0);

            c->dwarf.loc[UNW_PPC64_LR] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
            c->dwarf.loc[UNW_PPC64_CTR] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0);
            /* This CR0 assignment is probably wrong.  There are 8 dwarf columns
               assigned to the CR registers, but only one CR register in the
               mcontext structure */
            c->dwarf.loc[UNW_PPC64_CR0] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0);
            c->dwarf.loc[UNW_PPC64_XER] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0);
            c->dwarf.loc[UNW_PPC64_NIP] =
                DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0);

            /* TODO: Is there a way of obtaining the value of the
               pseudo frame pointer (which is sp + some fixed offset, I
               assume), based on the contents of the ucontext record
               structure?  For now, set this loc to null. */
            c->dwarf.loc[UNW_PPC64_FRAME_POINTER] = DWARF_NULL_LOC;

            c->dwarf.loc[UNW_PPC64_F0] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0);
            c->dwarf.loc[UNW_PPC64_F1] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0);
            c->dwarf.loc[UNW_PPC64_F2] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0);
            c->dwarf.loc[UNW_PPC64_F3] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0);
            c->dwarf.loc[UNW_PPC64_F4] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0);
            c->dwarf.loc[UNW_PPC64_F5] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0);
            c->dwarf.loc[UNW_PPC64_F6] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0);
            c->dwarf.loc[UNW_PPC64_F7] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0);
            c->dwarf.loc[UNW_PPC64_F8] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0);
            c->dwarf.loc[UNW_PPC64_F9] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0);
            c->dwarf.loc[UNW_PPC64_F10] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0);
            c->dwarf.loc[UNW_PPC64_F11] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0);
            c->dwarf.loc[UNW_PPC64_F12] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0);
            c->dwarf.loc[UNW_PPC64_F13] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0);
            c->dwarf.loc[UNW_PPC64_F14] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0);
            c->dwarf.loc[UNW_PPC64_F15] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0);
            c->dwarf.loc[UNW_PPC64_F16] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0);
            c->dwarf.loc[UNW_PPC64_F17] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0);
            c->dwarf.loc[UNW_PPC64_F18] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0);
            c->dwarf.loc[UNW_PPC64_F19] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0);
            c->dwarf.loc[UNW_PPC64_F20] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0);
            c->dwarf.loc[UNW_PPC64_F21] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0);
            c->dwarf.loc[UNW_PPC64_F22] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0);
            c->dwarf.loc[UNW_PPC64_F23] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0);
            c->dwarf.loc[UNW_PPC64_F24] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0);
            c->dwarf.loc[UNW_PPC64_F25] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0);
            c->dwarf.loc[UNW_PPC64_F26] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0);
            c->dwarf.loc[UNW_PPC64_F27] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0);
            c->dwarf.loc[UNW_PPC64_F28] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0);
            c->dwarf.loc[UNW_PPC64_F29] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0);
            c->dwarf.loc[UNW_PPC64_F30] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0);
            c->dwarf.loc[UNW_PPC64_F31] =
                DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0);
            /* Note that there is no .eh_section register column for the
               FPSCR register.  I don't know why this is.  */

            v_regs_loc = DWARF_LOC (ucontext + UC_MCONTEXT_V_REGS, 0);
            ret = dwarf_get (&c->dwarf, v_regs_loc, &v_regs_ptr);
            if (ret < 0)
            {
                Debug (2, "returning %d\n", ret);
                return ret;
            }
            if (v_regs_ptr != 0)
            {
                /* The v_regs_ptr is not null.  Set all of the AltiVec locs */

                c->dwarf.loc[UNW_PPC64_V0] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R0, 0);
                c->dwarf.loc[UNW_PPC64_V1] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R1, 0);
                c->dwarf.loc[UNW_PPC64_V2] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R2, 0);
                c->dwarf.loc[UNW_PPC64_V3] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R3, 0);
                c->dwarf.loc[UNW_PPC64_V4] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R4, 0);
                c->dwarf.loc[UNW_PPC64_V5] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R5, 0);
                c->dwarf.loc[UNW_PPC64_V6] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R6, 0);
                c->dwarf.loc[UNW_PPC64_V7] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R7, 0);
                c->dwarf.loc[UNW_PPC64_V8] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R8, 0);
                c->dwarf.loc[UNW_PPC64_V9] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R9, 0);
                c->dwarf.loc[UNW_PPC64_V10] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R10, 0);
                c->dwarf.loc[UNW_PPC64_V11] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R11, 0);
                c->dwarf.loc[UNW_PPC64_V12] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R12, 0);
                c->dwarf.loc[UNW_PPC64_V13] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R13, 0);
                c->dwarf.loc[UNW_PPC64_V14] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R14, 0);
                c->dwarf.loc[UNW_PPC64_V15] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R15, 0);
                c->dwarf.loc[UNW_PPC64_V16] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R16, 0);
                c->dwarf.loc[UNW_PPC64_V17] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R17, 0);
                c->dwarf.loc[UNW_PPC64_V18] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R18, 0);
                c->dwarf.loc[UNW_PPC64_V19] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R19, 0);
                c->dwarf.loc[UNW_PPC64_V20] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R20, 0);
                c->dwarf.loc[UNW_PPC64_V21] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R21, 0);
                c->dwarf.loc[UNW_PPC64_V22] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R22, 0);
                c->dwarf.loc[UNW_PPC64_V23] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R23, 0);
                c->dwarf.loc[UNW_PPC64_V24] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R24, 0);
                c->dwarf.loc[UNW_PPC64_V25] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R25, 0);
                c->dwarf.loc[UNW_PPC64_V26] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R26, 0);
                c->dwarf.loc[UNW_PPC64_V27] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R27, 0);
                c->dwarf.loc[UNW_PPC64_V28] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R28, 0);
                c->dwarf.loc[UNW_PPC64_V29] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R29, 0);
                c->dwarf.loc[UNW_PPC64_V30] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R30, 0);
                c->dwarf.loc[UNW_PPC64_V31] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R31, 0);
                c->dwarf.loc[UNW_PPC64_VRSAVE] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VRSAVE, 0);
                c->dwarf.loc[UNW_PPC64_VSCR] =
                    DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VSCR, 0);
            }
            else
            {
                c->dwarf.loc[UNW_PPC64_V0] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V1] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V2] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V3] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V4] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V5] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V6] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V7] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V8] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V9] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V10] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V11] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V12] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V13] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V14] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V15] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V16] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V17] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V18] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V19] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V20] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V21] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V22] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V23] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V24] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V25] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V26] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V27] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V28] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V29] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V30] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_V31] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_NULL_LOC;
                c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_NULL_LOC;
            }
            ret = 1;
        }
    }
    return ret;
}
PROTECTED int
unw_step (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret, i;

  Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip);

  /* ANDROID support update. */
  /* Save the current ip/cfa to prevent looping if the decode yields
     the same ip/cfa as before. */
  unw_word_t old_ip = c->dwarf.ip;
  unw_word_t old_cfa = c->dwarf.cfa;
  /* End of ANDROID update. */

  /* Try DWARF-based unwinding... */
  ret = dwarf_step (&c->dwarf);

#if !defined(UNW_LOCAL_ONLY)
  /* Do not use this method on a local unwind. There is a very high
   * probability this method will try to access unmapped memory, which
   * will crash the process. Since this almost never actually works,
   * it should be okay to skip.
   */
  if (ret < 0)
    {
      /* DWARF failed, let's see if we can follow the frame-chain
	 or skip over the signal trampoline.  */
      struct dwarf_loc ebp_loc, eip_loc;

      /* We could get here because of missing/bad unwind information.
         Validate all addresses before dereferencing. */
      c->validate = 1;

      Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);

      if (unw_is_signal_frame (cursor))
        {
          ret = unw_handle_signal_frame(cursor);
	  if (ret < 0)
	    {
	      Debug (2, "returning 0\n");
	      return 0;
	    }
        }
      else
	{
	  ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa);
	  if (ret < 0)
	    {
	      Debug (2, "returning %d\n", ret);
	      return ret;
	    }

	  Debug (13, "[EBP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EBP]),
		 c->dwarf.cfa);

	  ebp_loc = DWARF_LOC (c->dwarf.cfa, 0);
	  eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0);
	  c->dwarf.cfa += 8;

	  /* Mark all registers unsaved, since we don't know where
	     they are saved (if at all), except for the EBP and
	     EIP.  */
	  for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
	    c->dwarf.loc[i] = DWARF_NULL_LOC;

          c->dwarf.loc[EBP] = ebp_loc;
          c->dwarf.loc[EIP] = eip_loc;
	}
      c->dwarf.ret_addr_column = EIP;

      if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP]))
	{
	  ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip);
	  if (ret < 0)
	    {
	      Debug (13, "dwarf_get([EIP=0x%x]) failed\n", DWARF_GET_LOC (c->dwarf.loc[EIP]));
	      Debug (2, "returning %d\n", ret);
	      return ret;
	    }
	  else
	    {
	      Debug (13, "[EIP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EIP]),
		c->dwarf.ip);
	    }
	}
      else
	c->dwarf.ip = 0;
    }
#endif

  /* ANDROID support update. */
  if (ret >= 0)
    {
      if (c->dwarf.ip)
        {
          /* Adjust the pc to the instruction before. */
          c->dwarf.ip--;
        }
      /* If the decode yields the exact same ip/cfa as before, then indicate
         the unwind is complete. */
      if (old_ip == c->dwarf.ip && old_cfa == c->dwarf.cfa)
        {
          Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
                   __FUNCTION__, (long) c->dwarf.ip);
          return -UNW_EBADFRAME;
        }
      c->dwarf.frame++;
    }
  /* End of ANDROID update. */
  if (unlikely (ret <= 0))
    return 0;

  return (c->dwarf.ip == 0) ? 0 : 1;
}
Beispiel #12
0
PROTECTED int
unw_step (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret, i;

  Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip);

  /* Try DWARF-based unwinding... */
  ret = dwarf_step (&c->dwarf);

  if (ret < 0 && ret != -UNW_ENOINFO)
    {
      Debug (2, "returning %d\n", ret);
      return ret;
    }

  if (unlikely (ret < 0))
    {
      /* DWARF failed, let's see if we can follow the frame-chain
	 or skip over the signal trampoline.  */
      struct dwarf_loc ebp_loc, eip_loc;

      /* We could get here because of missing/bad unwind information.
         Validate all addresses before dereferencing. */
      c->validate = 1;

      Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);

      if (unw_is_signal_frame (cursor))
        {
          ret = unw_handle_signal_frame(cursor);
	  if (ret < 0)
	    {
	      Debug (2, "returning 0\n");
	      return 0;
	    }
        }
      else
	{
	  ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa);
	  if (ret < 0)
	    {
	      Debug (2, "returning %d\n", ret);
	      return ret;
	    }

	  Debug (13, "[EBP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EBP]),
		 c->dwarf.cfa);

	  ebp_loc = DWARF_LOC (c->dwarf.cfa, 0);
	  eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0);
	  c->dwarf.cfa += 8;

	  /* Mark all registers unsaved, since we don't know where
	     they are saved (if at all), except for the EBP and
	     EIP.  */
	  for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
	    c->dwarf.loc[i] = DWARF_NULL_LOC;

          c->dwarf.loc[EBP] = ebp_loc;
          c->dwarf.loc[EIP] = eip_loc;
	}
      c->dwarf.ret_addr_column = EIP;

      if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP]))
	{
	  ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip);
	  if (ret < 0)
	    {
	      Debug (13, "dwarf_get([EIP=0x%x]) failed\n", DWARF_GET_LOC (c->dwarf.loc[EIP]));
	      Debug (2, "returning %d\n", ret);
	      return ret;
	    }
	  else
	    {
	      Debug (13, "[EIP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EIP]),
		c->dwarf.ip);
	    }
	}
      else
	c->dwarf.ip = 0;
    }
  ret = (c->dwarf.ip == 0) ? 0 : 1;
  Debug (2, "returning %d\n", ret);
  return ret;
}
Beispiel #13
0
BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers)
{
    int st;
    unw_context_t unwContext;
    unw_cursor_t cursor;

    DWORD64 curPc = CONTEXTGetPC(context);

#ifndef __APPLE__
    // Check if the PC is the return address from the SEHProcessException in the common_signal_handler. 
    // If that's the case, extract its local variable containing the windows style context of the hardware 
    // exception and return that. This skips the hardware signal handler trampoline that the libunwind 
    // cannot cross on some systems.
    if ((void*)curPc == g_SEHProcessExceptionReturnAddress)
    {
        CONTEXT* signalContext = (CONTEXT*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset);
        memcpy_s(context, sizeof(CONTEXT), signalContext, sizeof(CONTEXT));

        return TRUE;
    }
#endif 

    if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0)
    {
        // The current frame is a source of hardware exception. Due to the fact that
        // we use the low level unwinder to unwind just one frame a time, the
        // unwinder doesn't have the signal_frame flag set. So it doesn't
        // know that it should not decrement the PC before looking up the unwind info.
        // So we compensate it by incrementing the PC before passing it to the unwinder.
        // Without it, the unwinder would not find unwind info if the hardware exception
        // happened in the first instruction of a function.
        CONTEXTSetPC(context, curPc + 1);
    }

#if !UNWIND_CONTEXT_IS_UCONTEXT_T
    st = unw_getcontext(&unwContext);
    if (st < 0)
    {
        return FALSE;
    }
#endif

    WinContextToUnwindContext(context, &unwContext);

    st = unw_init_local(&cursor, &unwContext);
    if (st < 0)
    {
        return FALSE;
    }

#if !UNWIND_CONTEXT_IS_UCONTEXT_T
    // Set the unwind context to the specified windows context
    WinContextToUnwindCursor(context, &cursor);
#endif

    st = unw_step(&cursor);
    if (st < 0)
    {
        return FALSE;
    }

    // Check if the frame we have unwound to is a frame that caused
    // synchronous signal, like a hardware exception and record it
    // in the context flags.
    if (unw_is_signal_frame(&cursor) > 0)
    {
        context->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
#if defined(_ARM_) || defined(_ARM64_) || defined(_X86_)
        context->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL;
#endif // _ARM_ || _ARM64_
    }
    else
    {
        context->ContextFlags &= ~CONTEXT_EXCEPTION_ACTIVE;
#if defined(_ARM_) || defined(_ARM64_) || defined(_X86_)
        context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL;
#endif // _ARM_ || _ARM64_
    }

    // Update the passed in windows context to reflect the unwind
    //
    UnwindContextToWinContext(&cursor, context);

    // FreeBSD, NetBSD, OSX and Alpine appear to do two different things when unwinding
    // 1: If it reaches where it cannot unwind anymore, say a 
    // managed frame.  It will return 0, but also update the $pc
    // 2: If it unwinds all the way to _start it will return
    // 0 from the step, but $pc will stay the same.
    // So we detect that here and set the $pc to NULL in that case.
    // This is the default behavior of the libunwind on Linux.
    if (st == 0 && CONTEXTGetPC(context) == curPc)
    {
        CONTEXTSetPC(context, 0);
    }

    if (contextPointers != NULL)
    {
        GetContextPointers(&cursor, &unwContext, contextPointers);
    }
    return TRUE;
}
Beispiel #14
0
static int
mips_handle_signal_frame (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  unw_word_t sc_addr, sp_addr = c->dwarf.cfa;
  unw_word_t ra, fp;
  int ret;

  switch (unw_is_signal_frame (cursor)) {
  case 1:
    sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) +
              LINUX_UC_MCONTEXT_OFF;
    break;
  case 2:
    sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF;
    break;
  default:
    return -UNW_EUNSPEC;
  }

  if (tdep_big_endian(c->dwarf.as))
    sc_addr += 4;

  c->sigcontext_addr = sc_addr;

  /* Update the dwarf cursor. */
  c->dwarf.loc[UNW_MIPS_R0]  = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R1]  = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R2]  = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R3]  = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R4]  = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R5]  = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R6]  = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R7]  = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R8]  = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R9]  = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0);
  c->dwarf.loc[UNW_MIPS_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0);
  c->dwarf.loc[UNW_MIPS_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0);

  /* Set SP/CFA and PC/IP. */
  dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_R29], &c->dwarf.cfa);

  if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0),
                       &c->dwarf.ip)) < 0)
    return ret;

  if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0),
                       &ra)) < 0)
    return ret;
  if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0),
                       &fp)) < 0)
    return ret;

  Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n",
         (unsigned long long)c->dwarf.ip, (unsigned long long)ra,
         (unsigned long long)c->dwarf.cfa, (unsigned long long)fp);

  c->dwarf.pi_valid = 0;
  c->dwarf.use_prev_instr = 0;

  return 1;
}
Beispiel #15
0
PROTECTED int
unw_step (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret, i;

  Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip);

  /* Try DWARF-based unwinding... */
  ret = dwarf_step (&c->dwarf);

  if (ret < 0 && ret != -UNW_ENOINFO)
    {
      Debug (2, "returning %d\n", ret);
      return ret;
    }

  if (unlikely (ret < 0))
    {
      /* DWARF failed, let's see if we can follow the frame-chain
	 or skip over the signal trampoline.  */

      Debug (13, "dwarf_step() failed (ret=%d), trying fallback\n", ret);

      if (unw_is_signal_frame (cursor))
	{
#ifdef __linux__
	  /* Assume that the trampoline is at the beginning of the
	     sigframe.  */
	  unw_word_t ip, sc_addr = c->dwarf.ip + LINUX_RT_SIGFRAME_UC_OFF;
	  dwarf_loc_t iaoq_loc = DWARF_LOC (sc_addr + LINUX_SC_IAOQ_OFF, 0);

	  c->sigcontext_format = HPPA_SCF_LINUX_RT_SIGFRAME;
	  c->sigcontext_addr = sc_addr;
	  c->dwarf.ret_addr_column = UNW_HPPA_RP;

	  if ((ret = dwarf_get (&c->dwarf, iaoq_loc, &ip)) , 0)
	    {
	      Debug (2, "failed to read IAOQ[1] (ret=%d)\n", ret);
	      return ret;
	    }
	  c->dwarf.ip = ip & ~0x3;	/* mask out the privilege level */

	  for (i = 0; i < 32; ++i)
	    {
	      c->dwarf.loc[UNW_HPPA_GR + i]
		= DWARF_LOC (sc_addr + LINUX_SC_GR_OFF + 4*i, 0);
	      c->dwarf.loc[UNW_HPPA_FR + i]
		= DWARF_LOC (sc_addr + LINUX_SC_FR_OFF + 4*i, 0);
	    }

	  if ((ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP],
				&c->dwarf.cfa)) < 0)
	    {
	      Debug (2, "failed to read SP (ret=%d)\n", ret);
	      return ret;
	    }
#else
# error Implement me!
#endif
	}
      else
	c->dwarf.ip = 0;
    }
  ret = (c->dwarf.ip == 0) ? 0 : 1;
  Debug (2, "returning %d\n", ret);
  return ret;
}