Пример #1
0
HIDDEN int
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
                 int write)
{
    struct dwarf_loc loc;

    switch (reg)
    {
    case UNW_HPPA_IP:
        if (write)
            c->dwarf.ip = *valp;		/* update the IP cache */
        if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip
                                  || *valp >= c->dwarf.pi.end_ip))
            c->dwarf.pi_valid = 0;		/* new IP outside of current proc */
        break;

    case UNW_HPPA_CFA:
    case UNW_HPPA_SP:
        if (write)
            return -UNW_EREADONLYREG;
        *valp = c->dwarf.cfa;
        return 0;

    /* Do the exception-handling register remapping: */
    case UNW_HPPA_EH0:
        reg = UNW_HPPA_GR + 20;
        break;
    case UNW_HPPA_EH1:
        reg = UNW_HPPA_GR + 21;
        break;
    case UNW_HPPA_EH2:
        reg = UNW_HPPA_GR + 22;
        break;
    case UNW_HPPA_EH3:
        reg = UNW_HPPA_GR + 31;
        break;

    default:
        break;
    }

    if ((unsigned) (reg - UNW_HPPA_GR) >= 32)
        return -UNW_EBADREG;

    loc = c->dwarf.loc[reg];

    if (write)
        return dwarf_put (&c->dwarf, loc, *valp);
    else
        return dwarf_get (&c->dwarf, loc, valp);
}
Пример #2
0
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret;

  if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
    struct sigframe *sf;
    uintptr_t uc_addr;
    struct dwarf_loc esp_loc;

    sf = (struct sigframe *)c->dwarf.cfa;
    uc_addr = (uintptr_t)&(sf->sf_uc);
    c->sigcontext_addr = c->dwarf.cfa;

    esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
    ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
    if (ret < 0)
    {
            Debug (2, "returning 0\n");
            return 0;
    }

    c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0);
    c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
    c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0);
    c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ECX_OFF, 0);
    c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDX_OFF, 0);
    c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBX_OFF, 0);
    c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0);
    c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESI_OFF, 0);
    c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDI_OFF, 0);
    c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0);
    c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_TRAPNO_OFF, 0);
    c->dwarf.loc[ST0] = DWARF_NULL_LOC;
  } else if (c->sigcontext_format == X86_SCF_FREEBSD_SYSCALL) {
    c->dwarf.loc[EIP] = DWARF_LOC (c->dwarf.cfa, 0);
    c->dwarf.loc[EAX] = DWARF_NULL_LOC;
    c->dwarf.cfa += 4;
    c->dwarf.use_prev_instr = 1;
  } else {
    Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format);
    abort();
  }
  return 0;
}
Пример #3
0
HIDDEN int
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
		 int write)
{
  dwarf_loc_t loc = DWARF_NULL_LOC;
  
  switch (reg)
    {
    case UNW_ARM_R0:
    case UNW_ARM_R1:
    case UNW_ARM_R2:
    case UNW_ARM_R3:
    case UNW_ARM_R4:
    case UNW_ARM_R5:
    case UNW_ARM_R6:
    case UNW_ARM_R7:
    case UNW_ARM_R8:
    case UNW_ARM_R9:
    case UNW_ARM_R10:
    case UNW_ARM_R11:
    case UNW_ARM_R12:
    case UNW_ARM_R13:
    case UNW_ARM_R14:
    case UNW_ARM_R15:
      loc = c->dwarf.loc[reg - UNW_ARM_R0];
      break;

    case UNW_ARM_CFA:
      if (write)
        return -UNW_EREADONLYREG;
      *valp = c->dwarf.cfa;
      return 0;

    /* FIXME: Initialise coprocessor & shadow registers?  */

    default:
      Debug (1, "bad register number %u\n", reg);
      return -UNW_EBADREG;
    }

  if (write)
    return dwarf_put (&c->dwarf, loc, *valp);
  else
    return dwarf_get (&c->dwarf, loc, valp);
}
Пример #4
0
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  unw_word_t ucontext;
  int ret;

  if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME)
   {
    ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc);
    c->sigcontext_addr = c->dwarf.cfa;
    Debug(1, "signal frame, skip over trampoline\n");

    struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
    ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
    if (ret < 0)
     {
       Debug (2, "returning %d\n", ret);
       return ret;
     }

    c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0);
    c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0);
    c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0);
    c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0);
    c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0);
    c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0);
    c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0);
    c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
    c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
    c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
    c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
    c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
    c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
    c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
    c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
    c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
    c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0);

    return 0;
   }
