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