diff --git a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp
index fd2208e14b46392c8dce259b5e3af9332850e8fd..e5bfb3f3365c7f6ed44f2fe49e5fefbefe0f7508 100644
--- a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp
@@ -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);
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp
index 26b6ceb69f7413aebfa948c389e102f2d4b94793..350403adbe3433490125cf05e5422836f86996ec 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp
@@ -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));
     }
 }
 
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.h b/src/plugins/debugger/gdb/trkgdbadapter.h
index bed271e6c69bacbd67ef299d419db3e128de0c96..69a770af3018194631ebaef2004b5a983d911c73 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.h
+++ b/src/plugins/debugger/gdb/trkgdbadapter.h
@@ -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();
diff --git a/src/shared/symbianutils/launcher.cpp b/src/shared/symbianutils/launcher.cpp
index 0948ca02c92e98dcab05b1c036f6bffc2c8eaaf6..a22c12f990533a42055d1a9a84650e4ceeb5e2dd 100644
--- a/src/shared/symbianutils/launcher.cpp
+++ b/src/shared/symbianutils/launcher.cpp
@@ -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
diff --git a/src/shared/symbianutils/launcher.h b/src/shared/symbianutils/launcher.h
index 993a5ae97bb5b6f7f08b01f726097a55c1c09d23..7e348e80842de984f231e93b1bb83e62d2fc5ba9 100644
--- a/src/shared/symbianutils/launcher.h
+++ b/src/shared/symbianutils/launcher.h
@@ -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();
diff --git a/src/shared/symbianutils/trkutils.cpp b/src/shared/symbianutils/trkutils.cpp
index 9caf807127b0d8585df5f2b5e34cd90d43fdb110..d09ed373d236c7a9769ad7608b06256949731714 100644
--- a/src/shared/symbianutils/trkutils.cpp
+++ b/src/shared/symbianutils/trkutils.cpp
@@ -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)
diff --git a/src/shared/symbianutils/trkutils.h b/src/shared/symbianutils/trkutils.h
index 394f9ba85d170d3503a35dcde84d04bd0dcb4618..9885053484562300925a80c5c3872027cf6d259e 100644
--- a/src/shared/symbianutils/trkutils.h
+++ b/src/shared/symbianutils/trkutils.h
@@ -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