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.codeseg = minfo.codeAddress;
 | 
			
		||||
        library.dataseg = minfo.dataAddress;
 | 
			
		||||
        library.pid = tcftrk::RunControlContext::processIdFromTcdfId(se.id());
 | 
			
		||||
        m_session.libraries.push_back(library);
 | 
			
		||||
    } else {
 | 
			
		||||
        const int index = m_session.modules.indexOf(moduleName);
 | 
			
		||||
 
 | 
			
		||||
@@ -164,18 +164,7 @@ QByteArray TrkGdbAdapter::trkContinueMessage(uint threadId)
 | 
			
		||||
    return ba;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QByteArray TrkGdbAdapter::trkReadRegistersMessage()
 | 
			
		||||
{
 | 
			
		||||
    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 TrkGdbAdapter::trkWriteRegisterMessage(trk::byte reg, uint value)
 | 
			
		||||
{
 | 
			
		||||
    QByteArray ba;
 | 
			
		||||
    appendByte(&ba, 0); // ?
 | 
			
		||||
@@ -187,21 +176,9 @@ QByteArray TrkGdbAdapter::trkReadRegistersMessage()
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    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)
 | 
			
		||||
@@ -539,7 +516,7 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
 | 
			
		||||
            sendGdbServerAck();
 | 
			
		||||
            sendTrkMessage(0x12,
 | 
			
		||||
                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);
 | 
			
		||||
        sendTrkMessage(0x12,
 | 
			
		||||
            TrkCB(handleAndReportReadRegisters),
 | 
			
		||||
            trkReadRegistersMessage());
 | 
			
		||||
            Launcher::readRegistersMessage(m_session.pid, m_session.tid));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (cmd.startsWith("salstep,")) {
 | 
			
		||||
@@ -611,7 +588,7 @@ void TrkGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
 | 
			
		||||
            //qDebug() << "Fetching single register";
 | 
			
		||||
            sendTrkMessage(0x12,
 | 
			
		||||
                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";
 | 
			
		||||
            sendTrkMessage(0x12,
 | 
			
		||||
                TrkCB(handleAndReportReadRegistersAfterStop),
 | 
			
		||||
                trkReadRegistersMessage());
 | 
			
		||||
                Launcher::readRegistersMessage(m_session.pid, m_session.tid));
 | 
			
		||||
#            else
 | 
			
		||||
            // As a source-line step typically consists of
 | 
			
		||||
            // 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);
 | 
			
		||||
            // type: 1 byte; for dll item, this value is 2.
 | 
			
		||||
            const trk::byte type = result.data.at(1);
 | 
			
		||||
            const uint pid = extractInt(data + 2);
 | 
			
		||||
            const uint tid = extractInt(data + 6);
 | 
			
		||||
            const uint codeseg = extractInt(data + 10);
 | 
			
		||||
            const uint dataseg = extractInt(data + 14);
 | 
			
		||||
            const uint len = extractShort(data + 18);
 | 
			
		||||
            const QByteArray name = result.data.mid(20, len); // library name
 | 
			
		||||
            m_session.modules += QString::fromAscii(name);
 | 
			
		||||
            const Library lib = Library(result);
 | 
			
		||||
            m_session.libraries.push_back(lib);
 | 
			
		||||
            m_session.modules += QString::fromAscii(lib.name);
 | 
			
		||||
            QString logMsg;
 | 
			
		||||
            QTextStream str(&logMsg);
 | 
			
		||||
            str << prefix << " NOTE: LIBRARY LOAD: token=" << result.token;
 | 
			
		||||
            if (error)
 | 
			
		||||
                str << " ERROR: " << int(error);
 | 
			
		||||
            str << " TYPE: " << int(type) << " PID: " << pid << " TID:   " <<  tid;
 | 
			
		||||
            str << " CODE: " << hexxNumber(codeseg);
 | 
			
		||||
            str << " DATA: " << hexxNumber(dataseg);
 | 
			
		||||
            str << " NAME: '" << name << '\'';
 | 
			
		||||
            Library lib;
 | 
			
		||||
            lib.name = name;
 | 
			
		||||
            lib.codeseg = codeseg;
 | 
			
		||||
            lib.dataseg = dataseg;
 | 
			
		||||
            m_session.libraries.append(lib);
 | 
			
		||||
            str << " TYPE: " << int(type) << " PID: " << lib.pid << " TID:   " <<  tid;
 | 
			
		||||
            str << " CODE: " << hexxNumber(lib.codeseg);
 | 
			
		||||
            str << " DATA: " << hexxNumber(lib.dataseg);
 | 
			
		||||
            str << " NAME: '" << lib.name << '\'';
 | 
			
		||||
            if (tid && tid != unsigned(-1) && m_snapshot.indexOfThread(tid) == -1)
 | 
			
		||||
                m_snapshot.addThread(tid);
 | 
			
		||||
            logMessage(logMsg);
 | 
			
		||||
@@ -1365,7 +1334,7 @@ void TrkGdbAdapter::handleStep(const TrkResult &result)
 | 
			
		||||
        // making some progress through a 'step'.
 | 
			
		||||
        //sendTrkMessage(0x12,
 | 
			
		||||
        //    TrkCB(handleAndReportReadRegistersAfterStop),
 | 
			
		||||
        //    trkReadRegistersMessage());
 | 
			
		||||
        //    Launcher::readRegistersMessage(m_session.pid, m_session.tid));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // 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("@@")) {
 | 
			
		||||
        // Read data
 | 
			
		||||
        sendTrkMessage(0x10, TrkCB(handleDirectWrite1),
 | 
			
		||||
           trkReadMemoryMessage(m_session.dataseg, 12));
 | 
			
		||||
                       Launcher::readMemoryMessage(m_session.pid, m_session.tid, m_session.dataseg, 12));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    m_gdbProc.write(data);
 | 
			
		||||
@@ -1745,7 +1714,7 @@ void TrkGdbAdapter::handleDirectWrite2(const TrkResult &response)
 | 
			
		||||
    } else {
 | 
			
		||||
        // Check
 | 
			
		||||
        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 {
 | 
			
		||||
        // Check
 | 
			
		||||
        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
 | 
			
		||||
        sendTrkMessage(0x12,
 | 
			
		||||
            TrkCB(handleAndReportReadRegistersAfterStop),
 | 
			
		||||
            trkReadRegistersMessage());
 | 
			
		||||
            Launcher::readRegistersMessage(m_session.pid, m_session.tid));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -185,10 +185,8 @@ private:
 | 
			
		||||
    void handleDirectWrite9(const TrkResult &response);
 | 
			
		||||
 | 
			
		||||
    QByteArray trkContinueMessage(uint threadId);
 | 
			
		||||
    QByteArray trkReadRegistersMessage();
 | 
			
		||||
    QByteArray trkWriteRegisterMessage(trk::byte reg, uint value);
 | 
			
		||||
    QByteArray trkReadMemoryMessage(const MemoryRange &range);
 | 
			
		||||
    QByteArray trkReadMemoryMessage(uint addr, uint len);
 | 
			
		||||
    QByteArray trkWriteMemoryMessage(uint addr, const QByteArray &date);
 | 
			
		||||
    QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true);
 | 
			
		||||
    QByteArray trkStepRangeMessage();
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,33 @@
 | 
			
		||||
 | 
			
		||||
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 CopyState {
 | 
			
		||||
        QString sourceFileName;
 | 
			
		||||
@@ -74,6 +101,7 @@ struct LauncherPrivate {
 | 
			
		||||
    int m_verbose;
 | 
			
		||||
    Launcher::Actions m_startupActions;
 | 
			
		||||
    bool m_closeDevice;
 | 
			
		||||
    CrashReportState m_crashReportState;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) :
 | 
			
		||||
@@ -190,6 +218,7 @@ void Launcher::setCloseDevice(bool c)
 | 
			
		||||
bool Launcher::startServer(QString *errorMessage)
 | 
			
		||||
{
 | 
			
		||||
    errorMessage->clear();
 | 
			
		||||
    d->m_crashReportState.clear();
 | 
			
		||||
    if (d->m_verbose) {
 | 
			
		||||
        QString msg;
 | 
			
		||||
        QTextStream str(&msg);
 | 
			
		||||
@@ -404,46 +433,37 @@ void Launcher::handleResult(const TrkResult &result)
 | 
			
		||||
 | 
			
		||||
        // target->host OS notification
 | 
			
		||||
        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)
 | 
			
		||||
                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;
 | 
			
		||||
            ba.append(result.data.mid(2, 8));
 | 
			
		||||
            d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
 | 
			
		||||
            //d->m_device->sendTrkAck(result.token)
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case TrkNotifyDeleted: { // NotifyDeleted
 | 
			
		||||
            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();
 | 
			
		||||
            logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3").
 | 
			
		||||
                       arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")).
 | 
			
		||||
                       arg(name));
 | 
			
		||||
            d->m_device->sendTrkAck(result.token);
 | 
			
		||||
            if (itemType == 0 // process
 | 
			
		||||
            if (itemType == kDSOSProcessItem // process
 | 
			
		||||
                && result.data.size() >= 10
 | 
			
		||||
                && d->m_session.pid == extractInt(result.data.data() + 6)) {
 | 
			
		||||
                    if (d->m_startupActions & ActionDownload)
 | 
			
		||||
@@ -451,6 +471,17 @@ void Launcher::handleResult(const TrkResult &result)
 | 
			
		||||
                    else
 | 
			
		||||
                        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;
 | 
			
		||||
        }
 | 
			
		||||
        case TrkNotifyProcessorStarted: { // NotifyProcessorStarted
 | 
			
		||||
@@ -696,6 +727,15 @@ void Launcher::handleCreateProcess(const TrkResult &result)
 | 
			
		||||
        logMessage(msg);
 | 
			
		||||
    }
 | 
			
		||||
    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;
 | 
			
		||||
    appendInt(&ba, d->m_session.pid);
 | 
			
		||||
    appendInt(&ba, d->m_session.tid);
 | 
			
		||||
@@ -847,6 +887,30 @@ QByteArray Launcher::startProcessMessage(const QString &executable,
 | 
			
		||||
    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()
 | 
			
		||||
{
 | 
			
		||||
    emit startingApplication();
 | 
			
		||||
@@ -898,4 +962,63 @@ void Launcher::releaseToDeviceManager(Launcher *launcher)
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@
 | 
			
		||||
#define LAUNCHER_H
 | 
			
		||||
 | 
			
		||||
#include "trkdevice.h"
 | 
			
		||||
#include "trkutils.h"
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QObject>
 | 
			
		||||
#include <QtCore/QVariant>
 | 
			
		||||
@@ -109,6 +110,9 @@ public:
 | 
			
		||||
    // Create Trk message to start a process.
 | 
			
		||||
    static QByteArray startProcessMessage(const QString &executable,
 | 
			
		||||
                                          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
 | 
			
		||||
    static bool parseNotifyStopped(const QByteArray &a,
 | 
			
		||||
                                   uint *pid, uint *tid, uint *address,
 | 
			
		||||
@@ -136,12 +140,18 @@ signals:
 | 
			
		||||
    void copyProgress(int percent);
 | 
			
		||||
    void stateChanged(int);
 | 
			
		||||
    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
 | 
			
		||||
    void destroyed(const QString &serverName);
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
    void terminate();
 | 
			
		||||
    void resumeProcess(uint pid, uint tid);
 | 
			
		||||
    //can be used to obtain traceback after a breakpoint / exception
 | 
			
		||||
    void getRegistersAndCallStack(uint pid, uint tid);
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void handleResult(const trk::TrkResult &data);
 | 
			
		||||
@@ -169,6 +179,8 @@ private:
 | 
			
		||||
    void handleStop(const TrkResult &result);
 | 
			
		||||
    void handleSupportMask(const TrkResult &result);
 | 
			
		||||
    void handleTrkVersion(const TrkResult &result);
 | 
			
		||||
    void handleReadRegisters(const TrkResult &result);
 | 
			
		||||
    void handleReadStack(const TrkResult &result);
 | 
			
		||||
 | 
			
		||||
    void copyFileToRemote();
 | 
			
		||||
    void copyFileFromRemote();
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,25 @@
 | 
			
		||||
 | 
			
		||||
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()
 | 
			
		||||
{
 | 
			
		||||
    reset();
 | 
			
		||||
@@ -260,18 +279,15 @@ SYMBIANUTILS_EXPORT QString stringFromArray(const QByteArray &ba, int maxLen)
 | 
			
		||||
    QString ascii;
 | 
			
		||||
    const int size = maxLen == -1 ? ba.size() : qMin(ba.size(), maxLen);
 | 
			
		||||
    for (int i = 0; i < size; ++i) {
 | 
			
		||||
        //if (i == 5 || i == ba.size() - 2)
 | 
			
		||||
        //    str += "  ";
 | 
			
		||||
        int c = byte(ba.at(i));
 | 
			
		||||
        str += QString("%1 ").arg(c, 2, 16, QChar('0'));
 | 
			
		||||
        if (i >= 8 && i < ba.size() - 2)
 | 
			
		||||
            ascii += QChar(c).isPrint() ? QChar(c) : QChar('.');
 | 
			
		||||
        const int c = byte(ba.at(i));
 | 
			
		||||
        str += QString::fromAscii("%1 ").arg(c, 2, 16, QChar('0'));
 | 
			
		||||
        ascii += QChar(c).isPrint() ? QChar(c) : QChar('.');
 | 
			
		||||
    }
 | 
			
		||||
    if (size != ba.size()) {
 | 
			
		||||
        str += "...";
 | 
			
		||||
        ascii += "...";
 | 
			
		||||
        str += QLatin1String("...");
 | 
			
		||||
        ascii += QLatin1String("...");
 | 
			
		||||
    }
 | 
			
		||||
    return str + "  " + ascii;
 | 
			
		||||
    return str + QLatin1String("  ") + ascii;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SYMBIANUTILS_EXPORT QByteArray hexNumber(uint n, int digits)
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@ QT_END_NAMESPACE
 | 
			
		||||
namespace trk {
 | 
			
		||||
 | 
			
		||||
typedef unsigned char byte;
 | 
			
		||||
struct TrkResult;
 | 
			
		||||
 | 
			
		||||
enum Command {
 | 
			
		||||
    //meta commands
 | 
			
		||||
@@ -123,6 +124,20 @@ enum Command {
 | 
			
		||||
    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 {
 | 
			
		||||
    MuxRaw = 0,
 | 
			
		||||
    MuxTextTrace = 0x0102,
 | 
			
		||||
@@ -152,11 +167,14 @@ SYMBIANUTILS_EXPORT void appendString(QByteArray *ba, const QByteArray &str, End
 | 
			
		||||
 | 
			
		||||
struct SYMBIANUTILS_EXPORT Library
 | 
			
		||||
{
 | 
			
		||||
    Library() {}
 | 
			
		||||
    Library();
 | 
			
		||||
    explicit Library(const TrkResult &r);
 | 
			
		||||
 | 
			
		||||
    QByteArray name;
 | 
			
		||||
    uint codeseg;
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user