Commit 205a838c authored by Niko Sams's avatar Niko Sams
Browse files

When starting gdb read breakpoints and merge them with existing ones

That way we don't get duplicates when the user adds new ones using .gdbinit
for every session, and we save them additionally.

BUG: 270970
parent d311d561
......@@ -160,6 +160,15 @@ void BreakpointController::slotEvent(IDebugSession::event_t e)
case IDebugSession::connected_to_program:
{
kDebug() << "connected to program";
//load breakpoints the user might have added through eg .gdbinit on startup
//*before* sending, so we avoid getting duplicates
debugSession()->addCommand(
new GDBCommand(GDBMI::BreakList,
"",
this,
&BreakpointController::handleBreakpointListInitial));
sendMaybeAll();
break;
}
......@@ -172,6 +181,47 @@ void BreakpointController::slotEvent(IDebugSession::event_t e)
}
}
void BreakpointController::handleBreakpointListInitial(const GDBMI::ResultRecord &r)
{
m_dontSendChanges++;
const GDBMI::Value& blist = r["BreakpointTable"]["body"];
for(int i = 0, e = blist.size(); i != e; ++i)
{
KDevelop::Breakpoint *updateBreakpoint = 0;
const GDBMI::Value& mi_b = blist[i];
QString type = mi_b["type"].literal();
foreach(KDevelop::Breakpoint *b, breakpointModel()->breakpoints()) {
if ((type == "watchpoint" || type == "hw watchpoint") && b->kind() == KDevelop::Breakpoint::WriteBreakpoint) {
if (mi_b["original-location"].literal() == b->expression()) {
updateBreakpoint = b;
}
} else if (type == "read watchpoint" && b->kind() == KDevelop::Breakpoint::ReadBreakpoint) {
if (mi_b["original-location"].literal() == b->expression()) {
updateBreakpoint = b;
}
} else if (type == "acc watchpoint" && b->kind() == KDevelop::Breakpoint::AccessBreakpoint) {
if (mi_b["original-location"].literal() == b->expression()) {
updateBreakpoint = b;
}
} else if (b->kind() == KDevelop::Breakpoint::CodeBreakpoint) {
if (mi_b["original-location"].literal() == b->location()) {
updateBreakpoint = b;
}
}
if (updateBreakpoint) break;
}
if (updateBreakpoint) {
update(updateBreakpoint, mi_b);
} else {
//ignore, we will load them in the first pause anyway
}
}
m_dontSendChanges--;
}
void BreakpointController::sendMaybe(KDevelop::Breakpoint* breakpoint)
{
if (debugSession()->stateIsOn(s_dbgNotStarted)) {
......
......@@ -65,6 +65,7 @@ private:
virtual void sendMaybe(KDevelop::Breakpoint *breakpoint);
void handleBreakpointListInitial(const GDBMI::ResultRecord &r);
void handleBreakpointList(const GDBMI::ResultRecord &r);
void update(KDevelop::Breakpoint *b, const GDBMI::Value& v);
......
......@@ -1274,6 +1274,33 @@ void GdbTest::testPickupManuallyInsertedBreakpoint()
QCOMPARE(b->url().url(), QString("debugee.cpp"));
}
//Bug 270970
void GdbTest::testPickupManuallyInsertedBreakpointOnlyOnce()
{
TestDebugSession *session = new TestDebugSession;
TestLaunchConfiguration cfg;
breakpoints()->addCodeBreakpoint(KUrl("debugee.cpp"), 31);
QVERIFY(session->startProgram(&cfg));
//inject here, so it behaves similar like a command from .gdbinit
session->addCommandToFront(new GDBCommand(GDBMI::NonMI, "break debugee.cpp:32"));
WAIT_FOR_STATE(session, DebugSession::PausedState);
session->stepInto();
WAIT_FOR_STATE(session, DebugSession::PausedState);
QTest::qWait(1000); //wait for breakpoints update
QCOMPARE(breakpoints()->breakpoints().count(), 1);
QCOMPARE(breakpoints()->rowCount(), 1+1);
KDevelop::Breakpoint *b = breakpoints()->breakpoint(0);
QVERIFY(b);
QCOMPARE(b->line(), 31); //we start with 0, gdb with 1
QCOMPARE(b->url().url(), QString("debugee.cpp"));
}
void GdbTest::waitForState(GDBDebugger::DebugSession *session, DebugSession::DebuggerState state,
const char *file, int line)
......
......@@ -73,6 +73,7 @@ private Q_SLOTS:
void testInsertAndRemoveBreakpointWhileRunning();
void testCommandOrderFastStepping();
void testPickupManuallyInsertedBreakpoint();
void testPickupManuallyInsertedBreakpointOnlyOnce();
private:
KDevelop::TestCore* m_core;
void waitForState(GDBDebugger::DebugSession *session, KDevelop::IDebugSession::DebuggerState state, const char *file, int line);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment