bool BreakptMgr::AddBreakpoint(const BreakpointInfo &bp) { if (bp.bp_type != BP_type_watchpt && bp.file.IsEmpty() && bp.function_name.IsEmpty() && bp.memory_address.IsEmpty() && bp.lineno == wxNOT_FOUND) { // no function nor file? no memory address? // do nothing then return true; } IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { // If the debugger is already running, tell it we want a new bp // If not, they'll all be added together when the debugger does start bool contIsNeeded = PauseDebuggerIfNeeded(); dbgr->Break(bp); if (contIsNeeded) { dbgr->Continue(); } } BreakpointInfo newBreakpoint(bp); SetBestBPType(newBreakpoint); BreakpointInfoVec_t::const_iterator iter = std::find(m_bps.begin(), m_bps.end(), newBreakpoint); if ( iter == m_bps.end() ) { // new breakpoint m_bps.push_back( newBreakpoint ); } DeleteAllBreakpointMarkers(); RefreshBreakpointMarkers(); return true; }
bool BreakptMgr::DelBreakpoint(const int id) { int index = FindBreakpointById(id, m_bps); if (index == wxNOT_FOUND) { return false; } //remove it from the debugger if it's running IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { if (id > FIRST_INTERNAL_ID) { // This shouldn't happen while the debugger is running (debugger_id should be valid) // But if it does, assume it was a bp that gdb couldn't create, and just remove from the bp list } else { bool contIsNeeded = PauseDebuggerIfNeeded(); if (dbgr->RemoveBreak(id)) { // Strangely, -break-delete doesn't output any confirmation except for ^done. So do it here wxString msg = ((m_bps.at(index).bp_type == BP_type_watchpt) ? _("Watchpoint ") : _("Breakpoint ")); ManagerST::Get()->UpdateAddLine(msg + wxString::Format(_("%u deleted"), id)); } if (contIsNeeded) { dbgr->Continue(); } } } // Delete all markers before removing bp from the vector. Otherwise if id was the last in a file... DeleteAllBreakpointMarkers(); m_bps.erase(m_bps.begin()+index); RefreshBreakpointMarkers(); return true; }
bool BreakptMgr::SetBPEnabledState(const int bid, const bool enable) { IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { // If the debugger is already running, tell it about the new 'enable' level // If not, it'll happen automatically when the debugger does start bool contIsNeeded = PauseDebuggerIfNeeded(); bool result = dbgr->SetEnabledState(bid, enable); if (contIsNeeded) { dbgr->Continue(); } return result; } return true; }
bool BreakptMgr::SetBPConditon(const BreakpointInfo& bp) { IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { // If the debugger is already running, tell it about the condition // If not, it'll happen automatically when the debugger does start bool contIsNeeded = PauseDebuggerIfNeeded(); bool result = dbgr->SetCondition(bp); if (contIsNeeded) { dbgr->Continue(); } return result; } return false; }
bool BreakptMgr::SetBPIgnoreCount(const int bid, const int ignorecount) { IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { // If the debugger is already running, tell it about the new ignore level // If not, it'll happen automatically when the debugger does start bool contIsNeeded = PauseDebuggerIfNeeded(); bool result = dbgr->SetIgnoreLevel(bid, ignorecount); if (contIsNeeded) { dbgr->Continue(); } return result; } return true; }
void BreakptMgr::DelAllBreakpoints() { IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { bool contIsNeeded = PauseDebuggerIfNeeded(); dbgr->RemoveAllBreaks(); if (contIsNeeded) { dbgr->Continue(); } } // Delete all markers before clearing m_bps, otherwise we won't know which files they were in DeleteAllBreakpointMarkers(); m_bps.clear(); m_pendingBreakpointsList.clear(); // Delete any pending bps too clMainFrame::Get()->GetDebuggerPane()->GetBreakpointView()->Initialize(); }
// When a a breakpoint is hit, see if it's got a command-list that needs faking void BreakptMgr::BreakpointHit(int id) { int index = FindBreakpointById(id, m_bps); if ((index == wxNOT_FOUND) || (index >= FIRST_INTERNAL_ID)) { return; } BreakpointInfo bp = m_bps.at(index); if (! bp.commandlist.IsEmpty()) { IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { // A likely command, presumably at the end of the command-list, is 'continue' or 'cont' // Filter this out and do it separately, otherwise Manager::UpdateLostControl isn't called to blank the indicator static wxRegEx reContinue(wxT("(([[:space:]]|(^))((cont$)|(continue)))")); bool needsCont = false; wxString commands = bp.commandlist; if (reContinue.IsValid() && reContinue.Matches(commands)) { size_t start, len; if (reContinue.GetMatch(&start,&len)) { commands = commands.Left(start); needsCont = true; } } if (! commands.IsEmpty()) { // Just in case someone's _only_ command is 'continue' ! dbgr->ExecuteCmd(commands); } if (needsCont) { dbgr->Continue(); } } } if (bp.bp_type == BP_type_tempbreak) { // If this is a temporary bp, remove it from m_bps now it's been hit // Otherwise it will be treated as a 'Pending' bp, the button will be displayed // and, if clicked, the bp will be resurrected. int index = FindBreakpointById(id, m_bps); if (index != wxNOT_FOUND) { m_bps.erase(m_bps.begin()+index); } } }
void BreakptMgr::SetAllBreakpointsEnabledState(bool enabled) { unsigned int successes = 0; bool debuggerIsRunning = false; bool contIsNeeded = false; IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { debuggerIsRunning = true; contIsNeeded = PauseDebuggerIfNeeded(); } for (size_t i=0; i<m_bps.size(); ++i) { BreakpointInfo &bp = m_bps.at(i); if (((bp.debugger_id != -1) || !debuggerIsRunning) // Sanity check for when the debugger's running && (bp.is_enabled != enabled)) { // No point setting it to the current status if (debuggerIsRunning) { if (dbgr->SetEnabledState(bp.debugger_id, enabled)) { bp.is_enabled = enabled; ++successes; } } else { bp.is_enabled = enabled; ++successes; } } } if (debuggerIsRunning && contIsNeeded) { dbgr->Continue(); } if (successes) { RefreshBreakpointMarkers(); clMainFrame::Get()->GetDebuggerPane()->GetBreakpointView()->Initialize(); wxString msg = wxString::Format(wxT("%u "), successes); msg << (enabled ? _("breakpoints enabled") : _("breakpoints disabled")); clMainFrame::Get()->SetStatusMessage(msg, 0); } }
void BreakptMgr::ApplyPendingBreakpoints() { if (!PendingBreakpointsExist()) { return; // Nothing to do } IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (!(dbgr && dbgr->IsRunning())) { return; // If the debugger isn't running, there's no point (and we shouldn't have reached here anyway) } bool contIsNeeded = PauseDebuggerIfNeeded(); for (size_t i=m_pendingBreakpointsList.size(); i>0; --i) { BreakpointInfo bp = m_pendingBreakpointsList.at(i-1); // First check to see if the debugger already accepted this one // The answer should be no, as acceptance should have removed it from this list int index = FindBreakpointById(bp.internal_id, m_bps); if (index != wxNOT_FOUND) { // Hmm. See if there's a valid debugger_id. If so, the bp *was* accepted, and shouldn't be on the pending list if (m_bps.at(index).debugger_id != -1) { m_pendingBreakpointsList.erase(m_pendingBreakpointsList.begin()+i-1); } continue; // The bp hasn't been assessed yet; it's probably pointless to try to reapply it atm } // This bp didn't 'take' the first time; "..try, try again" :p dbgr->Break(bp); m_bps.push_back(bp); } if (contIsNeeded) { dbgr->Continue(); } RefreshBreakpointMarkers(); }
void BreakptMgr::EditBreakpoint(int index, bool &bpExist) { // sanity bpExist = true; if (index < 0 || index >= (int)m_bps.size()) { wxLogMessage(wxT("BreakptMgr::EditBreakpoint: Insane index")); bpExist = false; return; } BreakpointInfo bp = m_bps.at(index); BreakptPropertiesDlg dlg(NULL); wxString title; if (bp.bp_type == BP_type_watchpt) { title = _("Properties for watchpoint "); } else { title = _("Properties for breakpoint "); } int id = bp.debugger_id; if (id == -1) { id = bp.internal_id - FIRST_INTERNAL_ID; } title << id; dlg.SetTitle(title); dlg.EnterBPData(bp); if (dlg.ShowModal() != wxID_OK) { return ; } SetBestBPType(dlg.b); // The edited data's available. Use it to determine the best bp_type if (bp == dlg.b) { // Nothing was altered return ; } // We've got our altered dlg.b If the debugger's running, we can update it now // Otherwise, it'll be automatically inserted correctly when the debugger starts IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger(); if (dbgr && dbgr->IsRunning()) { if (CanThisBreakpointBeUpdated(dlg.b, bp)) { if (dlg.b.ignore_number != bp.ignore_number) { if (! SetBPIgnoreCount(dlg.b.debugger_id, dlg.b.ignore_number)) { return; // Harsh, but what else can one do? } } if (dlg.b.is_enabled != bp.is_enabled) { if (! SetBPEnabledState(dlg.b.debugger_id, dlg.b.is_enabled)) { return ; } } if (dlg.b.conditions != bp.conditions) { if (! SetBPConditon(dlg.b)) { return ; } } if (dlg.b.commandlist != bp.commandlist) { if (! SetBPCommands(dlg.b)) { return ; } } } else { // If it can't be updated (because gdb wouldn't be able to cope with the change), replace bool contIsNeeded = PauseDebuggerIfNeeded(); dbgr->RemoveBreak(bp.debugger_id); dbgr->Break(dlg.b); // dbgr->Break(bp) doesn't set the ignore/disabled/etc states // but we can't do it now, as we don't yet know the debugger_id // However it will happen later, in SetBreakpointDebuggerID if (contIsNeeded) { dbgr->Continue(); } } } // Replace the old data with the new, in m_bps m_bps.at(index) = dlg.b; DeleteAllBreakpointMarkers(); RefreshBreakpointMarkers(); }