Commit 634bcc88 authored by hjk's avatar hjk

debugger: intercept calls to qFatal

On Windows that might kill the inferior even if we only want to
examine data.

Task-number: QTCREATORBUG-4145
parent 5426c3ac
......@@ -92,36 +92,6 @@ void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &respon
}
void AbstractPlainGdbAdapter::runEngine()
{
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
QString fileName;
{
QTemporaryFile symbols(QDir::tempPath() + "/gdb_ns_");
symbols.open();
fileName = symbols.fileName();
}
m_engine->postCommand("maint print msymbols " + fileName.toLocal8Bit(),
CB(handleNamespaceExtraction), fileName);
}
void AbstractPlainGdbAdapter::handleNamespaceExtraction(const GdbResponse &response)
{
QFile file(response.cookie.toString());
file.open(QIODevice::ReadOnly);
QByteArray ba = file.readAll();
file.remove();
int pos = ba.indexOf("7QString9fromAscii");
int pos1 = pos - 1;
while (pos1 > 0 && ba.at(pos1) != 'N' && ba.at(pos1) > '@')
--pos1;
++pos1;
const QByteArray ns = ba.mid(pos1, pos - pos1);
if (!ns.isEmpty())
m_engine->setQtNamespace(ns + "::");
doRunEngine();
}
void AbstractPlainGdbAdapter::doRunEngine()
{
m_engine->postCommand("-exec-run", GdbEngine::RunRequest, CB(handleExecRun));
}
......
......@@ -52,7 +52,6 @@ public:
protected:
void handleInfoTarget(const GdbResponse &response);
void handleNamespaceExtraction(const GdbResponse &response);
private:
virtual QByteArray execFilePath() const = 0;
......@@ -61,7 +60,6 @@ private:
virtual QString fromLocalEncoding(const QByteArray &ba) const = 0;
void handleExecRun(const GdbResponse &response);
void handleFileExecAndSymbols(const GdbResponse &response);
void doRunEngine();
};
} // namespace Debugger
......
......@@ -215,6 +215,7 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters,
m_stackNeeded = false;
m_preparedForQmlBreak = false;
m_disassembleUsesComma = false;
m_qFatalBreakpointNumber = 0;
invalidateSourcesList();
......@@ -1246,7 +1247,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
if (bkptno && frame.isValid()
&& !isQmlStepBreakpoint1(bkptno)
&& !isQmlStepBreakpoint2(bkptno)) {
&& !isQmlStepBreakpoint2(bkptno)
&& !isQFatalBreakpoint(bkptno)) {
// Use opportunity to update the breakpoint marker position.
BreakHandler *handler = breakHandler();
//qDebug() << " PROBLEM: " << m_qmlBreakpointNumbers << bkptno
......@@ -1268,7 +1270,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction)
&& QFileInfo(fullName).exists()
&& !isQmlStepBreakpoint1(bkptno)
&& !isQmlStepBreakpoint2(bkptno))
&& !isQmlStepBreakpoint2(bkptno)
&& !isQFatalBreakpoint(bkptno))
gotoLocation(Location(fullName, lineNumber));
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
......@@ -2169,7 +2172,7 @@ void GdbEngine::updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkp
} else if (child.hasName("func")) {
response.functionName = _(child.data());
} else if (child.hasName("addr")) {
// <MULTIPLE> happens in constructors, inline functions, and
// <MULTIPLE> happens in constructors, inline functions, and
// at other places like 'foreach' lines. In this case there are
// fields named "addr" in the response and/or the address
// is called <MULTIPLE>.
......@@ -2438,6 +2441,8 @@ void GdbEngine::handleBreakList(const GdbMi &table)
needle.number = bkpt.findChild("number").data().toInt();
if (isQmlStepBreakpoint2(needle.number))
continue;
if (isQFatalBreakpoint(needle.number))
continue;
BreakpointId id = breakHandler()->findSimilarBreakpoint(needle);
if (id != BreakpointId(-1)) {
updateBreakpointDataFromOutput(id, bkpt);
......@@ -4622,8 +4627,10 @@ void GdbEngine::handleInferiorPrepared()
// Apply source path mappings from global options.
const SourcePathMap sourcePathMap =
DebuggerSourcePathMappingWidget::mergePlatformQtPath(startParameters().qtInstallPath,
debuggerCore()->globalDebuggerOptions()->sourcePathMap);
DebuggerSourcePathMappingWidget::mergePlatformQtPath(
startParameters().qtInstallPath,
debuggerCore()->globalDebuggerOptions()->sourcePathMap);
if (!sourcePathMap.isEmpty()) {
const SourcePathMapIterator cend = sourcePathMap.constEnd();
for (SourcePathMapIterator it = sourcePathMap.constBegin(); it != cend; ++it) {
......@@ -4653,6 +4660,52 @@ void GdbEngine::handleInferiorPrepared()
void GdbEngine::finishInferiorSetup()
{
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
// Extract Qt namespace.
QString fileName;
{
QTemporaryFile symbols(QDir::tempPath() + _("/gdb_ns_"));
symbols.open();
fileName = symbols.fileName();
}
postCommand("maint print msymbols " + fileName.toLocal8Bit(),
CB(handleNamespaceExtraction), fileName);
}
void GdbEngine::handleNamespaceExtraction(const GdbResponse &response)
{
QFile file(response.cookie.toString());
file.open(QIODevice::ReadOnly);
QByteArray ba = file.readAll();
//file.remove();
int pos = ba.indexOf("7QString9fromAscii");
int pos1 = pos - 1;
while (pos1 > 0 && ba.at(pos1) != 'N' && ba.at(pos1) > '@')
--pos1;
++pos1;
const QByteArray ns = ba.mid(pos1, pos - pos1);
if (ns.isEmpty()) {
showMessage(_("FOUND NON-NAMESPACED QT"));
} else {
showMessage(_("FOUND NAMESPACED QT: " + ns));
setQtNamespace(ns + "::");
}
postCommand("-break-insert -f '" + qtNamespace() + "qFatal'",
CB(handleBreakOnQFatal));
}
void GdbEngine::handleBreakOnQFatal(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
GdbMi bkpt = response.data.findChild("bkpt");
GdbMi number = bkpt.findChild("number");
int bpnr = number.data().toInt();
if (bpnr) {
m_qFatalBreakpointNumber = bpnr;
postCommand("-break-commands " + number.data() + " return");
}
}
// Continue setup.
notifyInferiorSetupOk();
}
......@@ -4786,6 +4839,11 @@ bool GdbEngine::isQmlStepBreakpoint2(int bpnr) const
return bpnr && m_qmlBreakpointNumbers[2] == bpnr;
}
bool GdbEngine::isQFatalBreakpoint(int bpnr) const
{
return bpnr && m_qFatalBreakpointNumber == bpnr;
}
//
// Factory
//
......
......@@ -137,6 +137,7 @@ private: ////////// Gdb Process Management //////////
void handleGdbExit(const GdbResponse &response);
void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
void handleRemoteSetupFailed(const QString &message);
void handleNamespaceExtraction(const GdbResponse &response);
void handleAdapterStarted();
void defaultInferiorShutdown(const char *cmd);
......@@ -432,6 +433,7 @@ private: ////////// View & Data Stuff //////////
//void handleFetchDisassemblerByMiRangeMixed(const GdbResponse &response);
//void handleFetchDisassemblerByMiRangePlain(const GdbResponse &response);
void handleDisassemblerCheck(const GdbResponse &response);
void handleBreakOnQFatal(const GdbResponse &response);
DisassemblerLines parseDisassembler(const GdbMi &data);
DisassemblerLines parseCliDisassembler(const GdbMi &lines);
DisassemblerLines parseMiDisassembler(const GdbMi &lines);
......@@ -581,11 +583,13 @@ private: ////////// View & Data Stuff //////////
void handleSetQmlStepBreakpoint(const GdbResponse &response);
bool isQmlStepBreakpoint1(int bpnr) const;
bool isQmlStepBreakpoint2(int bpnr) const;
bool isQFatalBreakpoint(int bpnr) const;
// HACK:
StackFrame m_targetFrame;
QByteArray m_currentThread;
QString m_lastWinException;
int m_qFatalBreakpointNumber;
};
} // namespace Internal
......
Markdown is supported
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