Debugger: Add wow64 support to the cdbengine.

Change-Id: I1819c42438609553ce277e01b7c8a2d4fffbfb1b
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
David Schulz
2013-05-07 23:37:51 -07:00
parent 4fb5277834
commit 18dff5392c
2 changed files with 83 additions and 10 deletions

View File

@@ -356,6 +356,7 @@ CdbEngine::CdbEngine(const DebuggerStartParameters &sp, const OptionsPtr &option
m_notifyEngineShutdownOnTermination(false),
m_hasDebuggee(false),
m_cdbIs64Bit(false),
m_wow64State(wow64Uninitialized),
m_elapsedLogTime(0),
m_sourceStepInto(false),
m_watchPointX(0),
@@ -387,6 +388,7 @@ void CdbEngine::init()
m_watchPointX = m_watchPointY = 0;
m_ignoreCdbOutput = false;
m_watchInameToName.clear();
m_wow64State = wow64Uninitialized;
m_outputBuffer.clear();
m_builtinCommandQueue.clear();
@@ -642,6 +644,8 @@ bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessa
#else
false;
#endif
if (!m_cdbIs64Bit)
m_wow64State = noWow64Stack;
const QFileInfo extensionFi(CdbEngine::extensionLibraryName(m_cdbIs64Bit));
if (!extensionFi.isFile()) {
*errorMessage = QString::fromLatin1("Internal error: The extension %1 cannot be found.").
@@ -2220,6 +2224,10 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
case ParseStackStepOut: // Hit on a frame with no source while step into.
executeStepOut();
return;
case ParseStackWow64:
postBuiltinCommand("!wow64exts.info", 0, &CdbEngine::handleCheckWow64,
0, qVariantFromValue(stack));
return;
}
} else {
showMessage(QString::fromLatin1(stopReason["stackerror"].data()), LogError);
@@ -2247,6 +2255,52 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
showStoppedByExceptionMessageBox(exceptionBoxMessage);
}
void CdbEngine::handleCheckWow64(const CdbBuiltinCommandPtr &cmd)
{
// Using the stack command from the wow64exts cdb extension to
// check if there is a 32bit subsystem in this debuggee.
if (cmd->reply.first().startsWith("Could not get the address of the 32bit PEB")) {
m_wow64State = noWow64Stack;
if (cmd->cookie.canConvert<GdbMi>())
parseStackTrace(qvariant_cast<GdbMi>(cmd->cookie), false);
return;
}
postBuiltinCommand("k", 0, &CdbEngine::ensureUsing32BitStackInWow64, 0, cmd->cookie);
}
void CdbEngine::ensureUsing32BitStackInWow64(const CdbEngine::CdbBuiltinCommandPtr &cmd)
{
// Parsing the header of the stack output to check which bitness
// the cdb is currently using.
foreach (const QByteArray &line, cmd->reply) {
if (!line.startsWith("Child"))
continue;
if (line.startsWith("ChildEBP")) {
m_wow64State = wow64Stack32Bit;
return;
} else if (line.startsWith("Child-SP")) {
m_wow64State = wow64Stack64Bit;
postBuiltinCommand("!wow64exts.sw", 0, &CdbEngine::handleSwitchWow64Stack);
return;
}
}
m_wow64State = noWow64Stack;
if (cmd->cookie.canConvert<GdbMi>())
parseStackTrace(qvariant_cast<GdbMi>(cmd->cookie), false);
}
void CdbEngine::handleSwitchWow64Stack(const CdbEngine::CdbBuiltinCommandPtr &cmd)
{
if (cmd->reply.first() == "Switched to 32bit mode")
m_wow64State = wow64Stack32Bit;
else if (cmd->reply.first() == "Switched to 64bit mode")
m_wow64State = wow64Stack64Bit;
else
m_wow64State = noWow64Stack;
// reload threads and the stack after switching the mode
postCommandSequence(CommandListThreads | CommandListStack);
}
void CdbEngine::handleSessionAccessible(unsigned long cdbExState)
{
const DebuggerState s = state();
@@ -2866,17 +2920,21 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
StackFrames frames = parseFrames(data, &incomplete);
const int count = frames.size();
for (int i = 0; i < count; i++) {
if (m_wow64State == wow64Uninitialized) {
showMessage(QString::fromLatin1("Checking for wow64 subsystem..."), LogMisc);
return ParseStackWow64;
}
const bool hasFile = !frames.at(i).file.isEmpty();
// jmp-frame hit by step into, do another 't' and abort sequence.
if (!hasFile && i == 0 && sourceStepInto) {
if (frames.at(i).function.contains(QLatin1String("ILT+"))) {
showMessage(QString::fromLatin1("Step into: Call instruction hit, "
"performing additional step..."), LogMisc);
return ParseStackStepInto;
}
showMessage(QString::fromLatin1("Step into: Hit frame with no source, "
"step out..."), LogMisc);
return ParseStackStepOut;
if (frames.at(i).function.contains(QLatin1String("ILT+"))) {
showMessage(QString::fromLatin1("Step into: Call instruction hit, "
"performing additional step..."), LogMisc);
return ParseStackStepInto;
}
showMessage(QString::fromLatin1("Step into: Hit frame with no source, "
"step out..."), LogMisc);
return ParseStackStepOut;
}
if (hasFile) {
const NormalizedSourceFileName fileName = sourceMapNormalizeFileNameFromDebugger(frames.at(i).file);
@@ -2910,7 +2968,10 @@ void CdbEngine::handleStackTrace(const CdbExtensionCommandPtr &command)
if (command->success) {
GdbMi data;
data.fromString(command->reply);
parseStackTrace(data, false);
if (parseStackTrace(data, false) == ParseStackWow64) {
postBuiltinCommand("!wow64exts.info", 0, &CdbEngine::handleCheckWow64,
0, qVariantFromValue(data));
}
postCommandSequence(command->commandSequence);
} else {
showMessage(QString::fromLocal8Bit(command->errorMessage), LogError);
@@ -3145,3 +3206,5 @@ void CdbEngine::handleCustomSpecialStop(const QVariant &v)
} // namespace Internal
} // namespace Debugger
Q_DECLARE_METATYPE(Debugger::Internal::GdbMi)