Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) {
  Status error;
  std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
  FreeBSDThread *thread = static_cast<FreeBSDThread *>(
      m_thread_list.GetThreadAtIndex(0, false).get());
  if (thread)
    num = thread->NumSupportedHardwareWatchpoints();
  else
    error.SetErrorString("Process does not exist.");
  return error;
}
Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) {
  Status error;
  if (wp) {
    user_id_t watchID = wp->GetID();
    addr_t addr = wp->GetLoadAddress();
    Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
    if (log)
      log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
                  watchID);
    if (wp->IsEnabled()) {
      if (log)
        log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64
                    ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
                    watchID, (uint64_t)addr);
      return error;
    }

    // Try to find a vacant watchpoint slot in the inferiors' main thread
    uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
    std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
    FreeBSDThread *thread = static_cast<FreeBSDThread *>(
        m_thread_list.GetThreadAtIndex(0, false).get());

    if (thread)
      wp_hw_index = thread->FindVacantWatchpointIndex();

    if (wp_hw_index == LLDB_INVALID_INDEX32) {
      error.SetErrorString("Setting hardware watchpoint failed.");
    } else {
      wp->SetHardwareIndex(wp_hw_index);
      bool wp_enabled = true;
      uint32_t thread_count = m_thread_list.GetSize(false);
      for (uint32_t i = 0; i < thread_count; ++i) {
        thread = static_cast<FreeBSDThread *>(
            m_thread_list.GetThreadAtIndex(i, false).get());
        if (thread)
          wp_enabled &= thread->EnableHardwareWatchpoint(wp);
        else
          wp_enabled = false;
      }
      if (wp_enabled) {
        wp->SetEnabled(true, notify);
        return error;
      } else {
        // Watchpoint enabling failed on at least one of the threads so roll
        // back all of them
        DisableWatchpoint(wp, false);
        error.SetErrorString("Setting hardware watchpoint failed");
      }
    }
  } else
    error.SetErrorString("Watchpoint argument was NULL.");
  return error;
}
Status ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) {
  std::unique_ptr<EmulateInstruction> emulator_ap(
      EmulateInstruction::FindPlugin(GetTarget().GetArchitecture(),
                                     eInstructionTypePCModifying, nullptr));

  if (emulator_ap == nullptr)
    return Status("Instruction emulator not found!");

  FreeBSDThread *thread = static_cast<FreeBSDThread *>(
      m_thread_list.FindThreadByID(tid, false).get());
  if (thread == NULL)
    return Status("Thread not found not found!");

  lldb::RegisterContextSP register_context_sp = thread->GetRegisterContext();

  EmulatorBaton baton(this, register_context_sp.get());
  emulator_ap->SetBaton(&baton);
  emulator_ap->SetReadMemCallback(&ReadMemoryCallback);
  emulator_ap->SetReadRegCallback(&ReadRegisterCallback);
  emulator_ap->SetWriteMemCallback(&WriteMemoryCallback);
  emulator_ap->SetWriteRegCallback(&WriteRegisterCallback);

  if (!emulator_ap->ReadInstruction())
    return Status("Read instruction failed!");

  bool emulation_result =
      emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
  const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo(
      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
  auto pc_it =
      baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);

  lldb::addr_t next_pc;
  if (emulation_result) {
    assert(pc_it != baton.m_register_values.end() &&
           "Emulation was successful but PC wasn't updated");
    next_pc = pc_it->second.GetAsUInt64();
  } else if (pc_it == baton.m_register_values.end()) {
    // Emulate instruction failed and it haven't changed PC. Advance PC with
    // the size of the current opcode because the emulation of all
    // PC modifying instruction should be successful. The failure most
    // likely caused by a not supported instruction which don't modify PC.
    next_pc =
        register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize();
  } else {
    // The instruction emulation failed after it modified the PC. It is an
    // unknown error where we can't continue because the next instruction is
    // modifying the PC but we don't  know how.
    return Status("Instruction emulation failed unexpectedly");
  }

  SetSoftwareSingleStepBreakpoint(tid, next_pc);
  return Status();
}
Esempio n. 4
0
Error
ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num)
{
    Error error;
    Mutex::Locker lock(m_thread_list.GetMutex());
    FreeBSDThread *thread = static_cast<FreeBSDThread*>(
                          m_thread_list.GetThreadAtIndex(0, false).get());
    if (thread)
        num = thread->NumSupportedHardwareWatchpoints();
    else
        error.SetErrorString("Process does not exist.");
    return error;
}
Esempio n. 5
0
Error
ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify)
{
    Error error;
    if (wp)
    {
        user_id_t watchID = wp->GetID();
        addr_t addr = wp->GetLoadAddress();
        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
        if (log)
            log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
                        watchID);
        if (!wp->IsEnabled())
        {
            if (log)
                log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64
                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
                            watchID, (uint64_t)addr);
            // This is needed (for now) to keep watchpoints disabled correctly
            wp->SetEnabled(false, notify);
            return error;
        }

        if (wp->IsHardware())
        {
            bool wp_disabled = true;
            Mutex::Locker lock(m_thread_list.GetMutex());
            uint32_t thread_count = m_thread_list.GetSize(false);
            for (uint32_t i = 0; i < thread_count; ++i)
            {
                FreeBSDThread *thread = static_cast<FreeBSDThread*>(
                                      m_thread_list.GetThreadAtIndex(i, false).get());
                if (thread)
                    wp_disabled &= thread->DisableHardwareWatchpoint(wp);
                else
                    wp_disabled = false;
            }
            if (wp_disabled)
            {
                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
                wp->SetEnabled(false, notify);
                return error;
            }
            else
                error.SetErrorString("Disabling hardware watchpoint failed");
        }
    }
    else
        error.SetErrorString("Watchpoint argument was NULL.");
    return error;
}
bool ProcessFreeBSD::IsAThreadRunning() {
  bool is_running = false;
  std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
  uint32_t thread_count = m_thread_list.GetSize(false);
  for (uint32_t i = 0; i < thread_count; ++i) {
    FreeBSDThread *thread = static_cast<FreeBSDThread *>(
        m_thread_list.GetThreadAtIndex(i, false).get());
    StateType thread_state = thread->GetState();
    if (thread_state == eStateRunning || thread_state == eStateStepping) {
      is_running = true;
      break;
    }
  }
  return is_running;
}
Esempio n. 7
0
void ProcessFreeBSD::RefreshStateAfterStop() {
  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
  if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
    log->Printf("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__,
                (int)m_message_queue.size());

  std::lock_guard<std::recursive_mutex> guard(m_message_mutex);

  // This method used to only handle one message.  Changing it to loop allows
  // it to handle the case where we hit a breakpoint while handling a different
  // breakpoint.
  while (!m_message_queue.empty()) {
    ProcessMessage &message = m_message_queue.front();

    // Resolve the thread this message corresponds to and pass it along.
    lldb::tid_t tid = message.GetTID();
    if (log)
      log->Printf(
          "ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64,
          __FUNCTION__, (int)m_message_queue.size(), tid);

    m_thread_list.RefreshStateAfterStop();

    FreeBSDThread *thread = static_cast<FreeBSDThread *>(
        GetThreadList().FindThreadByID(tid, false).get());
    if (thread)
      thread->Notify(message);

    if (message.GetKind() == ProcessMessage::eExitMessage) {
      // FIXME: We should tell the user about this, but the limbo message is
      // probably better for that.
      if (log)
        log->Printf("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64,
                    __FUNCTION__, tid);

      std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());

      ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
      thread_sp.reset();
      m_seen_initial_stop.erase(tid);
    }

    m_message_queue.pop();
  }
}