Example #1
0
//--------------------------------------------------------------------------
// returns true-lowcnd was false, resumed the application
// nb: recursive calls to this function are not handled in any special way!
bool debmod_t::handle_lowcnd(lowcnd_t *lc, debug_event_t *event, int elc_flags)
{
  if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 )
  {
    // difficult case: we have to reset pc, remove the bpt, single step, and resume the app
    QASSERT(616, !handling_lowcnds.has(lc->ea));
    handling_lowcnds.push_back(lc->ea);

    int code;
    if ( (elc_flags & ELC_KEEP_EIP) == 0 )
    {
      regval_t rv;
      rv._set_int(lc->ea);
      code = dbg_write_register(event->tid, pc_idx, &rv);
      if ( code <= 0 )
      {
        handling_lowcnds.del(lc->ea);
        return false;
      }
    }

    code = dbg_freeze_threads_except(event->tid);
    if ( code > 0 )
    {
      int bptlen = lc->type == BPT_SOFT ? lc->orgbytes.size() : lc->size;
      code = dbg_del_bpt(lc->type, lc->ea, lc->orgbytes.begin(), bptlen);
      if ( code > 0 )
      {
        code = dbg_perform_single_step(event, lc->cmd);
        if ( code <= 0 )
          dmsg("%a: failed to single step\n", event->ea); // may happen

        if ( dbg_add_bpt(lc->type, lc->ea, bptlen) <= 0 )
        {
          // if this fails, it may be because the breakpoint is invalid
          // at this time so we should notify IDA it isn't available
          // any more
          code = 0;
          dwarning("%a: could not restore deleted bpt\n", lc->ea); // odd
        }
      }
      if ( dbg_thaw_threads_except(event->tid) <= 0 )
      {
        dwarning("%d: could not resume suspended threads\n", event->tid); // odd
        code = 0;
      }
    }
    handling_lowcnds.del(lc->ea);
    if ( code <= 0 || event->eid != STEP )
      return false; // did not resume
  }
  if ( (elc_flags & ELC_KEEP_SUSP) != 0 )
    return true;
  return dbg_continue_after_event(event) > 0;
}
Example #2
0
//--------------------------------------------------------------------------
// returns true-lowcnd was false, resumed the application
// nb: recursive calls to this function are not handled in any special way!
bool debmod_t::handle_lowcnd(lowcnd_t *lc, debug_event_t *event)
{
  if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 )
  {
    // difficult case: we have to reset pc, remove the bpt, single step, and resume the app
    handling_lowcnd = true;

    regval_t rv;
    rv._set_int(lc->ea);
    int code = dbg_write_register(event->tid, pc_idx, &rv);
    if ( code <= 0 )
    {
      handling_lowcnd = false;
      return false;
    }

    code = dbg_freeze_threads_except(event->tid);
    if ( code > 0 )
    {
      code = dbg_del_bpt(lc->type, lc->ea, lc->orgbytes.begin(), lc->orgbytes.size());
      if ( code > 0 )
      {
        code = dbg_perform_single_step(event, lc->cmd);
        if ( code <= 0 )
          dmsg("%a: failed to single step\n", event->ea); // may happen

        if ( dbg_add_bpt(lc->type, lc->ea, lc->orgbytes.size()) <= 0 )
        {
          code = 0;
          dwarning("%a: could not restore deleted bpt\n", lc->cmd.ea); // odd
        }
      }
      if ( dbg_thaw_threads_except(event->tid) <= 0 )
      {
        dwarning("%d: could not resume suspended threads\n", event->tid); // odd
        code = 0;
      }
    }
    handling_lowcnd = false;
    if ( code <= 0 || event->eid != STEP )
      return false; // did not resume
  }
  return dbg_continue_after_event(event);
}
Example #3
0
//--------------------------------------------------------------------------
// Cleanup after appcall()
// The debugger module must keep the stack blob in the memory until this function
// is called. It will be called by the kernel for each successful call_app_func()
int idaapi debmod_t::dbg_cleanup_appcall(thid_t tid)
{
  call_contexts_t &calls = appcalls[tid];
  if ( calls.empty() )
    return 0;

  // remove the return breakpoint
  call_context_t &ctx = calls.back();
  if ( !preprocess_appcall_cleanup(tid, ctx) )
    return 0;

  dbg_del_bpt(BPT_SOFT, ctx.ctrl_ea, bpt_code.begin(), bpt_code.size());
  if ( ctx.regs_spoiled )
  {
    if ( !write_registers(tid, 0, ctx.saved_regs.size(), ctx.saved_regs.begin()) )
    {
      dmsg("Failed to restore registers!\n");
      return 0;
    }
  }

  calls.pop();
  return events.empty() ? 1 : 2;
}
Example #4
0
//--------------------------------------------------------------------------
int idaapi debmod_t::dbg_update_bpts(
      update_bpt_info_t *bpts,
      int nadd,
      int ndel)
{
  // Write breakpoints to the process
  int cnt = 0;
  update_bpt_info_t *b;
  update_bpt_info_t *end = bpts + nadd;
  for ( b=bpts; b != end; b++ )
  {
    int code = b->code;
    if ( code != BPT_OK )
      continue;
    uchar len;
    char buf[32];
    int nread = 0;
    ea_t ea = b->ea;
    if ( b->type == BPT_SOFT )
    {
      len = bpt_code.size();
#ifdef __ARM__
      if ( (ea & 1) != 0 ) // T bit is set, use a thumb breakpoint
      {
        ea--;
        len = 2;
      }
#endif
      nread = len;
      if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 )
      { // we must save the original bytes before adding the bpt
        QASSERT(30017, sizeof(buf) >= len);
        if ( dbg_read_memory(ea, buf, len) <= 0 )
          code = BPT_READ_ERROR;
      }
    }
    else
    {
      len = b->size;
    }
    if ( code == BPT_OK )
      code = dbg_add_bpt(b->type, ea, len) ? BPT_OK : BPT_WRITE_ERROR;

    b->code = code;
    if ( code == BPT_OK )
    {
      cnt++;
      if ( nread > 0 )
        b->orgbytes = bytevec_t(buf, nread);
    }
  }

  // Delete breakpoints from the process.
  end += ndel;
  for ( ; b != end; b++ )
  {
    b->code = BPT_OK;
    int len = b->type == BPT_SOFT ? b->orgbytes.size() : b->size;
    if ( dbg_del_bpt(b->type, b->ea, b->orgbytes.begin(), len) > 0 )
      cnt++;
    else
      b->code = BPT_WRITE_ERROR;
  }

  return cnt;
}
Example #5
0
//--------------------------------------------------------------------------
int idaapi debmod_t::dbg_update_bpts(
      update_bpt_info_t *ubpts,
      int nadd,
      int ndel)
{
  // Write breakpoints to the process
  int cnt = 0;
  update_bpt_info_t *b;
  update_bpt_info_t *end = ubpts + nadd;
  for ( b=ubpts; b != end; b++ )
  {
    int code = b->code;
    if ( code != BPT_OK )
      continue; // should be BPT_SKIP
    int len;
    uchar buf[32];
    memset(buf, 0, sizeof(buf));
    int nread = 0;
    ea_t ea = b->ea;
    if ( b->type == BPT_SOFT )
    {
      len = bpt_code.size();
      nread = read_bpt_orgbytes(&ea, &len, buf, sizeof(buf));
      if ( nread < 0 )
        code = BPT_READ_ERROR;
    }
    else
    {
      len = b->size;
    }
    if ( code == BPT_OK )
    {
      switch ( dbg_add_bpt(b->type, ea, len) )
      {
        case 2:
          code = BPT_PAGE_OK;
          break;
        case 1:
          code = BPT_OK;
          break;
        default:
          code = BPT_WRITE_ERROR;
          break;
      }
    }

    b->code = code;
    if ( code == BPT_OK )
    {
      cnt++;
      if ( nread > 0 )
        b->orgbytes = bytevec_t(buf, nread);
    }
  }

  // Delete breakpoints from the process.
  end += ndel;
  for ( ; b != end; b++ )
  {
    b->code = BPT_OK;
    int len = b->type == BPT_SOFT ? b->orgbytes.size() : b->size;
    if ( dbg_del_bpt(b->type, b->ea, b->orgbytes.begin(), len) > 0 )
      cnt++;
    else
      b->code = BPT_WRITE_ERROR;
  }

  return cnt;
}