forked from qt-creator/qt-creator
debugger: make gdb-6.8-symbianelf work
This commit is contained in:
@@ -26,8 +26,12 @@ def qmin(n, m):
|
|||||||
return n
|
return n
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
def isGoodGdb():
|
||||||
|
return gdb.VERSION.startswith("6.8.50.2009") \
|
||||||
|
and gdb.VERSION != "6.8.50.20090630-cvs"
|
||||||
|
|
||||||
def parseAndEvaluate(exp):
|
def parseAndEvaluate(exp):
|
||||||
if gdb.VERSION.startswith("6.8.50.2009"):
|
if isGoodGdb():
|
||||||
return gdb.parse_and_eval(exp)
|
return gdb.parse_and_eval(exp)
|
||||||
# Work around non-existing gdb.parse_and_eval as in released 7.0
|
# Work around non-existing gdb.parse_and_eval as in released 7.0
|
||||||
gdb.execute("set logging redirect on")
|
gdb.execute("set logging redirect on")
|
||||||
@@ -41,10 +45,10 @@ def listOfLocals():
|
|||||||
frame = gdb.selected_frame()
|
frame = gdb.selected_frame()
|
||||||
#warn("FRAME %s: " % frame)
|
#warn("FRAME %s: " % frame)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
return ""
|
return []
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
if gdb.VERSION.startswith("6.8.50.2009"):
|
if isGoodGdb():
|
||||||
# archer-tromey-python
|
# archer-tromey-python
|
||||||
block = frame.block()
|
block = frame.block()
|
||||||
while True:
|
while True:
|
||||||
@@ -77,9 +81,11 @@ def listOfLocals():
|
|||||||
|
|
||||||
block = block.superblock
|
block = block.superblock
|
||||||
else:
|
else:
|
||||||
# Assuming gdb 7.0 release.
|
# Assuming gdb 7.0 release or 6.8-symbianelf.
|
||||||
file = tempfile.mkstemp(prefix="gdbpy_")
|
file = tempfile.mkstemp(prefix="gdbpy_")
|
||||||
filename = file[1]
|
filename = file[1]
|
||||||
|
gdb.execute("set logging off")
|
||||||
|
gdb.execute("set logging redirect off")
|
||||||
gdb.execute("set logging file %s" % filename)
|
gdb.execute("set logging file %s" % filename)
|
||||||
gdb.execute("set logging redirect on")
|
gdb.execute("set logging redirect on")
|
||||||
gdb.execute("set logging on")
|
gdb.execute("set logging on")
|
||||||
|
@@ -1244,11 +1244,16 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
|||||||
// signal-meaning="Trace/breakpoint trap",thread-id="2",
|
// signal-meaning="Trace/breakpoint trap",thread-id="2",
|
||||||
// frame={addr="0x7c91120f",func="ntdll!DbgUiConnectToDbg",
|
// frame={addr="0x7c91120f",func="ntdll!DbgUiConnectToDbg",
|
||||||
// args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
|
// args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
|
||||||
//if (reason == "signal-received"
|
// also seen on gdb 6.8-symbianelf without qXfer:libraries:read+;
|
||||||
// && data.findChild("signal-name").data() == "SIGTRAP") {
|
// FIXME: remote.c parses "loaded" reply. It should be turning
|
||||||
// continueInferiorInternal();
|
// that into a TARGET_WAITKIND_LOADED. Does it?
|
||||||
// return;
|
// The bandaid here has the problem that it breaks for 'next' over a
|
||||||
//}
|
// statement that indirectly loads shared libraries
|
||||||
|
if (reason == "signal-received"
|
||||||
|
&& data.findChild("signal-name").data() == "SIGTRAP") {
|
||||||
|
continueInferiorInternal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// jump over well-known frames
|
// jump over well-known frames
|
||||||
static int stepCounter = 0;
|
static int stepCounter = 0;
|
||||||
|
@@ -253,6 +253,7 @@ private: ////////// Gdb Command Management //////////
|
|||||||
CommandsDoneCallback m_commandsDoneCallback;
|
CommandsDoneCallback m_commandsDoneCallback;
|
||||||
|
|
||||||
QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
|
QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
|
||||||
|
int gdbVersion() const { return m_gdbVersion; }
|
||||||
|
|
||||||
private: ////////// Gdb Output, State & Capability Handling //////////
|
private: ////////// Gdb Output, State & Capability Handling //////////
|
||||||
|
|
||||||
|
@@ -147,6 +147,7 @@ void Snapshot::reset()
|
|||||||
memory.clear();
|
memory.clear();
|
||||||
for (int i = 0; i < RegisterCount; ++i)
|
for (int i = 0; i < RegisterCount; ++i)
|
||||||
registers[i] = 0;
|
registers[i] = 0;
|
||||||
|
registerValid = false;
|
||||||
wantedMemory = MemoryRange();
|
wantedMemory = MemoryRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,9 +198,11 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
|||||||
m_running(false),
|
m_running(false),
|
||||||
m_trkDevice(new trk::TrkDevice),
|
m_trkDevice(new trk::TrkDevice),
|
||||||
m_gdbAckMode(true),
|
m_gdbAckMode(true),
|
||||||
m_verbose(0),
|
m_verbose(0)
|
||||||
m_bufferedMemoryRead(true)
|
|
||||||
{
|
{
|
||||||
|
m_bufferedMemoryRead = false;
|
||||||
|
m_bufferedMemoryRead = true;
|
||||||
|
|
||||||
const QByteArray trkVerbose = qgetenv("QTC_TRK_VERBOSE");
|
const QByteArray trkVerbose = qgetenv("QTC_TRK_VERBOSE");
|
||||||
if (!trkVerbose.isEmpty()) {
|
if (!trkVerbose.isEmpty()) {
|
||||||
bool ok;
|
bool ok;
|
||||||
@@ -210,6 +213,7 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
|||||||
|
|
||||||
m_gdbServer = 0;
|
m_gdbServer = 0;
|
||||||
m_gdbConnection = 0;
|
m_gdbConnection = 0;
|
||||||
|
m_snapshot.reset();
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
const DWORD portOffset = GetCurrentProcessId() % 100;
|
const DWORD portOffset = GetCurrentProcessId() % 100;
|
||||||
#else
|
#else
|
||||||
@@ -388,11 +392,11 @@ void TrkGdbAdapter::slotEmitDelayedInferiorStartFailed()
|
|||||||
void TrkGdbAdapter::logMessage(const QString &msg)
|
void TrkGdbAdapter::logMessage(const QString &msg)
|
||||||
{
|
{
|
||||||
if (m_verbose) {
|
if (m_verbose) {
|
||||||
#ifdef STANDALONE_RUNNER
|
//#ifdef STANDALONE_RUNNER
|
||||||
emit output(msg);
|
// emit output(msg);
|
||||||
#else
|
//#else
|
||||||
m_engine->debugMessage(msg);
|
m_engine->debugMessage("TRK LOG: " + msg);
|
||||||
#endif
|
//#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,9 +633,15 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
|||||||
|
|
||||||
else if (cmd == "g") {
|
else if (cmd == "g") {
|
||||||
// Read general registers.
|
// Read general registers.
|
||||||
logMessage(msgGdbPacket(QLatin1String("Read registers")));
|
if (m_snapshot.registerValid) {
|
||||||
sendGdbServerAck();
|
logMessage(msgGdbPacket(QLatin1String("Read registers")));
|
||||||
reportRegisters();
|
sendGdbServerAck();
|
||||||
|
reportRegisters();
|
||||||
|
} else {
|
||||||
|
sendTrkMessage(0x12,
|
||||||
|
TrkCB(handleAndReportReadRegisters),
|
||||||
|
trkReadRegistersMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (cmd.startsWith("Hc")) {
|
else if (cmd.startsWith("Hc")) {
|
||||||
@@ -692,21 +702,27 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
|||||||
sendGdbServerAck();
|
sendGdbServerAck();
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
const uint registerNumber = cmd.mid(1).toInt(&ok, 16);
|
const uint registerNumber = cmd.mid(1).toInt(&ok, 16);
|
||||||
QByteArray logMsg = "Read Register";
|
if (m_snapshot.registerValid) {
|
||||||
if (registerNumber == RegisterPSGdb) {
|
QByteArray logMsg = "Read Register";
|
||||||
QByteArray ba;
|
if (registerNumber == RegisterPSGdb) {
|
||||||
appendInt(&ba, m_snapshot.registers[RegisterPSTrk], LittleEndian);
|
QByteArray ba;
|
||||||
logMsg += dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk]);
|
appendInt(&ba, m_snapshot.registers[RegisterPSTrk], LittleEndian);
|
||||||
sendGdbServerMessage(ba.toHex(), logMsg);
|
logMsg += dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk]);
|
||||||
} else if (registerNumber < 16) {
|
sendGdbServerMessage(ba.toHex(), logMsg);
|
||||||
QByteArray ba;
|
} else if (registerNumber < 16) {
|
||||||
appendInt(&ba, m_snapshot.registers[registerNumber], LittleEndian);
|
QByteArray ba;
|
||||||
logMsg += dumpRegister(registerNumber, m_snapshot.registers[registerNumber]);
|
appendInt(&ba, m_snapshot.registers[registerNumber], LittleEndian);
|
||||||
sendGdbServerMessage(ba.toHex(), logMsg);
|
logMsg += dumpRegister(registerNumber, m_snapshot.registers[registerNumber]);
|
||||||
|
sendGdbServerMessage(ba.toHex(), logMsg);
|
||||||
|
} else {
|
||||||
|
sendGdbServerMessage("0000", "read single unknown register #"
|
||||||
|
+ QByteArray::number(registerNumber));
|
||||||
|
//sendGdbServerMessage("E01", "read single unknown register");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sendGdbServerMessage("0000", "read single unknown register #"
|
sendTrkMessage(0x12,
|
||||||
+ QByteArray::number(registerNumber));
|
TrkCB(handleAndReportReadRegister),
|
||||||
//sendGdbServerMessage("E01", "read single unknown register");
|
trkReadRegistersMessage(), registerNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,18 +831,42 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
|||||||
else if (cmd.startsWith("qXfer:features:read:target.xml:")) {
|
else if (cmd.startsWith("qXfer:features:read:target.xml:")) {
|
||||||
// $qXfer:features:read:target.xml:0,7ca#46...Ack
|
// $qXfer:features:read:target.xml:0,7ca#46...Ack
|
||||||
sendGdbServerAck();
|
sendGdbServerAck();
|
||||||
sendGdbServerMessage("l<target><architecture>symbianelf</architecture></target>");
|
//sendGdbServerMessage("l<target><architecture>symbianelf</architecture></target>");
|
||||||
|
sendGdbServerMessage("l<target><architecture>arm</architecture></target>");
|
||||||
|
//sendGdbServerMessage("l<target><architecture>arm-none-symbianelf</architecture></target>");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (cmd == "qfThreadInfo") {
|
||||||
|
// That's the _first_ query package.
|
||||||
|
sendGdbServerAck();
|
||||||
|
if (!m_session.threads.isEmpty()) {
|
||||||
|
QByteArray response = "m";
|
||||||
|
// FIXME: Limit packet length by using qsThreadInfo packages?
|
||||||
|
qDebug() << "CURRENT THREAD: " << m_session.tid;
|
||||||
|
response += hexNumber(m_session.tid);
|
||||||
|
sendGdbServerMessage(response, "thread information transfered");
|
||||||
|
} else {
|
||||||
|
sendGdbServerMessage("l", "thread information transfer finished");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (cmd == "qsThreadInfo") {
|
||||||
|
// That's a following query package
|
||||||
|
sendGdbServerAck();
|
||||||
|
sendGdbServerMessage("l", "thread information transfer finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (cmd.startsWith("qXfer:libraries:read")) {
|
else if (cmd.startsWith("qXfer:libraries:read")) {
|
||||||
sendGdbServerAck();
|
sendGdbServerAck();
|
||||||
/*
|
QByteArray response = "l<library-list>";
|
||||||
<library-list>
|
for (int i = 0; i != m_session.libraries.size(); ++i) {
|
||||||
<library name="/lib/libc.so.6">
|
const Library &lib = m_session.libraries.at(i);
|
||||||
<segment address="0x10000000"/>
|
response += "<library name=\"" + lib.name + "\">";
|
||||||
</library>
|
response += "<segment address=\"0x" + hexNumber(lib.codeseg) + "\"/>";
|
||||||
</library-list>
|
response += "</library>";
|
||||||
i */
|
}
|
||||||
|
response += "</library-list>";
|
||||||
|
sendGdbServerMessage(response, "library information transfered");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (cmd == "QStartNoAckMode") {
|
else if (cmd == "QStartNoAckMode") {
|
||||||
@@ -855,6 +895,13 @@ i */
|
|||||||
sendTrkMessage(0x19, TrkCB(handleStepInto), ba, "Step range");
|
sendTrkMessage(0x19, TrkCB(handleStepInto), ba, "Step range");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (cmd.startsWith('T')) {
|
||||||
|
// FIXME: check whether thread is alive
|
||||||
|
sendGdbServerAck();
|
||||||
|
sendGdbServerMessage("OK"); // pretend all is well
|
||||||
|
//sendGdbServerMessage("E nn");
|
||||||
|
}
|
||||||
|
|
||||||
else if (cmd == "vCont?") {
|
else if (cmd == "vCont?") {
|
||||||
// actions supported by the vCont packet
|
// actions supported by the vCont packet
|
||||||
sendGdbServerAck();
|
sendGdbServerAck();
|
||||||
@@ -908,7 +955,7 @@ i */
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:")) {
|
else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:")) {
|
||||||
QByteArray data = cmd.mid(1 + cmd.indexOf(':'));
|
QByteArray data = cmd.mid(1 + cmd.indexOf(':'));
|
||||||
// "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux)
|
// "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux)
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
if (data.startsWith("auxv:read::")) {
|
if (data.startsWith("auxv:read::")) {
|
||||||
@@ -928,6 +975,7 @@ i */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // auxv read
|
} // auxv read
|
||||||
|
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ")
|
const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ")
|
||||||
+ QString::fromAscii(cmd);
|
+ QString::fromAscii(cmd);
|
||||||
@@ -1136,7 +1184,7 @@ void TrkGdbAdapter::handleDeleteProcess2(const TrkResult &result)
|
|||||||
|
|
||||||
void TrkGdbAdapter::handleReadRegisters(const TrkResult &result)
|
void TrkGdbAdapter::handleReadRegisters(const TrkResult &result)
|
||||||
{
|
{
|
||||||
logMessage(" RESULT: " + result.toString());
|
logMessage(" REGISTER RESULT: " + result.toString());
|
||||||
// [80 0B 00 00 00 00 00 C9 24 FF BC 00 00 00 00 00
|
// [80 0B 00 00 00 00 00 C9 24 FF BC 00 00 00 00 00
|
||||||
// 60 00 00 00 00 00 00 78 67 79 70 00 00 00 00 00...]
|
// 60 00 00 00 00 00 00 78 67 79 70 00 00 00 00 00...]
|
||||||
if (result.errorCode()) {
|
if (result.errorCode()) {
|
||||||
@@ -1146,6 +1194,7 @@ void TrkGdbAdapter::handleReadRegisters(const TrkResult &result)
|
|||||||
const char *data = result.data.data() + 1; // Skip ok byte
|
const char *data = result.data.data() + 1; // Skip ok byte
|
||||||
for (int i = 0; i < RegisterCount; ++i)
|
for (int i = 0; i < RegisterCount; ++i)
|
||||||
m_snapshot.registers[i] = extractInt(data + 4 * i);
|
m_snapshot.registers[i] = extractInt(data + 4 * i);
|
||||||
|
m_snapshot.registerValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleWriteRegister(const TrkResult &result)
|
void TrkGdbAdapter::handleWriteRegister(const TrkResult &result)
|
||||||
@@ -1176,6 +1225,34 @@ void TrkGdbAdapter::reportRegisters()
|
|||||||
sendGdbServerMessage(ba, logMsg);
|
sendGdbServerMessage(ba, logMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrkGdbAdapter::handleAndReportReadRegisters(const TrkResult &result)
|
||||||
|
{
|
||||||
|
handleReadRegisters(result);
|
||||||
|
reportRegisters();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrkGdbAdapter::handleAndReportReadRegister(const TrkResult &result)
|
||||||
|
{
|
||||||
|
handleReadRegisters(result);
|
||||||
|
int registerNumber = result.cookie.toInt();
|
||||||
|
QByteArray logMsg = "Read Register";
|
||||||
|
if (registerNumber == RegisterPSGdb) {
|
||||||
|
QByteArray ba;
|
||||||
|
appendInt(&ba, m_snapshot.registers[RegisterPSTrk], LittleEndian);
|
||||||
|
logMsg += dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk]);
|
||||||
|
sendGdbServerMessage(ba.toHex(), logMsg);
|
||||||
|
} else if (registerNumber < 16) {
|
||||||
|
QByteArray ba;
|
||||||
|
appendInt(&ba, m_snapshot.registers[registerNumber], LittleEndian);
|
||||||
|
logMsg += dumpRegister(registerNumber, m_snapshot.registers[registerNumber]);
|
||||||
|
sendGdbServerMessage(ba.toHex(), logMsg);
|
||||||
|
} else {
|
||||||
|
sendGdbServerMessage("0000", "read single unknown register #"
|
||||||
|
+ QByteArray::number(registerNumber));
|
||||||
|
//sendGdbServerMessage("E01", "read single unknown register");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void appendRegister(QByteArray *ba, uint regno, uint value)
|
static void appendRegister(QByteArray *ba, uint regno, uint value)
|
||||||
{
|
{
|
||||||
ba->append(hexNumber(regno, 2));
|
ba->append(hexNumber(regno, 2));
|
||||||
@@ -1312,7 +1389,7 @@ void TrkGdbAdapter::tryAnswerGdbMemoryRequest(bool buffered)
|
|||||||
logMessage(_("Requesting buffered memory %1 bytes from 0x%2")
|
logMessage(_("Requesting buffered memory %1 bytes from 0x%2")
|
||||||
.arg(MemoryChunkSize).arg(blockaddr, 0, 16));
|
.arg(MemoryChunkSize).arg(blockaddr, 0, 16));
|
||||||
MemoryRange range(blockaddr, blockaddr + MemoryChunkSize);
|
MemoryRange range(blockaddr, blockaddr + MemoryChunkSize);
|
||||||
MEMORY_DEBUGX(" FETCH MEMORY : " << range);
|
MEMORY_DEBUG(" FETCH MEMORY : " << range);
|
||||||
sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered),
|
sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered),
|
||||||
trkReadMemoryMessage(range),
|
trkReadMemoryMessage(range),
|
||||||
QVariant::fromValue(range));
|
QVariant::fromValue(range));
|
||||||
@@ -1323,7 +1400,7 @@ void TrkGdbAdapter::tryAnswerGdbMemoryRequest(bool buffered)
|
|||||||
sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
|
sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
|
||||||
trkReadMemoryMessage(needed),
|
trkReadMemoryMessage(needed),
|
||||||
QVariant::fromValue(needed));
|
QVariant::fromValue(needed));
|
||||||
MEMORY_DEBUGX(" FETCH MEMORY : " << needed);
|
MEMORY_DEBUG(" FETCH MEMORY : " << needed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -92,6 +92,7 @@ struct Snapshot
|
|||||||
void insertMemory(const MemoryRange &range, const QByteArray &ba);
|
void insertMemory(const MemoryRange &range, const QByteArray &ba);
|
||||||
|
|
||||||
uint registers[RegisterCount];
|
uint registers[RegisterCount];
|
||||||
|
bool registerValid;
|
||||||
typedef QMap<MemoryRange, QByteArray> Memory;
|
typedef QMap<MemoryRange, QByteArray> Memory;
|
||||||
Memory memory;
|
Memory memory;
|
||||||
|
|
||||||
@@ -204,6 +205,8 @@ private:
|
|||||||
void handleDeleteProcess(const TrkResult &result);
|
void handleDeleteProcess(const TrkResult &result);
|
||||||
void handleDeleteProcess2(const TrkResult &result);
|
void handleDeleteProcess2(const TrkResult &result);
|
||||||
void handleAndReportCreateProcess(const TrkResult &result);
|
void handleAndReportCreateProcess(const TrkResult &result);
|
||||||
|
void handleAndReportReadRegisters(const TrkResult &result);
|
||||||
|
void handleAndReportReadRegister(const TrkResult &result);
|
||||||
void handleAndReportReadRegistersAfterStop(const TrkResult &result);
|
void handleAndReportReadRegistersAfterStop(const TrkResult &result);
|
||||||
void reportRegisters();
|
void reportRegisters();
|
||||||
QByteArray memoryReadLogMessage(uint addr, const QByteArray &ba) const;
|
QByteArray memoryReadLogMessage(uint addr, const QByteArray &ba) const;
|
||||||
|
Reference in New Issue
Block a user