diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 423321fc7ba41e3cd1151baeb95d3e5f9f666dc7..60e91697b792a1ec13b981f2fa908c01f9a930e2 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -543,12 +543,6 @@ void DebuggerManager::notifyStartupFinished() { setStatus(DebuggerProcessReady); showStatusMessage(tr("Startup finished. Debugger ready."), -1); - if (m_startMode == attachExternal) { - // we continue the execution - engine()->continueInferior(); - } else { - engine()->runInferior(); - } } void DebuggerManager::notifyInferiorStopped() diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index f6413db72f9259d181413948d7159b8bd0c01e52..051c0f78fbf710d0156464572f6c8eda995190fe 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -100,6 +100,9 @@ enum GdbCommandType GdbQuerySources, GdbAsyncOutput2, GdbExecRun, + GdbExecStart1, + GdbExecStart2, + GdbExecStart3, GdbExecRunToFunction, GdbExecStep, GdbExecNext, @@ -635,6 +638,7 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) } if (pid == q->m_attachedPID) return; + //qDebug() << "FOUND PID " << pid; q->m_attachedPID = pid; qq->notifyInferiorPidChanged(pid); } @@ -686,8 +690,8 @@ void GdbEngine::sendCommand(const QString &command, int type, //qDebug() << qPrintable(currentTime()) << "RUNNING" << cmd.command; m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); //emit gdbInputAvailable(QString(), " " + currentTime()); - emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); - //emit gdbInputAvailable(QString(), cmd.command); + //emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); + emit gdbInputAvailable(QString(), cmd.command); } if (temporarilyStopped) @@ -753,9 +757,18 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, case GdbExecContinue: case GdbExecFinish: // evil code sharing - case GdbExecRun: handleExecRun(record); break; + + case GdbExecStart1: + handleExecStart1(record); + break; + case GdbExecStart2: + handleExecStart2(record); + break; + case GdbExecStart3: + handleExecStart3(record); + break; case GdbInfoProc: handleInfoProc(record); break; @@ -1134,6 +1147,34 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) const QString reason = data.findChild("reason").data(); QString console = data.findChild("consolestreamoutput").data(); + if (reason.isEmpty()) { + GdbMi frame = data.findChild("frame"); + if (frame.findChild("func").data() == "_start") { + // that's the "early stop" + frame.findChild("func").data() + '%'; + #if defined(Q_OS_WIN) + sendCommand("info proc", GdbInfoProc); + #endif + #if defined(Q_OS_LINUX) + sendCommand("info proc", GdbInfoProc); + #endif + #if defined(Q_OS_MAC) + sendCommand("info pid", GdbInfoProc, QVariant(), true); + #endif + sendCommand("-file-list-exec-source-files", GdbQuerySources); + sendCommand("set auto-solib-add on"); + sendCommand("sharedlibrary libc"); // for malloc + sendCommand("sharedlibrary libdl"); // for dlopen + tryLoadCustomDumpers(); + sendCommand("info shared", ModulesList, QVariant()); + // this will "continue" if done + attemptBreakpointSynchronization(); + return; + } + // fall through + } + +#if 0 if (console.contains("Stopped due to shared library event") || reason.isEmpty()) { ++m_shared; //if (m_shared == 2) @@ -1162,6 +1203,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) } return; } +#endif if (isExitedReason(reason)) { qq->notifyInferiorExited(); @@ -1218,7 +1260,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (reason == "breakpoint-hit") { q->showStatusMessage(tr("Stopped at breakpoint")); GdbMi frame = data.findChild("frame"); - //qDebug() << frame.toString(); + qDebug() << "HIT BREAKPOINT: " << frame.toString(); m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; @@ -1604,16 +1646,27 @@ bool GdbEngine::startDebugger() } } + if (q->startMode() == q->startInternal) { + sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); + //sendCommand("file " + fileName, GdbFileExecAndSymbols); + #ifdef Q_OS_MAC + sendCommand("sharedlibrary apply-load-rules all"); + #endif + //sendCommand("-gdb-set stop-on-solib-events 1"); + runInferior(); + } + if (q->startMode() == q->attachExternal) { sendCommand("attach " + QString::number(q->m_attachedPID)); } - if (q->startMode() == q->startInternal || q->startMode() == q->startExternal) { - sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); + if (q->startMode() == q->startExternal) { + //sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); + sendCommand("file " + fileName, GdbFileExecAndSymbols); #ifdef Q_OS_MAC sendCommand("sharedlibrary apply-load-rules all"); #endif - sendCommand("-file-list-exec-source-files", GdbQuerySources); + //sendCommand("-file-list-exec-source-files", GdbQuerySources); //sendCommand("-gdb-set stop-on-solib-events 1"); } @@ -1625,7 +1678,7 @@ bool GdbEngine::startDebugger() else qq->breakHandler()->setAllPending(); - QTimer::singleShot(0, this, SLOT(attemptBreakpointSynchronization())); + //QTimer::singleShot(0, this, SLOT(attemptBreakpointSynchronization())); return true; } @@ -1648,7 +1701,33 @@ void GdbEngine::runInferior() sendCommand("-exec-arguments " + q->m_processArgs.join(" ")); qq->notifyInferiorRunningRequested(); emit gdbInputAvailable(QString(), QString()); - sendCommand("-exec-run", GdbExecRun); + + sendCommand("set auto-solib-add off"); + sendCommand("x/2i _start", GdbExecStart1); +} + +void GdbEngine::handleExecStart1(const GdbResultRecord &response) +{ + if (response.resultClass == GdbResultDone) { + // stdout:&"x/2i _start\n" + // stdout:~"0x404540 <_start>:\txor %ebp,%ebp\n" + // stdout:~"0x404542 <_start+2>:\tmov %rdx,%r9\n" + QString msg = response.data.findChild("consolestreamoutput").data(); + QRegExp needle("0x([0-9a-f]+) <_start\\+.*>:"); + if (needle.indexIn(msg) != -1) { + //qDebug() << "STREAM: " << msg << needle.cap(1); + sendCommand("tbreak *0x" + needle.cap(1)); // GdbExecStart3); + sendCommand("-exec-run"); // GdbExecStart3); + } else { + qDebug() << "PARSING START ADDRESS FAILED" << msg; + } + } else if (response.resultClass == GdbResultError) { + qDebug() << "PARSING START ADDRESS FAILED" << response.toString(); + } +} + +void GdbEngine::handleExecStart3(const GdbResultRecord &response) +{ #if defined(Q_OS_WIN) sendCommand("info proc", GdbInfoProc); #endif @@ -1658,6 +1737,7 @@ void GdbEngine::runInferior() #if defined(Q_OS_MAC) sendCommand("info pid", GdbInfoProc, QVariant(), true); #endif + attemptBreakpointSynchronization(); } void GdbEngine::stepExec() @@ -2183,8 +2263,10 @@ void GdbEngine::attemptBreakpointSynchronization() //sendListBreakpoints(); } - if (!updateNeeded && q->status() == DebuggerProcessStartingUp) - qq->notifyStartupFinished(); + if (!updateNeeded && q->status() == DebuggerProcessStartingUp) { + // we continue the execution + continueInferior(); + } } @@ -3603,7 +3685,7 @@ void GdbEngine::updateLocals() // '2' is 'list with type and value' sendSynchronizedCommand("-stack-list-locals 2", StackListLocals); // stage 2/2 - tryLoadCustomDumpers(); + //tryLoadCustomDumpers(); } void GdbEngine::handleStackListArguments(const GdbResultRecord &record) diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index a603aee375dc5732cbd066b79fb06f97ef8f36b2..14cb65d7cdf332273f2aa5d76703d59a242a0bfa 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -185,6 +185,9 @@ private: void handleResultRecord(const GdbResultRecord &response); void handleFileExecAndSymbols(const GdbResultRecord &response); void handleExecRun(const GdbResultRecord &response); + void handleExecStart1(const GdbResultRecord &response); + void handleExecStart2(const GdbResultRecord &response); + void handleExecStart3(const GdbResultRecord &response); void handleExecJumpToLine(const GdbResultRecord &response); void handleExecRunToFunction(const GdbResultRecord &response); void handleInfoShared(const GdbResultRecord &response);