forked from qt-creator/qt-creator
CDB: Make disassembly work.
This commit is contained in:
@@ -36,6 +36,23 @@
|
||||
|
||||
#include <QtCore/QVector>
|
||||
|
||||
// Format a hex address with a given field width if possible. Convert
|
||||
// to number to ensure it is not truncated should it be larger than the
|
||||
// field width.
|
||||
static inline void formatAddress(QTextStream &str, const QString &hexAddressS, int fieldWidth)
|
||||
{
|
||||
const QChar oldPadChar = str.padChar();
|
||||
const int oldFieldWidth = str.fieldWidth();
|
||||
const int oldIntegerBase = str.integerBase();
|
||||
str.setFieldWidth(fieldWidth);
|
||||
str.setPadChar(QLatin1Char('0'));
|
||||
str.setIntegerBase(16);
|
||||
str << hexAddressS.toULongLong(0, 16);
|
||||
str.setFieldWidth(oldFieldWidth);
|
||||
str.setPadChar(oldPadChar);
|
||||
str.setIntegerBase(oldIntegerBase);
|
||||
}
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -89,7 +106,7 @@ class DisassemblerOutputParser
|
||||
{
|
||||
Q_DISABLE_COPY(DisassemblerOutputParser)
|
||||
public:
|
||||
explicit DisassemblerOutputParser(QTextStream &str, int addressFieldWith = 0);
|
||||
explicit DisassemblerOutputParser(QTextStream &str, int addressFieldWidth = 0);
|
||||
|
||||
void parse(const QStringList &l);
|
||||
|
||||
@@ -97,14 +114,14 @@ private:
|
||||
enum ParseResult { ParseOk, ParseIgnore, ParseFailed };
|
||||
ParseResult parseDisassembled(const QString &in);
|
||||
|
||||
const int m_addressFieldWith;
|
||||
const int m_addressFieldWidth;
|
||||
QTextStream &m_str;
|
||||
QString m_sourceSymbol;
|
||||
int m_sourceSymbolOffset;
|
||||
};
|
||||
|
||||
DisassemblerOutputParser::DisassemblerOutputParser(QTextStream &str, int addressFieldWith) :
|
||||
m_addressFieldWith(addressFieldWith),
|
||||
DisassemblerOutputParser::DisassemblerOutputParser(QTextStream &str, int addressFieldWidth) :
|
||||
m_addressFieldWidth(addressFieldWidth),
|
||||
m_str(str),
|
||||
m_sourceSymbolOffset(0)
|
||||
{
|
||||
@@ -151,16 +168,10 @@ DisassemblerOutputParser::ParseResult
|
||||
// which is important for setting the marker.
|
||||
const int addressToken = hasSourceFile ? 2 : 0;
|
||||
m_str << "0x";
|
||||
if (m_str.fieldWidth() == m_addressFieldWith) {
|
||||
if (m_str.fieldWidth() == m_addressFieldWidth) {
|
||||
m_str << tokens.at(addressToken);
|
||||
} else {
|
||||
const QChar oldPadChar = m_str.padChar();
|
||||
const int oldFieldWidth = m_str.fieldWidth();
|
||||
m_str.setFieldWidth(m_addressFieldWith);
|
||||
m_str.setPadChar(QLatin1Char('0'));
|
||||
m_str << tokens.at(addressToken);
|
||||
m_str.setFieldWidth(oldFieldWidth);
|
||||
m_str.setPadChar(oldPadChar);
|
||||
formatAddress(m_str, tokens.at(addressToken), m_addressFieldWidth);
|
||||
}
|
||||
m_str << ' ';
|
||||
// Symbol display: Do we know a symbol? -> Display with offset.
|
||||
@@ -200,7 +211,7 @@ bool dissassemble(CIDebugClient *client,
|
||||
ULONG64 offset,
|
||||
unsigned long beforeLines,
|
||||
unsigned long afterLines,
|
||||
int addressFieldWith,
|
||||
int addressFieldWidth,
|
||||
QTextStream &str,
|
||||
QString *errorMessage)
|
||||
{
|
||||
@@ -224,7 +235,7 @@ bool dissassemble(CIDebugClient *client,
|
||||
arg(offset, 0, 16).arg(msgComFailed("OutputDisassemblyLines", hr));
|
||||
return false;
|
||||
}
|
||||
DisassemblerOutputParser parser(str, addressFieldWith);
|
||||
DisassemblerOutputParser parser(str, addressFieldWidth);
|
||||
parser.parse(stringHandler.result().split(QLatin1Char('\n')));
|
||||
return true;
|
||||
}
|
||||
|
@@ -56,7 +56,7 @@ bool dissassemble(CIDebugClient *client,
|
||||
ULONG64 offset,
|
||||
unsigned long beforeLines,
|
||||
unsigned long afterLines,
|
||||
int addressFieldWith /* = 0*/,
|
||||
int addressFieldWidth /* = 0*/,
|
||||
QTextStream &str,
|
||||
QString *errorMessage);
|
||||
|
||||
|
@@ -330,7 +330,7 @@ bool CdbDebugEnginePrivate::init(QString *errorMessage)
|
||||
return false;
|
||||
}
|
||||
|
||||
m_cif.debugControl->SetCodeLevel(DEBUG_LEVEL_SOURCE);
|
||||
setCodeLevel();
|
||||
|
||||
hr = lib.debugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_cif.debugSystemObjects));
|
||||
if (FAILED(hr)) {
|
||||
@@ -382,6 +382,34 @@ IDebuggerEngine *CdbDebugEngine::create(DebuggerManager *parent,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Adapt code level setting to the setting of the action.
|
||||
static inline const char *codeLevelName(ULONG level)
|
||||
{
|
||||
return level == DEBUG_LEVEL_ASSEMBLY ? "assembly" : "source";
|
||||
}
|
||||
|
||||
bool CdbDebugEnginePrivate::setCodeLevel()
|
||||
{
|
||||
const ULONG codeLevel = theDebuggerBoolSetting(StepByInstruction) ?
|
||||
DEBUG_LEVEL_ASSEMBLY : DEBUG_LEVEL_SOURCE;
|
||||
ULONG currentCodeLevel = DEBUG_LEVEL_ASSEMBLY;
|
||||
HRESULT hr = m_cif.debugControl->GetCodeLevel(¤tCodeLevel);
|
||||
if (FAILED(hr)) {
|
||||
m_engine->warning(QString::fromLatin1("Cannot determine code level: %1").arg(msgComFailed("GetCodeLevel", hr)));
|
||||
return true;
|
||||
}
|
||||
if (debugCDB)
|
||||
qDebug() << Q_FUNC_INFO << "\nSetting code level to " << codeLevelName(codeLevel) << " (was" << codeLevelName(currentCodeLevel) << ')';
|
||||
if (currentCodeLevel == currentCodeLevel)
|
||||
return false;
|
||||
hr = m_cif.debugControl->SetCodeLevel(codeLevel);
|
||||
if (FAILED(hr)) {
|
||||
m_engine->warning(QString::fromLatin1("Cannot set code level: %1").arg(msgComFailed("SetCodeLevel", hr)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
|
||||
{
|
||||
cleanStackTrace();
|
||||
@@ -565,6 +593,7 @@ bool CdbDebugEngine::startDebugger(const QSharedPointer<DebuggerStartParameters>
|
||||
bool rc = false;
|
||||
bool needWatchTimer = false;
|
||||
m_d->clearForRun();
|
||||
m_d->setCodeLevel();
|
||||
switch (mode) {
|
||||
case AttachExternal:
|
||||
case AttachCrashedExternal:
|
||||
@@ -863,6 +892,7 @@ void CdbDebugEngine::stepExec()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_d->clearForRun();
|
||||
m_d->setCodeLevel();
|
||||
const HRESULT hr = m_d->m_cif.debugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO);
|
||||
if (FAILED(hr))
|
||||
warning(msgFunctionFailed(Q_FUNC_INFO, msgComFailed("SetExecutionStatus", hr)));
|
||||
@@ -919,6 +949,7 @@ void CdbDebugEngine::nextExec()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_d->clearForRun();
|
||||
m_d->setCodeLevel();
|
||||
const HRESULT hr = m_d->m_cif.debugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER);
|
||||
if (SUCCEEDED(hr)) {
|
||||
startWatchTimer();
|
||||
@@ -938,6 +969,7 @@ void CdbDebugEngine::nextIExec()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_d->clearForRun();
|
||||
m_d->setCodeLevel();
|
||||
const HRESULT hr = m_d->m_cif.debugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
|
||||
if (SUCCEEDED(hr)) {
|
||||
startWatchTimer();
|
||||
@@ -987,6 +1019,7 @@ bool CdbDebugEnginePrivate::continueInferior(QString *errorMessage)
|
||||
}
|
||||
|
||||
clearForRun();
|
||||
setCodeLevel();
|
||||
m_engine->killWatchTimer();
|
||||
m_debuggerManager->resetLocation();
|
||||
m_debuggerManagerAccess->notifyInferiorRunningRequested();
|
||||
@@ -1289,8 +1322,8 @@ void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent,
|
||||
}
|
||||
QString disassembly;
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
ok = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset, addressFieldWith,
|
||||
ContextLines, ContextLines, QTextStream(&disassembly), &errorMessage);
|
||||
ok = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset,
|
||||
ContextLines, ContextLines, addressFieldWith, QTextStream(&disassembly), &errorMessage);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (!ok)
|
||||
break;
|
||||
|
@@ -146,6 +146,8 @@ struct CdbDebugEnginePrivate
|
||||
QStringList symbolPaths() const;
|
||||
bool setSymbolPaths(const QStringList &s, QString *errorMessage);
|
||||
|
||||
bool setCodeLevel();
|
||||
|
||||
const QSharedPointer<CdbOptions> m_options;
|
||||
HANDLE m_hDebuggeeProcess;
|
||||
HANDLE m_hDebuggeeThread;
|
||||
|
Reference in New Issue
Block a user