Пример #5
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;
}
Пример #6
0
HIDDEN int
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
		 int write)
{
  dwarf_loc_t loc = DWARF_NULL_LOC;
  unsigned int mask;
  int arg_num;

  switch (reg)
    {

    case UNW_X86_EIP:
      if (write)
	c->dwarf.ip = *valp;		/* also update the EIP cache */
      loc = c->dwarf.loc[EIP];
      break;

    case UNW_X86_CFA:
    case UNW_X86_ESP:
      if (write)
	return -UNW_EREADONLYREG;
      *valp = c->dwarf.cfa;
      return 0;

    case UNW_X86_EAX:
    case UNW_X86_EDX:
      arg_num = reg - UNW_X86_EAX;
      mask = (1 << arg_num);
      if (write)
	{
	  c->dwarf.eh_args[arg_num] = *valp;
	  c->dwarf.eh_valid_mask |= mask;
	  return 0;
	}
      else if ((c->dwarf.eh_valid_mask & mask) != 0)
	{
	  *valp = c->dwarf.eh_args[arg_num];
	  return 0;
	}
      else
	loc = c->dwarf.loc[(reg == UNW_X86_EAX) ? EAX : EDX];
      break;

    case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break;
    case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break;

    case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break;
    case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break;
    case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break;
    case UNW_X86_EFLAGS: loc = c->dwarf.loc[EFLAGS]; break;
    case UNW_X86_TRAPNO: loc = c->dwarf.loc[TRAPNO]; break;

    case UNW_X86_FCW:
    case UNW_X86_FSW:
    case UNW_X86_FTW:
    case UNW_X86_FOP:
    case UNW_X86_FCS:
    case UNW_X86_FIP:
    case UNW_X86_FEA:
    case UNW_X86_FDS:
    case UNW_X86_MXCSR:
    case UNW_X86_GS:
    case UNW_X86_FS:
    case UNW_X86_ES:
    case UNW_X86_DS:
    case UNW_X86_SS:
    case UNW_X86_CS:
    case UNW_X86_TSS:
    case UNW_X86_LDT:
      loc = x86_scratch_loc (c, reg);
      break;

    default:
      Debug (1, "bad register number %u\n", reg);
      return -UNW_EBADREG;
    }

  if (write)
    return dwarf_put (&c->dwarf, loc, *valp);
  else
    return dwarf_get (&c->dwarf, loc, valp);
}
Пример #7
0
HIDDEN int
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
		 int write)
{
  dwarf_loc_t loc = DWARF_NULL_LOC;
  unsigned int mask;

  switch (reg)
    {
    case UNW_AARCH64_X0:
    case UNW_AARCH64_X1:
    case UNW_AARCH64_X2:
    case UNW_AARCH64_X3:
      mask = 1 << reg;
      if (write)
        {
          c->dwarf.eh_args[reg] = *valp;
          c->dwarf.eh_valid_mask |= mask;
          return 0;
        }
      else if ((c->dwarf.eh_valid_mask & mask) != 0)
        {
          *valp = c->dwarf.eh_args[reg];
          return 0;
        }
      else
        loc = c->dwarf.loc[reg];
      break;

    case UNW_AARCH64_X4:
    case UNW_AARCH64_X5:
    case UNW_AARCH64_X6:
    case UNW_AARCH64_X7:
    case UNW_AARCH64_X8:
    case UNW_AARCH64_X9:
    case UNW_AARCH64_X10:
    case UNW_AARCH64_X11:
    case UNW_AARCH64_X12:
    case UNW_AARCH64_X13:
    case UNW_AARCH64_X14:
    case UNW_AARCH64_X15:
    case UNW_AARCH64_X16:
    case UNW_AARCH64_X17:
    case UNW_AARCH64_X18:
    case UNW_AARCH64_X19:
    case UNW_AARCH64_X20:
    case UNW_AARCH64_X21:
    case UNW_AARCH64_X22:
    case UNW_AARCH64_X23:
    case UNW_AARCH64_X24:
    case UNW_AARCH64_X25:
    case UNW_AARCH64_X26:
    case UNW_AARCH64_X27:
    case UNW_AARCH64_X28:
    case UNW_AARCH64_X29:
    case UNW_AARCH64_X30:
    case UNW_AARCH64_PC:
    case UNW_AARCH64_PSTATE:
      loc = c->dwarf.loc[reg];
      break;

    case UNW_AARCH64_SP:
      if (write)
        return -UNW_EREADONLYREG;
      *valp = c->dwarf.cfa;
      return 0;

    default:
      Debug (1, "bad register number %u\n", reg);
      return -UNW_EBADREG;
    }

  if (write)
    return dwarf_put (&c->dwarf, loc, *valp);
  else
    return dwarf_get (&c->dwarf, loc, valp);
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
0
HIDDEN dwarf_loc_t
x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
{
  unw_word_t addr = c->sigcontext_addr, off, xmm_off;
  unw_word_t fpstate, fpformat;
  int ret, is_fpstate = 0, is_xmmstate = 0;

  switch (c->sigcontext_format)
    {
    case X86_SCF_NONE:
      return DWARF_REG_LOC (&c->dwarf, reg);

    case X86_SCF_FREEBSD_SIGFRAME:
      addr += offsetof(struct sigframe, sf_uc) + FREEBSD_UC_MCONTEXT_OFF;
      break;

    case X86_SCF_FREEBSD_SIGFRAME4:
      abort();
      break;

    case X86_SCF_FREEBSD_OSIGFRAME:
      /* XXXKIB */
      abort();
      break;

    case X86_SCF_FREEBSD_SYSCALL:
      /* XXXKIB */
      abort();
      break;

    default:
      /* XXXKIB */
      abort();
      break;
    }

  off = 0; /* shut gcc warning */
  switch (reg)
    {
    case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break;
    case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break;
    case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break;
    case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
    case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break;
    case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break;
    case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break;
    case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break;
    case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break;
    case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break;
    case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break;
    case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break;
    case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break;
    case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break;
    case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break;
    case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break;
    case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;

    case UNW_X86_FCW:
      is_fpstate = 1;
      off = FREEBSD_UC_MCONTEXT_CW_OFF;
      xmm_off = FREEBSD_UC_MCONTEXT_CW_XMM_OFF;
      break;
    case UNW_X86_FSW:
      is_fpstate = 1;
      off = FREEBSD_UC_MCONTEXT_SW_OFF;
      xmm_off = FREEBSD_UC_MCONTEXT_SW_XMM_OFF;
      break;
    case UNW_X86_FTW:
      is_fpstate = 1;
      xmm_off = FREEBSD_UC_MCONTEXT_TAG_XMM_OFF;
      off = FREEBSD_UC_MCONTEXT_TAG_OFF;
      break;
    case UNW_X86_FCS:
      is_fpstate = 1;
      off = FREEBSD_UC_MCONTEXT_CSSEL_OFF;
      xmm_off = FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF;
      break;
    case UNW_X86_FIP:
      is_fpstate = 1;
      off = FREEBSD_UC_MCONTEXT_IPOFF_OFF;
      xmm_off = FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF;
      break;
    case UNW_X86_FEA:
      is_fpstate = 1;
      off = FREEBSD_UC_MCONTEXT_DATAOFF_OFF;
      xmm_off = FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF;
      break;
    case UNW_X86_FDS:
      is_fpstate = 1;
      off = FREEBSD_US_MCONTEXT_DATASEL_OFF;
      xmm_off = FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF;
      break;
    case UNW_X86_MXCSR:
      is_fpstate = 1;
      is_xmmstate = 1;
      xmm_off = FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF;
      break;

      /* stacked fp registers */
    case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3:
    case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7:
      is_fpstate = 1;
      off = FREEBSD_UC_MCONTEXT_ST0_OFF + 10*(reg - UNW_X86_ST0);
      xmm_off = FREEBSD_UC_MCONTEXT_ST0_XMM_OFF + 10*(reg - UNW_X86_ST0);
      break;

     /* SSE fp registers */
    case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi:
    case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi:
    case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi:
    case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi:
    case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi:
    case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi:
    case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi:
    case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi:
      is_fpstate = 1;
      is_xmmstate = 1;
      xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo);
      break;
    case UNW_X86_XMM0:
    case UNW_X86_XMM1:
    case UNW_X86_XMM2:
    case UNW_X86_XMM3:
    case UNW_X86_XMM4:
    case UNW_X86_XMM5:
    case UNW_X86_XMM6:
    case UNW_X86_XMM7:
      is_fpstate = 1;
      is_xmmstate = 1;
      xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 16*(reg - UNW_X86_XMM0);
      break;

    case UNW_X86_FOP:
    case UNW_X86_TSS:
    case UNW_X86_LDT:
    default:
      return DWARF_REG_LOC (&c->dwarf, reg);
    }

  if (is_fpstate)
    {
      if ((ret = dwarf_get (&c->dwarf,
           DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPSTATE_OFF),
           &fpstate)) < 0)
        return DWARF_NULL_LOC;
      if (fpstate == FREEBSD_UC_MCONTEXT_FPOWNED_NONE)
        return DWARF_NULL_LOC;
      if ((ret = dwarf_get (&c->dwarf,
           DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF),
           &fpformat)) < 0)
        return DWARF_NULL_LOC;
      if (fpformat == FREEBSD_UC_MCONTEXT_FPFMT_NODEV ||
          (is_xmmstate && fpformat != FREEBSD_UC_MCONTEXT_FPFMT_XMM))
        return DWARF_NULL_LOC;
      if (is_xmmstate)
        off = xmm_off;
    }

    return DWARF_MEM_LOC (c, addr + off);
}
Пример #13
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;
}
Пример #14
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;
}
Пример #15
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;
}
Пример #16
0
static inline dwarf_loc_t
linux_scratch_loc (struct cursor *c, unw_regnum_t reg)
{
  unw_word_t addr = c->sigcontext_addr, fpstate_addr, off;
  int ret, is_fpstate = 0;

  switch (c->sigcontext_format)
    {
    case X86_SCF_NONE:
      return DWARF_REG_LOC (&c->dwarf, reg);

    case X86_SCF_LINUX_SIGFRAME:
      break;

    case X86_SCF_LINUX_RT_SIGFRAME:
      addr += LINUX_UC_MCONTEXT_OFF;
      break;
    }

  switch (reg)
    {
    case UNW_X86_GS: off = LINUX_SC_GS_OFF; break;
    case UNW_X86_FS: off = LINUX_SC_FS_OFF; break;
    case UNW_X86_ES: off = LINUX_SC_ES_OFF; break;
    case UNW_X86_DS: off = LINUX_SC_DS_OFF; break;
    case UNW_X86_EDI: off = LINUX_SC_EDI_OFF; break;
    case UNW_X86_ESI: off = LINUX_SC_ESI_OFF; break;
    case UNW_X86_EBP: off = LINUX_SC_EBP_OFF; break;
    case UNW_X86_ESP: off = LINUX_SC_ESP_OFF; break;
    case UNW_X86_EBX: off = LINUX_SC_EBX_OFF; break;
    case UNW_X86_EDX: off = LINUX_SC_EDX_OFF; break;
    case UNW_X86_ECX: off = LINUX_SC_ECX_OFF; break;
    case UNW_X86_EAX: off = LINUX_SC_EAX_OFF; break;
    case UNW_X86_TRAPNO: off = LINUX_SC_TRAPNO_OFF; break;
    case UNW_X86_EIP: off = LINUX_SC_EIP_OFF; break;
    case UNW_X86_CS: off = LINUX_SC_CS_OFF; break;
    case UNW_X86_EFLAGS: off = LINUX_SC_EFLAGS_OFF; break;
    case UNW_X86_SS: off = LINUX_SC_SS_OFF; break;

      /* The following is probably not correct for all possible cases.
	 Somebody who understands this better should review this for
	 correctness.  */

    case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break;
    case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break;
    case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break;
    case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break;
    case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break;
    case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break;
    case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break;
    case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break;

      /* stacked fp registers */
    case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3:
    case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7:
      is_fpstate = 1;
      off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0);
      break;

     /* SSE fp registers */
    case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi:
    case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi:
    case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi:
    case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi:
    case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi:
    case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi:
    case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi:
    case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi:
      is_fpstate = 1;
      off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo);
      break;
    case UNW_X86_XMM0:
    case UNW_X86_XMM1:
    case UNW_X86_XMM2:
    case UNW_X86_XMM3:
    case UNW_X86_XMM4:
    case UNW_X86_XMM5:
    case UNW_X86_XMM6:
    case UNW_X86_XMM7:
      is_fpstate = 1;
      off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0);
      break;

    case UNW_X86_FOP:
    case UNW_X86_TSS:
    case UNW_X86_LDT:
    default:
      return DWARF_REG_LOC (&c->dwarf, reg);
    }

  if (is_fpstate)
    {
      if ((ret = dwarf_get (&c->dwarf,
			    DWARF_MEM_LOC (&c->dwarf,
					   addr + LINUX_SC_FPSTATE_OFF),
			    &fpstate_addr)) < 0)
	return DWARF_NULL_LOC;

      if (!fpstate_addr)
	return DWARF_NULL_LOC;

      return DWARF_MEM_LOC (c, fpstate_addr + off);
    }
  else
    return DWARF_MEM_LOC (c, addr + off);
}
Пример #17
0
HIDDEN int
tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
		 int write)
{
  dwarf_loc_t loc = DWARF_NULL_LOC;
  unsigned int mask;
  int arg_num;

  switch (reg)
    {

    case UNW_X86_64_RIP:
      if (write)
	c->dwarf.ip = *valp;		/* also update the RIP cache */
      loc = c->dwarf.loc[RIP];
      break;

    case UNW_X86_64_CFA:
    case UNW_X86_64_RSP:
      if (write)
	return -UNW_EREADONLYREG;
      *valp = c->dwarf.cfa;
      return 0;

    case UNW_X86_64_RAX:
    case UNW_X86_64_RDX:
      arg_num = reg - UNW_X86_64_RAX;
      mask = (1 << arg_num);
      if (write)
	{
	  c->dwarf.eh_args[arg_num] = *valp;
	  c->dwarf.eh_valid_mask |= mask;
	  return 0;
	}
      else if ((c->dwarf.eh_valid_mask & mask) != 0)
	{
	  *valp = c->dwarf.eh_args[arg_num];
	  return 0;
	}
      else
	loc = c->dwarf.loc[(reg == UNW_X86_64_RAX) ? RAX : RDX];
      break;

    case UNW_X86_64_RCX: loc = c->dwarf.loc[RCX]; break;
    case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break;

    case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break;
    case UNW_X86_64_RSI: loc = c->dwarf.loc[RSI]; break;
    case UNW_X86_64_RDI: loc = c->dwarf.loc[RDI]; break;
    case UNW_X86_64_R8: loc = c->dwarf.loc[R8]; break;
    case UNW_X86_64_R9: loc = c->dwarf.loc[R9]; break;
    case UNW_X86_64_R10: loc = c->dwarf.loc[R10]; break;
    case UNW_X86_64_R11: loc = c->dwarf.loc[R11]; break;
    case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break;
    case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break;
    case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break;
    case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break;

    default:
      Debug (1, "bad register number %u\n", reg);
      return -UNW_EBADREG;
    }

  if (write)
    return dwarf_put (&c->dwarf, loc, *valp);
  else
    return dwarf_get (&c->dwarf, loc, valp);
}
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;
}
Пример #19
0
static int
apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
{
    unw_word_t regnum, addr, cfa, ip;
    unw_word_t prev_ip, prev_cfa;
    unw_addr_space_t as;
    dwarf_loc_t cfa_loc;
    unw_accessors_t *a;
    int i, ret;
    void *arg;

    prev_ip = c->ip;
    prev_cfa = c->cfa;

    as = c->as;
    arg = c->as_arg;
    a = unw_get_accessors (as);

    /* Evaluate the CFA first, because it may be referred to by other
       expressions.  */

    if (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
    {
        /* CFA is equal to [reg] + offset: */

        /* As a special-case, if the stack-pointer is the CFA and the
           stack-pointer wasn't saved, popping the CFA implicitly pops
           the stack-pointer as well.  */
        if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP)
                && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg))
                && (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME))
            cfa = c->cfa;
        else
        {
            regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val);
            if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0)
                return ret;
        }
        cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val;
    }
    else
    {
        /* CFA is equal to EXPR: */

        assert (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_EXPR);

        addr = rs->reg[DWARF_CFA_REG_COLUMN].val;
        if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0)
            return ret;
        /* the returned location better be a memory location... */
        if (DWARF_IS_REG_LOC (cfa_loc))
            return -UNW_EBADFRAME;
        cfa = DWARF_GET_LOC (cfa_loc);
    }

    for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
    {
        switch ((dwarf_where_t) rs->reg[i].where)
        {
        case DWARF_WHERE_UNDEF:
            c->loc[i] = DWARF_NULL_LOC;
            break;

        case DWARF_WHERE_SAME:
            break;

        case DWARF_WHERE_CFAREL:
            c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val);
            break;

        case DWARF_WHERE_REG:
            c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val));
            break;

        case DWARF_WHERE_EXPR:
            addr = rs->reg[i].val;
            if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
                return ret;
            break;

        case DWARF_WHERE_VAL_EXPR:
            addr = rs->reg[i].val;
            if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
                return ret;
            c->loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (c->loc[i]));
            break;
        }
    }

    c->cfa = cfa;
    /* DWARF spec says undefined return address location means end of stack. */
    if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column]))
        c->ip = 0;
    else
    {
        ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip);
        if (ret < 0)
            return ret;
        c->ip = ip;
    }

    /* XXX: check for ip to be code_aligned */
    if (c->ip == prev_ip && c->cfa == prev_cfa)
    {
        Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
                 __FUNCTION__, (long) c->ip);
        return -UNW_EBADFRAME;
    }

    if (c->stash_frames)
        tdep_stash_frame (c, rs);

    return 0;
}
Пример #20
0
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
  struct cursor *c = (struct cursor *) cursor;
  int ret;

  /* c->esp points at the arguments to the handler.  Without
     SA_SIGINFO, the arguments consist of a signal number
     followed by a struct sigcontext.  With SA_SIGINFO, the
     arguments consist a signal number, a siginfo *, and a
     ucontext *. */
  unw_word_t sc_addr;
  unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4;
  unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8;
  unw_word_t siginfo_ptr, sigcontext_ptr;
  struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc;

  siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0);
  sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0);
  ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr)
	 | dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr));
  if (ret < 0)
    {
      Debug (2, "returning 0\n");
      return 0;
    }
  if (siginfo_ptr < c->dwarf.cfa
      || siginfo_ptr > c->dwarf.cfa + 256
      || sigcontext_ptr < c->dwarf.cfa
      || sigcontext_ptr > c->dwarf.cfa + 256)
    {
      /* Not plausible for SA_SIGINFO signal */
      c->sigcontext_format = X86_SCF_LINUX_SIGFRAME;
      c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4;
    }
  else
    {
      /* If SA_SIGINFO were not specified, we actually read
	 various segment pointers instead.  We believe that at
	 least fs and _fsh are always zero for linux, so it is
	 not just unlikely, but impossible that we would end
	 up here. */
      c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME;
      c->sigcontext_addr = sigcontext_ptr;
      sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF;
    }
  esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0);
  ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
  if (ret < 0)
    {
      Debug (2, "returning 0\n");
      return 0;
    }

  c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0);
  c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0);
  c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0);
  c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0);
  c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0);
  c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0);
  c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0);
  c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC;
  c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC;
  c->dwarf.loc[ST0] = DWARF_NULL_LOC;
  c->dwarf.loc[EIP] = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0);
  c->dwarf.loc[ESP] = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0);

  return 0;
}