Esempio n. 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;
}
Esempio n. 2
0
int
unw_step (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret;

  ret = mips_handle_signal_frame (cursor);
  if (ret < 0)
    /* Not a signal frame, 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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 7
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;
}
Esempio n. 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);

  /* Try DWARF-based unwinding...  this is the only method likely to work for
     ARM.  */
  if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
    {
      ret = dwarf_step (&c->dwarf);
      Debug(1, "dwarf_step()=%d\n", ret);

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

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

  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;
}
Esempio n. 9
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;
}