forked from qt-creator/qt-creator
Trk/Launcher: Add infrastructure for reporting crashes.
currently used for runonphone only. Initial-patch-by: Shane Kearns <shane.kearns@accenture.com>
This commit is contained in:
@@ -200,6 +200,7 @@ void TcfTrkGdbAdapter::handleTcfTrkRunControlModuleLoadContextSuspendedEvent(con
|
|||||||
library.name = minfo.name;
|
library.name = minfo.name;
|
||||||
library.codeseg = minfo.codeAddress;
|
library.codeseg = minfo.codeAddress;
|
||||||
library.dataseg = minfo.dataAddress;
|
library.dataseg = minfo.dataAddress;
|
||||||
|
library.pid = tcftrk::RunControlContext::processIdFromTcdfId(se.id());
|
||||||
m_session.libraries.push_back(library);
|
m_session.libraries.push_back(library);
|
||||||
} else {
|
} else {
|
||||||
const int index = m_session.modules.indexOf(moduleName);
|
const int index = m_session.modules.indexOf(moduleName);
|
||||||
|
|||||||
@@ -164,18 +164,7 @@ QByteArray TrkGdbAdapter::trkContinueMessage(uint threadId)
|
|||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray TrkGdbAdapter::trkReadRegistersMessage()
|
QByteArray TrkGdbAdapter::trkWriteRegisterMessage(trk::byte reg, uint value)
|
||||||
{
|
|
||||||
QByteArray ba;
|
|
||||||
appendByte(&ba, 0); // Register set, only 0 supported
|
|
||||||
appendShort(&ba, 0);
|
|
||||||
appendShort(&ba, RegisterCount - 1); // last register
|
|
||||||
appendInt(&ba, m_session.pid);
|
|
||||||
appendInt(&ba, m_session.tid);
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray TrkGdbAdapter::trkWriteRegisterMessage(trk::byte reg, uint value)
|
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
appendByte(&ba, 0); // ?
|
appendByte(&ba, 0); // ?
|
||||||
@@ -187,21 +176,9 @@ QByteArray TrkGdbAdapter::trkReadRegistersMessage()
|
|||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray TrkGdbAdapter::trkReadMemoryMessage(uint from, uint len)
|
|
||||||
{
|
|
||||||
QByteArray ba;
|
|
||||||
ba.reserve(11);
|
|
||||||
appendByte(&ba, 0x08); // Options, FIXME: why?
|
|
||||||
appendShort(&ba, len);
|
|
||||||
appendInt(&ba, from);
|
|
||||||
appendInt(&ba, m_session.pid);
|
|
||||||
appendInt(&ba, m_session.tid);
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray TrkGdbAdapter::trkReadMemoryMessage(const MemoryRange &range)
|
QByteArray TrkGdbAdapter::trkReadMemoryMessage(const MemoryRange &range)
|
||||||
{
|
{
|
||||||
return trkReadMemoryMessage(range.from, range.size());
|
return trk::Launcher::readMemoryMessage(m_session.pid, m_session.tid, range.from, range.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray TrkGdbAdapter::trkWriteMemoryMessage(uint addr, const QByteArray &data)
|
QByteArray TrkGdbAdapter::trkWriteMemoryMessage(uint addr, const QByteArray &data)
|
||||||
@@ -539,7 +516,7 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
|||||||
sendGdbServerAck();
|
sendGdbServerAck();
|
||||||
sendTrkMessage(0x12,
|
sendTrkMessage(0x12,
|
||||||
TrkCB(handleAndReportReadRegisters),
|
TrkCB(handleAndReportReadRegisters),
|
||||||
trkReadRegistersMessage());
|
Launcher::readRegistersMessage(m_session.pid, m_session.tid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,7 +526,7 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
|||||||
m_snapshot.setRegistersValid(m_session.tid, false);
|
m_snapshot.setRegistersValid(m_session.tid, false);
|
||||||
sendTrkMessage(0x12,
|
sendTrkMessage(0x12,
|
||||||
TrkCB(handleAndReportReadRegisters),
|
TrkCB(handleAndReportReadRegisters),
|
||||||
trkReadRegistersMessage());
|
Launcher::readRegistersMessage(m_session.pid, m_session.tid));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (cmd.startsWith("salstep,")) {
|
else if (cmd.startsWith("salstep,")) {
|
||||||
@@ -611,7 +588,7 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
|||||||
//qDebug() << "Fetching single register";
|
//qDebug() << "Fetching single register";
|
||||||
sendTrkMessage(0x12,
|
sendTrkMessage(0x12,
|
||||||
TrkCB(handleAndReportReadRegister),
|
TrkCB(handleAndReportReadRegister),
|
||||||
trkReadRegistersMessage(), registerNumber);
|
Launcher::readRegistersMessage(m_session.pid, m_session.tid), registerNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,7 +955,7 @@ void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
|
|||||||
//qDebug() << "Auto-fetching registers";
|
//qDebug() << "Auto-fetching registers";
|
||||||
sendTrkMessage(0x12,
|
sendTrkMessage(0x12,
|
||||||
TrkCB(handleAndReportReadRegistersAfterStop),
|
TrkCB(handleAndReportReadRegistersAfterStop),
|
||||||
trkReadRegistersMessage());
|
Launcher::readRegistersMessage(m_session.pid, m_session.tid));
|
||||||
# else
|
# else
|
||||||
// As a source-line step typically consists of
|
// As a source-line step typically consists of
|
||||||
// several instruction steps, better avoid the multiple
|
// several instruction steps, better avoid the multiple
|
||||||
@@ -1018,27 +995,19 @@ void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
|
|||||||
const trk::byte error = result.data.at(0);
|
const trk::byte error = result.data.at(0);
|
||||||
// type: 1 byte; for dll item, this value is 2.
|
// type: 1 byte; for dll item, this value is 2.
|
||||||
const trk::byte type = result.data.at(1);
|
const trk::byte type = result.data.at(1);
|
||||||
const uint pid = extractInt(data + 2);
|
|
||||||
const uint tid = extractInt(data + 6);
|
const uint tid = extractInt(data + 6);
|
||||||
const uint codeseg = extractInt(data + 10);
|
const Library lib = Library(result);
|
||||||
const uint dataseg = extractInt(data + 14);
|
m_session.libraries.push_back(lib);
|
||||||
const uint len = extractShort(data + 18);
|
m_session.modules += QString::fromAscii(lib.name);
|
||||||
const QByteArray name = result.data.mid(20, len); // library name
|
|
||||||
m_session.modules += QString::fromAscii(name);
|
|
||||||
QString logMsg;
|
QString logMsg;
|
||||||
QTextStream str(&logMsg);
|
QTextStream str(&logMsg);
|
||||||
str << prefix << " NOTE: LIBRARY LOAD: token=" << result.token;
|
str << prefix << " NOTE: LIBRARY LOAD: token=" << result.token;
|
||||||
if (error)
|
if (error)
|
||||||
str << " ERROR: " << int(error);
|
str << " ERROR: " << int(error);
|
||||||
str << " TYPE: " << int(type) << " PID: " << pid << " TID: " << tid;
|
str << " TYPE: " << int(type) << " PID: " << lib.pid << " TID: " << tid;
|
||||||
str << " CODE: " << hexxNumber(codeseg);
|
str << " CODE: " << hexxNumber(lib.codeseg);
|
||||||
str << " DATA: " << hexxNumber(dataseg);
|
str << " DATA: " << hexxNumber(lib.dataseg);
|
||||||
str << " NAME: '" << name << '\'';
|
str << " NAME: '" << lib.name << '\'';
|
||||||
Library lib;
|
|
||||||
lib.name = name;
|
|
||||||
lib.codeseg = codeseg;
|
|
||||||
lib.dataseg = dataseg;
|
|
||||||
m_session.libraries.append(lib);
|
|
||||||
if (tid && tid != unsigned(-1) && m_snapshot.indexOfThread(tid) == -1)
|
if (tid && tid != unsigned(-1) && m_snapshot.indexOfThread(tid) == -1)
|
||||||
m_snapshot.addThread(tid);
|
m_snapshot.addThread(tid);
|
||||||
logMessage(logMsg);
|
logMessage(logMsg);
|
||||||
@@ -1365,7 +1334,7 @@ void TrkGdbAdapter::handleStep(const TrkResult &result)
|
|||||||
// making some progress through a 'step'.
|
// making some progress through a 'step'.
|
||||||
//sendTrkMessage(0x12,
|
//sendTrkMessage(0x12,
|
||||||
// TrkCB(handleAndReportReadRegistersAfterStop),
|
// TrkCB(handleAndReportReadRegistersAfterStop),
|
||||||
// trkReadRegistersMessage());
|
// Launcher::readRegistersMessage(m_session.pid, m_session.tid));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The gdb server response is triggered later by the Stop Reply packet.
|
// The gdb server response is triggered later by the Stop Reply packet.
|
||||||
@@ -1681,7 +1650,7 @@ void TrkGdbAdapter::write(const QByteArray &data)
|
|||||||
if (data.startsWith("@@")) {
|
if (data.startsWith("@@")) {
|
||||||
// Read data
|
// Read data
|
||||||
sendTrkMessage(0x10, TrkCB(handleDirectWrite1),
|
sendTrkMessage(0x10, TrkCB(handleDirectWrite1),
|
||||||
trkReadMemoryMessage(m_session.dataseg, 12));
|
Launcher::readMemoryMessage(m_session.pid, m_session.tid, m_session.dataseg, 12));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_gdbProc.write(data);
|
m_gdbProc.write(data);
|
||||||
@@ -1745,7 +1714,7 @@ void TrkGdbAdapter::handleDirectWrite2(const TrkResult &response)
|
|||||||
} else {
|
} else {
|
||||||
// Check
|
// Check
|
||||||
sendTrkMessage(0x10, TrkCB(handleDirectWrite3),
|
sendTrkMessage(0x10, TrkCB(handleDirectWrite3),
|
||||||
trkReadMemoryMessage(scratch, 12));
|
trk::Launcher::readMemoryMessage(m_session.pid, m_session.tid, scratch, 12));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1811,7 +1780,8 @@ void TrkGdbAdapter::handleDirectWrite7(const TrkResult &response)
|
|||||||
} else {
|
} else {
|
||||||
// Check
|
// Check
|
||||||
sendTrkMessage(0x10, TrkCB(handleDirectWrite8),
|
sendTrkMessage(0x10, TrkCB(handleDirectWrite8),
|
||||||
trkReadMemoryMessage(scratch, 8));
|
trk::Launcher::readMemoryMessage(m_session.pid, m_session.tid,
|
||||||
|
scratch, 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1824,7 +1794,7 @@ void TrkGdbAdapter::handleDirectWrite8(const TrkResult &response)
|
|||||||
// Re-read registers
|
// Re-read registers
|
||||||
sendTrkMessage(0x12,
|
sendTrkMessage(0x12,
|
||||||
TrkCB(handleAndReportReadRegistersAfterStop),
|
TrkCB(handleAndReportReadRegistersAfterStop),
|
||||||
trkReadRegistersMessage());
|
Launcher::readRegistersMessage(m_session.pid, m_session.tid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -185,10 +185,8 @@ private:
|
|||||||
void handleDirectWrite9(const TrkResult &response);
|
void handleDirectWrite9(const TrkResult &response);
|
||||||
|
|
||||||
QByteArray trkContinueMessage(uint threadId);
|
QByteArray trkContinueMessage(uint threadId);
|
||||||
QByteArray trkReadRegistersMessage();
|
|
||||||
QByteArray trkWriteRegisterMessage(trk::byte reg, uint value);
|
QByteArray trkWriteRegisterMessage(trk::byte reg, uint value);
|
||||||
QByteArray trkReadMemoryMessage(const MemoryRange &range);
|
QByteArray trkReadMemoryMessage(const MemoryRange &range);
|
||||||
QByteArray trkReadMemoryMessage(uint addr, uint len);
|
|
||||||
QByteArray trkWriteMemoryMessage(uint addr, const QByteArray &date);
|
QByteArray trkWriteMemoryMessage(uint addr, const QByteArray &date);
|
||||||
QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true);
|
QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true);
|
||||||
QByteArray trkStepRangeMessage();
|
QByteArray trkStepRangeMessage();
|
||||||
|
|||||||
@@ -46,6 +46,33 @@
|
|||||||
|
|
||||||
namespace trk {
|
namespace trk {
|
||||||
|
|
||||||
|
struct CrashReportState {
|
||||||
|
CrashReportState();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
typedef uint Thread;
|
||||||
|
typedef QList<Thread> Threads;
|
||||||
|
Threads threads;
|
||||||
|
|
||||||
|
QList<uint> registers;
|
||||||
|
QByteArray stack;
|
||||||
|
uint sp;
|
||||||
|
uint fetchingStackPID;
|
||||||
|
uint fetchingStackTID;
|
||||||
|
};
|
||||||
|
|
||||||
|
CrashReportState::CrashReportState()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashReportState::clear()
|
||||||
|
{
|
||||||
|
threads.clear();
|
||||||
|
stack.clear();
|
||||||
|
sp = fetchingStackPID = fetchingStackTID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct LauncherPrivate {
|
struct LauncherPrivate {
|
||||||
struct CopyState {
|
struct CopyState {
|
||||||
QString sourceFileName;
|
QString sourceFileName;
|
||||||
@@ -74,6 +101,7 @@ struct LauncherPrivate {
|
|||||||
int m_verbose;
|
int m_verbose;
|
||||||
Launcher::Actions m_startupActions;
|
Launcher::Actions m_startupActions;
|
||||||
bool m_closeDevice;
|
bool m_closeDevice;
|
||||||
|
CrashReportState m_crashReportState;
|
||||||
};
|
};
|
||||||
|
|
||||||
LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) :
|
LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) :
|
||||||
@@ -190,6 +218,7 @@ void Launcher::setCloseDevice(bool c)
|
|||||||
bool Launcher::startServer(QString *errorMessage)
|
bool Launcher::startServer(QString *errorMessage)
|
||||||
{
|
{
|
||||||
errorMessage->clear();
|
errorMessage->clear();
|
||||||
|
d->m_crashReportState.clear();
|
||||||
if (d->m_verbose) {
|
if (d->m_verbose) {
|
||||||
QString msg;
|
QString msg;
|
||||||
QTextStream str(&msg);
|
QTextStream str(&msg);
|
||||||
@@ -404,46 +433,37 @@ void Launcher::handleResult(const TrkResult &result)
|
|||||||
|
|
||||||
// target->host OS notification
|
// target->host OS notification
|
||||||
case TrkNotifyCreated: { // Notify Created
|
case TrkNotifyCreated: { // Notify Created
|
||||||
/*
|
|
||||||
const char *data = result.data.data();
|
|
||||||
byte error = result.data.at(0);
|
|
||||||
byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2.
|
|
||||||
uint pid = extractInt(data + 2); // ProcessID: 4 bytes;
|
|
||||||
uint tid = extractInt(data + 6); //threadID: 4 bytes
|
|
||||||
uint codeseg = extractInt(data + 10); //code address: 4 bytes; code base address for the library
|
|
||||||
uint dataseg = extractInt(data + 14); //data address: 4 bytes; data base address for the library
|
|
||||||
uint len = extractShort(data + 18); //length: 2 bytes; length of the library name string to follow
|
|
||||||
QByteArray name = result.data.mid(20, len); // name: library name
|
|
||||||
|
|
||||||
logMessage(prefix + "NOTE: LIBRARY LOAD: " + str);
|
|
||||||
logMessage(prefix + "TOKEN: " + result.token);
|
|
||||||
logMessage(prefix + "ERROR: " + int(error));
|
|
||||||
logMessage(prefix + "TYPE: " + int(type));
|
|
||||||
logMessage(prefix + "PID: " + pid);
|
|
||||||
logMessage(prefix + "TID: " + tid);
|
|
||||||
logMessage(prefix + "CODE: " + codeseg);
|
|
||||||
logMessage(prefix + "DATA: " + dataseg);
|
|
||||||
logMessage(prefix + "LEN: " + len);
|
|
||||||
logMessage(prefix + "NAME: " + name);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (result.data.size() < 10)
|
if (result.data.size() < 10)
|
||||||
break;
|
break;
|
||||||
|
const char *data = result.data.constData();
|
||||||
|
const byte error = result.data.at(0);
|
||||||
|
Q_UNUSED(error)
|
||||||
|
const byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2.
|
||||||
|
const uint tid = extractInt(data + 6); //threadID: 4 bytes
|
||||||
|
Q_UNUSED(tid)
|
||||||
|
if (type == kDSOSDLLItem && result.data.size() >=20) {
|
||||||
|
const Library lib = Library(result);
|
||||||
|
d->m_session.libraries.push_back(lib);
|
||||||
|
emit libraryLoaded(lib);
|
||||||
|
}
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
ba.append(result.data.mid(2, 8));
|
ba.append(result.data.mid(2, 8));
|
||||||
d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
|
d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
|
||||||
//d->m_device->sendTrkAck(result.token)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TrkNotifyDeleted: { // NotifyDeleted
|
case TrkNotifyDeleted: { // NotifyDeleted
|
||||||
const ushort itemType = (unsigned char)result.data.at(1);
|
const ushort itemType = (unsigned char)result.data.at(1);
|
||||||
const ushort len = result.data.size() > 12 ? extractShort(result.data.data() + 10) : ushort(0);
|
const uint pid = result.data.size() >= 6 ? extractShort(result.data.constData() + 2) : 0;
|
||||||
|
const uint tid = result.data.size() >= 10 ? extractShort(result.data.constData() + 6) : 0;
|
||||||
|
Q_UNUSED(tid)
|
||||||
|
const ushort len = result.data.size() > 12 ? extractShort(result.data.constData() + 10) : ushort(0);
|
||||||
const QString name = len ? QString::fromAscii(result.data.mid(12, len)) : QString();
|
const QString name = len ? QString::fromAscii(result.data.mid(12, len)) : QString();
|
||||||
logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3").
|
logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3").
|
||||||
arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")).
|
arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")).
|
||||||
arg(name));
|
arg(name));
|
||||||
d->m_device->sendTrkAck(result.token);
|
d->m_device->sendTrkAck(result.token);
|
||||||
if (itemType == 0 // process
|
if (itemType == kDSOSProcessItem // process
|
||||||
&& result.data.size() >= 10
|
&& result.data.size() >= 10
|
||||||
&& d->m_session.pid == extractInt(result.data.data() + 6)) {
|
&& d->m_session.pid == extractInt(result.data.data() + 6)) {
|
||||||
if (d->m_startupActions & ActionDownload)
|
if (d->m_startupActions & ActionDownload)
|
||||||
@@ -451,6 +471,17 @@ void Launcher::handleResult(const TrkResult &result)
|
|||||||
else
|
else
|
||||||
disconnectTrk();
|
disconnectTrk();
|
||||||
}
|
}
|
||||||
|
else if (itemType == kDSOSDLLItem && len) {
|
||||||
|
// Remove libraries of process.
|
||||||
|
for (QList<Library>::iterator it = d->m_session.libraries.begin(); it != d->m_session.libraries.end(); ) {
|
||||||
|
if ((*it).pid == pid && (*it).name == name) {
|
||||||
|
emit libraryUnloaded(*it);
|
||||||
|
it = d->m_session.libraries.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TrkNotifyProcessorStarted: { // NotifyProcessorStarted
|
case TrkNotifyProcessorStarted: { // NotifyProcessorStarted
|
||||||
@@ -696,6 +727,15 @@ void Launcher::handleCreateProcess(const TrkResult &result)
|
|||||||
logMessage(msg);
|
logMessage(msg);
|
||||||
}
|
}
|
||||||
emit applicationRunning(d->m_session.pid);
|
emit applicationRunning(d->m_session.pid);
|
||||||
|
//create a "library" entry for the executable which launched the process
|
||||||
|
Library lib;
|
||||||
|
lib.pid = d->m_session.pid;
|
||||||
|
lib.codeseg = d->m_session.codeseg;
|
||||||
|
lib.dataseg = d->m_session.dataseg;
|
||||||
|
lib.name = d->m_fileName.toUtf8();
|
||||||
|
d->m_session.libraries << lib;
|
||||||
|
emit libraryLoaded(lib);
|
||||||
|
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
appendInt(&ba, d->m_session.pid);
|
appendInt(&ba, d->m_session.pid);
|
||||||
appendInt(&ba, d->m_session.tid);
|
appendInt(&ba, d->m_session.tid);
|
||||||
@@ -847,6 +887,30 @@ QByteArray Launcher::startProcessMessage(const QString &executable,
|
|||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray Launcher::readMemoryMessage(uint pid, uint tid, uint from, uint len)
|
||||||
|
{
|
||||||
|
QByteArray ba;
|
||||||
|
ba.reserve(11);
|
||||||
|
ba.append(char(0x8)); // Options, FIXME: why?
|
||||||
|
appendShort(&ba, len);
|
||||||
|
appendInt(&ba, from);
|
||||||
|
appendInt(&ba, pid);
|
||||||
|
appendInt(&ba, tid);
|
||||||
|
return ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Launcher::readRegistersMessage(uint pid, uint tid)
|
||||||
|
{
|
||||||
|
QByteArray ba;
|
||||||
|
ba.reserve(15);
|
||||||
|
ba.append(char(0)); // Register set, only 0 supported
|
||||||
|
appendShort(&ba, 0); //R0
|
||||||
|
appendShort(&ba, 16); // last register CPSR
|
||||||
|
appendInt(&ba, pid);
|
||||||
|
appendInt(&ba, tid);
|
||||||
|
return ba;
|
||||||
|
}
|
||||||
|
|
||||||
void Launcher::startInferiorIfNeeded()
|
void Launcher::startInferiorIfNeeded()
|
||||||
{
|
{
|
||||||
emit startingApplication();
|
emit startingApplication();
|
||||||
@@ -898,4 +962,63 @@ void Launcher::releaseToDeviceManager(Launcher *launcher)
|
|||||||
sdm->releaseDevice(launcher->trkServerName());
|
sdm->releaseDevice(launcher->trkServerName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Launcher::getRegistersAndCallStack(uint pid, uint tid)
|
||||||
|
{
|
||||||
|
d->m_device->sendTrkMessage(TrkReadRegisters,
|
||||||
|
TrkCallback(this, &Launcher::handleReadRegisters),
|
||||||
|
Launcher::readRegistersMessage(pid, tid));
|
||||||
|
d->m_crashReportState.fetchingStackPID = pid;
|
||||||
|
d->m_crashReportState.fetchingStackTID = tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::handleReadRegisters(const TrkResult &result)
|
||||||
|
{
|
||||||
|
if(result.errorCode() || result.data.size() < (17*4)) {
|
||||||
|
terminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char* data = result.data.constData() + 1;
|
||||||
|
d->m_crashReportState.registers.clear();
|
||||||
|
d->m_crashReportState.stack.clear();
|
||||||
|
for (int i=0;i<17;i++) {
|
||||||
|
uint r = extractInt(data);
|
||||||
|
data += 4;
|
||||||
|
d->m_crashReportState.registers.append(r);
|
||||||
|
}
|
||||||
|
d->m_crashReportState.sp = d->m_crashReportState.registers.at(13);
|
||||||
|
|
||||||
|
const ushort len = 1024 - (d->m_crashReportState.sp % 1024); //read to 1k boundary first
|
||||||
|
const QByteArray ba = Launcher::readMemoryMessage(d->m_crashReportState.fetchingStackPID,
|
||||||
|
d->m_crashReportState.fetchingStackTID,
|
||||||
|
d->m_crashReportState.sp,
|
||||||
|
len);
|
||||||
|
d->m_device->sendTrkMessage(TrkReadMemory, TrkCallback(this, &Launcher::handleReadStack), ba);
|
||||||
|
d->m_crashReportState.sp += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::handleReadStack(const TrkResult &result)
|
||||||
|
{
|
||||||
|
if (result.errorCode()) {
|
||||||
|
//error implies memory fault when reaching end of stack
|
||||||
|
emit registersAndCallStackReadComplete(d->m_crashReportState.registers, d->m_crashReportState.stack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint len = extractShort(result.data.constData() + 1);
|
||||||
|
d->m_crashReportState.stack.append(result.data.mid(3, len));
|
||||||
|
|
||||||
|
if (d->m_crashReportState.sp - d->m_crashReportState.registers.at(13) > 0x10000) {
|
||||||
|
//read enough stack, stop here
|
||||||
|
emit registersAndCallStackReadComplete(d->m_crashReportState.registers, d->m_crashReportState.stack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//read 1k more
|
||||||
|
const QByteArray ba = Launcher::readMemoryMessage(d->m_crashReportState.fetchingStackPID,
|
||||||
|
d->m_crashReportState.fetchingStackTID,
|
||||||
|
d->m_crashReportState.sp,
|
||||||
|
1024);
|
||||||
|
d->m_device->sendTrkMessage(TrkReadMemory, TrkCallback(this, &Launcher::handleReadStack), ba);
|
||||||
|
d->m_crashReportState.sp += 1024;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace trk
|
} // namespace trk
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#define LAUNCHER_H
|
#define LAUNCHER_H
|
||||||
|
|
||||||
#include "trkdevice.h"
|
#include "trkdevice.h"
|
||||||
|
#include "trkutils.h"
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QVariant>
|
#include <QtCore/QVariant>
|
||||||
@@ -109,6 +110,9 @@ public:
|
|||||||
// Create Trk message to start a process.
|
// Create Trk message to start a process.
|
||||||
static QByteArray startProcessMessage(const QString &executable,
|
static QByteArray startProcessMessage(const QString &executable,
|
||||||
const QStringList &arguments);
|
const QStringList &arguments);
|
||||||
|
// Create Trk message to read memory
|
||||||
|
static QByteArray readMemoryMessage(uint pid, uint tid, uint from, uint len);
|
||||||
|
static QByteArray readRegistersMessage(uint pid, uint tid);
|
||||||
// Parse a TrkNotifyStopped message
|
// Parse a TrkNotifyStopped message
|
||||||
static bool parseNotifyStopped(const QByteArray &a,
|
static bool parseNotifyStopped(const QByteArray &a,
|
||||||
uint *pid, uint *tid, uint *address,
|
uint *pid, uint *tid, uint *address,
|
||||||
@@ -136,12 +140,18 @@ signals:
|
|||||||
void copyProgress(int percent);
|
void copyProgress(int percent);
|
||||||
void stateChanged(int);
|
void stateChanged(int);
|
||||||
void processStopped(uint pc, uint pid, uint tid, const QString& reason);
|
void processStopped(uint pc, uint pid, uint tid, const QString& reason);
|
||||||
|
void processResumed(uint pid, uint tid);
|
||||||
|
void libraryLoaded(const trk::Library &lib);
|
||||||
|
void libraryUnloaded(const trk::Library &lib);
|
||||||
|
void registersAndCallStackReadComplete(const QList<uint>& registers, const QByteArray& stack);
|
||||||
// Emitted by the destructor, for releasing devices of SymbianDeviceManager by name
|
// Emitted by the destructor, for releasing devices of SymbianDeviceManager by name
|
||||||
void destroyed(const QString &serverName);
|
void destroyed(const QString &serverName);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void terminate();
|
void terminate();
|
||||||
void resumeProcess(uint pid, uint tid);
|
void resumeProcess(uint pid, uint tid);
|
||||||
|
//can be used to obtain traceback after a breakpoint / exception
|
||||||
|
void getRegistersAndCallStack(uint pid, uint tid);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleResult(const trk::TrkResult &data);
|
void handleResult(const trk::TrkResult &data);
|
||||||
@@ -169,6 +179,8 @@ private:
|
|||||||
void handleStop(const TrkResult &result);
|
void handleStop(const TrkResult &result);
|
||||||
void handleSupportMask(const TrkResult &result);
|
void handleSupportMask(const TrkResult &result);
|
||||||
void handleTrkVersion(const TrkResult &result);
|
void handleTrkVersion(const TrkResult &result);
|
||||||
|
void handleReadRegisters(const TrkResult &result);
|
||||||
|
void handleReadStack(const TrkResult &result);
|
||||||
|
|
||||||
void copyFileToRemote();
|
void copyFileToRemote();
|
||||||
void copyFileFromRemote();
|
void copyFileFromRemote();
|
||||||
|
|||||||
@@ -40,6 +40,25 @@
|
|||||||
|
|
||||||
namespace trk {
|
namespace trk {
|
||||||
|
|
||||||
|
Library::Library() : codeseg(0), dataseg(0), pid(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Library::Library(const TrkResult &result) : codeseg(0), dataseg(0), pid(0)
|
||||||
|
{
|
||||||
|
if (result.data.size() < 20) {
|
||||||
|
qWarning("Invalid trk creation notification received.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *data = result.data.constData();
|
||||||
|
pid = extractInt(data + 2);
|
||||||
|
codeseg = extractInt(data + 10);
|
||||||
|
dataseg = extractInt(data + 14);
|
||||||
|
const uint len = extractShort(data + 18);
|
||||||
|
name = result.data.mid(20, len);
|
||||||
|
}
|
||||||
|
|
||||||
TrkAppVersion::TrkAppVersion()
|
TrkAppVersion::TrkAppVersion()
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
@@ -260,18 +279,15 @@ SYMBIANUTILS_EXPORT QString stringFromArray(const QByteArray &ba, int maxLen)
|
|||||||
QString ascii;
|
QString ascii;
|
||||||
const int size = maxLen == -1 ? ba.size() : qMin(ba.size(), maxLen);
|
const int size = maxLen == -1 ? ba.size() : qMin(ba.size(), maxLen);
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
//if (i == 5 || i == ba.size() - 2)
|
const int c = byte(ba.at(i));
|
||||||
// str += " ";
|
str += QString::fromAscii("%1 ").arg(c, 2, 16, QChar('0'));
|
||||||
int c = byte(ba.at(i));
|
ascii += QChar(c).isPrint() ? QChar(c) : QChar('.');
|
||||||
str += QString("%1 ").arg(c, 2, 16, QChar('0'));
|
|
||||||
if (i >= 8 && i < ba.size() - 2)
|
|
||||||
ascii += QChar(c).isPrint() ? QChar(c) : QChar('.');
|
|
||||||
}
|
}
|
||||||
if (size != ba.size()) {
|
if (size != ba.size()) {
|
||||||
str += "...";
|
str += QLatin1String("...");
|
||||||
ascii += "...";
|
ascii += QLatin1String("...");
|
||||||
}
|
}
|
||||||
return str + " " + ascii;
|
return str + QLatin1String(" ") + ascii;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBIANUTILS_EXPORT QByteArray hexNumber(uint n, int digits)
|
SYMBIANUTILS_EXPORT QByteArray hexNumber(uint n, int digits)
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ QT_END_NAMESPACE
|
|||||||
namespace trk {
|
namespace trk {
|
||||||
|
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
|
struct TrkResult;
|
||||||
|
|
||||||
enum Command {
|
enum Command {
|
||||||
//meta commands
|
//meta commands
|
||||||
@@ -123,6 +124,20 @@ enum Command {
|
|||||||
TrkDSPositionFile = 0xd4
|
TrkDSPositionFile = 0xd4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DSOSItemTypes {
|
||||||
|
kDSOSProcessItem = 0x0000,
|
||||||
|
kDSOSThreadItem = 0x0001,
|
||||||
|
kDSOSDLLItem = 0x0002,
|
||||||
|
kDSOSAppItem = 0x0003,
|
||||||
|
kDSOSMemBlockItem = 0x0004,
|
||||||
|
kDSOSProcAttachItem = 0x0005,
|
||||||
|
kDSOSThreadAttachItem = 0x0006,
|
||||||
|
kDSOSProcAttach2Item = 0x0007,
|
||||||
|
kDSOSProcRunItem = 0x0008,
|
||||||
|
/* 0x0009 - 0x00ff reserved for general expansion */
|
||||||
|
/* 0x0100 - 0xffff available for target-specific use */
|
||||||
|
};
|
||||||
|
|
||||||
enum SerialMultiplexor {
|
enum SerialMultiplexor {
|
||||||
MuxRaw = 0,
|
MuxRaw = 0,
|
||||||
MuxTextTrace = 0x0102,
|
MuxTextTrace = 0x0102,
|
||||||
@@ -152,11 +167,14 @@ SYMBIANUTILS_EXPORT void appendString(QByteArray *ba, const QByteArray &str, End
|
|||||||
|
|
||||||
struct SYMBIANUTILS_EXPORT Library
|
struct SYMBIANUTILS_EXPORT Library
|
||||||
{
|
{
|
||||||
Library() {}
|
Library();
|
||||||
|
explicit Library(const TrkResult &r);
|
||||||
|
|
||||||
QByteArray name;
|
QByteArray name;
|
||||||
uint codeseg;
|
uint codeseg;
|
||||||
uint dataseg;
|
uint dataseg;
|
||||||
|
//library addresses are valid for a given process (depending on memory model, they might be loaded at the same address in all processes or not)
|
||||||
|
uint pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SYMBIANUTILS_EXPORT TrkAppVersion
|
struct SYMBIANUTILS_EXPORT TrkAppVersion
|
||||||
|
|||||||
Reference in New Issue
Block a user