CDB: Compile, new Disassembler architecture.

This commit is contained in:
Friedemann Kleint
2009-08-17 16:03:27 +02:00
parent 7fb0de70e5
commit 9fe978fe39
9 changed files with 115 additions and 98 deletions

View File

@@ -32,7 +32,6 @@
#include "cdbdebugengine_p.h" #include "cdbdebugengine_p.h"
#include "cdbsymbolgroupcontext.h" #include "cdbsymbolgroupcontext.h"
#include "disassemblerhandler.h"
#include "registerhandler.h" #include "registerhandler.h"
#include <QtCore/QVector> #include <QtCore/QVector>
@@ -40,8 +39,6 @@
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
typedef QList<DisassemblerLine> DisassemblerLineList;
bool getRegisters(CIDebugControl *ctl, bool getRegisters(CIDebugControl *ctl,
CIDebugRegisters *ireg, CIDebugRegisters *ireg,
QList<Register> *registers, QList<Register> *registers,
@@ -90,35 +87,39 @@ bool getRegisters(CIDebugControl *ctl,
// it uses that symbol. // it uses that symbol.
class DisassemblerOutputParser class DisassemblerOutputParser
{ {
Q_DISABLE_COPY(DisassemblerOutputParser)
public: public:
explicit DisassemblerOutputParser(DisassemblerLineList *list); explicit DisassemblerOutputParser(QTextStream &str, int addressFieldWith = 0);
void parse(const QStringList &l); void parse(const QStringList &l);
private: private:
enum ParseResult { ParseOk, ParseIgnore, ParseFailed }; enum ParseResult { ParseOk, ParseIgnore, ParseFailed };
ParseResult parseDisassembled(const QString &in, DisassemblerLine* l); ParseResult parseDisassembled(const QString &in);
DisassemblerLineList *m_list; const int m_addressFieldWith;
QTextStream &m_str;
QString m_sourceSymbol; QString m_sourceSymbol;
int m_sourceSymbolOffset; int m_sourceSymbolOffset;
}; };
DisassemblerOutputParser::DisassemblerOutputParser(DisassemblerLineList *list) : DisassemblerOutputParser::DisassemblerOutputParser(QTextStream &str, int addressFieldWith) :
m_list(list), m_addressFieldWith(addressFieldWith),
m_str(str),
m_sourceSymbolOffset(0) m_sourceSymbolOffset(0)
{ {
} }
// Parse a disassembler line: /* Parse a disassembler line:
// module!class::foo: * \code
// 004017cf cc int 3 module!class::foo:
// 77 mainwindow.cpp 004018ff 8d4da8 lea ecx,[ebp-0x58] 004017cf cc int 3
DisassemblerOutputParser::ParseResult 77 mainwindow.cpp 004018ff 8d4da8 lea ecx,[ebp-0x58]
DisassemblerOutputParser::parseDisassembled(const QString &in, DisassemblerLine* l) \endcode */
{
l->clear();
DisassemblerOutputParser::ParseResult
DisassemblerOutputParser::parseDisassembled(const QString &in)
{
// Check if there is a source file // Check if there is a source file
if (in.size() < 7) if (in.size() < 7)
return ParseIgnore; return ParseIgnore;
@@ -129,9 +130,11 @@ DisassemblerOutputParser::ParseResult
if (simplified.isEmpty()) if (simplified.isEmpty())
return ParseIgnore; return ParseIgnore;
QStringList tokens = simplified.split(QLatin1Char(' '), QString::SkipEmptyParts); const QStringList tokens = simplified.split(QLatin1Char(' '), QString::SkipEmptyParts);
const int tokenCount = tokens.size();
// Check for symbols as 'module!class::foo:' (start of function encountered) // Check for symbols as 'module!class::foo:' (start of function encountered)
if (tokens.size() == 1) { // and store as state.
if (tokenCount == 1) {
QString symbol = tokens.front(); QString symbol = tokens.front();
if (symbol.endsWith(QLatin1Char(':')) && symbol.contains(QLatin1Char('!'))) { if (symbol.endsWith(QLatin1Char(':')) && symbol.contains(QLatin1Char('!'))) {
symbol.truncate(symbol.size() - 1); symbol.truncate(symbol.size() - 1);
@@ -140,51 +143,49 @@ DisassemblerOutputParser::ParseResult
} }
return ParseIgnore; return ParseIgnore;
} }
if (tokens.size() < 2) if (tokenCount < 2)
return ParseIgnore; return ParseIgnore;
// Symbol display: Do we know a symbol? if (tokenCount < 3)
if (!m_sourceSymbol.isEmpty()) { return ParseFailed;
l->symbol = QString(QLatin1Char('<')); // Format line. Start with address with the field width given,
l->symbol += m_sourceSymbol; // which is important for setting the marker.
if (m_sourceSymbolOffset) { const int addressToken = hasSourceFile ? 2 : 0;
l->symbol += QLatin1Char('+'); m_str << "0x";
l->symbol += QString::number(m_sourceSymbolOffset); if (m_str.fieldWidth() == m_addressFieldWith) {
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);
} }
l->symbol += QLatin1Char('>'); m_str << ' ';
// Symbol display: Do we know a symbol? -> Display with offset.
// Else default to source file information.
if (m_sourceSymbol.isEmpty()) {
if (hasSourceFile)
m_str << tokens.at(1) << '+' << tokens.front();
} else {
m_str << '<' << m_sourceSymbol;
if (m_sourceSymbolOffset)
m_str << '+' << m_sourceSymbolOffset;
m_str << '>';
m_sourceSymbolOffset++; m_sourceSymbolOffset++;
} }
// Read source file information: If we don't know a symbol yet, for (int i = addressToken + 1; i < tokenCount; i++)
// use the source file. m_str << ' ' << tokens.at(i);
if (hasSourceFile) { m_str << '\n';
if (l->symbol.isEmpty()) {
l->symbol = tokens.at(1);
l->symbol += QLatin1Char('+');
l->symbol += tokens.front();
}
tokens.pop_front();
tokens.pop_front();
}
l->symbolDisplay = l->symbol;
// Get offset address and instruction
if (tokens.size() < 3)
return ParseFailed;
l->addressDisplay = l->address = tokens.front();
tokens.pop_front();
// The rest is effective address & instructions
if (tokens.size() > 1)
tokens.pop_front();
l->mnemonic = tokens.join(QString(QLatin1Char(' ')));
return ParseOk; return ParseOk;
} }
void DisassemblerOutputParser::parse(const QStringList &l) void DisassemblerOutputParser::parse(const QStringList &l)
{ {
DisassemblerLine dLine;
foreach(const QString &line, l) { foreach(const QString &line, l) {
switch (parseDisassembled(line, &dLine)) { switch (parseDisassembled(line)) {
case ParseOk: case ParseOk:
m_list->push_back(dLine);
break;
case ParseIgnore: case ParseIgnore:
break; break;
case ParseFailed: case ParseFailed:
@@ -199,12 +200,13 @@ bool dissassemble(CIDebugClient *client,
ULONG64 offset, ULONG64 offset,
unsigned long beforeLines, unsigned long beforeLines,
unsigned long afterLines, unsigned long afterLines,
QList<DisassemblerLine> *lines, int addressFieldWith,
QTextStream &str,
QString *errorMessage) QString *errorMessage)
{ {
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << offset; qDebug() << Q_FUNC_INFO << offset;
lines->clear();
const ULONG flags = DEBUG_DISASM_MATCHING_SYMBOLS|DEBUG_DISASM_SOURCE_LINE_NUMBER|DEBUG_DISASM_SOURCE_FILE_NAME; const ULONG flags = DEBUG_DISASM_MATCHING_SYMBOLS|DEBUG_DISASM_SOURCE_LINE_NUMBER|DEBUG_DISASM_SOURCE_FILE_NAME;
// Catch the output by temporarily setting another handler. // Catch the output by temporarily setting another handler.
// We use the method that outputs to the output handler as it // We use the method that outputs to the output handler as it
@@ -219,10 +221,10 @@ bool dissassemble(CIDebugClient *client,
offset, flags, 0, 0, 0, 0); offset, flags, 0, 0, 0, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
*errorMessage= QString::fromLatin1("Unable to dissamble at 0x%1: %2"). *errorMessage= QString::fromLatin1("Unable to dissamble at 0x%1: %2").
arg(QString::number(offset, 16), msgComFailed("OutputDisassemblyLines", hr)); arg(offset, 0, 16).arg(msgComFailed("OutputDisassemblyLines", hr));
return false; return false;
} }
DisassemblerOutputParser parser(lines); DisassemblerOutputParser parser(str, addressFieldWith);
parser.parse(stringHandler.result().split(QLatin1Char('\n'))); parser.parse(stringHandler.result().split(QLatin1Char('\n')));
return true; return true;
} }

View File

@@ -35,11 +35,13 @@
#include "cdbcom.h" #include "cdbcom.h"
QT_BEGIN_NAMESPACE
class QTextStream;
QT_END_NAMESPACE
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
class DisassemblerLine;
// Utilities related to assembler code. // Utilities related to assembler code.
class Register; class Register;
@@ -54,7 +56,8 @@ bool dissassemble(CIDebugClient *client,
ULONG64 offset, ULONG64 offset,
unsigned long beforeLines, unsigned long beforeLines,
unsigned long afterLines, unsigned long afterLines,
QList<DisassemblerLine> *lines, int addressFieldWith /* = 0*/,
QTextStream &str,
QString *errorMessage); QString *errorMessage);
} // namespace Internal } // namespace Internal

View File

@@ -37,6 +37,7 @@
#include "cdbassembler.h" #include "cdbassembler.h"
#include "cdboptionspage.h" #include "cdboptionspage.h"
#include "cdboptions.h" #include "cdboptions.h"
#include "debuggeragents.h"
#include "debuggeractions.h" #include "debuggeractions.h"
#include "debuggermanager.h" #include "debuggermanager.h"
@@ -45,7 +46,6 @@
#include "watchhandler.h" #include "watchhandler.h"
#include "registerhandler.h" #include "registerhandler.h"
#include "moduleshandler.h" #include "moduleshandler.h"
#include "disassemblerhandler.h"
#include "watchutils.h" #include "watchutils.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -1260,35 +1260,48 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent, void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent,
const StackFrame & frame) const StackFrame & frame)
{ {
// was: void CdbDebugEngine::reloadDisassembler()
// use agent->address() to create a listing
/*
enum { ContextLines = 40 }; enum { ContextLines = 40 };
// Do we have a top stack frame? bool ok = false;
const ULONG64 offset = m_d->m_currentStackTrace ? m_d->m_currentStackTrace->instructionOffset() : ULONG64(0);
if (debugCDB)
qDebug() << Q_FUNC_INFO << offset;
DisassemblerHandler *dh = m_d->m_debuggerManagerAccess->disassemblerHandler();
if (offset) {
QList<DisassemblerLine> lines;
QString errorMessage; QString errorMessage;
do {
// get address
QString address;
if (!frame.file.isEmpty())
address = frame.address;
if (address.isEmpty())
address = agent->address();
if (debugCDB)
qDebug() << "fetchDisassembler" << address << " Agent: " << agent->address()
<< " Frame" << frame.file << frame.line << frame.address;
if (address.isEmpty()) { // Clear window
agent->setContents(QString());
ok = true;
break;
}
if (address.startsWith(QLatin1String("0x")))
address.remove(0, 2);
const int addressFieldWith = address.size(); // For the Marker
const ULONG64 offset = address.toULongLong(&ok, 16);
if (!ok) {
errorMessage = QString::fromLatin1("Internal error: Invalid address for disassembly: '%1'.").arg(agent->address());
break;
}
QString disassembly;
QApplication::setOverrideCursor(Qt::WaitCursor); QApplication::setOverrideCursor(Qt::WaitCursor);
const bool drc = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset, ok = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset, addressFieldWith,
ContextLines, ContextLines, &lines, &errorMessage); ContextLines, ContextLines, QTextStream(&disassembly), &errorMessage);
QApplication::restoreOverrideCursor(); QApplication::restoreOverrideCursor();
if (drc) { if (!ok)
dh->setLines(lines); break;
if (lines.size() > ContextLines) agent->setContents(disassembly);
dh->setCurrentLine(ContextLines);
} else { } while (false);
warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
if (!ok) {
agent->setContents(QString());
warning(errorMessage);
} }
} else {
dh->setLines(QList<DisassemblerLine>());
}
*/
} }
void CdbDebugEngine::reloadModules() void CdbDebugEngine::reloadModules()

View File

@@ -81,7 +81,7 @@ STDMETHODIMP CdbDebugOutputBase::Output(
) )
{ {
const QString msg = QString::fromUtf16(reinterpret_cast<const ushort *>(text)); const QString msg = QString::fromUtf16(reinterpret_cast<const ushort *>(text));
output(mask, msg.trimmed()); output(mask, msg);
return S_OK; return S_OK;
} }
@@ -124,10 +124,8 @@ CdbDebugOutput::CdbDebugOutput()
{ {
} }
void CdbDebugOutput::output(ULONG mask, const QString &_msg) void CdbDebugOutput::output(ULONG mask, const QString &msg)
{ {
QString msg = _msg + '\n';
if (debugCDB > 1) if (debugCDB > 1)
qDebug() << Q_FUNC_INFO << "\n " << msg; qDebug() << Q_FUNC_INFO << "\n " << msg;

View File

@@ -47,6 +47,7 @@
#include "moduleshandler.h" #include "moduleshandler.h"
#include "registerhandler.h" #include "registerhandler.h"
#include "stackhandler.h" #include "stackhandler.h"
#include "stackframe.h"
#include "watchhandler.h" #include "watchhandler.h"
#include "debuggerdialogs.h" #include "debuggerdialogs.h"

View File

@@ -76,7 +76,7 @@ class BreakpointData;
class ModulesHandler; class ModulesHandler;
class RegisterHandler; class RegisterHandler;
class SourceFilesWindow; class SourceFilesWindow;
class StackFrame; struct StackFrame;
class StackHandler; class StackHandler;
class Symbol; class Symbol;
class ThreadsHandler; class ThreadsHandler;

View File

@@ -62,7 +62,7 @@ class DebuggerManager;
class DebuggerRunner; class DebuggerRunner;
class DebugMode; class DebugMode;
class DisassemblerViewAgent; class DisassemblerViewAgent;
class StackFrame; struct StackFrame;
class DebuggerPlugin : public ExtensionSystem::IPlugin class DebuggerPlugin : public ExtensionSystem::IPlugin
{ {

View File

@@ -49,7 +49,7 @@ namespace Internal {
class DebuggerStartParameters; class DebuggerStartParameters;
class DisassemblerViewAgent; class DisassemblerViewAgent;
class MemoryViewAgent; class MemoryViewAgent;
class StackFrame; struct StackFrame;
class Symbol; class Symbol;
class WatchData; class WatchData;
@@ -98,8 +98,8 @@ public:
virtual void watchPoint(const QPoint &) {} virtual void watchPoint(const QPoint &) {}
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length) virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length)
{ Q_UNUSED(addr); Q_UNUSED(length); } { Q_UNUSED(addr); Q_UNUSED(length); }
virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame &frame) virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame & /* frame */)
{ Q_UNUSED(frame); } { }
}; };
} // namespace Internal } // namespace Internal

View File

@@ -31,7 +31,7 @@
#define DEBUGGER_STACKFRAME_H #define DEBUGGER_STACKFRAME_H
#include <QtCore/QString> #include <QtCore/QString>
#include <QtCore/QVariant> #include <QtCore/QMetaType>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {