Commit 9fe978fe authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

CDB: Compile, new Disassembler architecture.

parent 7fb0de70
......@@ -32,7 +32,6 @@
#include "cdbdebugengine_p.h"
#include "cdbsymbolgroupcontext.h"
#include "disassemblerhandler.h"
#include "registerhandler.h"
#include <QtCore/QVector>
......@@ -40,8 +39,6 @@
namespace Debugger {
namespace Internal {
typedef QList<DisassemblerLine> DisassemblerLineList;
bool getRegisters(CIDebugControl *ctl,
CIDebugRegisters *ireg,
QList<Register> *registers,
......@@ -90,35 +87,39 @@ bool getRegisters(CIDebugControl *ctl,
// it uses that symbol.
class DisassemblerOutputParser
{
Q_DISABLE_COPY(DisassemblerOutputParser)
public:
explicit DisassemblerOutputParser(DisassemblerLineList *list);
explicit DisassemblerOutputParser(QTextStream &str, int addressFieldWith = 0);
void parse(const QStringList &l);
private:
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;
int m_sourceSymbolOffset;
};
DisassemblerOutputParser::DisassemblerOutputParser(DisassemblerLineList *list) :
m_list(list),
DisassemblerOutputParser::DisassemblerOutputParser(QTextStream &str, int addressFieldWith) :
m_addressFieldWith(addressFieldWith),
m_str(str),
m_sourceSymbolOffset(0)
{
}
// Parse a disassembler line:
// module!class::foo:
// 004017cf cc int 3
// 77 mainwindow.cpp 004018ff 8d4da8 lea ecx,[ebp-0x58]
/* Parse a disassembler line:
* \code
module!class::foo:
004017cf cc int 3
77 mainwindow.cpp 004018ff 8d4da8 lea ecx,[ebp-0x58]
\endcode */
DisassemblerOutputParser::ParseResult
DisassemblerOutputParser::parseDisassembled(const QString &in, DisassemblerLine* l)
DisassemblerOutputParser::parseDisassembled(const QString &in)
{
l->clear();
// Check if there is a source file
if (in.size() < 7)
return ParseIgnore;
......@@ -129,9 +130,11 @@ DisassemblerOutputParser::ParseResult
if (simplified.isEmpty())
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)
if (tokens.size() == 1) {
// and store as state.
if (tokenCount == 1) {
QString symbol = tokens.front();
if (symbol.endsWith(QLatin1Char(':')) && symbol.contains(QLatin1Char('!'))) {
symbol.truncate(symbol.size() - 1);
......@@ -140,51 +143,49 @@ DisassemblerOutputParser::ParseResult
}
return ParseIgnore;
}
if (tokens.size() < 2)
if (tokenCount < 2)
return ParseIgnore;
// Symbol display: Do we know a symbol?
if (!m_sourceSymbol.isEmpty()) {
l->symbol = QString(QLatin1Char('<'));
l->symbol += m_sourceSymbol;
if (m_sourceSymbolOffset) {
l->symbol += QLatin1Char('+');
l->symbol += QString::number(m_sourceSymbolOffset);
}
l->symbol += QLatin1Char('>');
m_sourceSymbolOffset++;
if (tokenCount < 3)
return ParseFailed;
// Format line. Start with address with the field width given,
// which is important for setting the marker.
const int addressToken = hasSourceFile ? 2 : 0;
m_str << "0x";
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);
}
// Read source file information: If we don't know a symbol yet,
// use the source file.
if (hasSourceFile) {
if (l->symbol.isEmpty()) {
l->symbol = tokens.at(1);
l->symbol += QLatin1Char('+');
l->symbol += tokens.front();
}
tokens.pop_front();
tokens.pop_front();
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++;
}
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(' ')));
for (int i = addressToken + 1; i < tokenCount; i++)
m_str << ' ' << tokens.at(i);
m_str << '\n';
return ParseOk;
}
void DisassemblerOutputParser::parse(const QStringList &l)
{
DisassemblerLine dLine;
foreach(const QString &line, l) {
switch (parseDisassembled(line, &dLine)) {
switch (parseDisassembled(line)) {
case ParseOk:
m_list->push_back(dLine);
break;
case ParseIgnore:
break;
case ParseFailed:
......@@ -199,12 +200,13 @@ bool dissassemble(CIDebugClient *client,
ULONG64 offset,
unsigned long beforeLines,
unsigned long afterLines,
QList<DisassemblerLine> *lines,
int addressFieldWith,
QTextStream &str,
QString *errorMessage)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << offset;
lines->clear();
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.
// 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);
if (FAILED(hr)) {
*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;
}
DisassemblerOutputParser parser(lines);
DisassemblerOutputParser parser(str, addressFieldWith);
parser.parse(stringHandler.result().split(QLatin1Char('\n')));
return true;
}
......
......@@ -35,11 +35,13 @@
#include "cdbcom.h"
QT_BEGIN_NAMESPACE
class QTextStream;
QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
class DisassemblerLine;
// Utilities related to assembler code.
class Register;
......@@ -54,7 +56,8 @@ bool dissassemble(CIDebugClient *client,
ULONG64 offset,
unsigned long beforeLines,
unsigned long afterLines,
QList<DisassemblerLine> *lines,
int addressFieldWith /* = 0*/,
QTextStream &str,
QString *errorMessage);
} // namespace Internal
......
......@@ -37,6 +37,7 @@
#include "cdbassembler.h"
#include "cdboptionspage.h"
#include "cdboptions.h"
#include "debuggeragents.h"
#include "debuggeractions.h"
#include "debuggermanager.h"
......@@ -45,7 +46,6 @@
#include "watchhandler.h"
#include "registerhandler.h"
#include "moduleshandler.h"
#include "disassemblerhandler.h"
#include "watchutils.h"
#include <coreplugin/icore.h>
......@@ -1258,37 +1258,50 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
}
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 };
// Do we have a top stack frame?
const ULONG64 offset = m_d->m_currentStackTrace ? m_d->m_currentStackTrace->instructionOffset() : ULONG64(0);
if (debugCDB)
qDebug() << Q_FUNC_INFO << offset;
bool ok = false;
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
DisassemblerHandler *dh = m_d->m_debuggerManagerAccess->disassemblerHandler();
if (offset) {
QList<DisassemblerLine> lines;
QString errorMessage;
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);
const bool drc = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset,
ContextLines, ContextLines, &lines, &errorMessage);
ok = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset, addressFieldWith,
ContextLines, ContextLines, QTextStream(&disassembly), &errorMessage);
QApplication::restoreOverrideCursor();
if (drc) {
dh->setLines(lines);
if (lines.size() > ContextLines)
dh->setCurrentLine(ContextLines);
} else {
warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
}
} else {
dh->setLines(QList<DisassemblerLine>());
if (!ok)
break;
agent->setContents(disassembly);
} while (false);
if (!ok) {
agent->setContents(QString());
warning(errorMessage);
}
*/
}
void CdbDebugEngine::reloadModules()
......
......@@ -81,7 +81,7 @@ STDMETHODIMP CdbDebugOutputBase::Output(
)
{
const QString msg = QString::fromUtf16(reinterpret_cast<const ushort *>(text));
output(mask, msg.trimmed());
output(mask, msg);
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)
qDebug() << Q_FUNC_INFO << "\n " << msg;
......
......@@ -47,6 +47,7 @@
#include "moduleshandler.h"
#include "registerhandler.h"
#include "stackhandler.h"
#include "stackframe.h"
#include "watchhandler.h"
#include "debuggerdialogs.h"
......
......@@ -76,7 +76,7 @@ class BreakpointData;
class ModulesHandler;
class RegisterHandler;
class SourceFilesWindow;
class StackFrame;
struct StackFrame;
class StackHandler;
class Symbol;
class ThreadsHandler;
......
......@@ -62,7 +62,7 @@ class DebuggerManager;
class DebuggerRunner;
class DebugMode;
class DisassemblerViewAgent;
class StackFrame;
struct StackFrame;
class DebuggerPlugin : public ExtensionSystem::IPlugin
{
......
......@@ -49,7 +49,7 @@ namespace Internal {
class DebuggerStartParameters;
class DisassemblerViewAgent;
class MemoryViewAgent;
class StackFrame;
struct StackFrame;
class Symbol;
class WatchData;
......@@ -98,8 +98,8 @@ public:
virtual void watchPoint(const QPoint &) {}
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length)
{ Q_UNUSED(addr); Q_UNUSED(length); }
virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame &frame)
{ Q_UNUSED(frame); }
virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame & /* frame */)
{ }
};
} // namespace Internal
......
......@@ -31,7 +31,7 @@
#define DEBUGGER_STACKFRAME_H
#include <QtCore/QString>
#include <QtCore/QVariant>
#include <QtCore/QMetaType>
namespace Debugger {
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