From 85dcd851da2e1da0ca60a200ef69d0817515b07f Mon Sep 17 00:00:00 2001 From: ck Date: Tue, 8 Sep 2009 11:59:21 +0200 Subject: [PATCH 01/43] Added 64 bit support to BinEditor. --- src/plugins/bineditor/bineditor.cpp | 63 ++++++++++++++--------- src/plugins/bineditor/bineditor.h | 12 +++-- src/plugins/bineditor/bineditorplugin.cpp | 15 +++--- src/plugins/debugger/debuggeragents.cpp | 16 +++--- src/plugins/debugger/debuggeragents.h | 2 +- 5 files changed, 65 insertions(+), 43 deletions(-) diff --git a/src/plugins/bineditor/bineditor.cpp b/src/plugins/bineditor/bineditor.cpp index 306de5d80ad..27629a130ea 100644 --- a/src/plugins/bineditor/bineditor.cpp +++ b/src/plugins/bineditor/bineditor.cpp @@ -77,6 +77,7 @@ BinEditor::BinEditor(QWidget *parent) { m_ieditor = 0; m_inLazyMode = false; + m_baseAddr = 0; m_blockSize = 4096; init(); m_unmodifiedState = 0; @@ -88,7 +89,7 @@ BinEditor::BinEditor(QWidget *parent) m_cursorVisible = false; m_caseSensitiveSearch = false; setFocusPolicy(Qt::WheelFocus); - m_addressString = QString(9, QLatin1Char(':')); + m_addressString = QString(16 + 3, QLatin1Char(':')); } BinEditor::~BinEditor() @@ -108,7 +109,7 @@ void BinEditor::init() m_numVisibleLines = viewport()->height() / m_lineHeight; m_textWidth = 16 * m_charWidth + m_charWidth; int m_numberWidth = fm.width(QChar(QLatin1Char('9'))); - m_labelWidth = 8 * m_numberWidth + 2 * m_charWidth; + m_labelWidth = 16 * m_numberWidth + 4 * m_charWidth; int expectedCharWidth = m_columnWidth / 3; const char *hex = "0123456789abcdef"; @@ -129,13 +130,17 @@ void BinEditor::init() } -void BinEditor::addLazyData(int block, const QByteArray &data) +void BinEditor::addLazyData(quint64 block, const QByteArray &data) { Q_ASSERT(m_inLazyMode); Q_ASSERT(data.size() == m_blockSize); - m_lazyData.insert(block, data); - m_lazyRequests.remove(block); - viewport()->update(); + const quint64 addr = block * m_blockSize; + if (addr >= m_baseAddr && addr <= m_baseAddr + m_size - 1) { + const int translatedBlock = (addr - m_baseAddr) / m_blockSize; + m_lazyData.insert(translatedBlock, data); + m_lazyRequests.remove(translatedBlock); + viewport()->update(); + } } bool BinEditor::requestDataAt(int pos, bool synchronous) const @@ -148,7 +153,8 @@ bool BinEditor::requestDataAt(int pos, bool synchronous) const if (it == m_lazyData.end()) { if (!m_lazyRequests.contains(block)) { m_lazyRequests.insert(block); - emit const_cast(this)->lazyDataRequested(block, synchronous); + emit const_cast(this)-> + lazyDataRequested(m_baseAddr / m_blockSize + block, synchronous); if (!m_lazyRequests.contains(block)) return true; // synchronous data source } @@ -294,6 +300,7 @@ bool BinEditor::isReadOnly() const void BinEditor::setData(const QByteArray &data) { m_inLazyMode = false; + m_baseAddr = 0; m_lazyData.clear(); m_lazyRequests.clear(); m_data = data; @@ -325,12 +332,12 @@ bool BinEditor::applyModifications(QByteArray &data) const if (data.size() != m_size) return false; for (QMap::const_iterator it = m_lazyData.begin(); it != m_lazyData.end(); ++it) { - ::memcpy(data.data() + it.key() * m_blockSize, it->constData(), m_blockSize); + ::memcpy(data.data() + m_baseAddr + it.key() * m_blockSize, it->constData(), m_blockSize); } return true; } -void BinEditor::setLazyData(int cursorPosition, int size, int blockSize) +void BinEditor::setLazyData(quint64 startAddr, int range, int blockSize) { m_inLazyMode = true; m_blockSize = blockSize; @@ -339,7 +346,14 @@ void BinEditor::setLazyData(int cursorPosition, int size, int blockSize) m_data.clear(); m_lazyData.clear(); m_lazyRequests.clear(); - m_size = size; + + // In lazy mode, users can edit data in the range + // [startAddr - range/2, startAddr + range/2]. + m_baseAddr = static_cast(range/2) > startAddr + ? 0 : startAddr - range/2; + m_baseAddr = (m_baseAddr / blockSize) * blockSize; + m_size = m_baseAddr != 0 && static_cast(range) >= -m_baseAddr + ? -m_baseAddr : range; m_unmodifiedState = 0; m_undoStack.clear(); @@ -347,7 +361,7 @@ void BinEditor::setLazyData(int cursorPosition, int size, int blockSize) init(); - m_cursorPosition = cursorPosition; + m_cursorPosition = startAddr - m_baseAddr; verticalScrollBar()->setValue(m_cursorPosition / 16); emit cursorPositionChanged(m_cursorPosition); @@ -526,7 +540,8 @@ int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSen } -int BinEditor::find(const QByteArray &pattern_arg, int from, QTextDocument::FindFlags findFlags) +int BinEditor::find(const QByteArray &pattern_arg, int from, + QTextDocument::FindFlags findFlags) { if (pattern_arg.isEmpty()) return 0; @@ -541,7 +556,7 @@ int BinEditor::find(const QByteArray &pattern_arg, int from, QTextDocument::Find bool backwards = (findFlags & QTextDocument::FindBackward); int found = backwards ? dataLastIndexOf(pattern, from, caseSensitiveSearch) : dataIndexOf(pattern, from, caseSensitiveSearch); - + int foundHex = -1; QByteArray hexPattern = calculateHexPattern(pattern_arg); if (!hexPattern.isEmpty()) { @@ -593,20 +608,21 @@ void BinEditor::drawItems(QPainter *painter, int x, int y, const QString &itemSt } } -QString BinEditor::addressString(uint address) +QString BinEditor::addressString(quint64 address) { QChar *addressStringData = m_addressString.data(); const char *hex = "0123456789abcdef"; - for (int h = 0; h < 4; ++h) { - int shift = 4*(7-h); - addressStringData[h] = hex[(address & (0xf<>shift]; - } - for (int h = 4; h < 8; ++h) { - int shift = 4*(7-h); - addressStringData[h+1] = hex[(address & (0xf<>shift]; + + // Take colons into account. + const int indices[16] = { + 0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18 + }; + + for (int b = 0; b < 8; ++b) { + addressStringData[indices[15 - b*2]] = hex[(address >> (8*b)) & 0xf]; + addressStringData[indices[14 - b*2]] = hex[(address >> (8*b + 4)) & 0xf]; } return m_addressString; - } void BinEditor::paintEvent(QPaintEvent *e) @@ -663,7 +679,8 @@ void BinEditor::paintEvent(QPaintEvent *e) continue; - painter.drawText(-xoffset, i * m_lineHeight + m_ascent, addressString(((uint) line) * 16)); + painter.drawText(-xoffset, i * m_lineHeight + m_ascent, + addressString(m_baseAddr + ((uint) line) * 16)); int cursor = -1; if (line * 16 <= m_cursorPosition && m_cursorPosition < line * 16 + 16) diff --git a/src/plugins/bineditor/bineditor.h b/src/plugins/bineditor/bineditor.h index 0b9184b7c4c..dc14fd7e608 100644 --- a/src/plugins/bineditor/bineditor.h +++ b/src/plugins/bineditor/bineditor.h @@ -64,9 +64,9 @@ public: inline int dataSize() const { return m_size; } inline bool inLazyMode() const { return m_inLazyMode; } - Q_INVOKABLE void setLazyData(int cursorPosition, int size, int blockSize = 4096); + Q_INVOKABLE void setLazyData(quint64 startAddr, int range, int blockSize = 4096); inline int lazyDataBlockSize() const { return m_blockSize; } - Q_INVOKABLE void addLazyData(int block, const QByteArray &data); + Q_INVOKABLE void addLazyData(quint64 block, const QByteArray &data); bool applyModifications(QByteArray &data) const; void zoomIn(int range = 1); @@ -86,7 +86,8 @@ public: void setReadOnly(bool); bool isReadOnly() const; - int find(const QByteArray &pattern, int from = 0, QTextDocument::FindFlags findFlags = 0); + int find(const QByteArray &pattern, int from = 0, + QTextDocument::FindFlags findFlags = 0); void selectAll(); void clear(); @@ -106,7 +107,7 @@ public: bool isUndoAvailable() const { return m_undoStack.size(); } bool isRedoAvailable() const { return m_redoStack.size(); } - QString addressString(uint address); + QString addressString(quint64 address); public Q_SLOTS: @@ -121,7 +122,7 @@ Q_SIGNALS: void copyAvailable(bool); void cursorPositionChanged(int position); - void lazyDataRequested(int block, bool syncronous); + void lazyDataRequested(quint64 block, bool synchronous); protected: void scrollContentsBy(int dx, int dy); @@ -169,6 +170,7 @@ private: int m_numLines; int m_numVisibleLines; + quint64 m_baseAddr; bool m_cursorVisible; int m_cursorPosition; diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp index ddbb6250a25..2d0f2054de4 100644 --- a/src/plugins/bineditor/bineditorplugin.cpp +++ b/src/plugins/bineditor/bineditorplugin.cpp @@ -137,7 +137,7 @@ public: m_mimeType(QLatin1String(BINEditor::Constants::C_BINEDITOR_MIMETYPE)) { m_editor = parent; - connect(m_editor, SIGNAL(lazyDataRequested(int, bool)), this, SLOT(provideData(int))); + connect(m_editor, SIGNAL(lazyDataRequested(quint64, bool)), this, SLOT(provideData(quint64))); } ~BinEditorFile() {} @@ -162,7 +162,8 @@ public: file.write(data); file.close(); m_editor->setModified(false); - m_editor->editorInterface()->setDisplayName(QFileInfo(fileName).fileName()); + m_editor->editorInterface()-> + setDisplayName(QFileInfo(fileName).fileName()); m_fileName = fileName; emit changed(); return true; @@ -174,11 +175,13 @@ public: QFile file(fileName); if (file.open(QIODevice::ReadOnly)) { m_fileName = fileName; - if (file.isSequential()) { + if (file.isSequential() && file.size() <= INT_MAX) { m_editor->setData(file.readAll()); } else { - m_editor->setLazyData(0, file.size()); - m_editor->editorInterface()->setDisplayName(QFileInfo(fileName).fileName()); + m_editor->setLazyData(0, qMin(file.size(), + static_cast(INT_MAX))); + m_editor->editorInterface()-> + setDisplayName(QFileInfo(fileName).fileName()); } file.close(); return true; @@ -187,7 +190,7 @@ public: } private slots: - void provideData(int block) { + void provideData(quint64 block) { QFile file(m_fileName); if (file.open(QIODevice::ReadOnly)) { int blockSize = m_editor->lazyDataBlockSize(); diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp index ad1b6d67710..2b41b39394c 100644 --- a/src/plugins/debugger/debuggeragents.cpp +++ b/src/plugins/debugger/debuggeragents.cpp @@ -57,7 +57,7 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -/*! +/*! \class MemoryViewAgent Objects form this class are created in response to user actions in @@ -84,30 +84,30 @@ MemoryViewAgent::~MemoryViewAgent() m_editor->deleteLater(); } -void MemoryViewAgent::init(quint64 addr) +void MemoryViewAgent::init(quint64 addr) { Core::EditorManager *editorManager = Core::EditorManager::instance(); QString titlePattern = tr("Memory $"); m_editor = editorManager->openEditorWithContents( Core::Constants::K_DEFAULT_BINARY_EDITOR, &titlePattern); - connect(m_editor->widget(), SIGNAL(lazyDataRequested(int,bool)), - this, SLOT(fetchLazyData(int,bool))); + connect(m_editor->widget(), SIGNAL(lazyDataRequested(quint64,bool)), + this, SLOT(fetchLazyData(quint64,bool))); editorManager->activateEditor(m_editor); QMetaObject::invokeMethod(m_editor->widget(), "setLazyData", - Q_ARG(int, addr), Q_ARG(int, INT_MAX), Q_ARG(int, BinBlockSize)); + Q_ARG(quint64, addr), Q_ARG(int, INT_MAX), Q_ARG(int, BinBlockSize)); } -void MemoryViewAgent::fetchLazyData(int block, bool sync) +void MemoryViewAgent::fetchLazyData(quint64 block, bool sync) { Q_UNUSED(sync); // FIXME: needed support for incremental searching - m_engine->fetchMemory(this, BinBlockSize * block, BinBlockSize); + m_engine->fetchMemory(this, BinBlockSize * block, BinBlockSize); } void MemoryViewAgent::addLazyData(quint64 addr, const QByteArray &ba) { QMetaObject::invokeMethod(m_editor->widget(), "addLazyData", - Q_ARG(int, addr / BinBlockSize), Q_ARG(QByteArray, ba)); + Q_ARG(quint64, addr / BinBlockSize), Q_ARG(QByteArray, ba)); } diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h index 2ee788ccedc..7e52f96fae9 100644 --- a/src/plugins/debugger/debuggeragents.h +++ b/src/plugins/debugger/debuggeragents.h @@ -63,7 +63,7 @@ public slots: // Called from Engine void addLazyData(quint64 addr, const QByteArray &data); // Called from Editor - void fetchLazyData(int block, bool sync); + void fetchLazyData(quint64 block, bool sync); private: void init(quint64 startaddr); From d9e7a39081091629dfa5231f7a666e7ee9805a6d Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 09:42:59 +0200 Subject: [PATCH 02/43] debugger: simplify trk device logic a bit --- tests/manual/trk/runner.cpp | 1 - tests/manual/trk/trkdevicex.cpp | 44 ++++++++++++++++----------------- tests/manual/trk/trkdevicex.h | 6 ----- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index 1ed357b5df0..cd0df3010d1 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -999,7 +999,6 @@ void Adapter::handleTrkError(const QString &msg) void Adapter::handleTrkResult(const TrkResult &result) { - logMessage("HANDLING RESULT: " + result.data); if (result.isDebugOutput) { sendTrkAck(result.token); logMessage(QLatin1String("APPLICATION OUTPUT: ") + diff --git a/tests/manual/trk/trkdevicex.cpp b/tests/manual/trk/trkdevicex.cpp index d9abfdf1dfb..12f4f08481d 100644 --- a/tests/manual/trk/trkdevicex.cpp +++ b/tests/manual/trk/trkdevicex.cpp @@ -257,8 +257,18 @@ void TrkWriteQueue::queueTrkInitialPing() trkWriteQueue.append(TrkMessage(0, 0)); } -struct TrkDevicePrivate { + +/////////////////////////////////////////////////////////////////////// +// +// TrkDevicePrivate +// +/////////////////////////////////////////////////////////////////////// + +struct TrkDevicePrivate +{ TrkDevicePrivate(); + + TrkWriteQueue queue; #ifdef Q_OS_WIN HANDLE hdevice; #else @@ -298,11 +308,13 @@ TrkDevicePrivate::TrkDevicePrivate() : TrkDevice::TrkDevice(QObject *parent) : QObject(parent), - d(new TrkDevicePrivate), - qd(new TrkWriteQueue) + d(new TrkDevicePrivate) +{} + +TrkDevice::~TrkDevice() { - connect(this, SIGNAL(messageReceived(trk::TrkResult)), - this, SLOT(slotHandleResult(trk::TrkResult))); + close(); + delete d; } bool TrkDevice::open(const QString &port, QString *errorMessage) @@ -355,14 +367,6 @@ bool TrkDevice::open(const QString &port, QString *errorMessage) #endif } - -TrkDevice::~TrkDevice() -{ - close(); - delete d; - delete qd; -} - void TrkDevice::close() { if (!isOpen()) @@ -493,6 +497,7 @@ void TrkDevice::tryTrkRead() //if (verbose()) // logMessage("Read TrkResult " + r.data.toHex()); qDebug() << "RECEIVE DATA: " << r.data.toHex(); + d->queue.slotHandleResult(r); emit messageReceived(r); if (!rawData.isEmpty()) emit rawDataReceived(rawData); @@ -515,12 +520,12 @@ void TrkDevice::emitError(const QString &s) void TrkDevice::sendTrkMessage(byte code, Callback callback, const QByteArray &data, const QVariant &cookie, bool invokeOnNAK) { - qd->queueTrkMessage(code, callback, data, cookie, invokeOnNAK); + d->queue.queueTrkMessage(code, callback, data, cookie, invokeOnNAK); } void TrkDevice::sendTrkInitialPing() { - qd->queueTrkInitialPing(); + d->queue.queueTrkInitialPing(); } bool TrkDevice::sendTrkAck(byte token) @@ -536,10 +541,10 @@ bool TrkDevice::sendTrkAck(byte token) void TrkDevice::tryTrkWrite() { TrkMessage message; - if (!qd->pendingMessage(&message)) + if (!d->queue.pendingMessage(&message)) return; const bool success = trkWriteRawMessage(message); - qd->notifyWriteResult(success); + d->queue.notifyWriteResult(success); } bool TrkDevice::trkWriteRawMessage(const TrkMessage &msg) @@ -554,10 +559,5 @@ bool TrkDevice::trkWriteRawMessage(const TrkMessage &msg) return rc; } -void TrkDevice::slotHandleResult(const TrkResult &result) -{ - qd->slotHandleResult(result); -} - } // namespace trk diff --git a/tests/manual/trk/trkdevicex.h b/tests/manual/trk/trkdevicex.h index 9d0e9da0dcc..1873f458e7c 100644 --- a/tests/manual/trk/trkdevicex.h +++ b/tests/manual/trk/trkdevicex.h @@ -46,8 +46,6 @@ namespace trk { struct TrkResult; struct TrkMessage; struct TrkDevicePrivate; -class TrkWriteQueue; -struct TrkWriteQueueIODevicePrivate; /* TrkDevice: Implements a Windows COM or Linux device for * Trk communications. Provides synchronous write and asynchronous @@ -116,15 +114,11 @@ public: // Send an Ack synchronously, bypassing the queue bool sendTrkAck(unsigned char token); -private slots: - void slotHandleResult(const trk::TrkResult &); - private: void tryTrkWrite(); bool trkWriteRawMessage(const TrkMessage &msg); TrkDevicePrivate *d; - TrkWriteQueue *qd; }; } // namespace trk From 2da891ee887eecbe8421da50f5461541f45234d1 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 10:12:50 +0200 Subject: [PATCH 03/43] trk: fix size of 'kill' packet. also, do not announce the library loading to gdb as it starts asking questions afterwards. --- tests/manual/trk/runner.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index cd0df3010d1..c6d03cfa602 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -664,6 +664,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) // kill sendGdbServerAck(); QByteArray ba; + appendByte(&ba, 0); // ? appendByte(&ba, 0); // Sub-command: Delete Process appendInt(&ba, m_session.pid); sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); // Delete Item @@ -1006,6 +1007,7 @@ void Adapter::handleTrkResult(const TrkResult &result) sendGdbServerMessage("O" + result.data.toHex()); return; } + logMessage("READ TRK " + result.toString()); QByteArray prefix = "READ BUF: "; QByteArray str = result.toString().toUtf8(); switch (result.code) { @@ -1074,8 +1076,9 @@ void Adapter::handleTrkResult(const TrkResult &result) str << " DATA: 0x" << hexNumber(dataseg); str << " NAME: '" << name << '\''; logMessage(logMsg); - sendGdbServerMessage("T05library:" + name); - //sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); + // This lets gdb trigger a register update etc + //sendGdbServerMessage("T05library:r;"); + sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); break; } case 0xa1: { // NotifyDeleted From db8cddf55bf9b12796f37619b4a20c86abddd9d3 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 10:17:10 +0200 Subject: [PATCH 04/43] trk: rename 'response' to 'cmd' in handleGdbServerCommand --- tests/manual/trk/runner.cpp | 95 +++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 51 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index c6d03cfa602..27fb8e0cfb4 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -251,7 +251,7 @@ public: Q_SLOT void handleGdbConnection(); Q_SLOT void readGdbServerCommand(); void readGdbResponse(); - void handleGdbServerCommand(const QByteArray &ba); + void handleGdbServerCommand(const QByteArray &cmd); void sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote = QByteArray()); void sendGdbServerMessageAfterTrkResponse(const QByteArray &msg, @@ -475,9 +475,9 @@ void Adapter::readGdbServerCommand() + quoteUnprintableLatin1(ba)).arg(checkSum).arg(sum)); } - QByteArray response = ba.left(pos); + QByteArray cmd = ba.left(pos); ba.remove(0, pos + 3); - handleGdbServerCommand(response); + handleGdbServerCommand(cmd); } } @@ -569,18 +569,18 @@ QByteArray Adapter::trkBreakpointMessage(uint addr, int len, int pid, bool armMo return ba; } -void Adapter::handleGdbServerCommand(const QByteArray &response) +void Adapter::handleGdbServerCommand(const QByteArray &cmd) { // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html if (0) {} - else if (response == "!") { + else if (cmd == "!") { sendGdbServerAck(); //sendGdbServerMessage("", "extended mode not enabled"); sendGdbServerMessage("OK", "extended mode enabled"); } - else if (response.startsWith("?")) { + else if (cmd.startsWith("?")) { logMessage(msgGdbPacket(QLatin1String("Query halted"))); // Indicate the reason the target halted. // The reply is the same as for step and continue. @@ -594,7 +594,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) //sendGdbServerMessage("O" + QByteArray("Starting...").toHex()); } - else if (response == "c") { + else if (cmd == "c") { logMessage(msgGdbPacket(QLatin1String("Continue"))); sendGdbServerAck(); QByteArray ba; @@ -606,26 +606,26 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendTrkMessage(0x18, TrkCallback(), ba); } - else if (response.startsWith("C")) { + else if (cmd.startsWith("C")) { logMessage(msgGdbPacket(QLatin1String("Continue with signal"))); // C sig[;addr] Continue with signal sig (hex signal number) //Reply: See section D.3 Stop Reply Packets, for the reply specifications. sendGdbServerAck(); bool ok = false; - uint signalNumber = response.mid(1).toInt(&ok, 16); + uint signalNumber = cmd.mid(1).toInt(&ok, 16); QByteArray ba; appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); sendTrkMessage(0x18, TrkCB(handleSignalContinue), ba, signalNumber); // Continue } - else if (response.startsWith("D")) { + else if (cmd.startsWith("D")) { sendGdbServerAck(); sendGdbServerMessage("OK", "shutting down"); qApp->quit(); } - else if (response == "g") { + else if (cmd == "g") { logMessage(msgGdbPacket(QLatin1String("Read registers"))); // Read general registers. //sendGdbServerMessage("00000000", "read registers"); @@ -639,7 +639,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendTrkMessage(0x12, TrkCB(handleAndReportReadRegisters), ba, QVariant(), true); } - else if (response.startsWith("Hc")) { + else if (cmd.startsWith("Hc")) { logMessage(msgGdbPacket(QLatin1String("Set thread & continue"))); // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). // for step and continue operations @@ -648,18 +648,18 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendGdbServerMessage("OK", "Set current thread for step & continue"); } - else if (response.startsWith("Hg")) { + else if (cmd.startsWith("Hg")) { logMessage(msgGdbPacket(QLatin1String("Set thread"))); // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). // for 'other operations. 0 - any thread //$Hg0#df sendGdbServerAck(); - m_session.currentThread = response.mid(2).toInt(0, 16); + m_session.currentThread = cmd.mid(2).toInt(0, 16); sendGdbServerMessage("OK", "Set current thread " + QByteArray::number(m_session.currentThread)); } - else if (response == "k") { + else if (cmd == "k") { logMessage(msgGdbPacket(QLatin1String("kill"))); // kill sendGdbServerAck(); @@ -671,30 +671,30 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendGdbServerMessageAfterTrkResponse("", "process killed"); } - else if (response.startsWith("m")) { + else if (cmd.startsWith("m")) { logMessage(msgGdbPacket(QLatin1String("Read memory"))); // m addr,length sendGdbServerAck(); uint addr = 0, len = 0; do { - const int pos = response.indexOf(','); + const int pos = cmd.indexOf(','); if (pos == -1) break; bool ok; - addr = response.mid(1, pos - 1).toUInt(&ok, 16); + addr = cmd.mid(1, pos - 1).toUInt(&ok, 16); if (!ok) break; - len = response.mid(pos + 1).toUInt(&ok, 16); + len = cmd.mid(pos + 1).toUInt(&ok, 16); if (!ok) break; } while (false); if (len) { readMemory(addr, len); } else { - sendGdbServerMessage("E20", "Error " + response); + sendGdbServerMessage("E20", "Error " + cmd); } } - else if (response.startsWith("p")) { + else if (cmd.startsWith("p")) { logMessage(msgGdbPacket(QLatin1String("read register"))); // 0xf == current instruction pointer? //sendGdbServerMessage("0000", "current IP"); @@ -732,7 +732,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) LAST_FP_ARG = F3 #endif bool ok = false; - const uint registerNumber = response.mid(1).toInt(&ok, 16); + const uint registerNumber = cmd.mid(1).toInt(&ok, 16); QByteArray logMsg = "Read Register"; if (registerNumber == RegisterPSGdb) { QByteArray ba; @@ -750,7 +750,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) } } - else if (response == "qAttached") { + else if (cmd == "qAttached") { //$qAttached#8f // 1: attached to an existing process // 0: created a new process @@ -760,7 +760,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) //sendGdbServerMessage("E01", "new process created"); } - else if (response.startsWith("qC")) { + else if (cmd.startsWith("qC")) { logMessage(msgGdbPacket(QLatin1String("query thread id"))); // Return the current thread ID //$qC#b4 @@ -768,7 +768,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendGdbServerMessageAfterTrkResponse("QC@TID@"); } - else if (response.startsWith("qSupported")) { + else if (cmd.startsWith("qSupported")) { //$qSupported#37 //$qSupported:multiprocess+#c6 //logMessage("Handling 'qSupported'"); @@ -784,7 +784,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) "qXfer:features:read+"); } - else if (response == "qPacketInfo") { + else if (cmd == "qPacketInfo") { // happens with gdb 6.4.50.20060226-cvs / CodeSourcery // deprecated by qSupported? @@ -792,12 +792,12 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendGdbServerMessage("", "FIXME: nothing?"); } - else if (response == "qOffsets") { + else if (cmd == "qOffsets") { sendGdbServerAck(); sendGdbServerMessageAfterTrkResponse("TextSeg=@CODESEG@;DataSeg=@DATASEG@"); } - else if (response == "qSymbol::") { + else if (cmd == "qSymbol::") { if (m_verbose) logMessage(msgGdbPacket(QLatin1String("notify can handle symbol lookup"))); // Notify the target that GDB is prepared to serve symbol lookup requests. @@ -808,13 +808,13 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendGdbServerMessage("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(), "ask for more"); } - else if (response.startsWith("qXfer:features:read:target.xml:")) { + else if (cmd.startsWith("qXfer:features:read:target.xml:")) { // $qXfer:features:read:target.xml:0,7ca#46...Ack sendGdbServerAck(); sendGdbServerMessage("lsymbianelf"); } - else if (response == "QStartNoAckMode") { + else if (cmd == "QStartNoAckMode") { //$qSupported#37 //logMessage("Handling 'QStartNoAckMode'"); sendGdbServerAck(); @@ -822,7 +822,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) m_gdbAckMode = false; } - else if (response.startsWith("QPassSignals")) { + else if (cmd.startsWith("QPassSignals")) { // list of signals to pass directly to inferior // $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c;#8f // happens only if "QPassSignals+;" is qSupported @@ -831,7 +831,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendGdbServerMessage("OK", "passing signals accepted"); } - else if (response == "s") { + else if (cmd == "s" || cmd.startsWith("vCont;s")) { if (m_verbose) logMessage(msgGdbPacket(QLatin1String("Step range"))); sendGdbServerAck(); @@ -846,28 +846,21 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) //sendGdbServerMessageAfterTrkResponse("S05", "target halted"); } - else if (response == "vCont?") { + else if (cmd == "vCont?") { // actions supported by the vCont packet sendGdbServerAck(); sendGdbServerMessage("OK"); // we don't support vCont. //sendGdbServerMessage("vCont;c"); } - else if (response == "vCont;c") { + else if (cmd == "vCont;c") { // vCont[;action[:thread-id]]...' sendGdbServerAck(); m_running = true; sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); } - else if (response.startsWith("vCont;s")) { - // vCont[;action[:thread-id]]...' - sendGdbServerAck(); - m_running = true; - sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); - } - - else if (response.startsWith("vKill")) { + else if (cmd.startsWith("vKill")) { // kill sendGdbServerAck(); QByteArray ba; @@ -877,20 +870,20 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) sendGdbServerMessageAfterTrkResponse("", "process killed"); } - else if (0 && response.startsWith("Z0,")) { + else if (0 && cmd.startsWith("Z0,")) { // Tell gdb we don't support software breakpoints sendGdbServerMessage(""); } - else if (response.startsWith("Z0,") || response.startsWith("Z1,")) { + else if (cmd.startsWith("Z0,") || cmd.startsWith("Z1,")) { // Insert breakpoint if (m_verbose) logMessage(msgGdbPacket(QLatin1String("Insert breakpoint"))); // $z0,786a4ccc,4#99 - const int pos = response.lastIndexOf(','); + const int pos = cmd.lastIndexOf(','); bool ok = false; - const uint addr = response.mid(3, pos - 3).toInt(&ok, 16); - const uint len = response.mid(pos + 1).toInt(&ok, 16); + const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); + const uint len = cmd.mid(pos + 1).toInt(&ok, 16); qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len; if (m_verbose) logMessage(QString::fromLatin1("Inserting breakpoint at 0x%1, %2") @@ -915,8 +908,8 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) // Command: 0x80 Acknowledge // Error: 0x00 // [80 09 00 00 00 00 0A] - } else if (response.startsWith("qPart:") || response.startsWith("qXfer:")) { - QByteArray data = response.mid(1 + response.indexOf(':')); + } else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:")) { + QByteArray data = cmd.mid(1 + cmd.indexOf(':')); // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux) bool handled = false; if (data.startsWith("auxv:read::")) { @@ -938,14 +931,14 @@ void Adapter::handleGdbServerCommand(const QByteArray &response) } // auxv read if (!handled) { const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ") - + QString::fromAscii(response); + + QString::fromAscii(cmd); logMessage(msgGdbPacket(msg), true); sendGdbServerMessage("E20", msg.toLatin1()); } } // qPart/qXfer else { logMessage(msgGdbPacket(QLatin1String("FIXME unknown: ") - + QString::fromAscii(response))); + + QString::fromAscii(cmd))); } } From fbeeb8677ab3520ca5c41f8c317834a79fd3c419 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 10:38:06 +0200 Subject: [PATCH 05/43] trk: remove a debug message --- tests/manual/trk/trkdevicex.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/manual/trk/trkdevicex.cpp b/tests/manual/trk/trkdevicex.cpp index 12f4f08481d..0323d82eadf 100644 --- a/tests/manual/trk/trkdevicex.cpp +++ b/tests/manual/trk/trkdevicex.cpp @@ -496,7 +496,6 @@ void TrkDevice::tryTrkRead() while (extractResult(&d->trkReadBuffer, d->serialFrame, &r, &rawData)) { //if (verbose()) // logMessage("Read TrkResult " + r.data.toHex()); - qDebug() << "RECEIVE DATA: " << r.data.toHex(); d->queue.slotHandleResult(r); emit messageReceived(r); if (!rawData.isEmpty()) From 0fc3129b3c18dbc29cf24d461b7b31571c0a834b Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 10:57:33 +0200 Subject: [PATCH 06/43] trk: we always want to be called back independent of ACK/NAK --- tests/manual/trk/runner.cpp | 97 ++++++++++++++++++--------------- tests/manual/trk/trkdevicex.cpp | 22 +++----- tests/manual/trk/trkdevicex.h | 4 +- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index 27fb8e0cfb4..f73f8409363 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -180,8 +180,7 @@ public: void sendTrkMessage(byte code, TrkCallback callback = TrkCallback(), const QByteArray &data = QByteArray(), - const QVariant &cookie = QVariant(), - bool invokeOnFailure = false); + const QVariant &cookie = QVariant()); Q_SLOT void handleTrkResult(const trk::TrkResult &data); Q_SLOT void handleTrkError(const QString &msg); @@ -206,8 +205,9 @@ public: void handleAndReportReadRegisters(const TrkResult &result); QByteArray memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const; QByteArray trkContinueMessage(); - QByteArray trkBreakpointMessage(uint addr, int len, int pid, - bool armMode = true); + QByteArray trkReadRegisterMessage(); + QByteArray trkReadMemoryMessage(uint addr, uint len); + QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true); void handleAndReportSetBreakpoint(const TrkResult &result); void handleReadMemoryBuffered(const TrkResult &result); void handleReadMemoryUnbuffered(const TrkResult &result); @@ -358,6 +358,36 @@ uint Adapter::gdbServerPort() const return m_gdbServerName.mid(pos + 1).toUInt(); } +QByteArray Adapter::trkContinueMessage() +{ + QByteArray ba; + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + return ba; +} + +QByteArray Adapter::trkReadRegisterMessage() +{ + 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 Adapter::trkReadMemoryMessage(uint addr, uint len) +{ + QByteArray ba; + appendByte(&ba, 0x08); // Options, FIXME: why? + appendShort(&ba, len); + appendInt(&ba, addr); + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + return ba; +} + void Adapter::startInferior() { QString errorMessage; @@ -556,7 +586,7 @@ void Adapter::reportToGdb(const TrkResult &result) sendGdbServerMessage(message, note); } -QByteArray Adapter::trkBreakpointMessage(uint addr, int len, int pid, bool armMode) +QByteArray Adapter::trkBreakpointMessage(uint addr, uint len, bool armMode) { QByteArray ba; appendByte(&ba, 0x82); // unused option @@ -564,7 +594,7 @@ QByteArray Adapter::trkBreakpointMessage(uint addr, int len, int pid, bool armMo appendInt(&ba, addr); appendInt(&ba, len); appendInt(&ba, 0x00000001); - appendInt(&ba, pid); + appendInt(&ba, m_session.pid); appendInt(&ba, 0xFFFFFFFF); return ba; } @@ -630,13 +660,8 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) // Read general registers. //sendGdbServerMessage("00000000", "read registers"); sendGdbServerAck(); - 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); - sendTrkMessage(0x12, TrkCB(handleAndReportReadRegisters), ba, QVariant(), true); + sendTrkMessage(0x12, TrkCB(handleAndReportReadRegisters), + trkReadRegisterMessage()); } else if (cmd.startsWith("Hc")) { @@ -787,7 +812,6 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) else if (cmd == "qPacketInfo") { // happens with gdb 6.4.50.20060226-cvs / CodeSourcery // deprecated by qSupported? - sendGdbServerAck(); sendGdbServerMessage("", "FIXME: nothing?"); } @@ -832,9 +856,12 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) } else if (cmd == "s" || cmd.startsWith("vCont;s")) { - if (m_verbose) - logMessage(msgGdbPacket(QLatin1String("Step range"))); + static int used = 0; + if (!used) { + ++used; + logMessage(msgGdbPacket(QLatin1String("Step range"))); sendGdbServerAck(); + m_running = true; QByteArray ba; appendByte(&ba, 0); // options appendInt(&ba, m_snapshot.registers[RegisterPC]); // start address @@ -844,6 +871,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) sendTrkMessage(0x19, TrkCB(handleStepRange), ba, "Step range"); // FIXME: should be triggered by "real" stop" //sendGdbServerMessageAfterTrkResponse("S05", "target halted"); + } } else if (cmd == "vCont?") { @@ -948,6 +976,8 @@ void Adapter::executeCommand(const QString &msg) sendGdbMessage("-exec-interrupt"); } else if (msg == "C") { sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); + } else if (msg == "R") { + sendTrkMessage(0x18, TrkCallback(), trkReadRegisterMessage(), "READ REGS"); } else if (msg == "I") { interruptInferior(); } else { @@ -969,9 +999,9 @@ bool Adapter::openTrkPort(const QString &port, QString *errorMessage) } void Adapter::sendTrkMessage(byte code, TrkCallback callback, - const QByteArray &data, const QVariant &cookie, bool invokeOnFailure) + const QByteArray &data, const QVariant &cookie) { - m_trkDevice.sendTrkMessage(code, callback, data, cookie, invokeOnFailure); + m_trkDevice.sendTrkMessage(code, callback, data, cookie); } void Adapter::waitForTrkFinished() @@ -1310,14 +1340,6 @@ QByteArray Adapter::memoryReadLogMessage(uint addr, uint len, const QByteArray & return logMsg; } -QByteArray Adapter::trkContinueMessage() -{ - QByteArray ba; - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - return ba; -} - void Adapter::reportReadMemoryBuffered(const TrkResult &result) { const qulonglong cookie = result.cookie.toULongLong(); @@ -1368,7 +1390,7 @@ void Adapter::handleStepRange(const TrkResult &result) // [80 0f 12] //uint bpnr = extractInt(result.data.data()); logMessage("STEPPING FINISHED " + stringFromArray(result.data.data())); - sendGdbServerMessage("S05", "Stepping finished"); + //sendGdbServerMessage("S05", "Stepping finished"); } void Adapter::handleAndReportSetBreakpoint(const TrkResult &result) @@ -1514,17 +1536,6 @@ void Adapter::cleanUp() // Error: 0x00 } -static inline QByteArray memoryRequestTrkMessage(uint addr, uint len, int pid, int tid) -{ - QByteArray ba; - appendByte(&ba, 0x08); // Options, FIXME: why? - appendShort(&ba, len); - appendInt(&ba, addr); - appendInt(&ba, pid); - appendInt(&ba, tid); - return ba; -} - void Adapter::readMemory(uint addr, uint len) { Q_ASSERT(len < (2 << 16)); @@ -1543,9 +1554,8 @@ void Adapter::readMemory(uint addr, uint len) "memory %1 bytes from 0x%2") .arg(MemoryChunkSize).arg(blockaddr, 0, 16)); sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered), - memoryRequestTrkMessage(blockaddr, MemoryChunkSize, - m_session.pid, m_session.tid), - QVariant(blockaddr), true); + trkReadMemoryMessage(blockaddr, MemoryChunkSize), + QVariant(blockaddr)); } } const qulonglong cookie = (qulonglong(addr) << 32) + len; @@ -1556,8 +1566,7 @@ void Adapter::readMemory(uint addr, uint len) logMessage(QString::fromLatin1("Requesting unbuffered memory %1 " "bytes from 0x%2").arg(len).arg(addr, 0, 16)); sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered), - memoryRequestTrkMessage(addr, len, m_session.pid, m_session.tid), - QVariant(addr), true); + trkReadMemoryMessage(addr, len), QVariant(addr)); } } @@ -1754,7 +1763,7 @@ void Adapter::handleInfoMainAddress(const GdbResult &result) { bool ok; uint addr = result.data.toInt(&ok, 16); - const QByteArray ba = trkBreakpointMessage(addr, 1, m_session.pid); + const QByteArray ba = trkBreakpointMessage(addr, 1); sendTrkMessage(0x1B, TrkCB(handleSetTrkMainBreakpoint), ba); } diff --git a/tests/manual/trk/trkdevicex.cpp b/tests/manual/trk/trkdevicex.cpp index 0323d82eadf..42c7f72e175 100644 --- a/tests/manual/trk/trkdevicex.cpp +++ b/tests/manual/trk/trkdevicex.cpp @@ -117,14 +117,12 @@ struct TrkMessage QByteArray data; QVariant cookie; Callback callback; - bool invokeOnNAK; }; TrkMessage::TrkMessage(byte c, byte t, Callback cb) : code(c), token(t), - callback(cb), - invokeOnNAK(false) + callback(cb) { } @@ -144,8 +142,7 @@ public: // Enqueue messages. void queueTrkMessage(byte code, Callback callback, - const QByteArray &data, const QVariant &cookie, - bool invokeOnNAK); + const QByteArray &data, const QVariant &cookie); void queueTrkInitialPing(); // Call this from the device read notification with the results. @@ -184,14 +181,13 @@ byte TrkWriteQueue::nextTrkWriteToken() } void TrkWriteQueue::queueTrkMessage(byte code, Callback callback, - const QByteArray &data, const QVariant &cookie, bool invokeOnNAK) + const QByteArray &data, const QVariant &cookie) { const byte token = code == TRK_WRITE_QUEUE_NOOP_CODE ? byte(0) : nextTrkWriteToken(); TrkMessage msg(code, token, callback); msg.data = data; msg.cookie = cookie; - msg.invokeOnNAK = invokeOnNAK; trkWriteQueue.append(msg); } @@ -233,16 +229,14 @@ void TrkWriteQueue::notifyWriteResult(bool ok) void TrkWriteQueue::slotHandleResult(const TrkResult &result) { trkWriteBusy = false; - if (result.code != TrkNotifyAck && result.code != TrkNotifyNak) - return; + //if (result.code != TrkNotifyAck && result.code != TrkNotifyNak) + // return; // Find which request the message belongs to and invoke callback // if ACK or on NAK if desired. const TokenMessageMap::iterator it = writtenTrkMessages.find(result.token); if (it == writtenTrkMessages.end()) return; - const bool invokeCB = it.value().callback - && (result.code == TrkNotifyAck || it.value().invokeOnNAK); - + const bool invokeCB = it.value().callback; if (invokeCB) { TrkResult result1 = result; result1.cookie = it.value().cookie; @@ -517,9 +511,9 @@ void TrkDevice::emitError(const QString &s) } void TrkDevice::sendTrkMessage(byte code, Callback callback, - const QByteArray &data, const QVariant &cookie, bool invokeOnNAK) + const QByteArray &data, const QVariant &cookie) { - d->queue.queueTrkMessage(code, callback, data, cookie, invokeOnNAK); + d->queue.queueTrkMessage(code, callback, data, cookie); } void TrkDevice::sendTrkInitialPing() diff --git a/tests/manual/trk/trkdevicex.h b/tests/manual/trk/trkdevicex.h index 1873f458e7c..5a7a7440775 100644 --- a/tests/manual/trk/trkdevicex.h +++ b/tests/manual/trk/trkdevicex.h @@ -104,9 +104,7 @@ public: void sendTrkMessage(unsigned char code, Callback callBack = Callback(), const QByteArray &data = QByteArray(), - const QVariant &cookie = QVariant(), - // Invoke callback on receiving NAK, too. - bool invokeOnNAK = false); + const QVariant &cookie = QVariant()); // Enqeue an initial ping void sendTrkInitialPing(); From a1ea6f5f1f864c8d0e641de3420a5c30662a959c Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 12:49:03 +0200 Subject: [PATCH 07/43] trk: refactoring --- tests/manual/trk/runner.cpp | 54 +++++++++++++++++++---------------- tests/manual/trk/trkutils.cpp | 16 +++++++++++ tests/manual/trk/trkutils.h | 2 ++ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index f73f8409363..a0bcef7f302 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -108,7 +108,7 @@ static QByteArray dumpRegister(int n, uint value) ba += '#'; ba += QByteArray::number(n); } - ba += "=0x" + hexNumber(value); + ba += "=" + hexxNumber(value); return ba; } @@ -856,22 +856,19 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) } else if (cmd == "s" || cmd.startsWith("vCont;s")) { - static int used = 0; - if (!used) { - ++used; logMessage(msgGdbPacket(QLatin1String("Step range"))); + logMessage(" from " + hexxNumber(m_snapshot.registers[RegisterPC])); sendGdbServerAck(); m_running = true; QByteArray ba; - appendByte(&ba, 0); // options + appendByte(&ba, 1); // options appendInt(&ba, m_snapshot.registers[RegisterPC]); // start address - appendInt(&ba, m_snapshot.registers[RegisterPC] + 8); // end address + appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); sendTrkMessage(0x19, TrkCB(handleStepRange), ba, "Step range"); // FIXME: should be triggered by "real" stop" //sendGdbServerMessageAfterTrkResponse("S05", "target halted"); - } } else if (cmd == "vCont?") { @@ -977,7 +974,8 @@ void Adapter::executeCommand(const QString &msg) } else if (msg == "C") { sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); } else if (msg == "R") { - sendTrkMessage(0x18, TrkCallback(), trkReadRegisterMessage(), "READ REGS"); + sendTrkMessage(0x18, TrkCB(handleReadRegisters), + trkReadRegisterMessage(), "READ REGS"); } else if (msg == "I") { interruptInferior(); } else { @@ -1095,8 +1093,8 @@ void Adapter::handleTrkResult(const TrkResult &result) if (error) str << " ERROR: " << int(error); str << " TYPE: " << int(type) << " PID: " << pid << " TID: " << tid; - str << " CODE: 0x" << hexNumber(codeseg); - str << " DATA: 0x" << hexNumber(dataseg); + str << " CODE: " << hexxNumber(codeseg); + str << " DATA: " << hexxNumber(dataseg); str << " NAME: '" << name << '\''; logMessage(logMsg); // This lets gdb trigger a register update etc @@ -1198,7 +1196,7 @@ void Adapter::handleSetTrkBreakpoint(const TrkResult &result) // [80 09 00 00 00 00 0A] const uint bpnr = extractInt(result.data.data()); if (m_verbose) - logMessage("SET BREAKPOINT 0x" + hexNumber(bpnr) + logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + stringFromArray(result.data.data())); } @@ -1213,10 +1211,10 @@ void Adapter::handleCreateProcess(const TrkResult &result) m_session.codeseg = extractInt(data + 9); m_session.dataseg = extractInt(data + 13); - logMessage("PID: 0x" + hexNumber(m_session.pid)); - logMessage("TID: 0x" + hexNumber(m_session.tid)); - logMessage("COD: 0x" + hexNumber(m_session.codeseg)); - logMessage("DAT: 0x" + hexNumber(m_session.dataseg)); + logMessage("PID: " + hexxNumber(m_session.pid)); + logMessage("TID: " + hexxNumber(m_session.tid)); + logMessage("COD: " + hexxNumber(m_session.codeseg)); + logMessage("DAT: " + hexxNumber(m_session.dataseg)); QByteArray ba; appendInt(&ba, m_session.pid); @@ -1263,7 +1261,10 @@ void Adapter::handleReadRegisters(const TrkResult &result) logMessage(" RESULT: " + result.toString()); // [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...] - + if (result.errorCode()) { + logMessage("ERROR: " + result.errorString()); + return; + } const char *data = result.data.data() + 1; // Skip ok byte for (int i = 0; i < RegisterCount; ++i) m_snapshot.registers[i] = extractInt(data + 4 * i); @@ -1313,8 +1314,7 @@ QByteArray Adapter::memoryReadLogMessage(uint addr, uint len, const QByteArray & { QByteArray logMsg = "memory contents"; if (m_verbose > 1) { - logMsg += " addr: 0x"; - logMsg += QByteArray::number(addr, 16); + logMsg += " addr: " + hexxNumber(addr); // indicate dereferencing of registers if (len == 4) { if (addr == m_snapshot.registers[RegisterPC]) { @@ -1387,9 +1387,12 @@ void Adapter::handleReadMemoryUnbuffered(const TrkResult &result) void Adapter::handleStepRange(const TrkResult &result) { - // [80 0f 12] - //uint bpnr = extractInt(result.data.data()); - logMessage("STEPPING FINISHED " + stringFromArray(result.data.data())); + // [80 0f 00] + if (result.errorCode()) { + logMessage("ERROR: " + result.errorString()); + return; + } + logMessage("STEPPING FINISHED "); //sendGdbServerMessage("S05", "Stepping finished"); } @@ -1400,7 +1403,7 @@ void Adapter::handleAndReportSetBreakpoint(const TrkResult &result) // Error: 0x00 // [80 09 00 00 00 00 0A] uint bpnr = extractByte(result.data.data()); - logMessage("SET BREAKPOINT 0x" + hexNumber(bpnr) + " " + logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + " " + stringFromArray(result.data.data())); sendGdbServerMessage("OK"); } @@ -1656,6 +1659,7 @@ void Adapter::startGdb() sendGdbMessage("set endian little"); sendGdbMessage("set remotebreak on"); sendGdbMessage("set breakpoint pending on"); + sendGdbMessage("set trust-readonly-sections on"); // FIXME: "remote noack" does not seem to be supported on cs-gdb? //sendGdbMessage("set remote noack-packet"); @@ -1677,8 +1681,8 @@ void Adapter::startGdb() //sendGdbMessage("info files"); //sendGdbMessage("file filebrowseapp.sym -readnow"); - sendGdbMessage("add-symbol-file filebrowseapp.sym 0x" - + hexNumber(m_session.codeseg)); + sendGdbMessage("add-symbol-file filebrowseapp.sym " + + hexxNumber(m_session.codeseg)); sendGdbMessage("symbol-file filebrowseapp.sym"); // -symbol-info-address not implemented in cs-gdb 6.4-6.8 (at least) @@ -1772,7 +1776,7 @@ void Adapter::handleSetTrkMainBreakpoint(const TrkResult &result) //---TRK------------------------------------------------------ // [80 09 00 00 00 00 0A] const uint bpnr = extractInt(result.data.data()); - logMessage("SET MAIN BREAKPOINT 0x" + hexNumber(bpnr) + logMessage("SET MAIN BREAKPOINT " + hexxNumber(bpnr) + stringFromArray(result.data.data())); // 'continue after initial break' diff --git a/tests/manual/trk/trkutils.cpp b/tests/manual/trk/trkutils.cpp index 81925c07d67..4036b2ad656 100644 --- a/tests/manual/trk/trkutils.cpp +++ b/tests/manual/trk/trkutils.cpp @@ -43,6 +43,11 @@ QByteArray hexNumber(uint n, int digits) return QByteArray(digits - ba.size(), '0') + ba; } +QByteArray hexxNumber(uint n, int digits) +{ + return "0x" + hexNumber(n, digits); +} + TrkResult::TrkResult() : code(0), token(0), @@ -345,5 +350,16 @@ int TrkResult::errorCode() const return errorCode; return isNAK ? 0xff : 0; } + +QString TrkResult::errorString() const +{ + // NAK means always error, else data sized 1 with a non-null element + if (code == 0xff) + return "NAK"; + if (data.size() < 1) + return "Unknown error packet"; + return errorMessage(data.at(0)); +} + } // namespace trk diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h index 6bc05db157d..3ed06e3ca4a 100644 --- a/tests/manual/trk/trkutils.h +++ b/tests/manual/trk/trkutils.h @@ -178,6 +178,7 @@ struct TrkResult QString toString() const; // 0 for no error. int errorCode() const; + QString errorString() const; byte code; byte token; @@ -193,6 +194,7 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame); bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, QByteArray *rawData = 0); QByteArray errorMessage(byte code); QByteArray hexNumber(uint n, int digits = 0); +QByteArray hexxNumber(uint n, int digits = 0); // prepends '0x', too uint swapEndian(uint in); From ae09799416aaed3e506038b33f59d2ed8f2aff9b Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 13:08:58 +0200 Subject: [PATCH 08/43] trk: make ad-hoc UI a bit friendlier --- tests/manual/trk/runner.cpp | 103 ++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 34 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index a0bcef7f302..74ba1954eea 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -30,7 +30,6 @@ #include "trkutils.h" #include "trkdevicex.h" -#include #include #include #include @@ -43,10 +42,13 @@ #include #include +#include #include +#include #include #include #include +#include #include #include @@ -281,7 +283,7 @@ public: Q_SLOT void handleRfcommReadyReadStandardOutput(); // Debuggee state - void executeCommand(const QString &msg); + Q_SLOT void executeCommand(const QString &msg); Session m_session; // global-ish data (process id, target information) Snapshot m_snapshot; // local-ish data (memory and registers) int m_verbose; @@ -1813,57 +1815,90 @@ void Adapter::handleRfcommReadyReadStandardOutput() // /////////////////////////////////////////////////////////////////////// -class RunnerGui : public QTextEdit +class TextEdit : public QTextEdit +{ + Q_OBJECT + +signals: + void executeCommand(QString); + +public slots: + void handleOutput(const QString &senderName, const QString &data) + { + QString str = senderName + data; + str.replace("\\t", QString(QChar(0x09))); + str.replace("\\n", QString("\n")); + append(str); + + QTextCursor tc = textCursor(); + tc.movePosition(QTextCursor::End); + setTextCursor(tc); + /* + int pos1 = str.indexOf("#"); + int pos2 = str.indexOf(")", pos1); + if (pos1 != -1 && pos2 != -1) + str = str.left(pos1) + "" + str.mid(pos1, pos2 - pos1 + 1) + + " " + str.mid(pos2 + 1); + insertHtml(str + "\n"); + */ + setCurrentCharFormat(QTextCharFormat()); + ensureCursorVisible(); + } + + void keyPressEvent(QKeyEvent *ev) + { + if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return) + emit executeCommand(textCursor().block().text()); + else + QTextEdit::keyPressEvent(ev); + } +}; + +/////////////////////////////////////////////////////////////////////// +// +// RunnerGui +// +/////////////////////////////////////////////////////////////////////// + +class RunnerGui : public QMainWindow { Q_OBJECT public: RunnerGui(Adapter *adapter); - void keyPressEvent(QKeyEvent *ev); private slots: - void handleOutput(const QString &senderName, const QString &data); + void executeStepICommand(); private: Adapter *m_adapter; + TextEdit m_textEdit; + QToolBar m_toolBar; + QAction m_stepIAction; }; RunnerGui::RunnerGui(Adapter *adapter) - : m_adapter(adapter) + : m_adapter(adapter), m_stepIAction(0) { resize(1200, 1000); + setCentralWidget(&m_textEdit); + + addToolBar(&m_toolBar); + + m_stepIAction.setText("StepI"); + m_toolBar.addAction(&m_stepIAction); + connect(adapter, SIGNAL(output(QString,QString)), - this, SLOT(handleOutput(QString,QString))); + &m_textEdit, SLOT(handleOutput(QString,QString))); + connect(&m_textEdit, SIGNAL(executeCommand(QString)), + m_adapter, SLOT(executeCommand(QString))); + connect(&m_stepIAction, SIGNAL(triggered()), + this, SLOT(executeStepICommand())); } -void RunnerGui::handleOutput(const QString &senderName, const QString &data) +void RunnerGui::executeStepICommand() { - append(senderName + data); - QTextCursor tc = textCursor(); - tc.movePosition(QTextCursor::End); - setTextCursor(tc); -/* - QString str = data; - int pos1 = str.indexOf("#"); - int pos2 = str.indexOf(")", pos1); - if (pos1 != -1 && pos2 != -1) - str = str.left(pos1) + "" + str.mid(pos1, pos2 - pos1 + 1) - + " " + str.mid(pos2 + 1); - str.replace("\\t", QString(QChar(0x09))); - str.replace("\\n", QString("\n")); - insertHtml(str + "\n"); -*/ - setCurrentCharFormat(QTextCharFormat()); - ensureCursorVisible(); - -} - -void RunnerGui::keyPressEvent(QKeyEvent *ev) -{ - if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return) - m_adapter->executeCommand(textCursor().block().text()); - else - QTextEdit::keyPressEvent(ev); + m_adapter->executeCommand("stepi"); } /////////////////////////////////////////////////////////////////////// From 087eca4566f70ab95819b4f1c584bbc714b786e5 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 8 Sep 2009 14:45:19 +0200 Subject: [PATCH 09/43] trk: step-by-instruction --- tests/manual/trk/runner.cpp | 111 +++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index 74ba1954eea..9d2d719d88d 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -230,8 +230,6 @@ public: TrkDevice m_trkDevice; - QList m_breakpoints; - // // Gdb // @@ -302,9 +300,6 @@ Adapter::Adapter() m_serialFrame = false; m_bufferedMemoryRead = true; //m_bufferedMemoryRead = false; - // m_breakpoints.append(Breakpoint(0x0040)); // E32Main - m_breakpoints.append(Breakpoint(0x0cc8)); // E32Main - m_breakpoints.append(Breakpoint(0x0cd0)); // E32Main m_trkServerName = "/dev/rfcomm0"; uid_t userId = getuid(); @@ -863,9 +858,10 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) sendGdbServerAck(); m_running = true; QByteArray ba; - appendByte(&ba, 1); // options + appendByte(&ba, 0x01); // options appendInt(&ba, m_snapshot.registers[RegisterPC]); // start address - appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address + //appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address + appendInt(&ba, -1); // end address appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); sendTrkMessage(0x19, TrkCB(handleStepRange), ba, "Step range"); @@ -911,10 +907,9 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) bool ok = false; const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); const uint len = cmd.mid(pos + 1).toInt(&ok, 16); - qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len; - if (m_verbose) - logMessage(QString::fromLatin1("Inserting breakpoint at 0x%1, %2") - .arg(addr, 0, 16).arg(len)); + //qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len; + logMessage(QString::fromLatin1("Inserting breakpoint at 0x%1, %2") + .arg(addr, 0, 16).arg(len)); //---IDE------------------------------------------------------ // Command: 0x1B Set Break @@ -1060,8 +1055,7 @@ void Adapter::handleTrkResult(const TrkResult &result) sendGdbServerMessage("S05", "Target stopped"); } } else { - if (m_verbose) - logMessage(QLatin1String("Ignoring stop at 0")); + logMessage(QLatin1String("Ignoring stop at 0")); } break; } @@ -1197,9 +1191,8 @@ void Adapter::handleSetTrkBreakpoint(const TrkResult &result) // Error: 0x00 // [80 09 00 00 00 00 0A] const uint bpnr = extractInt(result.data.data()); - if (m_verbose) - logMessage("SET BREAKPOINT " + hexxNumber(bpnr) - + stringFromArray(result.data.data())); + logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + + stringFromArray(result.data.data())); } void Adapter::handleCreateProcess(const TrkResult &result) @@ -1502,8 +1495,8 @@ void Adapter::cleanUp() // Error: 0x00 // [80 24 00] - foreach (const Breakpoint &bp, m_breakpoints) - clearTrkBreakpoint(bp); + //foreach (const Breakpoint &bp, m_breakpoints) + // clearTrkBreakpoint(bp); sendTrkMessage(0x02, TrkCB(handleDisconnect)); //---IDE------------------------------------------------------ @@ -1662,6 +1655,7 @@ void Adapter::startGdb() sendGdbMessage("set remotebreak on"); sendGdbMessage("set breakpoint pending on"); sendGdbMessage("set trust-readonly-sections on"); + //sendGdbMessage("mem 0 ~0ll rw 8 cache"); // FIXME: "remote noack" does not seem to be supported on cs-gdb? //sendGdbMessage("set remote noack-packet"); @@ -1688,24 +1682,21 @@ void Adapter::startGdb() sendGdbMessage("symbol-file filebrowseapp.sym"); // -symbol-info-address not implemented in cs-gdb 6.4-6.8 (at least) - sendGdbMessage("info address E32Main", GdbCB(handleInfoMainAddress)); + sendGdbMessage("info address E32Main", + GdbCB(handleInfoMainAddress)); + sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL", + GdbCB(handleInfoMainAddress)); #if 1 // FIXME: Gdb based version. That's the goal //sendGdbMessage("break E32Main"); //sendGdbMessage("continue"); - QByteArray ba; - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); //sendTrkMessage(0x18, TrkCB(handleContinueAfterCreateProcess), // trkContinueMessage(), "CONTINUE"); #else // Directly talk to TRK. Works for now... sendGdbMessage("break E32Main"); sendGdbMessage("break filebrowseappui.cpp:39"); - //foreach (const Breakpoint &bp, m_breakpoints) - // setTrkBreakpoint(bp); - //sendTrkContinue(); // sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); #endif } @@ -1753,42 +1744,43 @@ void Adapter::handleGdbReadyReadStandardOutput() if (!cmd.callback.isNull()) cmd.callback(result); #else + bool ok; QRegExp re(QString("Symbol .._Z7E32Mainv.. is a function at address 0x(.*)\\.")); - if (re.indexIn(str) == -1) { - logMessage(QString("-> GDB: %1").arg(str)); + if (re.indexIn(str) != -1) { + logMessage(QString("-> GDB MAIN BREAKPOINT: %1").arg(re.cap(1))); + uint addr = re.cap(1).toInt(&ok, 16); + sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); return; } - logMessage(QString("-> GDB MAIN: %1").arg(re.cap(1))); - GdbResult result; - result.data = re.cap(1).toLatin1(); - handleInfoMainAddress(result); + QRegExp re1(QString("Symbol .._ZN16CFileBrowseAppUi14HandleCommandLEi.. is a function at address 0x(.*)\\.")); + if (re1.indexIn(str) != -1) { + logMessage(QString("-> GDB USER BREAKPOINT: %1").arg(re1.cap(1))); + uint addr = re1.cap(1).toInt(&ok, 16); + sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); + + sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); + sendGdbMessage("target remote " + m_gdbServerName); + return; + } + logMessage(QString("-> GDB: %1").arg(str)); #endif } void Adapter::handleInfoMainAddress(const GdbResult &result) { - bool ok; - uint addr = result.data.toInt(&ok, 16); - const QByteArray ba = trkBreakpointMessage(addr, 1); - sendTrkMessage(0x1B, TrkCB(handleSetTrkMainBreakpoint), ba); + Q_UNUSED(result); } void Adapter::handleSetTrkMainBreakpoint(const TrkResult &result) { + Q_UNUSED(result); +/* //---TRK------------------------------------------------------ // [80 09 00 00 00 00 0A] const uint bpnr = extractInt(result.data.data()); logMessage("SET MAIN BREAKPOINT " + hexxNumber(bpnr) + stringFromArray(result.data.data())); - - // 'continue after initial break' - QByteArray ba; - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - sendTrkMessage(0x18, TrkCallback(), ba, "CONTINUE"); - - // this attaches - sendGdbMessage("target remote " + m_gdbServerName); +*/ } void Adapter::handleInfoAddress(const GdbResult &result) @@ -1869,16 +1861,23 @@ public: private slots: void executeStepICommand(); + void executeStepCommand(); + void executeDisassICommand(); private: Adapter *m_adapter; TextEdit m_textEdit; QToolBar m_toolBar; QAction m_stepIAction; + QAction m_stepAction; + QAction m_disassIAction; }; RunnerGui::RunnerGui(Adapter *adapter) - : m_adapter(adapter), m_stepIAction(0) + : m_adapter(adapter), + m_stepIAction(0), + m_stepAction(0), + m_disassIAction(0) { resize(1200, 1000); setCentralWidget(&m_textEdit); @@ -1886,19 +1885,39 @@ RunnerGui::RunnerGui(Adapter *adapter) addToolBar(&m_toolBar); m_stepIAction.setText("StepI"); + m_disassIAction.setText("DisassI"); m_toolBar.addAction(&m_stepIAction); + m_toolBar.addAction(&m_stepAction); + m_toolBar.addAction(&m_disassIAction); connect(adapter, SIGNAL(output(QString,QString)), &m_textEdit, SLOT(handleOutput(QString,QString))); connect(&m_textEdit, SIGNAL(executeCommand(QString)), m_adapter, SLOT(executeCommand(QString))); + connect(&m_stepIAction, SIGNAL(triggered()), this, SLOT(executeStepICommand())); + connect(&m_stepAction, SIGNAL(triggered()), + this, SLOT(executeStepCommand())); + connect(&m_disassIAction, SIGNAL(triggered()), + this, SLOT(executeDisassICommand())); +} + +void RunnerGui::executeStepCommand() +{ + //m_adapter->executeCommand("stepi"); + m_adapter->executeCommand("-exec-step"); } void RunnerGui::executeStepICommand() { - m_adapter->executeCommand("stepi"); + //m_adapter->executeCommand("stepi"); + m_adapter->executeCommand("-exec-step-instruction"); +} + +void RunnerGui::executeDisassICommand() +{ + m_adapter->executeCommand("disass $pc $pc+4"); } /////////////////////////////////////////////////////////////////////// From f1c881c4e08af3949bfd438e9d9b5c29012ab9d8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 8 Sep 2009 14:13:50 +0200 Subject: [PATCH 10/43] cache_valuemap doesn't have to be a member any more --- src/shared/proparser/profileevaluator.cpp | 5 +++-- src/shared/proparser/profileevaluator.h | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index c4718c08495..948ff00cf30 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -1139,10 +1139,11 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr } if (!qmake_cache.isEmpty()) { qmake_cache = QDir::cleanPath(qmake_cache); - if (evaluateFileInto(qmake_cache, &m_option->cache_valuemap, 0)) { + QHash cache_valuemap; + if (evaluateFileInto(qmake_cache, &cache_valuemap, 0)) { m_option->cachefile = qmake_cache; if (m_option->qmakespec.isEmpty()) { - const QStringList &vals = m_option->cache_valuemap.value(QLatin1String("QMAKESPEC")); + const QStringList &vals = cache_valuemap.value(QLatin1String("QMAKESPEC")); if (!vals.isEmpty()) m_option->qmakespec = vals.first(); } diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h index cba159c6b8f..691dd78e02b 100644 --- a/src/shared/proparser/profileevaluator.h +++ b/src/shared/proparser/profileevaluator.h @@ -88,8 +88,7 @@ public: friend class ProFileEvaluator; friend class ProFileEvaluator::Private; static QString field_sep; // Just a cache for quick construction - QHash cache_valuemap; // Cached results of .qmake.cache - QHash base_valuemap; // ~ and qmake.conf and default_pre.prf + QHash base_valuemap; // Cached results of qmake.conf, .qmake.cache & default_pre.prf FunctionDefs base_functions; QStringList feature_roots; }; From 37c5e2ddd32ae3ebad15d7226f2d5387710d65ec Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 8 Sep 2009 14:18:06 +0200 Subject: [PATCH 11/43] revert acd090200 - no crash or even memory corruption reproducible --- src/shared/proparser/profileevaluator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 948ff00cf30..7495bcc7bfd 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -1198,7 +1198,8 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr &m_option->base_valuemap, &m_option->base_functions)) { errorMessage(format("Could not read qmake configuration file %1").arg(spec)); } else { - evaluateFileInto(qmake_cache, &m_option->base_valuemap, 0); + evaluateFileInto(qmake_cache, + &m_option->base_valuemap, &m_option->base_functions); } } From 2513c0a93f2fabbe4a0fad1433d36c8f7c0949d3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 8 Sep 2009 14:19:34 +0200 Subject: [PATCH 12/43] don't attempt to read qmake cache if there is none evaluating a file (which might not exist) is a bit different than just merging a (possibly empty) map ... --- src/shared/proparser/profileevaluator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 7495bcc7bfd..d536a03ef0f 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -1197,8 +1197,8 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr if (!evaluateFileInto(spec, &m_option->base_valuemap, &m_option->base_functions)) { errorMessage(format("Could not read qmake configuration file %1").arg(spec)); - } else { - evaluateFileInto(qmake_cache, + } else if (!m_option->cachefile.isEmpty()) { + evaluateFileInto(m_option->cachefile, &m_option->base_valuemap, &m_option->base_functions); } } From 5d26f533688cca90914c335f26ee6112c6cd292f Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 9 Sep 2009 11:46:18 +0200 Subject: [PATCH 13/43] trk: progress in breakpoint setting; removal of unused code --- tests/manual/trk/runner.cpp | 254 +++++++++++++----------------------- tests/manual/trk/trkutils.h | 2 +- 2 files changed, 91 insertions(+), 165 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index 9d2d719d88d..bf55d0b6f40 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -141,7 +141,6 @@ public: void setGdbServerName(const QString &name); QString gdbServerIP() const; uint gdbServerPort() const; - void setTrkServerName(const QString &name) { m_trkServerName = name; } void setVerbose(int verbose) { m_verbose = verbose; } void setSerialFrame(bool b) { m_serialFrame = b; } void setRegisterEndianness(Endianness r) { m_registerEndianness = r; } @@ -167,7 +166,7 @@ private: void sendOutput(QObject *sender, const QString &data); void sendOutput(const QString &data) { sendOutput(0, data); } - QString m_trkServerName; // + QString m_rfcommDevice; // /dev/rfcomm0 QString m_gdbServerName; // 127.0.0.1:(2222+uid) QProcess m_gdbProc; @@ -178,7 +177,6 @@ public: // // TRK // - bool openTrkPort(const QString &port, QString *errorMessage); void sendTrkMessage(byte code, TrkCallback callback = TrkCallback(), const QByteArray &data = QByteArray(), @@ -187,17 +185,12 @@ public: Q_SLOT void handleTrkError(const QString &msg); // convenience messages - void waitForTrkFinished(); void sendTrkAck(byte token); - // kill process and breakpoints - void cleanUp(); - void handleCpuType(const TrkResult &result); void handleCreateProcess(const TrkResult &result); void handleClearBreakpoint(const TrkResult &result); void handleSignalContinue(const TrkResult &result); - void handleWaitForFinished(const TrkResult &result); void handleStop(const TrkResult &result); void handleSupportMask(const TrkResult &result); void handleTrkVersions(const TrkResult &result); @@ -218,8 +211,6 @@ public: void reportReadMemoryBuffered(const TrkResult &result); void reportToGdb(const TrkResult &result); - void clearTrkBreakpoint(const Breakpoint &bp); - // set breakpoints behind gdb's back void setTrkBreakpoint(const Breakpoint &bp); void handleSetTrkBreakpoint(const TrkResult &result); @@ -296,11 +287,9 @@ Adapter::Adapter() m_gdbAckMode = true; m_verbose = 2; m_registerEndianness = LittleEndian; - //m_serialFrame = true; m_serialFrame = false; m_bufferedMemoryRead = true; - //m_bufferedMemoryRead = false; - m_trkServerName = "/dev/rfcomm0"; + m_rfcommDevice = "/dev/rfcomm0"; uid_t userId = getuid(); m_gdbServerName = QString("127.0.0.1:%1").arg(2222 + userId); @@ -319,6 +308,10 @@ Adapter::Adapter() connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()), this, SLOT(handleRfcommReadyReadStandardOutput())); + if (m_verbose > 1) + m_trkDevice.setVerbose(true); + m_trkDevice.setSerialFrame(m_serialFrame); + connect(&m_trkDevice, SIGNAL(logMessage(QString)), this, SLOT(trkLogMessage(QString))); } @@ -388,8 +381,7 @@ QByteArray Adapter::trkReadMemoryMessage(uint addr, uint len) void Adapter::startInferior() { QString errorMessage; - if (!openTrkPort(m_trkServerName, &errorMessage)) { - logMessage(errorMessage, true); + if (!m_trkDevice.open(m_rfcommDevice, &errorMessage)) { logMessage("LOOPING"); QTimer::singleShot(1000, this, SLOT(startInferior())); return; @@ -800,7 +792,7 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) else sendGdbServerMessage( "PacketSize=7cf;" - //"QPassSignals+;" + "QPassSignals+;" "qXfer:libraries:read+;" //"qXfer:auxv:read+;" "qXfer:features:read+"); @@ -872,8 +864,8 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) else if (cmd == "vCont?") { // actions supported by the vCont packet sendGdbServerAck(); - sendGdbServerMessage("OK"); // we don't support vCont. - //sendGdbServerMessage("vCont;c"); + //sendGdbServerMessage("OK"); // we don't support vCont. + sendGdbServerMessage("vCont;c;C;s;S"); } else if (cmd == "vCont;c") { @@ -899,10 +891,10 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) } else if (cmd.startsWith("Z0,") || cmd.startsWith("Z1,")) { + sendGdbServerAck(); // Insert breakpoint - if (m_verbose) - logMessage(msgGdbPacket(QLatin1String("Insert breakpoint"))); - // $z0,786a4ccc,4#99 + logMessage(msgGdbPacket(QLatin1String("Insert breakpoint"))); + // $Z0,786a4ccc,4#99 const int pos = cmd.lastIndexOf(','); bool ok = false; const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); @@ -923,14 +915,40 @@ void Adapter::handleGdbServerCommand(const QByteArray &cmd) // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00 // 00 00 01 B5 FF FF FF FF] const QByteArray ba = trkBreakpointMessage(addr, len, m_session.pid); - sendTrkMessage(0x1B, TrkCB(handleAndReportSetBreakpoint), ba); - //m_session.toekn - + sendTrkMessage(0x1B, TrkCB(handleAndReportSetBreakpoint), ba, addr); //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge // Error: 0x00 // [80 09 00 00 00 00 0A] - } else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:")) { + } + + else if (cmd.startsWith("z0,") || cmd.startsWith("z1,")) { + sendGdbServerAck(); + // Remove breakpoint + logMessage(msgGdbPacket(QLatin1String("Remove breakpoint"))); + // $z0,786a4ccc,4#99 + const int pos = cmd.lastIndexOf(','); + bool ok = false; + const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); + const uint len = cmd.mid(pos + 1).toInt(&ok, 16); + const uint bp = m_session.addressToBP[addr]; + if (bp == 0) { + logMessage(QString::fromLatin1("NO RECORDED BP AT 0x%1, %2") + .arg(addr, 0, 16).arg(len)); + } else { + //---IDE------------------------------------------------------ + // Command: 0x1C Clear Break + // [1C 25 00 00 00 0A 78 6A 43 40] + m_session.addressToBP.remove(addr); + QByteArray ba; + appendByte(&ba, 0x00); + appendShort(&ba, bp); + appendInt(&ba, addr); + sendTrkMessage(0x1C, TrkCB(handleClearBreakpoint), ba, addr); + } + } + + else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:")) { QByteArray data = cmd.mid(1 + cmd.indexOf(':')); // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux) bool handled = false; @@ -981,30 +999,12 @@ void Adapter::executeCommand(const QString &msg) } } -bool Adapter::openTrkPort(const QString &port, QString *errorMessage) -{ - connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)), - this, SLOT(handleTrkResult(trk::TrkResult))); - connect(&m_trkDevice, SIGNAL(error(QString)), - this, SLOT(handleTrkError(QString))); - if (m_verbose > 1) - m_trkDevice.setVerbose(true); - m_trkDevice.setSerialFrame(m_serialFrame); - return m_trkDevice.open(port, errorMessage); -} - void Adapter::sendTrkMessage(byte code, TrkCallback callback, const QByteArray &data, const QVariant &cookie) { m_trkDevice.sendTrkMessage(code, callback, data, cookie); } -void Adapter::waitForTrkFinished() -{ - // initiate one last roundtrip to ensure all is flushed - sendTrkMessage(0x0, TrkCB(handleWaitForFinished)); -} - void Adapter::sendTrkAck(byte token) { logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token))); @@ -1398,31 +1398,27 @@ void Adapter::handleAndReportSetBreakpoint(const TrkResult &result) // Error: 0x00 // [80 09 00 00 00 00 0A] uint bpnr = extractByte(result.data.data()); + uint addr = result.cookie.toUInt(); + m_session.addressToBP[addr] = bpnr; logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + " " + stringFromArray(result.data.data())); sendGdbServerMessage("OK"); -} - -void Adapter::clearTrkBreakpoint(const Breakpoint &bp) -{ - //---IDE------------------------------------------------------ - // Command: 0x1C Clear Break - // [1C 25 00 00 00 0A 78 6A 43 40] - QByteArray ba; - appendByte(&ba, 0x00); - appendShort(&ba, bp.number); - appendInt(&ba, m_session.codeseg + bp.offset); - sendTrkMessage(0x1C, TrkCB(handleClearBreakpoint), ba); + //sendGdbServerMessage("OK"); } void Adapter::handleClearBreakpoint(const TrkResult &result) { - Q_UNUSED(result); + logMessage("CLEAR BREAKPOINT "); + if (result.errorCode()) { + logMessage("ERROR: " + result.errorString()); + //return; + } //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge // Error: 0x00 // [80 09 00 00 00 00 0A] - logMessage("CLEAR BREAKPOINT "); + // FIXME: + sendGdbServerMessage("OK"); } void Adapter::handleSignalContinue(const TrkResult &result) @@ -1434,12 +1430,6 @@ void Adapter::handleSignalContinue(const TrkResult &result) sendGdbServerMessage("W81"); // "Process exited with result 1 } -void Adapter::handleWaitForFinished(const TrkResult &result) -{ - logMessage(" FINISHED: " + stringFromArray(result.data)); - //qApp->exit(1); -} - void Adapter::handleSupportMask(const TrkResult &result) { const char *data = result.data.data(); @@ -1472,68 +1462,6 @@ void Adapter::handleDisconnect(const TrkResult & /*result*/) logMessage(QLatin1String("Trk disconnected"), true); } -void Adapter::cleanUp() -{ - // - //---IDE------------------------------------------------------ - // Command: 0x41 Delete Item - // Sub Cmd: Delete Process - //ProcessID: 0x0000071F (1823) - // [41 24 00 00 00 00 07 1F] - logMessage(QString::fromLatin1("Cleanup PID=%1").arg(m_session.pid), true); - if (!m_session.pid) - return; - - QByteArray ba; - appendByte(&ba, 0x00); - appendByte(&ba, 0x00); - appendInt(&ba, m_session.pid); - sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); - - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 24 00] - - //foreach (const Breakpoint &bp, m_breakpoints) - // clearTrkBreakpoint(bp); - - sendTrkMessage(0x02, TrkCB(handleDisconnect)); - //---IDE------------------------------------------------------ - // Command: 0x1C Clear Break - // [1C 25 00 00 00 0A 78 6A 43 40] - - //---TRK------------------------------------------------------ - // Command: 0xA1 Notify Deleted - // [A1 09 00 00 00 00 00 00 00 00 07 1F] - //---IDE------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 09 00] - - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 25 00] - - //---IDE------------------------------------------------------ - // Command: 0x1C Clear Break - // [1C 26 00 00 00 0B 78 6A 43 70] - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 26 00] - - - //---IDE------------------------------------------------------ - // Command: 0x02 Disconnect - // [02 27] -// sendTrkMessage(0x02, TrkCB(handleDisconnect)); - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 -} - void Adapter::readMemory(uint addr, uint len) { Q_ASSERT(len < (2 << 16)); @@ -1622,9 +1550,16 @@ void Adapter::handleProcStateChanged(QProcess::ProcessState newState) void Adapter::run() { - startInferior(); sendOutput("### Starting Adapter"); - m_rfcommProc.start("rfcomm listen /dev/rfcomm0 1"); + m_rfcommProc.start("rfcomm listen " + m_rfcommDevice + " 1"); + m_rfcommProc.waitForStarted(); + + connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)), + this, SLOT(handleTrkResult(trk::TrkResult))); + connect(&m_trkDevice, SIGNAL(error(QString)), + this, SLOT(handleTrkError(QString))); + + startInferior(); } void Adapter::startGdb() @@ -1710,7 +1645,7 @@ void Adapter::sendGdbMessage(const QString &msg, GdbCallback callback, data.command = msg; data.callback = callback; data.cookie = cookie; - m_gdbCookieForToken[++token] = data; + m_gdbCookieForToken[token] = data; logMessage(QString("<- GDB: %1 %2").arg(token).arg(msg)); m_gdbProc.write(QString("%1%2\n").arg(token).arg(msg).toLatin1()); } @@ -1860,64 +1795,55 @@ public: RunnerGui(Adapter *adapter); private slots: - void executeStepICommand(); - void executeStepCommand(); - void executeDisassICommand(); + void executeStepICommand() { executeCommand("-exec-step-instruction"); } + void executeStepCommand() { executeCommand("-exec-step"); } + void executeNextICommand() { executeCommand("-exec-next-instruction"); } + void executeNextCommand() { executeCommand("-exec-next"); } + void executeContinueCommand() { executeCommand("-exec-continue"); } + void executeDisassICommand() { executeCommand("disass $pc $pc+4"); } private: + void executeCommand(const QString &cmd) { m_adapter->executeCommand(cmd); } + void connectAction(QAction *&, QString name, const char *slot); + Adapter *m_adapter; TextEdit m_textEdit; QToolBar m_toolBar; - QAction m_stepIAction; - QAction m_stepAction; - QAction m_disassIAction; + QAction *m_stepIAction; + QAction *m_stepAction; + QAction *m_nextIAction; + QAction *m_nextAction; + QAction *m_disassIAction; + QAction *m_continueAction; }; RunnerGui::RunnerGui(Adapter *adapter) - : m_adapter(adapter), - m_stepIAction(0), - m_stepAction(0), - m_disassIAction(0) + : m_adapter(adapter) { resize(1200, 1000); setCentralWidget(&m_textEdit); addToolBar(&m_toolBar); - m_stepIAction.setText("StepI"); - m_disassIAction.setText("DisassI"); - m_toolBar.addAction(&m_stepIAction); - m_toolBar.addAction(&m_stepAction); - m_toolBar.addAction(&m_disassIAction); + connectAction(m_stepIAction, "Step Inst", SLOT(executeStepICommand())); + connectAction(m_stepAction, "Step", SLOT(executeStepCommand())); + connectAction(m_nextIAction, "Next Inst", SLOT(executeNextICommand())); + connectAction(m_nextAction, "Next", SLOT(executeNextCommand())); + connectAction(m_disassIAction, "Disass Inst", SLOT(executeDisassICommand())); + connectAction(m_continueAction, "Continue", SLOT(executeContinueCommand())); connect(adapter, SIGNAL(output(QString,QString)), &m_textEdit, SLOT(handleOutput(QString,QString))); connect(&m_textEdit, SIGNAL(executeCommand(QString)), m_adapter, SLOT(executeCommand(QString))); - - connect(&m_stepIAction, SIGNAL(triggered()), - this, SLOT(executeStepICommand())); - connect(&m_stepAction, SIGNAL(triggered()), - this, SLOT(executeStepCommand())); - connect(&m_disassIAction, SIGNAL(triggered()), - this, SLOT(executeDisassICommand())); } -void RunnerGui::executeStepCommand() +void RunnerGui::connectAction(QAction *&action, QString name, const char *slot) { - //m_adapter->executeCommand("stepi"); - m_adapter->executeCommand("-exec-step"); -} - -void RunnerGui::executeStepICommand() -{ - //m_adapter->executeCommand("stepi"); - m_adapter->executeCommand("-exec-step-instruction"); -} - -void RunnerGui::executeDisassICommand() -{ - m_adapter->executeCommand("disass $pc $pc+4"); + action = new QAction(this); + action->setText(name); + m_toolBar.addAction(action); + connect(action, SIGNAL(triggered()), this, slot); } /////////////////////////////////////////////////////////////////////// diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h index 3ed06e3ca4a..7b1709498ce 100644 --- a/tests/manual/trk/trkutils.h +++ b/tests/manual/trk/trkutils.h @@ -144,7 +144,7 @@ struct Session uint tid; uint codeseg; uint dataseg; - QHash tokenToBreakpointIndex; + QHash addressToBP; // Gdb request uint currentThread; From 1614d6b6b85dc0762215f8e812dd68469457acad Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 9 Sep 2009 12:39:15 +0200 Subject: [PATCH 14/43] debugger: small refactoring of the access to the gdb process in the gdbengine That's the first step to make the gdb/trk Adapter work with the otherwise unmodified gdb engine. GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter. In the GdbProcess case it's just a wrapper around a QProcess running gdb, in the Adapter case it's the interface to the gdb process in the whole rfomm/gdb/gdbserver combo. --- src/plugins/debugger/gdb/gdbengine.cpp | 76 +++++++++++++------------- src/plugins/debugger/gdb/gdbengine.h | 70 +++++++++++++++++++++++- 2 files changed, 107 insertions(+), 39 deletions(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 89669c9df5e..055d8adfdf2 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -144,7 +144,7 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record) // /////////////////////////////////////////////////////////////////////// -GdbEngine::GdbEngine(DebuggerManager *parent) : +GdbEngine::GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc) : #ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit) m_dumperInjectionLoad(true), #else @@ -153,6 +153,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent) : q(parent), qq(parent->engineInterface()) { + m_gdbProc = gdbProc; m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug); #ifdef Q_OS_UNIX m_stubProc.setSettings(Core::ICore::instance()->settings()); @@ -164,19 +165,20 @@ GdbEngine::GdbEngine(DebuggerManager *parent) : GdbEngine::~GdbEngine() { // prevent sending error messages afterwards - m_gdbProc.disconnect(this); + m_gdbProc->disconnect(this); + delete m_gdbProc; } void GdbEngine::initializeConnections() { // Gdb Process interaction - connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), + connect(m_gdbProc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(gdbProcError(QProcess::ProcessError))); - connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), + connect(m_gdbProc, SIGNAL(readyReadStandardOutput()), this, SLOT(readGdbStandardOutput())); - connect(&m_gdbProc, SIGNAL(readyReadStandardError()), + connect(m_gdbProc, SIGNAL(readyReadStandardError()), this, SLOT(readGdbStandardError())); - connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), + connect(m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), q, SLOT(exitDebugger())); connect(&m_stubProc, SIGNAL(processError(QString)), @@ -614,7 +616,7 @@ void GdbEngine::stubError(const QString &msg) void GdbEngine::readGdbStandardError() { - qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError(); + qWarning() << "Unexpected gdb stderr:" << m_gdbProc->readAllStandardError(); } void GdbEngine::readGdbStandardOutput() @@ -622,7 +624,7 @@ void GdbEngine::readGdbStandardOutput() int newstart = 0; int scan = m_inbuffer.size(); - m_inbuffer.append(m_gdbProc.readAllStandardOutput()); + m_inbuffer.append(m_gdbProc->readAllStandardOutput()); while (newstart < m_inbuffer.size()) { int start = newstart; @@ -651,7 +653,7 @@ void GdbEngine::interruptInferior() { qq->notifyInferiorStopRequested(); - if (m_gdbProc.state() == QProcess::NotRunning) { + if (m_gdbProc->state() == QProcess::NotRunning) { debugMessage(_("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB")); qq->notifyInferiorExited(); return; @@ -698,7 +700,7 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags, GdbCommandCallback callback, const char *callbackName, const QVariant &cookie) { - if (m_gdbProc.state() == QProcess::NotRunning) { + if (m_gdbProc->state() == QProcess::NotRunning) { debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + command); return; } @@ -742,7 +744,7 @@ void GdbEngine::flushCommand(GdbCommand &cmd) if (cmd.flags & EmbedToken) cmd.command = cmd.command.arg(currentToken()); - m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); + m_gdbProc->write(cmd.command.toLatin1() + "\r\n"); //emit gdbInputAvailable(QString(), " " + currentTime()); //emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); emit gdbInputAvailable(LogInput, cmd.command); @@ -829,12 +831,12 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record) void GdbEngine::executeDebuggerCommand(const QString &command) { - if (m_gdbProc.state() == QProcess::NotRunning) { + if (m_gdbProc->state() == QProcess::NotRunning) { debugMessage(_("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: ") + command); return; } - m_gdbProc.write(command.toLocal8Bit() + "\r\n"); + m_gdbProc->write(command.toLocal8Bit() + "\r\n"); } void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &) @@ -1434,15 +1436,15 @@ void GdbEngine::detachDebugger() void GdbEngine::exitDebugger() { - debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc.state())); - if (m_gdbProc.state() == QProcess::Starting) { + debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc->state())); + if (m_gdbProc->state() == QProcess::Starting) { debugMessage(_("WAITING FOR GDB STARTUP TO SHUTDOWN: %1") - .arg(m_gdbProc.state())); - m_gdbProc.waitForStarted(); + .arg(m_gdbProc->state())); + m_gdbProc->waitForStarted(); } - if (m_gdbProc.state() == QProcess::Running) { + if (m_gdbProc->state() == QProcess::Running) { debugMessage(_("WAITING FOR RUNNING GDB TO SHUTDOWN: %1") - .arg(m_gdbProc.state())); + .arg(m_gdbProc->state())); if (q->status() != DebuggerInferiorStopped && q->status() != DebuggerProcessStartingUp) { QTC_ASSERT(q->status() == DebuggerInferiorRunning, @@ -1455,17 +1457,17 @@ void GdbEngine::exitDebugger() postCommand(_("kill")); postCommand(_("-gdb-exit"), CB(handleExit)); // 20s can easily happen when loading webkit debug information - if (!m_gdbProc.waitForFinished(20000)) { + if (!m_gdbProc->waitForFinished(20000)) { debugMessage(_("FORCING TERMINATION: %1") - .arg(m_gdbProc.state())); - m_gdbProc.terminate(); - m_gdbProc.waitForFinished(20000); + .arg(m_gdbProc->state())); + m_gdbProc->terminate(); + m_gdbProc->waitForFinished(20000); } } - if (m_gdbProc.state() != QProcess::NotRunning) { + if (m_gdbProc->state() != QProcess::NotRunning) { debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1") - .arg(m_gdbProc.state())); - m_gdbProc.kill(); + .arg(m_gdbProc->state())); + m_gdbProc->kill(); } m_outputCollector.shutdown(); @@ -1487,9 +1489,9 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) QStringList gdbArgs; - if (m_gdbProc.state() != QProcess::NotRunning) { - debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc.state())); - m_gdbProc.kill(); + if (m_gdbProc->state() != QProcess::NotRunning) { + debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc->state())); + m_gdbProc->kill(); return false; } @@ -1529,16 +1531,16 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName()); if (!sp->workingDir.isEmpty()) - m_gdbProc.setWorkingDirectory(sp->workingDir); + m_gdbProc->setWorkingDirectory(sp->workingDir); if (!sp->environment.isEmpty()) - m_gdbProc.setEnvironment(sp->environment); + m_gdbProc->setEnvironment(sp->environment); } #if 0 qDebug() << "Command:" << q->settings()->m_gdbCmd; - qDebug() << "WorkingDirectory:" << m_gdbProc.workingDirectory(); + qDebug() << "WorkingDirectory:" << m_gdbProc->workingDirectory(); qDebug() << "ScriptFile:" << q->settings()->m_scriptFile; - qDebug() << "Environment:" << m_gdbProc.environment(); + qDebug() << "Environment:" << m_gdbProc->environment(); qDebug() << "Arguments:" << gdbArgs; qDebug() << "BuildDir:" << sp->buildDir; qDebug() << "ExeFile:" << sp->executable; @@ -1546,10 +1548,10 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) QString loc = theDebuggerStringSetting(GdbLocation); q->showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" "))); - m_gdbProc.start(loc, gdbArgs); - if (!m_gdbProc.waitForStarted()) { + m_gdbProc->start(loc, gdbArgs); + if (!m_gdbProc->waitForStarted()) { QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), - tr("Cannot start debugger: %1").arg(m_gdbProc.errorString())); + tr("Cannot start debugger: %1").arg(m_gdbProc->errorString())); m_outputCollector.shutdown(); m_stubProc.blockSignals(true); m_stubProc.stop(); @@ -4198,7 +4200,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record, IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList *opts) { opts->push_back(new GdbOptionsPage); - return new GdbEngine(parent); + return new GdbEngine(parent, new GdbProcess); } } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 2694ec01fbd..60af08ae3cc 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -56,6 +56,7 @@ QT_END_NAMESPACE namespace Debugger { namespace Internal { + class DebuggerManager; class IDebuggerManagerAccessForEngines; class GdbResultRecord; @@ -72,13 +73,78 @@ enum DebuggingHelperState DebuggingHelperUnavailable, }; +// GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter. +// In the GdbProcess case it's just a wrapper around a QProcess running +// gdb, in the Adapter case it's the interface to the gdb process in +// the whole rfomm/gdb/gdbserver combo. +class GdbProcessBase : public QObject +{ + Q_OBJECT + +public: + GdbProcessBase(QObject *parent) : QObject(parent) {} + + virtual void start(const QString &program, const QStringList &args, + QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0; + virtual void kill() = 0; + virtual void terminate() = 0; + virtual bool waitForStarted(int msecs = 30000) = 0; + virtual bool waitForFinished(int msecs = 30000) = 0; + virtual QProcess::ProcessState state() const = 0; + virtual QString errorString() const = 0; + virtual QByteArray readAllStandardError() = 0; + virtual QByteArray readAllStandardOutput() = 0; + virtual qint64 write(const char *data) = 0; + virtual void setWorkingDirectory(const QString &dir) = 0; + virtual void setEnvironment(const QStringList &env) = 0; + +signals: + void error(QProcess::ProcessError); + void readyReadStandardOutput(); + void readyReadStandardError(); + void finished(int, QProcess::ExitStatus); +}; + +class GdbProcess : public GdbProcessBase +{ +public: + GdbProcess(QObject *parent = 0) + : GdbProcessBase(parent) + { + connect(&m_proc, SIGNAL(error(QProcess::ProcessError)), + this, SIGNAL(error(QProcess::ProcessError))); + connect(&m_proc, SIGNAL(readyReadStandardOutput()), + this, SIGNAL(readyReadStandardOutput())); + connect(&m_proc, SIGNAL(readyReadStandardError()), + this, SIGNAL(readyReadStandardError())); + connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SIGNAL(finished(int, QProcess::ExitStatus))); + } + + void start(const QString &program, const QStringList &args, + QIODevice::OpenMode mode) { m_proc.start(program, args, mode); } + void kill() { m_proc.kill(); } + void terminate() { m_proc.terminate(); } + bool waitForStarted(int msecs) { return m_proc.waitForStarted(msecs); } + bool waitForFinished(int msecs) { return m_proc.waitForFinished(msecs); } + QProcess::ProcessState state() const { return m_proc.state(); } + QString errorString() const { return m_proc.errorString(); } + QByteArray readAllStandardError() { return m_proc.readAllStandardError(); } + QByteArray readAllStandardOutput() { return m_proc.readAllStandardOutput(); } + qint64 write(const char *data) { return m_proc.write(data); } + void setWorkingDirectory(const QString &dir) { m_proc.setWorkingDirectory(dir); } + void setEnvironment(const QStringList &env) { m_proc.setEnvironment(env); } + +private: + QProcess m_proc; +}; class GdbEngine : public IDebuggerEngine { Q_OBJECT public: - GdbEngine(DebuggerManager *parent); + GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc); ~GdbEngine(); signals: @@ -251,7 +317,7 @@ private: QByteArray m_inbuffer; - QProcess m_gdbProc; + GdbProcessBase *m_gdbProc; QProcess m_uploadProc; Core::Utils::ConsoleProcess m_stubProc; From f269031b5e147106eb1cea54c2ee390cb072bebe Mon Sep 17 00:00:00 2001 From: mae Date: Wed, 9 Sep 2009 13:55:11 +0200 Subject: [PATCH 15/43] Make indentation/tabbing more developer friendly: - when doing backspace, preserve the previous indentation litterally - when having auto-indentation turned off, simply repeat the previous indentation litterally instead of jumping to 0 --- src/plugins/texteditor/basetexteditor.cpp | 22 ++++++++++++---------- src/plugins/texteditor/tabsettings.cpp | 6 ++++++ src/plugins/texteditor/tabsettings.h | 1 + 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 59c55fcb2d4..a675ea4e8bc 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -887,13 +887,18 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e) QTextCursor cursor = textCursor(); if (d->m_inBlockSelectionMode) cursor.clearSelection(); - if (d->m_document->tabSettings().m_autoIndent) { + const TabSettings &ts = d->m_document->tabSettings(); + if (ts.m_autoIndent) { cursor.beginEditBlock(); cursor.insertBlock(); indent(document(), cursor, QChar::Null); cursor.endEditBlock(); } else { + cursor.beginEditBlock(); + QString previousBlockText = cursor.block().text(); cursor.insertBlock(); + cursor.insertText(ts.indentationString(previousBlockText)); + cursor.endEditBlock(); } e->accept(); setTextCursor(cursor); @@ -3189,17 +3194,14 @@ void BaseTextEditor::handleBackspaceKey() continue; previousIndent = tabSettings.columnAt(previousNonEmptyBlockText, tabSettings.firstNonSpace(previousNonEmptyBlockText)); - if (previousIndent < indent) + if (previousIndent < indent) { + cursor.beginEditBlock(); + cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor); + cursor.insertText(tabSettings.indentationString(previousNonEmptyBlockText)); + cursor.endEditBlock(); break; + } } - - if (previousIndent >= indent) - previousIndent = 0; - - cursor.beginEditBlock(); - cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor); - cursor.insertText(tabSettings.indentationString(0, previousIndent)); - cursor.endEditBlock(); } void BaseTextEditor::wheelEvent(QWheelEvent *e) diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp index e0225ce8bcd..1c20ab7b904 100644 --- a/src/plugins/texteditor/tabsettings.cpp +++ b/src/plugins/texteditor/tabsettings.cpp @@ -110,6 +110,12 @@ int TabSettings::firstNonSpace(const QString &text) const return i; } +QString TabSettings::indentationString(const QString &text) const +{ + return text.left(firstNonSpace(text)); +} + + int TabSettings::trailingWhitespaces(const QString &text) const { int i = 0; diff --git a/src/plugins/texteditor/tabsettings.h b/src/plugins/texteditor/tabsettings.h index ec2c3dfe8ea..2fbede49502 100644 --- a/src/plugins/texteditor/tabsettings.h +++ b/src/plugins/texteditor/tabsettings.h @@ -63,6 +63,7 @@ struct TEXTEDITOR_EXPORT TabSettings int spacesLeftFromPosition(const QString &text, int position) const; int indentedColumn(int column, bool doIndent = true) const; QString indentationString(int startColumn, int targetColumn) const; + QString indentationString(const QString &text) const; void indentLine(QTextBlock block, int newIndent) const; From 32229e30b49f08b7f0b11f7ceae0fd0b78e46af2 Mon Sep 17 00:00:00 2001 From: mae Date: Wed, 9 Sep 2009 14:58:47 +0200 Subject: [PATCH 16/43] mark all-whitespace-lines with the correct visual format. --- src/plugins/cppeditor/cpphighlighter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp index 95e25b4b257..d2cda6f77df 100644 --- a/src/plugins/cppeditor/cpphighlighter.cpp +++ b/src/plugins/cppeditor/cpphighlighter.cpp @@ -73,6 +73,8 @@ void CppHighlighter::highlightBlock(const QString &text) userData->setCollapseMode(TextBlockUserData::NoCollapse); } TextEditDocumentLayout::clearParentheses(currentBlock()); + if (text.length()) // the empty line can still contain whitespace + setFormat(0, text.length(), visualSpaceFormat); return; } @@ -171,7 +173,7 @@ void CppHighlighter::highlightBlock(const QString &text) } // mark the trailing white spaces - if (! tokens.isEmpty()) { + { const SimpleToken tk = tokens.last(); const int lastTokenEnd = tk.position() + tk.length(); if (text.length() > lastTokenEnd) From 16e7f0c16f57e984310cd1bba838a69221f4a18a Mon Sep 17 00:00:00 2001 From: mae Date: Wed, 9 Sep 2009 16:16:46 +0200 Subject: [PATCH 17/43] be more conservative when reindenting code: only change the actual whitespace when the indentation column changes. Complete whitespace cleanup can still be done either automatically on save (when configured) or when explicitely called with the "Clean Whitespace" action from Edit/Advanced. --- src/plugins/texteditor/basetextdocument.cpp | 11 +++++------ src/plugins/texteditor/basetextdocument.h | 2 +- src/plugins/texteditor/tabsettings.cpp | 14 +++++++------- src/plugins/texteditor/tabsettings.h | 1 + 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/plugins/texteditor/basetextdocument.cpp b/src/plugins/texteditor/basetextdocument.cpp index 8de81100d8c..b2b0e75eeea 100644 --- a/src/plugins/texteditor/basetextdocument.cpp +++ b/src/plugins/texteditor/basetextdocument.cpp @@ -93,7 +93,7 @@ bool BaseTextDocument::save(const QString &fileName) cursor.beginEditBlock(); if (m_storageSettings.m_cleanWhitespace) - cleanWhitespace(cursor, m_storageSettings.m_inEntireDocument); + cleanWhitespace(cursor, m_storageSettings.m_cleanIndentation, m_storageSettings.m_inEntireDocument); if (m_storageSettings.m_addFinalNewLine) ensureFinalNewLine(cursor); cursor.endEditBlock(); @@ -305,13 +305,12 @@ void BaseTextDocument::cleanWhitespace() { QTextCursor cursor(m_document); cursor.beginEditBlock(); - cleanWhitespace(cursor, true); - if (m_storageSettings.m_addFinalNewLine) - ensureFinalNewLine(cursor); + cleanWhitespace(cursor, true, true); + ensureFinalNewLine(cursor); cursor.endEditBlock(); } -void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool inEntireDocument) +void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument) { TextEditDocumentLayout *documentLayout = qobject_cast(m_document->documentLayout()); @@ -327,7 +326,7 @@ void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool inEntireDocumen cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, trailing); cursor.removeSelectedText(); } - if (m_storageSettings.m_cleanIndentation && !m_tabSettings.isIndentationClean(blockText)) { + if (cleanIndentation && !m_tabSettings.isIndentationClean(blockText)) { cursor.setPosition(block.position()); int firstNonSpace = m_tabSettings.firstNonSpace(blockText); if (firstNonSpace == blockText.length()) { diff --git a/src/plugins/texteditor/basetextdocument.h b/src/plugins/texteditor/basetextdocument.h index 88e1c609a13..24dabd7a0aa 100644 --- a/src/plugins/texteditor/basetextdocument.h +++ b/src/plugins/texteditor/basetextdocument.h @@ -146,7 +146,7 @@ private: bool m_hasDecodingError; QByteArray m_decodingErrorSample; - void cleanWhitespace(QTextCursor& cursor, bool onlyInModifiedLines); + void cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument); void ensureFinalNewLine(QTextCursor& cursor); }; diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp index 1c20ab7b904..393434d9085 100644 --- a/src/plugins/texteditor/tabsettings.cpp +++ b/src/plugins/texteditor/tabsettings.cpp @@ -116,6 +116,12 @@ QString TabSettings::indentationString(const QString &text) const } +int TabSettings::indentationColumn(const QString &text) const +{ + return columnAt(text, firstNonSpace(text)); +} + + int TabSettings::trailingWhitespaces(const QString &text) const { int i = 0; @@ -231,7 +237,7 @@ void TabSettings::indentLine(QTextBlock block, int newIndent) const const int oldBlockLength = text.size(); // Quickly check whether indenting is required. - if (oldBlockLength == 0 && newIndent == 0) + if (indentationColumn(text) == newIndent) return; const QString indentString = indentationString(0, newIndent); @@ -240,12 +246,6 @@ void TabSettings::indentLine(QTextBlock block, int newIndent) const if (oldBlockLength == indentString.length() && text == indentString) return; - if (oldBlockLength > indentString.length() && - text.startsWith(indentString) && - !text.at(indentString.length()).isSpace()) { - return; - } - QTextCursor cursor(block); cursor.beginEditBlock(); cursor.movePosition(QTextCursor::StartOfBlock); diff --git a/src/plugins/texteditor/tabsettings.h b/src/plugins/texteditor/tabsettings.h index 2fbede49502..f26e0bb5ad9 100644 --- a/src/plugins/texteditor/tabsettings.h +++ b/src/plugins/texteditor/tabsettings.h @@ -64,6 +64,7 @@ struct TEXTEDITOR_EXPORT TabSettings int indentedColumn(int column, bool doIndent = true) const; QString indentationString(int startColumn, int targetColumn) const; QString indentationString(const QString &text) const; + int indentationColumn(const QString &text) const; void indentLine(QTextBlock block, int newIndent) const; From 99435d5f0e2f6993df22965b38564cd73e3409f1 Mon Sep 17 00:00:00 2001 From: mae Date: Wed, 9 Sep 2009 16:37:09 +0200 Subject: [PATCH 18/43] Make "Edit/Advanced/Clean_Whitespace work on the current selection (if there is one) --- src/plugins/texteditor/basetextdocument.cpp | 22 +++++++++++++-------- src/plugins/texteditor/basetextdocument.h | 2 +- src/plugins/texteditor/basetexteditor.cpp | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/plugins/texteditor/basetextdocument.cpp b/src/plugins/texteditor/basetextdocument.cpp index b2b0e75eeea..6da82ccdf59 100644 --- a/src/plugins/texteditor/basetextdocument.cpp +++ b/src/plugins/texteditor/basetextdocument.cpp @@ -301,13 +301,15 @@ void BaseTextDocument::setSyntaxHighlighter(QSyntaxHighlighter *highlighter) -void BaseTextDocument::cleanWhitespace() +void BaseTextDocument::cleanWhitespace(const QTextCursor &cursor) { - QTextCursor cursor(m_document); - cursor.beginEditBlock(); - cleanWhitespace(cursor, true, true); - ensureFinalNewLine(cursor); - cursor.endEditBlock(); + bool hasSelection = cursor.hasSelection(); + QTextCursor copyCursor = cursor; + copyCursor.beginEditBlock(); + cleanWhitespace(copyCursor, true, true); + if (!hasSelection) + ensureFinalNewLine(copyCursor); + copyCursor.endEditBlock(); } void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument) @@ -315,8 +317,12 @@ void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool cleanIndentatio TextEditDocumentLayout *documentLayout = qobject_cast(m_document->documentLayout()); - QTextBlock block = m_document->firstBlock(); - while (block.isValid()) { + QTextBlock block = m_document->findBlock(cursor.selectionStart()); + QTextBlock end; + if (cursor.hasSelection()) + end = m_document->findBlock(cursor.selectionEnd()-1).next(); + + while (block.isValid() && block != end) { if (inEntireDocument || block.revision() > documentLayout->lastSaveRevision) { diff --git a/src/plugins/texteditor/basetextdocument.h b/src/plugins/texteditor/basetextdocument.h index 24dabd7a0aa..eaf37c91caf 100644 --- a/src/plugins/texteditor/basetextdocument.h +++ b/src/plugins/texteditor/basetextdocument.h @@ -110,7 +110,7 @@ public: void reload(QTextCodec *codec); - void cleanWhitespace(); + void cleanWhitespace(const QTextCursor &cursor); signals: void titleChanged(QString title); diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index a675ea4e8bc..cce27c4c21b 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -833,7 +833,7 @@ void BaseTextEditor::moveLineUpDown(bool up) void BaseTextEditor::cleanWhitespace() { - d->m_document->cleanWhitespace(); + d->m_document->cleanWhitespace(textCursor()); } void BaseTextEditor::keyPressEvent(QKeyEvent *e) From 6f5cea2aaafb6475cf725413de04c5cc70d43888 Mon Sep 17 00:00:00 2001 From: ck Date: Wed, 9 Sep 2009 17:11:00 +0200 Subject: [PATCH 19/43] Various improvements for BinEditor. - Saving to file only takes modified data into account. - Search functionality does not exhaust memory anymore. - Searches can be canceled. This required updating the IFindSupport interface and all classes implementing it. No functional changes were done in those. Reviewed-by: mae --- src/plugins/bineditor/bineditor.cpp | 97 +++++++++++---- src/plugins/bineditor/bineditor.h | 6 +- src/plugins/bineditor/bineditorplugin.cpp | 115 +++++++++++------- .../coreplugin/editormanager/ieditor.h | 1 + src/plugins/debugger/debuggeragents.cpp | 2 +- src/plugins/find/basetextfind.cpp | 8 +- src/plugins/find/basetextfind.h | 4 +- src/plugins/find/currentdocumentfind.cpp | 8 +- src/plugins/find/currentdocumentfind.h | 4 +- src/plugins/find/findtoolbar.cpp | 25 +++- src/plugins/find/findtoolbar.h | 5 + src/plugins/find/ifindsupport.h | 6 +- src/plugins/help/helpfindsupport.cpp | 26 ++-- src/plugins/help/helpfindsupport.h | 8 +- 14 files changed, 209 insertions(+), 106 deletions(-) diff --git a/src/plugins/bineditor/bineditor.cpp b/src/plugins/bineditor/bineditor.cpp index 27629a130ea..453e0d2f5b5 100644 --- a/src/plugins/bineditor/bineditor.cpp +++ b/src/plugins/bineditor/bineditor.cpp @@ -33,6 +33,9 @@ #include #include +#include +#include + #include #include #include @@ -136,6 +139,8 @@ void BinEditor::addLazyData(quint64 block, const QByteArray &data) Q_ASSERT(data.size() == m_blockSize); const quint64 addr = block * m_blockSize; if (addr >= m_baseAddr && addr <= m_baseAddr + m_size - 1) { + if (m_lazyData.size() * m_blockSize >= 64 * 1024 * 1024) + m_lazyData.clear(); const int translatedBlock = (addr - m_baseAddr) / m_blockSize; m_lazyData.insert(translatedBlock, data); m_lazyRequests.remove(translatedBlock); @@ -149,7 +154,10 @@ bool BinEditor::requestDataAt(int pos, bool synchronous) const return true; int block = pos / m_blockSize; - QMap::const_iterator it = m_lazyData.find(block); + QMap::const_iterator it = m_modifiedData.find(block); + if (it != m_modifiedData.constEnd()) + return true; + it = m_lazyData.find(block); if (it == m_lazyData.end()) { if (!m_lazyRequests.contains(block)) { m_lazyRequests.insert(block); @@ -168,10 +176,8 @@ char BinEditor::dataAt(int pos) const { if (!m_inLazyMode) return m_data.at(pos); - int block = pos / m_blockSize; - return m_lazyData.value(block, m_emptyBlock).at(pos - (block*m_blockSize)); - + return blockData(block).at(pos - (block*m_blockSize)); } void BinEditor::changeDataAt(int pos, char c) @@ -181,8 +187,17 @@ void BinEditor::changeDataAt(int pos, char c) return; } int block = pos / m_blockSize; - if (m_lazyData.contains(block)) - m_lazyData[block][pos - (block*m_blockSize)] = c; + QMap::iterator it = m_modifiedData.find(block); + if (it != m_modifiedData.end()) { + it.value()[pos - (block*m_blockSize)] = c; + } else { + it = m_lazyData.find(block); + if (it != m_lazyData.end()) { + QByteArray data = it.value(); + data[pos - (block*m_blockSize)] = c; + m_modifiedData.insert(block, data); + } + } } QByteArray BinEditor::dataMid(int from, int length) const @@ -195,7 +210,7 @@ QByteArray BinEditor::dataMid(int from, int length) const QByteArray data; do { - data += m_lazyData.value(block++, m_emptyBlock); + data += blockData(block++); } while (block * m_blockSize < end); return data.mid(from - ((from / m_blockSize) * m_blockSize), length); @@ -209,7 +224,9 @@ QByteArray BinEditor::blockData(int block) const data.resize(m_blockSize); return data; } - return m_lazyData.value(block, m_emptyBlock); + QMap::const_iterator it = m_modifiedData.find(block); + return it != m_modifiedData.constEnd() + ? it.value() : m_lazyData.value(block, m_emptyBlock); } @@ -302,6 +319,7 @@ void BinEditor::setData(const QByteArray &data) m_inLazyMode = false; m_baseAddr = 0; m_lazyData.clear(); + m_modifiedData.clear(); m_lazyRequests.clear(); m_data = data; m_size = data.size(); @@ -323,17 +341,45 @@ QByteArray BinEditor::data() const return m_data; } -bool BinEditor::applyModifications(QByteArray &data) const +bool BinEditor::save(const QString &oldFileName, const QString &newFileName) { - if (!m_inLazyMode) { - data = m_data; - return true; - } - if (data.size() != m_size) - return false; - for (QMap::const_iterator it = m_lazyData.begin(); it != m_lazyData.end(); ++it) { - ::memcpy(data.data() + m_baseAddr + it.key() * m_blockSize, it->constData(), m_blockSize); + if (m_inLazyMode) { + if (oldFileName != newFileName) { + QString tmpName; + { + QTemporaryFile tmp; + if (!tmp.open()) + return false; + tmpName = tmp.fileName(); + } + if (!QFile::copy(oldFileName, tmpName)) + return false; + if (QFile::exists(newFileName) && !QFile::remove(newFileName)) + return false; + if (!QFile::rename(tmpName, newFileName)) + return false; + } + QFile output(newFileName); + if (!output.open(QIODevice::ReadWrite)) // QtBug: WriteOnly truncates. + return false; + const qint64 size = output.size(); + for (QMap::const_iterator it = m_modifiedData.constBegin(); + it != m_modifiedData.constEnd(); ++it) { + if (!output.seek(it.key() * m_blockSize)) + return false; + if (output.write(it.value()) < m_blockSize) + return false; + } + if (size % m_blockSize != 0 && !output.resize(size)) + return false; + } else { + QFile output(newFileName); + if (!output.open(QIODevice::WriteOnly | QIODevice::Truncate)) + return false; + if (output.write(m_data) < m_size) + return false; } + setModified(false); return true; } @@ -345,6 +391,7 @@ void BinEditor::setLazyData(quint64 startAddr, int range, int blockSize) m_emptyBlock = QByteArray(blockSize, '\0'); m_data.clear(); m_lazyData.clear(); + m_modifiedData.clear(); m_lazyRequests.clear(); // In lazy mode, users can edit data in the range @@ -485,8 +532,9 @@ int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensiti QByteArrayMatcher matcher(pattern); int block = from / m_blockSize; - - while (from < m_size) { + const int end = + qMin(static_cast(from) + SearchStride, m_size); + while (from < end) { if (!requestDataAt(block * m_blockSize, true)) return -1; QByteArray data = blockData(block); @@ -502,7 +550,7 @@ int BinEditor::dataIndexOf(const QByteArray &pattern, int from, bool caseSensiti ++block; from = block * m_blockSize - trailing; } - return -1; + return end == m_size ? -1 : -2; } int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSensitive) const @@ -519,8 +567,8 @@ int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSen char *b = buffer.data(); int block = from / m_blockSize; - - while (from > 0) { + const int lowerBound = qMax(0, from - SearchStride); + while (from > lowerBound) { if (!requestDataAt(block * m_blockSize, true)) return -1; QByteArray data = blockData(block); @@ -536,7 +584,7 @@ int BinEditor::dataLastIndexOf(const QByteArray &pattern, int from, bool caseSen --block; from = block * m_blockSize + (m_blockSize-1) + trailing; } - return -1; + return lowerBound == 0 ? -1 : -2; } @@ -564,7 +612,8 @@ int BinEditor::find(const QByteArray &pattern_arg, int from, : dataIndexOf(hexPattern, from); } - int pos = (found >= 0 && (foundHex < 0 || found < foundHex)) ? found : foundHex; + int pos = foundHex == -1 || (found >= 0 && (foundHex == -2 || found < foundHex)) + ? found : foundHex; if (pos >= m_size) pos = -1; diff --git a/src/plugins/bineditor/bineditor.h b/src/plugins/bineditor/bineditor.h index dc14fd7e608..4b7aa1653ff 100644 --- a/src/plugins/bineditor/bineditor.h +++ b/src/plugins/bineditor/bineditor.h @@ -31,8 +31,10 @@ #define BINEDITOR_H #include +#include #include #include +#include #include #include @@ -67,7 +69,7 @@ public: Q_INVOKABLE void setLazyData(quint64 startAddr, int range, int blockSize = 4096); inline int lazyDataBlockSize() const { return m_blockSize; } Q_INVOKABLE void addLazyData(quint64 block, const QByteArray &data); - bool applyModifications(QByteArray &data) const; + bool save(const QString &oldFileName, const QString &newFileName); void zoomIn(int range = 1); void zoomOut(int range = 1); @@ -109,6 +111,7 @@ public: QString addressString(quint64 address); + static const int SearchStride = 1024 * 1024; public Q_SLOTS: void setFontSettings(const TextEditor::FontSettings &fs); @@ -143,6 +146,7 @@ private: QByteArray m_data; QMap m_lazyData; int m_blockSize; + QMap m_modifiedData; mutable QSet m_lazyRequests; QByteArray m_emptyBlock; QByteArray m_lowerBlock; diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp index 2d0f2054de4..9782b9bb6d4 100644 --- a/src/plugins/bineditor/bineditorplugin.cpp +++ b/src/plugins/bineditor/bineditorplugin.cpp @@ -61,7 +61,11 @@ class BinEditorFind : public Find::IFindSupport { Q_OBJECT public: - BinEditorFind(BinEditor *editor) { m_editor = editor; m_incrementalStartPos = -1; } + BinEditorFind(BinEditor *editor) + { + m_editor = editor; + m_incrementalStartPos = m_contPos = -1; + } ~BinEditorFind() {} bool supportsReplace() const { return false; } @@ -70,7 +74,11 @@ public: return IFindSupport::FindBackward | IFindSupport::FindCaseSensitively; } - void resetIncrementalSearch() { m_incrementalStartPos = -1; } + void resetIncrementalSearch() + { + m_incrementalStartPos = m_contPos = -1; + } + void clearResults() { m_editor->highlightSearchResults(QByteArray()); } QString currentFindString() const { return QString(); } QString completedFindString() const { return QString(); } @@ -82,41 +90,68 @@ public: return pos; } - int found = m_editor->find(pattern, pos, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); - if (found < 0) - found = m_editor->find(pattern, - (findFlags & Find::IFindSupport::FindBackward)?m_editor->dataSize()-1:0, - Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); - return found; + return m_editor->find(pattern, pos, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); } - bool findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) { + Result findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) { QByteArray pattern = txt.toLatin1(); + if (pattern != m_lastPattern) + resetIncrementalSearch(); // Because we don't search for nibbles. + m_lastPattern = pattern; if (m_incrementalStartPos < 0) m_incrementalStartPos = m_editor->selectionStart(); - int pos = m_incrementalStartPos; + if (m_contPos == -1) + m_contPos = m_incrementalStartPos; findFlags &= ~Find::IFindSupport::FindBackward; - int found = find(pattern, pos, findFlags); - if (found >= 0) + int found = find(pattern, m_contPos, findFlags); + Result result; + if (found >= 0) { + result = Found; m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); - else - m_editor->highlightSearchResults(QByteArray(), 0); - return found >= 0; + m_contPos = -1; + } else { + if (found == -2) { + result = NotYetFound; + m_contPos += + findFlags & Find::IFindSupport::FindBackward + ? -BinEditor::SearchStride : BinEditor::SearchStride; + } else { + result = NotFound; + m_contPos = -1; + m_editor->highlightSearchResults(QByteArray(), 0); + } + } + return result; } - bool findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) { + Result findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) { QByteArray pattern = txt.toLatin1(); bool wasReset = (m_incrementalStartPos < 0); - int pos = m_editor->cursorPosition(); - if (findFlags & Find::IFindSupport::FindBackward) - pos = m_editor->selectionStart()-1; - int found = find(pattern, pos, findFlags); - if (found) + if (m_contPos == -1) { + m_contPos = m_editor->cursorPosition(); + if (findFlags & Find::IFindSupport::FindBackward) + m_contPos = m_editor->selectionStart()-1; + } + int found = find(pattern, m_contPos, findFlags); + Result result; + if (found >= 0) { + result = Found; m_incrementalStartPos = found; - if (wasReset && found >= 0) - m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); - return found >= 0; + m_contPos = -1; + if (wasReset) + m_editor->highlightSearchResults(pattern, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags)); + } else if (found == -2) { + result = NotYetFound; + m_contPos += findFlags & Find::IFindSupport::FindBackward + ? -BinEditor::SearchStride : BinEditor::SearchStride; + } else { + result = NotFound; + m_contPos = -1; + } + + return result; } + bool replaceStep(const QString &, const QString &, Find::IFindSupport::FindFlags) { return false;} int replaceAll(const QString &, const QString &, @@ -125,6 +160,8 @@ public: private: BinEditor *m_editor; int m_incrementalStartPos; + int m_contPos; // Only valid if last result was NotYetFound. + QByteArray m_lastPattern; }; @@ -144,42 +181,26 @@ public: virtual QString mimeType() const { return m_mimeType; } bool save(const QString &fileName = QString()) { - QFile file(fileName); - - QByteArray data; - if (m_editor->inLazyMode()) { - QFile read(m_fileName); - if (!read.open(QIODevice::ReadOnly)) - return false; - data = read.readAll(); - read.close(); - if (!m_editor->applyModifications(data)) - return false; - } else { - data = m_editor->data(); - } - if (file.open(QIODevice::WriteOnly)) { - file.write(data); - file.close(); - m_editor->setModified(false); - m_editor->editorInterface()-> - setDisplayName(QFileInfo(fileName).fileName()); + if (m_editor->save(m_fileName, fileName)) { m_fileName = fileName; + m_editor->editorInterface()-> + setDisplayName(QFileInfo(fileName).fileName()); emit changed(); return true; + } else { + return false; } - return false; } bool open(const QString &fileName) { QFile file(fileName); if (file.open(QIODevice::ReadOnly)) { m_fileName = fileName; - if (file.isSequential() && file.size() <= INT_MAX) { + if (file.isSequential() && file.size() <= 64 * 1024 * 1024) { m_editor->setData(file.readAll()); } else { m_editor->setLazyData(0, qMin(file.size(), - static_cast(INT_MAX))); + static_cast(INT_MAX-16))); m_editor->editorInterface()-> setDisplayName(QFileInfo(fileName).fileName()); } diff --git a/src/plugins/coreplugin/editormanager/ieditor.h b/src/plugins/coreplugin/editormanager/ieditor.h index 56c4e6fbc6d..5248b298a70 100644 --- a/src/plugins/coreplugin/editormanager/ieditor.h +++ b/src/plugins/coreplugin/editormanager/ieditor.h @@ -40,6 +40,7 @@ class CORE_EXPORT IEditor : public IContext { Q_OBJECT public: + IEditor(QObject *parent = 0) : IContext(parent) {} virtual ~IEditor() {} diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp index 2b41b39394c..ede60b4c7e0 100644 --- a/src/plugins/debugger/debuggeragents.cpp +++ b/src/plugins/debugger/debuggeragents.cpp @@ -95,7 +95,7 @@ void MemoryViewAgent::init(quint64 addr) this, SLOT(fetchLazyData(quint64,bool))); editorManager->activateEditor(m_editor); QMetaObject::invokeMethod(m_editor->widget(), "setLazyData", - Q_ARG(quint64, addr), Q_ARG(int, INT_MAX), Q_ARG(int, BinBlockSize)); + Q_ARG(quint64, addr), Q_ARG(int, 1024 * 1024), Q_ARG(int, BinBlockSize)); } void MemoryViewAgent::fetchLazyData(quint64 block, bool sync) diff --git a/src/plugins/find/basetextfind.cpp b/src/plugins/find/basetextfind.cpp index 89ec9ccdb3f..5fb4a33d565 100644 --- a/src/plugins/find/basetextfind.cpp +++ b/src/plugins/find/basetextfind.cpp @@ -125,7 +125,7 @@ QString BaseTextFind::completedFindString() const return cursor.selectedText(); } -bool BaseTextFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags) +IFindSupport::Result BaseTextFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags) { QTextCursor cursor = textCursor(); if (m_incrementalStartPos < 0) @@ -137,15 +137,15 @@ bool BaseTextFind::findIncremental(const QString &txt, IFindSupport::FindFlags f emit highlightAll(txt, findFlags); else emit highlightAll(QString(), 0); - return found; + return found ? Found : NotFound; } -bool BaseTextFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags) +IFindSupport::Result BaseTextFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags) { bool found = find(txt, findFlags, textCursor()); if (found) m_incrementalStartPos = textCursor().selectionStart(); - return found; + return found ? Found : NotFound; } namespace { diff --git a/src/plugins/find/basetextfind.h b/src/plugins/find/basetextfind.h index ec4cc0b344d..97aca8f4f6c 100644 --- a/src/plugins/find/basetextfind.h +++ b/src/plugins/find/basetextfind.h @@ -53,8 +53,8 @@ public: QString currentFindString() const; QString completedFindString() const; - bool findIncremental(const QString &txt, IFindSupport::FindFlags findFlags); - bool findStep(const QString &txt, IFindSupport::FindFlags findFlags); + Result findIncremental(const QString &txt, IFindSupport::FindFlags findFlags); + Result findStep(const QString &txt, IFindSupport::FindFlags findFlags); bool replaceStep(const QString &before, const QString &after, IFindSupport::FindFlags findFlags); int replaceAll(const QString &before, const QString &after, diff --git a/src/plugins/find/currentdocumentfind.cpp b/src/plugins/find/currentdocumentfind.cpp index 15f6a944b3b..16457382a2f 100644 --- a/src/plugins/find/currentdocumentfind.cpp +++ b/src/plugins/find/currentdocumentfind.cpp @@ -106,15 +106,15 @@ void CurrentDocumentFind::highlightAll(const QString &txt, IFindSupport::FindFla m_currentFind->highlightAll(txt, findFlags); } -bool CurrentDocumentFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags) +IFindSupport::Result CurrentDocumentFind::findIncremental(const QString &txt, IFindSupport::FindFlags findFlags) { - QTC_ASSERT(m_currentFind, return false); + QTC_ASSERT(m_currentFind, return IFindSupport::NotFound); return m_currentFind->findIncremental(txt, findFlags); } -bool CurrentDocumentFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags) +IFindSupport::Result CurrentDocumentFind::findStep(const QString &txt, IFindSupport::FindFlags findFlags) { - QTC_ASSERT(m_currentFind, return false); + QTC_ASSERT(m_currentFind, return IFindSupport::NotFound); return m_currentFind->findStep(txt, findFlags); } diff --git a/src/plugins/find/currentdocumentfind.h b/src/plugins/find/currentdocumentfind.h index bd0e19e022f..a3b9a7b362b 100644 --- a/src/plugins/find/currentdocumentfind.h +++ b/src/plugins/find/currentdocumentfind.h @@ -55,8 +55,8 @@ public: bool isEnabled() const; bool candidateIsEnabled() const; void highlightAll(const QString &txt, IFindSupport::FindFlags findFlags); - bool findIncremental(const QString &txt, IFindSupport::FindFlags findFlags); - bool findStep(const QString &txt, IFindSupport::FindFlags findFlags); + IFindSupport::Result findIncremental(const QString &txt, IFindSupport::FindFlags findFlags); + IFindSupport::Result findStep(const QString &txt, IFindSupport::FindFlags findFlags); bool replaceStep(const QString &before, const QString &after, IFindSupport::FindFlags findFlags); int replaceAll(const QString &before, const QString &after, diff --git a/src/plugins/find/findtoolbar.cpp b/src/plugins/find/findtoolbar.cpp index 44ecc6fb237..1c2c59ca503 100644 --- a/src/plugins/find/findtoolbar.cpp +++ b/src/plugins/find/findtoolbar.cpp @@ -69,7 +69,8 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen m_replaceNextAction(0), m_casesensitiveIcon(":/find/images/casesensitively.png"), m_regexpIcon(":/find/images/regexp.png"), - m_wholewordsIcon(":/find/images/wholewords.png") + m_wholewordsIcon(":/find/images/wholewords.png"), + m_findIncrementalTimer(this), m_findStepTimer(this) { //setup ui m_ui.setupUi(this); @@ -215,6 +216,12 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen connect(m_currentDocumentFind, SIGNAL(candidateChanged()), this, SLOT(adaptToCandidate())); connect(m_currentDocumentFind, SIGNAL(changed()), this, SLOT(updateToolBar())); updateToolBar(); + + m_findIncrementalTimer.setSingleShot(true); + m_findStepTimer.setSingleShot(true); + connect(&m_findIncrementalTimer, SIGNAL(timeout()), + this, SLOT(invokeFindIncremental())); + connect(&m_findStepTimer, SIGNAL(timeout()), this, SLOT(invokeFindStep())); } FindToolBar::~FindToolBar() @@ -373,17 +380,27 @@ void FindToolBar::selectFindText() void FindToolBar::invokeFindStep() { + m_findStepTimer.stop(); + m_findIncrementalTimer.stop(); if (m_currentDocumentFind->isEnabled()) { m_plugin->updateFindCompletion(getFindText()); - m_currentDocumentFind->findStep(getFindText(), effectiveFindFlags()); + IFindSupport::Result result = + m_currentDocumentFind->findStep(getFindText(), effectiveFindFlags()); + if (result == IFindSupport::NotYetFound) + m_findStepTimer.start(50); } } void FindToolBar::invokeFindIncremental() { + m_findIncrementalTimer.stop(); + m_findStepTimer.stop(); if (m_currentDocumentFind->isEnabled()) { QString text = getFindText(); - m_currentDocumentFind->findIncremental(text, effectiveFindFlags()); + IFindSupport::Result result = + m_currentDocumentFind->findIncremental(text, effectiveFindFlags()); + if (result == IFindSupport::NotYetFound) + m_findIncrementalTimer.start(50); if (text.isEmpty()) m_currentDocumentFind->clearResults(); } @@ -421,6 +438,8 @@ void FindToolBar::invokeReplaceAll() void FindToolBar::invokeResetIncrementalSearch() { + m_findIncrementalTimer.stop(); + m_findStepTimer.stop(); if (m_currentDocumentFind->isEnabled()) m_currentDocumentFind->resetIncrementalSearch(); } diff --git a/src/plugins/find/findtoolbar.h b/src/plugins/find/findtoolbar.h index 14dbed88524..cbde5eceb52 100644 --- a/src/plugins/find/findtoolbar.h +++ b/src/plugins/find/findtoolbar.h @@ -37,6 +37,8 @@ #include #include +#include + #include #include #include @@ -124,6 +126,9 @@ private: QPixmap m_casesensitiveIcon; QPixmap m_regexpIcon; QPixmap m_wholewordsIcon; + + QTimer m_findIncrementalTimer; + QTimer m_findStepTimer; }; } // namespace Internal diff --git a/src/plugins/find/ifindsupport.h b/src/plugins/find/ifindsupport.h index 0e2d5ef2dc7..35b5c7779ed 100644 --- a/src/plugins/find/ifindsupport.h +++ b/src/plugins/find/ifindsupport.h @@ -50,6 +50,8 @@ public: }; Q_DECLARE_FLAGS(FindFlags, FindFlag) + enum Result { Found, NotFound, NotYetFound }; + IFindSupport() : QObject(0) {} virtual ~IFindSupport() {} @@ -61,8 +63,8 @@ public: virtual QString completedFindString() const = 0; virtual void highlightAll(const QString &txt, FindFlags findFlags); - virtual bool findIncremental(const QString &txt, FindFlags findFlags) = 0; - virtual bool findStep(const QString &txt, FindFlags findFlags) = 0; + virtual Result findIncremental(const QString &txt, FindFlags findFlags) = 0; + virtual Result findStep(const QString &txt, FindFlags findFlags) = 0; virtual bool replaceStep(const QString &before, const QString &after, FindFlags findFlags) = 0; virtual int replaceAll(const QString &before, const QString &after, diff --git a/src/plugins/help/helpfindsupport.cpp b/src/plugins/help/helpfindsupport.cpp index d6086858f4b..bfb688db571 100644 --- a/src/plugins/help/helpfindsupport.cpp +++ b/src/plugins/help/helpfindsupport.cpp @@ -72,17 +72,19 @@ QString HelpFindSupport::completedFindString() const return QString(); } -bool HelpFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) +Find::IFindSupport::Result HelpFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) { - QTC_ASSERT(m_centralWidget, return false); + QTC_ASSERT(m_centralWidget, return NotFound); findFlags &= ~Find::IFindSupport::FindBackward; - return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), true); + return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), true) + ? Found : NotFound; } -bool HelpFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) +Find::IFindSupport::Result HelpFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) { - QTC_ASSERT(m_centralWidget, return false); - return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), false); + QTC_ASSERT(m_centralWidget, return NotFound); + return m_centralWidget->find(txt, Find::IFindSupport::textDocumentFlagsForFindFlags(findFlags), false) + ? Found : NotFound; } HelpViewerFindSupport::HelpViewerFindSupport(HelpViewer *viewer) @@ -106,17 +108,17 @@ QString HelpViewerFindSupport::currentFindString() const #endif } -bool HelpViewerFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) +Find::IFindSupport::Result HelpViewerFindSupport::findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags) { - QTC_ASSERT(m_viewer, return false); + QTC_ASSERT(m_viewer, return NotFound); findFlags &= ~Find::IFindSupport::FindBackward; - return find(txt, findFlags, true); + return find(txt, findFlags, true) ? Found : NotFound; } -bool HelpViewerFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) +Find::IFindSupport::Result HelpViewerFindSupport::findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags) { - QTC_ASSERT(m_viewer, return false); - return find(txt, findFlags, false); + QTC_ASSERT(m_viewer, return NotFound); + return find(txt, findFlags, false) ? Found : NotFound; } bool HelpViewerFindSupport::find(const QString &txt, Find::IFindSupport::FindFlags findFlags, bool incremental) diff --git a/src/plugins/help/helpfindsupport.h b/src/plugins/help/helpfindsupport.h index 94908d39165..1adfb1c9037 100644 --- a/src/plugins/help/helpfindsupport.h +++ b/src/plugins/help/helpfindsupport.h @@ -57,8 +57,8 @@ public: QString currentFindString() const; QString completedFindString() const; - bool findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags); - bool findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags); + Result findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags); + Result findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags); bool replaceStep(const QString &, const QString &, Find::IFindSupport::FindFlags ) { return false; } int replaceAll(const QString &, const QString &, @@ -84,8 +84,8 @@ public: QString currentFindString() const; QString completedFindString() const { return QString(); } - bool findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags); - bool findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags); + Result findIncremental(const QString &txt, Find::IFindSupport::FindFlags findFlags); + Result findStep(const QString &txt, Find::IFindSupport::FindFlags findFlags); bool replaceStep(const QString &, const QString &, Find::IFindSupport::FindFlags ) { return false; } int replaceAll(const QString &, const QString &, From ffaa42e5855c6afd6dc0cf98f78e5b9fc4eab4df Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 9 Sep 2009 17:24:21 +0200 Subject: [PATCH 20/43] debugger: merge trk adapter into debugger sources --- src/plugins/debugger/debugger.pro | 2 + src/plugins/debugger/debuggermanager.cpp | 2 + src/plugins/debugger/gdb/gdbengine.h | 33 +- src/plugins/debugger/gdb/gdbprocessbase.h | 74 + src/plugins/debugger/symbian/symbian.pri | 14 + .../debugger/symbian/symbianadapter.cpp | 1599 ++++++++++++++++ src/plugins/debugger/symbian/symbianadapter.h | 247 +++ .../debugger/symbian/symbianengine.cpp | 66 + .../plugins/debugger/symbian/trkclient.cpp | 3 +- .../plugins/debugger/symbian/trkclient.h | 0 .../plugins/debugger/symbian}/trkfunctor.h | 4 +- .../plugins/debugger/symbian}/trkutils.cpp | 0 .../plugins/debugger/symbian}/trkutils.h | 1 - tests/manual/trk/adapter.pro | 18 +- tests/manual/trk/runner.cpp | 1634 +---------------- tests/manual/trk/runner.pro | 16 +- tests/manual/trk/trklauncher.pri | 18 +- tests/manual/trk/trkserver.pro | 11 +- 18 files changed, 2058 insertions(+), 1684 deletions(-) create mode 100644 src/plugins/debugger/gdb/gdbprocessbase.h create mode 100644 src/plugins/debugger/symbian/symbian.pri create mode 100644 src/plugins/debugger/symbian/symbianadapter.cpp create mode 100644 src/plugins/debugger/symbian/symbianadapter.h create mode 100644 src/plugins/debugger/symbian/symbianengine.cpp rename tests/manual/trk/trkdevicex.cpp => src/plugins/debugger/symbian/trkclient.cpp (99%) rename tests/manual/trk/trkdevicex.h => src/plugins/debugger/symbian/trkclient.h (100%) rename {tests/manual/trk => src/plugins/debugger/symbian}/trkfunctor.h (98%) rename {tests/manual/trk => src/plugins/debugger/symbian}/trkutils.cpp (100%) rename {tests/manual/trk => src/plugins/debugger/symbian}/trkutils.h (99%) diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 3cdc4f16f56..c9be97b7260 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -87,5 +87,7 @@ include(cdb/cdb.pri) include(gdb/gdb.pri) include(script/script.pri) include(tcf/tcf.pri) +include(symbian/symbian.pri) include(shared/shared.pri) + OTHER_FILES += Debugger.pluginspec diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index a17056ec1f8..b4a5c84a7ee 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -103,6 +103,8 @@ namespace Internal { IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList *); +IDebuggerEngine *createSymbianEngine(DebuggerManager *parent, QList *); + QDebug operator<<(QDebug str, const DebuggerStartParameters &p) { QDebug nospace = str.nospace(); diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 60af08ae3cc..88eadb4c095 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -32,6 +32,7 @@ #include "idebuggerengine.h" #include "gdbmi.h" +#include "gdbprocessbase.h" #include "outputcollector.h" #include "watchutils.h" @@ -73,38 +74,6 @@ enum DebuggingHelperState DebuggingHelperUnavailable, }; -// GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter. -// In the GdbProcess case it's just a wrapper around a QProcess running -// gdb, in the Adapter case it's the interface to the gdb process in -// the whole rfomm/gdb/gdbserver combo. -class GdbProcessBase : public QObject -{ - Q_OBJECT - -public: - GdbProcessBase(QObject *parent) : QObject(parent) {} - - virtual void start(const QString &program, const QStringList &args, - QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0; - virtual void kill() = 0; - virtual void terminate() = 0; - virtual bool waitForStarted(int msecs = 30000) = 0; - virtual bool waitForFinished(int msecs = 30000) = 0; - virtual QProcess::ProcessState state() const = 0; - virtual QString errorString() const = 0; - virtual QByteArray readAllStandardError() = 0; - virtual QByteArray readAllStandardOutput() = 0; - virtual qint64 write(const char *data) = 0; - virtual void setWorkingDirectory(const QString &dir) = 0; - virtual void setEnvironment(const QStringList &env) = 0; - -signals: - void error(QProcess::ProcessError); - void readyReadStandardOutput(); - void readyReadStandardError(); - void finished(int, QProcess::ExitStatus); -}; - class GdbProcess : public GdbProcessBase { public: diff --git a/src/plugins/debugger/gdb/gdbprocessbase.h b/src/plugins/debugger/gdb/gdbprocessbase.h new file mode 100644 index 00000000000..b6adfc763bb --- /dev/null +++ b/src/plugins/debugger/gdb/gdbprocessbase.h @@ -0,0 +1,74 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef DEBUGGER_PROCESSBASE_H +#define DEBUGGER_PROCESSBASE_H + +#include +#include + +namespace Debugger { +namespace Internal { + +// GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter. +// In the GdbProcess case it's just a wrapper around a QProcess running +// gdb, in the Adapter case it's the interface to the gdb process in +// the whole rfomm/gdb/gdbserver combo. +class GdbProcessBase : public QObject +{ + Q_OBJECT + +public: + GdbProcessBase(QObject *parent = 0) : QObject(parent) {} + + virtual void start(const QString &program, const QStringList &args, + QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0; + virtual void kill() = 0; + virtual void terminate() = 0; + virtual bool waitForStarted(int msecs = 30000) = 0; + virtual bool waitForFinished(int msecs = 30000) = 0; + virtual QProcess::ProcessState state() const = 0; + virtual QString errorString() const = 0; + virtual QByteArray readAllStandardError() = 0; + virtual QByteArray readAllStandardOutput() = 0; + virtual qint64 write(const char *data) = 0; + virtual void setWorkingDirectory(const QString &dir) = 0; + virtual void setEnvironment(const QStringList &env) = 0; + +signals: + void error(QProcess::ProcessError); + void readyReadStandardOutput(); + void readyReadStandardError(); + void finished(int, QProcess::ExitStatus); +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_PROCESSBASE_H diff --git a/src/plugins/debugger/symbian/symbian.pri b/src/plugins/debugger/symbian/symbian.pri new file mode 100644 index 00000000000..1ffb8081d4f --- /dev/null +++ b/src/plugins/debugger/symbian/symbian.pri @@ -0,0 +1,14 @@ +HEADERS += \ + $$PWD/trkclient.h \ + $$PWD/symbianadapter.h \ + #$$PWD/gdboptionspage.h \ + +SOURCES += \ + $$PWD/trkclient.cpp \ + $$PWD/symbianadapter.cpp \ + $$PWD/symbianengine.cpp \ + #$$PWD/gdboptionspage.cpp \ + +#FORMS += $$PWD/gdboptionspage.ui + +#RESOURCES += $$PWD/gdb.qrc diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp new file mode 100644 index 00000000000..8f66b331242 --- /dev/null +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -0,0 +1,1599 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "symbianadapter.h" + +#define TrkCB(s) TrkCallback(this, &SymbianAdapter::s) +#define GdbCB(s) GdbCallback(this, &SymbianAdapter::s) + + +/* +fetch-register p info registers +set-register P set +binary-download X load, set +read-aux-vector qXfer:auxv:read info auxv +symbol-lookup qSymbol Detecting multiple threads +attach vAttach attach +verbose-resume vCont Stepping or resuming multiple threads +run vRun run +software-breakpoint Z0 break +hardware-breakpoint Z1 hbreak +write-watchpoint Z2 watch +read-watchpoint Z3 rwatch +access-watchpoint Z4 awatch +target-features qXfer:features:read set architecture +library-info qXfer:libraries:read info sharedlibrary +memory-map qXfer:memory-map:read info mem +read-spu-object qXfer:spu:read info spu +write-spu-object qXfer:spu:write info spu +get-thread-local- +storage-address qGetTLSAddr Displaying __thread variables +supported-packets qSupported Remote communications parameters +pass-signals QPassSignals handle signal +hostio-close-packet vFile:close remote get, remote put +hostio-open-packet vFile:open remote get, remote put +hostio-pread-packet vFile:pread remote get, remote put +hostio-pwrite-packet vFile:pwrite remote get, remote put +hostio-unlink-packet vFile:unlink remote delete +*/ + +using namespace trk; + +enum { KnownRegisters = RegisterPSGdb + 1}; + +static const char *registerNames[KnownRegisters] = +{ + "A1", "A2", "A3", "A4", + 0, 0, 0, 0, + 0, 0, 0, "AP", + "IP", "SP", "LR", "PC", + "PSTrk", 0, 0, 0, + 0, 0, 0, 0, + 0, "PSGdb" +}; + +static QByteArray dumpRegister(int n, uint value) +{ + QByteArray ba; + ba += ' '; + if (n < KnownRegisters && registerNames[n]) { + ba += registerNames[n]; + } else { + ba += '#'; + ba += QByteArray::number(n); + } + ba += "=" + hexxNumber(value); + return ba; +} + +namespace Debugger { +namespace Internal { + +trk::Endianness m_registerEndianness = LittleEndian; + +SymbianAdapter::SymbianAdapter() +{ + m_running = false; + m_gdbAckMode = true; + m_verbose = 2; + m_serialFrame = false; + m_bufferedMemoryRead = true; + m_rfcommDevice = "/dev/rfcomm0"; + + uid_t userId = getuid(); + m_gdbServerName = QString("127.0.0.1:%1").arg(2222 + userId); + + m_gdbProc.setObjectName("GDB PROCESS"); + connectProcess(&m_gdbProc); + connect(&m_gdbProc, SIGNAL(readyReadStandardError()), + this, SLOT(handleGdbReadyReadStandardError())); + connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), + this, SLOT(handleGdbReadyReadStandardOutput())); + + m_rfcommProc.setObjectName("RFCOMM PROCESS"); + connectProcess(&m_rfcommProc); + connect(&m_rfcommProc, SIGNAL(readyReadStandardError()), + this, SLOT(handleRfcommReadyReadStandardError())); + connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()), + this, SLOT(handleRfcommReadyReadStandardOutput())); + + if (m_verbose > 1) + m_trkDevice.setVerbose(true); + m_trkDevice.setSerialFrame(m_serialFrame); + + connect(&m_trkDevice, SIGNAL(logMessage(QString)), + this, SLOT(trkLogMessage(QString))); +} + +SymbianAdapter::~SymbianAdapter() +{ + m_gdbServer.close(); + logMessage("Shutting down.\n", true); +} + +void SymbianAdapter::trkLogMessage(const QString &msg) +{ + logMessage("TRK " + msg); +} + +void SymbianAdapter::setGdbServerName(const QString &name) +{ + m_gdbServerName = name; +} + +QString SymbianAdapter::gdbServerIP() const +{ + int pos = m_gdbServerName.indexOf(':'); + if (pos == -1) + return m_gdbServerName; + return m_gdbServerName.left(pos); +} + +uint SymbianAdapter::gdbServerPort() const +{ + int pos = m_gdbServerName.indexOf(':'); + if (pos == -1) + return 0; + return m_gdbServerName.mid(pos + 1).toUInt(); +} + +QByteArray SymbianAdapter::trkContinueMessage() +{ + QByteArray ba; + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + return ba; +} + +QByteArray SymbianAdapter::trkReadRegisterMessage() +{ + 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 SymbianAdapter::trkReadMemoryMessage(uint addr, uint len) +{ + QByteArray ba; + appendByte(&ba, 0x08); // Options, FIXME: why? + appendShort(&ba, len); + appendInt(&ba, addr); + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + return ba; +} + +void SymbianAdapter::startInferior() +{ + QString errorMessage; + if (!m_trkDevice.open(m_rfcommDevice, &errorMessage)) { + logMessage("LOOPING"); + QTimer::singleShot(1000, this, SLOT(startInferior())); + return; + } + + m_trkDevice.sendTrkInitialPing(); + sendTrkMessage(0x01); // Connect + sendTrkMessage(0x05, TrkCB(handleSupportMask)); + sendTrkMessage(0x06, TrkCB(handleCpuType)); + sendTrkMessage(0x04, TrkCB(handleTrkVersions)); // Versions + //sendTrkMessage(0x09); // Unrecognized command + //sendTrkMessage(0x4a, 0, + // "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File + //sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File + + QByteArray ba; + appendByte(&ba, 0); // ? + appendByte(&ba, 0); // ? + appendByte(&ba, 0); // ? + + QByteArray file("C:\\sys\\bin\\filebrowseapp.exe"); + appendString(&ba, file, TargetByteOrder); + sendTrkMessage(0x40, TrkCB(handleCreateProcess), ba); // Create Item + //sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(startGdbServer)); +} + +void SymbianAdapter::logMessage(const QString &msg, bool force) +{ + if (m_verbose || force) + emit output(QString(), msg); +} + +// +// Gdb +// +void SymbianAdapter::handleGdbConnection() +{ + logMessage("HANDLING GDB CONNECTION"); + + m_gdbConnection = m_gdbServer.nextPendingConnection(); + connect(m_gdbConnection, SIGNAL(disconnected()), + m_gdbConnection, SLOT(deleteLater())); + connect(m_gdbConnection, SIGNAL(readyRead()), + this, SLOT(readGdbServerCommand())); +} + +static inline QString msgGdbPacket(const QString &p) +{ + return QLatin1String("gdb: ") + p; +} + +void SymbianAdapter::readGdbServerCommand() +{ + QByteArray packet = m_gdbConnection->readAll(); + m_gdbReadBuffer.append(packet); + + logMessage("gdb: -> " + QString::fromAscii(packet)); + if (packet != m_gdbReadBuffer) + logMessage("buffer: " + m_gdbReadBuffer); + + QByteArray &ba = m_gdbReadBuffer; + while (ba.size()) { + char code = ba.at(0); + ba = ba.mid(1); + + if (code == '+') { + //logMessage("ACK"); + continue; + } + + if (code == '-') { + logMessage("NAK: Retransmission requested"); + continue; + } + + if (code == char(0x03)) { + logMessage("INTERRUPT RECEIVED"); + interruptInferior(); + continue; + } + + if (code != '$') { + logMessage("Broken package (2) " + quoteUnprintableLatin1(ba) + + hexNumber(code)); + continue; + } + + int pos = ba.indexOf('#'); + if (pos == -1) { + logMessage("Invalid checksum format in " + + quoteUnprintableLatin1(ba)); + continue; + } + + bool ok = false; + uint checkSum = ba.mid(pos + 1, 2).toUInt(&ok, 16); + if (!ok) { + logMessage("Invalid checksum format 2 in " + + quoteUnprintableLatin1(ba)); + return; + } + + //logMessage(QString("Packet checksum: %1").arg(checkSum)); + byte sum = 0; + for (int i = 0; i < pos; ++i) + sum += ba.at(i); + + if (sum != checkSum) { + logMessage(QString("ERROR: Packet checksum wrong: %1 %2 in " + + quoteUnprintableLatin1(ba)).arg(checkSum).arg(sum)); + } + + QByteArray cmd = ba.left(pos); + ba.remove(0, pos + 3); + handleGdbServerCommand(cmd); + } +} + +bool SymbianAdapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush) +{ + if (!m_gdbConnection) { + logMessage(QString::fromLatin1("Cannot write to gdb: No connection (%1)") + .arg(QString::fromLatin1(packet)), true); + return false; + } + if (m_gdbConnection->state() != QAbstractSocket::ConnectedState) { + logMessage(QString::fromLatin1("Cannot write to gdb: Not connected (%1)") + .arg(QString::fromLatin1(packet)), true); + return false; + } + if (m_gdbConnection->write(packet) == -1) { + logMessage(QString::fromLatin1("Cannot write to gdb: %1 (%2)") + .arg(m_gdbConnection->errorString()).arg(QString::fromLatin1(packet)), true); + return false; + } + if (doFlush) + m_gdbConnection->flush(); + return true; +} + +void SymbianAdapter::sendGdbServerAck() +{ + if (!m_gdbAckMode) + return; + QByteArray packet = "+"; + logMessage("gdb: <- " + packet); + sendGdbServerPacket(packet, false); +} + +void SymbianAdapter::sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote) +{ + byte sum = 0; + for (int i = 0; i != msg.size(); ++i) + sum += msg.at(i); + + char checkSum[30]; + qsnprintf(checkSum, sizeof(checkSum) - 1, "%02x ", sum); + + //logMessage(QString("Packet checksum: %1").arg(sum)); + + QByteArray packet; + packet.append("$"); + packet.append(msg); + packet.append('#'); + packet.append(checkSum); + int pad = qMax(0, 24 - packet.size()); + logMessage("gdb: <- " + packet + QByteArray(pad, ' ') + logNote); + sendGdbServerPacket(packet, true); +} + +void SymbianAdapter::sendGdbServerMessageAfterTrkResponse(const QByteArray &msg, + const QByteArray &logNote) +{ + QByteArray ba = msg + char(1) + logNote; + sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportToGdb), "", ba); // Answer gdb +} + +void SymbianAdapter::reportToGdb(const TrkResult &result) +{ + QByteArray message = result.cookie.toByteArray(); + QByteArray note; + int pos = message.lastIndexOf(char(1)); // HACK + if (pos != -1) { + note = message.mid(pos + 1); + message = message.left(pos); + } + message.replace("@CODESEG@", hexNumber(m_session.codeseg)); + message.replace("@DATASEG@", hexNumber(m_session.dataseg)); + message.replace("@PID@", hexNumber(m_session.pid)); + message.replace("@TID@", hexNumber(m_session.tid)); + sendGdbServerMessage(message, note); +} + +QByteArray SymbianAdapter::trkBreakpointMessage(uint addr, uint len, bool armMode) +{ + QByteArray ba; + appendByte(&ba, 0x82); // unused option + appendByte(&ba, armMode /*bp.mode == ArmMode*/ ? 0x00 : 0x01); + appendInt(&ba, addr); + appendInt(&ba, len); + appendInt(&ba, 0x00000001); + appendInt(&ba, m_session.pid); + appendInt(&ba, 0xFFFFFFFF); + return ba; +} + +void SymbianAdapter::handleGdbServerCommand(const QByteArray &cmd) +{ + // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html + if (0) {} + + else if (cmd == "!") { + sendGdbServerAck(); + //sendGdbServerMessage("", "extended mode not enabled"); + sendGdbServerMessage("OK", "extended mode enabled"); + } + + else if (cmd.startsWith("?")) { + logMessage(msgGdbPacket(QLatin1String("Query halted"))); + // Indicate the reason the target halted. + // The reply is the same as for step and continue. + sendGdbServerAck(); + // The command below will trigger fetching a stack trace while + // the process does not seem to be fully functional. Most notably + // the PC points to a 0x9..., which is not in "our" range + //sendGdbServerMessage("T05library:r;", "target halted (library load)"); + //sendGdbServerMessage("S05", "target halted (trap)"); + sendGdbServerMessage("S00", "target halted (trap)"); + //sendGdbServerMessage("O" + QByteArray("Starting...").toHex()); + } + + else if (cmd == "c") { + logMessage(msgGdbPacket(QLatin1String("Continue"))); + sendGdbServerAck(); + QByteArray ba; + appendByte(&ba, 0); // options + appendInt(&ba, 0); // start address + appendInt(&ba, 0); // end address + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + sendTrkMessage(0x18, TrkCallback(), ba); + } + + else if (cmd.startsWith("C")) { + logMessage(msgGdbPacket(QLatin1String("Continue with signal"))); + // C sig[;addr] Continue with signal sig (hex signal number) + //Reply: See section D.3 Stop Reply Packets, for the reply specifications. + sendGdbServerAck(); + bool ok = false; + uint signalNumber = cmd.mid(1).toInt(&ok, 16); + QByteArray ba; + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + sendTrkMessage(0x18, TrkCB(handleSignalContinue), ba, signalNumber); // Continue + } + + else if (cmd.startsWith("D")) { + sendGdbServerAck(); + sendGdbServerMessage("OK", "shutting down"); + qApp->quit(); + } + + else if (cmd == "g") { + logMessage(msgGdbPacket(QLatin1String("Read registers"))); + // Read general registers. + //sendGdbServerMessage("00000000", "read registers"); + sendGdbServerAck(); + sendTrkMessage(0x12, TrkCB(handleAndReportReadRegisters), + trkReadRegisterMessage()); + } + + else if (cmd.startsWith("Hc")) { + logMessage(msgGdbPacket(QLatin1String("Set thread & continue"))); + // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). + // for step and continue operations + //$Hc-1#09 + sendGdbServerAck(); + sendGdbServerMessage("OK", "Set current thread for step & continue"); + } + + else if (cmd.startsWith("Hg")) { + logMessage(msgGdbPacket(QLatin1String("Set thread"))); + // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). + // for 'other operations. 0 - any thread + //$Hg0#df + sendGdbServerAck(); + m_session.currentThread = cmd.mid(2).toInt(0, 16); + sendGdbServerMessage("OK", "Set current thread " + + QByteArray::number(m_session.currentThread)); + } + + else if (cmd == "k") { + logMessage(msgGdbPacket(QLatin1String("kill"))); + // kill + sendGdbServerAck(); + QByteArray ba; + appendByte(&ba, 0); // ? + appendByte(&ba, 0); // Sub-command: Delete Process + appendInt(&ba, m_session.pid); + sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); // Delete Item + sendGdbServerMessageAfterTrkResponse("", "process killed"); + } + + else if (cmd.startsWith("m")) { + logMessage(msgGdbPacket(QLatin1String("Read memory"))); + // m addr,length + sendGdbServerAck(); + uint addr = 0, len = 0; + do { + const int pos = cmd.indexOf(','); + if (pos == -1) + break; + bool ok; + addr = cmd.mid(1, pos - 1).toUInt(&ok, 16); + if (!ok) + break; + len = cmd.mid(pos + 1).toUInt(&ok, 16); + if (!ok) + break; + } while (false); + if (len) { + readMemory(addr, len); + } else { + sendGdbServerMessage("E20", "Error " + cmd); + } + } + else if (cmd.startsWith("p")) { + logMessage(msgGdbPacket(QLatin1String("read register"))); + // 0xf == current instruction pointer? + //sendGdbServerMessage("0000", "current IP"); + sendGdbServerAck(); + #if 0 + A1 = 0, first integer-like argument + A4 = 3, last integer-like argument + AP = 11, + IP = 12, + SP = 13, Contains address of top of stack + LR = 14, address to return to from a function call + PC = 15, Contains program counter + F0 = 16, first floating point register + F3 = 19, last floating point argument register + F7 = 23, last floating point register + FPS = 24, floating point status register + PS = 25, Contains processor status + WR0, WMMX data registers. + WR15 = WR0 + 15, + WC0, WMMX control registers. + WCSSF = WC0 + 2, + WCASF = WC0 + 3, + WC7 = WC0 + 7, + WCGR0, WMMX general purpose registers. + WCGR3 = WCGR0 + 3, + WCGR7 = WCGR0 + 7, + NUM_REGS, + + // Other useful registers. + FP = 11, Frame register in ARM code, if used. + THUMB_FP = 7, Frame register in Thumb code, if used. + NUM_ARG_REGS = 4, + LAST_ARG = A4, + NUM_FP_ARG_REGS = 4, + LAST_FP_ARG = F3 + #endif + bool ok = false; + const uint registerNumber = cmd.mid(1).toInt(&ok, 16); + QByteArray logMsg = "Read Register"; + if (registerNumber == RegisterPSGdb) { + QByteArray ba; + appendInt(&ba, m_snapshot.registers[RegisterPSTrk], m_registerEndianness); + logMsg += dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk]); + sendGdbServerMessage(ba.toHex(), logMsg); + } else if (registerNumber < RegisterCount) { + QByteArray ba; + appendInt(&ba, m_snapshot.registers[registerNumber], m_registerEndianness); + 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 if (cmd == "qAttached") { + //$qAttached#8f + // 1: attached to an existing process + // 0: created a new process + sendGdbServerAck(); + sendGdbServerMessage("0", "new process created"); + //sendGdbServerMessage("1", "attached to existing process"); + //sendGdbServerMessage("E01", "new process created"); + } + + else if (cmd.startsWith("qC")) { + logMessage(msgGdbPacket(QLatin1String("query thread id"))); + // Return the current thread ID + //$qC#b4 + sendGdbServerAck(); + sendGdbServerMessageAfterTrkResponse("QC@TID@"); + } + + else if (cmd.startsWith("qSupported")) { + //$qSupported#37 + //$qSupported:multiprocess+#c6 + //logMessage("Handling 'qSupported'"); + sendGdbServerAck(); + if (0) + sendGdbServerMessage(QByteArray(), "nothing supported"); + else + sendGdbServerMessage( + "PacketSize=7cf;" + "QPassSignals+;" + "qXfer:libraries:read+;" + //"qXfer:auxv:read+;" + "qXfer:features:read+"); + } + + else if (cmd == "qPacketInfo") { + // happens with gdb 6.4.50.20060226-cvs / CodeSourcery + // deprecated by qSupported? + sendGdbServerAck(); + sendGdbServerMessage("", "FIXME: nothing?"); + } + + else if (cmd == "qOffsets") { + sendGdbServerAck(); + sendGdbServerMessageAfterTrkResponse("TextSeg=@CODESEG@;DataSeg=@DATASEG@"); + } + + else if (cmd == "qSymbol::") { + if (m_verbose) + logMessage(msgGdbPacket(QLatin1String("notify can handle symbol lookup"))); + // Notify the target that GDB is prepared to serve symbol lookup requests. + sendGdbServerAck(); + if (1) + sendGdbServerMessage("OK", "no further symbols needed"); + else + sendGdbServerMessage("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(), "ask for more"); + } + + else if (cmd.startsWith("qXfer:features:read:target.xml:")) { + // $qXfer:features:read:target.xml:0,7ca#46...Ack + sendGdbServerAck(); + sendGdbServerMessage("lsymbianelf"); + } + + else if (cmd == "QStartNoAckMode") { + //$qSupported#37 + //logMessage("Handling 'QStartNoAckMode'"); + sendGdbServerAck(); + sendGdbServerMessage("OK", "ack no-ack mode"); + m_gdbAckMode = false; + } + + else if (cmd.startsWith("QPassSignals")) { + // list of signals to pass directly to inferior + // $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c;#8f + // happens only if "QPassSignals+;" is qSupported + sendGdbServerAck(); + // FIXME: use the parameters + sendGdbServerMessage("OK", "passing signals accepted"); + } + + else if (cmd == "s" || cmd.startsWith("vCont;s")) { + logMessage(msgGdbPacket(QLatin1String("Step range"))); + logMessage(" from " + hexxNumber(m_snapshot.registers[RegisterPC])); + sendGdbServerAck(); + m_running = true; + QByteArray ba; + appendByte(&ba, 0x01); // options + appendInt(&ba, m_snapshot.registers[RegisterPC]); // start address + //appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address + appendInt(&ba, -1); // end address + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + sendTrkMessage(0x19, TrkCB(handleStepRange), ba, "Step range"); + // FIXME: should be triggered by "real" stop" + //sendGdbServerMessageAfterTrkResponse("S05", "target halted"); + } + + else if (cmd == "vCont?") { + // actions supported by the vCont packet + sendGdbServerAck(); + //sendGdbServerMessage("OK"); // we don't support vCont. + sendGdbServerMessage("vCont;c;C;s;S"); + } + + else if (cmd == "vCont;c") { + // vCont[;action[:thread-id]]...' + sendGdbServerAck(); + m_running = true; + sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); + } + + else if (cmd.startsWith("vKill")) { + // kill + sendGdbServerAck(); + QByteArray ba; + appendByte(&ba, 0); // Sub-command: Delete Process + appendInt(&ba, m_session.pid); + sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); // Delete Item + sendGdbServerMessageAfterTrkResponse("", "process killed"); + } + + else if (0 && cmd.startsWith("Z0,")) { + // Tell gdb we don't support software breakpoints + sendGdbServerMessage(""); + } + + else if (cmd.startsWith("Z0,") || cmd.startsWith("Z1,")) { + sendGdbServerAck(); + // Insert breakpoint + logMessage(msgGdbPacket(QLatin1String("Insert breakpoint"))); + // $Z0,786a4ccc,4#99 + const int pos = cmd.lastIndexOf(','); + bool ok = false; + const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); + const uint len = cmd.mid(pos + 1).toInt(&ok, 16); + //qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len; + logMessage(QString::fromLatin1("Inserting breakpoint at 0x%1, %2") + .arg(addr, 0, 16).arg(len)); + + //---IDE------------------------------------------------------ + // Command: 0x1B Set Break + //BreakType: 0x82 + // Options: 0x00 + // Address: 0x78674340 (2020033344) i.e + 0x00000340 + // Length: 0x00000001 (1) + // Count: 0x00000000 (0) + //ProcessID: 0x000001b5 (437) + // ThreadID: 0xffffffff (-1) + // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00 + // 00 00 01 B5 FF FF FF FF] + const QByteArray ba = trkBreakpointMessage(addr, len, m_session.pid); + sendTrkMessage(0x1B, TrkCB(handleAndReportSetBreakpoint), ba, addr); + //---TRK------------------------------------------------------ + // Command: 0x80 Acknowledge + // Error: 0x00 + // [80 09 00 00 00 00 0A] + } + + else if (cmd.startsWith("z0,") || cmd.startsWith("z1,")) { + sendGdbServerAck(); + // Remove breakpoint + logMessage(msgGdbPacket(QLatin1String("Remove breakpoint"))); + // $z0,786a4ccc,4#99 + const int pos = cmd.lastIndexOf(','); + bool ok = false; + const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); + const uint len = cmd.mid(pos + 1).toInt(&ok, 16); + const uint bp = m_session.addressToBP[addr]; + if (bp == 0) { + logMessage(QString::fromLatin1("NO RECORDED BP AT 0x%1, %2") + .arg(addr, 0, 16).arg(len)); + } else { + //---IDE------------------------------------------------------ + // Command: 0x1C Clear Break + // [1C 25 00 00 00 0A 78 6A 43 40] + m_session.addressToBP.remove(addr); + QByteArray ba; + appendByte(&ba, 0x00); + appendShort(&ba, bp); + appendInt(&ba, addr); + sendTrkMessage(0x1C, TrkCB(handleClearBreakpoint), ba, addr); + } + } + + else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:")) { + QByteArray data = cmd.mid(1 + cmd.indexOf(':')); + // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux) + bool handled = false; + if (data.startsWith("auxv:read::")) { + const int offsetPos = data.lastIndexOf(':') + 1; + const int commaPos = data.lastIndexOf(','); + if (commaPos != -1) { + bool ok1 = false, ok2 = false; + const int offset = data.mid(offsetPos, commaPos - offsetPos) + .toInt(&ok1, 16); + const int length = data.mid(commaPos + 1).toInt(&ok2, 16); + if (ok1 && ok2) { + const QString msg = QString::fromLatin1("Read of OS auxilary " + "vector (%1, %2) not implemented.").arg(offset).arg(length); + logMessage(msgGdbPacket(msg), true); + sendGdbServerMessage("E20", msg.toLatin1()); + handled = true; + } + } + } // auxv read + if (!handled) { + const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ") + + QString::fromAscii(cmd); + logMessage(msgGdbPacket(msg), true); + sendGdbServerMessage("E20", msg.toLatin1()); + } + } // qPart/qXfer + else { + logMessage(msgGdbPacket(QLatin1String("FIXME unknown: ") + + QString::fromAscii(cmd))); + } +} + +void SymbianAdapter::executeCommand(const QString &msg) +{ + if (msg == "EI") { + sendGdbMessage("-exec-interrupt"); + } else if (msg == "C") { + sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); + } else if (msg == "R") { + sendTrkMessage(0x18, TrkCB(handleReadRegisters), + trkReadRegisterMessage(), "READ REGS"); + } else if (msg == "I") { + interruptInferior(); + } else { + logMessage("EXECUTING GDB COMMAND " + msg); + sendGdbMessage(msg); + } +} + +void SymbianAdapter::sendTrkMessage(byte code, TrkCallback callback, + const QByteArray &data, const QVariant &cookie) +{ + m_trkDevice.sendTrkMessage(code, callback, data, cookie); +} + +void SymbianAdapter::sendTrkAck(byte token) +{ + logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token))); + m_trkDevice.sendTrkAck(token); +} + +void SymbianAdapter::handleTrkError(const QString &msg) +{ + logMessage("## TRK ERROR: " + msg); +} + +void SymbianAdapter::handleTrkResult(const TrkResult &result) +{ + if (result.isDebugOutput) { + sendTrkAck(result.token); + logMessage(QLatin1String("APPLICATION OUTPUT: ") + + QString::fromAscii(result.data)); + sendGdbServerMessage("O" + result.data.toHex()); + return; + } + logMessage("READ TRK " + result.toString()); + QByteArray prefix = "READ BUF: "; + QByteArray str = result.toString().toUtf8(); + switch (result.code) { + case 0x80: // ACK + break; + case 0xff: { // NAK. This mostly means transmission error, not command failed. + QString logMsg; + QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token + << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str; + logMessage(logMsg, true); + break; + } + case 0x90: { // Notified Stopped + // 90 01 78 6a 40 40 00 00 07 23 00 00 07 24 00 00 + const char *data = result.data.data(); + const uint addr = extractInt(data); + const uint pid = extractInt(data + 4); + const uint tid = extractInt(data + 8); + logMessage(prefix + QString::fromLatin1("NOTE: PID %1/TID %2 " + "STOPPED at 0x%3").arg(pid).arg(tid).arg(addr, 0, 16)); + sendTrkAck(result.token); + if (addr) { + // Todo: Do not send off GdbMessages if a synced gdb + // query is pending, queue instead + if (m_running) { + m_running = false; + sendGdbServerMessage("S05", "Target stopped"); + } + } else { + logMessage(QLatin1String("Ignoring stop at 0")); + } + break; + } + case 0x91: { // Notify Exception (obsolete) + logMessage(prefix + "NOTE: EXCEPTION " + str); + sendTrkAck(result.token); + break; + } + case 0x92: { // + logMessage(prefix + "NOTE: INTERNAL ERROR: " + str); + sendTrkAck(result.token); + break; + } + + // target->host OS notification + case 0xa0: { // Notify Created + const char *data = result.data.data(); + const byte error = result.data.at(0); + // type: 1 byte; for dll item, this value is 2. + const 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); + 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 << '\''; + logMessage(logMsg); + // This lets gdb trigger a register update etc + //sendGdbServerMessage("T05library:r;"); + sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); + break; + } + case 0xa1: { // NotifyDeleted + const ushort itemType = extractByte(result.data.data() + 1); + const ushort len = result.data.size() > 12 + ? extractShort(result.data.data() + 10) : ushort(0); + const QString name = len + ? QString::fromAscii(result.data.mid(12, len)) : QString(); + if (!name.isEmpty()) + m_session.modules.removeAll(name); + logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3") + .arg(QString::fromAscii(prefix)) + .arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")) + .arg(name)); + sendTrkAck(result.token); + if (itemType == 0) { + sendGdbServerMessage("W00", "Process exited"); + //sendTrkMessage(0x02, TrkCB(handleDisconnect)); + } + break; + } + case 0xa2: { // NotifyProcessorStarted + logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str); + sendTrkAck(result.token); + break; + } + case 0xa6: { // NotifyProcessorStandby + logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str); + sendTrkAck(result.token); + break; + } + case 0xa7: { // NotifyProcessorReset + logMessage(prefix + "NOTE: PROCESSOR RESET: " + str); + sendTrkAck(result.token); + break; + } + default: { + logMessage(prefix + "INVALID: " + str); + break; + } + } +} + +void SymbianAdapter::handleCpuType(const TrkResult &result) +{ + //---TRK------------------------------------------------------ + // Command: 0x80 Acknowledge + // Error: 0x00 + // [80 03 00 04 00 00 04 00 00 00] + m_session.cpuMajor = result.data[1]; + m_session.cpuMinor = result.data[2]; + m_session.bigEndian = result.data[3]; + m_session.defaultTypeSize = result.data[4]; + m_session.fpTypeSize = result.data[5]; + m_session.extended1TypeSize = result.data[6]; + //m_session.extended2TypeSize = result.data[6]; + QString logMsg; + QTextStream(&logMsg) << "HANDLE CPU TYPE: CPU=" << m_session.cpuMajor << '.' + << m_session.cpuMinor << " bigEndian=" << m_session.bigEndian + << " defaultTypeSize=" << m_session.defaultTypeSize + << " fpTypeSize=" << m_session.fpTypeSize + << " extended1TypeSize=" << m_session.extended1TypeSize; + logMessage(logMsg); +} + +void SymbianAdapter::handleSetTrkBreakpoint(const TrkResult &result) +{ + //---TRK------------------------------------------------------ + // Command: 0x80 Acknowledge + // Error: 0x00 + // [80 09 00 00 00 00 0A] + const uint bpnr = extractInt(result.data.data()); + logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + + stringFromArray(result.data.data())); +} + +void SymbianAdapter::handleCreateProcess(const TrkResult &result) +{ + // 40 00 00] + //logMessage(" RESULT: " + result.toString()); + // [80 08 00 00 00 01 B5 00 00 01 B6 78 67 40 00 00 40 00 00] + const char *data = result.data.data(); + m_session.pid = extractInt(data + 1); + m_session.tid = extractInt(data + 5); + m_session.codeseg = extractInt(data + 9); + m_session.dataseg = extractInt(data + 13); + + logMessage("PID: " + hexxNumber(m_session.pid)); + logMessage("TID: " + hexxNumber(m_session.tid)); + logMessage("COD: " + hexxNumber(m_session.codeseg)); + logMessage("DAT: " + hexxNumber(m_session.dataseg)); + + QByteArray ba; + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); + + startGdb(); + + +#if 0 + //---IDE------------------------------------------------------ + // Command: 0x42 Read Info + // [42 0C 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F + // 72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00] + sendTrkMessage(0x42, TrkCB(handleReadInfo), + "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " + "72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00"); + //sendTrkMessage(0x42, TrkCB(handleReadInfo), + // "00 01 00 00 00 00"); + //---TRK------------------------------------------------------ + // Command: 0x80 Acknowledge + // Error: 0x20 Unspecified general OS-related error + // [80 0C 20] + + + //---IDE------------------------------------------------------ + // Command: 0x42 Read Info + // [42 0D 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F + // 72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00] + sendTrkMessage(0x42, TrkCB(handleReadInfo), + "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " + "72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00"); + //---TRK------------------------------------------------------ + // Command: 0x80 Acknowledge + // Error: 0x20 Unspecified general OS-related error + // [80 0D 20] +#endif + + //sendTrkMessage(0x18, TrkCB(handleStop), + // "01 " + formatInt(m_session.pid) + formatInt(m_session.tid)); +} + +void SymbianAdapter::handleReadRegisters(const TrkResult &result) +{ + logMessage(" RESULT: " + result.toString()); + // [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...] + if (result.errorCode()) { + logMessage("ERROR: " + result.errorString()); + return; + } + const char *data = result.data.data() + 1; // Skip ok byte + for (int i = 0; i < RegisterCount; ++i) + m_snapshot.registers[i] = extractInt(data + 4 * i); +} + +void SymbianAdapter::handleAndReportReadRegisters(const TrkResult &result) +{ + handleReadRegisters(result); + QByteArray ba; + for (int i = 0; i < 16; ++i) { + const uint reg = m_registerEndianness == LittleEndian + ? swapEndian(m_snapshot.registers[i]) : m_snapshot.registers[i]; + ba += hexNumber(reg, 8); + } + QByteArray logMsg = "REGISTER CONTENTS: "; + if (m_verbose > 1) { + for (int i = 0; i < RegisterCount; ++i) { + logMsg += dumpRegister(i, m_snapshot.registers[i]); + logMsg += ' '; + } + } + sendGdbServerMessage(ba, logMsg); +} + +static inline QString msgMemoryReadError(int code, uint addr, uint len = 0) +{ + const QString lenS = len ? QString::number(len) : QLatin1String(""); + return QString::fromLatin1("Memory read error %1 at: 0x%2 %3") + .arg(code).arg(addr, 0 ,16).arg(lenS); +} + +void SymbianAdapter::handleReadMemoryBuffered(const TrkResult &result) +{ + if (extractShort(result.data.data() + 1) + 3 != result.data.size()) + logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n"); + const uint blockaddr = result.cookie.toUInt(); + if (const int errorCode = result.errorCode()) { + logMessage(msgMemoryReadError(errorCode, blockaddr)); + return; + } + const QByteArray ba = result.data.mid(3); + m_snapshot.memory.insert(blockaddr, ba); +} + +// Format log message for memory access with some smartness about registers +QByteArray SymbianAdapter::memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const +{ + QByteArray logMsg = "memory contents"; + if (m_verbose > 1) { + logMsg += " addr: " + hexxNumber(addr); + // indicate dereferencing of registers + if (len == 4) { + if (addr == m_snapshot.registers[RegisterPC]) { + logMsg += "[PC]"; + } else if (addr == m_snapshot.registers[RegisterPSTrk]) { + logMsg += "[PSTrk]"; + } else if (addr == m_snapshot.registers[RegisterSP]) { + logMsg += "[SP]"; + } else if (addr == m_snapshot.registers[RegisterLR]) { + logMsg += "[LR]"; + } else if (addr > m_snapshot.registers[RegisterSP] && + (addr - m_snapshot.registers[RegisterSP]) < 10240) { + logMsg += "[SP+"; // Stack area ...stack seems to be top-down + logMsg += QByteArray::number(addr - m_snapshot.registers[RegisterSP]); + logMsg += ']'; + } + } + logMsg += " length "; + logMsg += QByteArray::number(len); + logMsg += " :"; + logMsg += stringFromArray(ba, 16).toAscii(); + } + return logMsg; +} + +void SymbianAdapter::reportReadMemoryBuffered(const TrkResult &result) +{ + const qulonglong cookie = result.cookie.toULongLong(); + const uint addr = cookie >> 32; + const uint len = uint(cookie); + + // Gdb accepts less memory according to documentation. + // Send E on complete failure. + QByteArray ba; + uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize; + for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) { + const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr); + if (it == m_snapshot.memory.constEnd()) + break; + ba.append(it.value()); + } + const int previousChunkOverlap = addr % MemoryChunkSize; + if (previousChunkOverlap != 0 && ba.size() > previousChunkOverlap) + ba.remove(0, previousChunkOverlap); + if (ba.size() > int(len)) + ba.truncate(len); + + if (ba.isEmpty()) { + ba = "E20"; + sendGdbServerMessage(ba, msgMemoryReadError(32, addr, len).toLatin1()); + } else { + sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba)); + } +} + +void SymbianAdapter::handleReadMemoryUnbuffered(const TrkResult &result) +{ + //logMessage("UNBUFFERED MEMORY READ: " + stringFromArray(result.data)); + const uint blockaddr = result.cookie.toUInt(); + if (extractShort(result.data.data() + 1) + 3 != result.data.size()) + logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n"); + if (const int errorCode = result.errorCode()) { + const QByteArray ba = "E20"; + sendGdbServerMessage(ba, msgMemoryReadError(32, blockaddr).toLatin1()); + } else { + const QByteArray ba = result.data.mid(3); + sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(blockaddr, ba.size(), ba)); + } +} + +void SymbianAdapter::handleStepRange(const TrkResult &result) +{ + // [80 0f 00] + if (result.errorCode()) { + logMessage("ERROR: " + result.errorString()); + return; + } + logMessage("STEPPING FINISHED "); + //sendGdbServerMessage("S05", "Stepping finished"); +} + +void SymbianAdapter::handleAndReportSetBreakpoint(const TrkResult &result) +{ + //---TRK------------------------------------------------------ + // Command: 0x80 Acknowledge + // Error: 0x00 + // [80 09 00 00 00 00 0A] + uint bpnr = extractByte(result.data.data()); + uint addr = result.cookie.toUInt(); + m_session.addressToBP[addr] = bpnr; + logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + " " + + stringFromArray(result.data.data())); + sendGdbServerMessage("OK"); + //sendGdbServerMessage("OK"); +} + +void SymbianAdapter::handleClearBreakpoint(const TrkResult &result) +{ + logMessage("CLEAR BREAKPOINT "); + if (result.errorCode()) { + logMessage("ERROR: " + result.errorString()); + //return; + } + //---TRK------------------------------------------------------ + // Command: 0x80 Acknowledge + // Error: 0x00 + // [80 09 00 00 00 00 0A] + // FIXME: + sendGdbServerMessage("OK"); +} + +void SymbianAdapter::handleSignalContinue(const TrkResult &result) +{ + int signalNumber = result.cookie.toInt(); + logMessage(" HANDLE SIGNAL CONTINUE: " + stringFromArray(result.data)); + logMessage("NUMBER" + QString::number(signalNumber)); + sendGdbServerMessage("O" + QByteArray("Console output").toHex()); + sendGdbServerMessage("W81"); // "Process exited with result 1 +} + +void SymbianAdapter::handleSupportMask(const TrkResult &result) +{ + const char *data = result.data.data(); + QByteArray str; + for (int i = 0; i < 32; ++i) { + //str.append(" [" + formatByte(data[i]) + "]: "); + for (int j = 0; j < 8; ++j) + if (data[i] & (1 << j)) + str.append(QByteArray::number(i * 8 + j, 16)); + } + logMessage("SUPPORTED: " + str); + } + +void SymbianAdapter::handleTrkVersions(const TrkResult &result) +{ + QString logMsg; + QTextStream str(&logMsg); + str << "Versions: "; + if (result.data.size() >= 5) { + str << "Trk version " << int(result.data.at(1)) << '.' + << int(result.data.at(2)) + << ", Protocol version " << int(result.data.at(3)) + << '.' << int(result.data.at(4)); + } + logMessage(logMsg); +} + +void SymbianAdapter::handleDisconnect(const TrkResult & /*result*/) +{ + logMessage(QLatin1String("Trk disconnected"), true); +} + +void SymbianAdapter::readMemory(uint addr, uint len) +{ + Q_ASSERT(len < (2 << 16)); + + // We try to get medium-sized chunks of data from the device + if (m_verbose > 2) + logMessage(QString::fromLatin1("readMemory %1 bytes from 0x%2 blocksize=%3") + .arg(len).arg(addr, 0, 16).arg(MemoryChunkSize)); + + if (m_bufferedMemoryRead) { + uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize; + for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) { + if (!m_snapshot.memory.contains(blockaddr)) { + if (m_verbose) + logMessage(QString::fromLatin1("Requesting buffered " + "memory %1 bytes from 0x%2") + .arg(MemoryChunkSize).arg(blockaddr, 0, 16)); + sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered), + trkReadMemoryMessage(blockaddr, MemoryChunkSize), + QVariant(blockaddr)); + } + } + const qulonglong cookie = (qulonglong(addr) << 32) + len; + sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportReadMemoryBuffered), + QByteArray(), cookie); + } else { + if (m_verbose) + logMessage(QString::fromLatin1("Requesting unbuffered memory %1 " + "bytes from 0x%2").arg(len).arg(addr, 0, 16)); + sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered), + trkReadMemoryMessage(addr, len), QVariant(addr)); + } +} + +void SymbianAdapter::interruptInferior() +{ + QByteArray ba; + // stop the thread (2) or the process (1) or the whole system (0) + // We choose 2, as 1 does not seem to work. + appendByte(&ba, 2); + appendInt(&ba, m_session.pid); + appendInt(&ba, m_session.tid); // threadID: 4 bytes Variable number of bytes. + sendTrkMessage(0x1a, TrkCallback(), ba, "Interrupting..."); +} + +void SymbianAdapter::connectProcess(QProcess *proc) +{ + connect(proc, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(handleProcError(QProcess::ProcessError))); + connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(handleProcFinished(int, QProcess::ExitStatus))); + connect(proc, SIGNAL(started()), + this, SLOT(handleProcStarted())); + connect(proc, SIGNAL(stateChanged(QProcess::ProcessState)), + this, SLOT(handleProcStateChanged(QProcess::ProcessState))); +} + +void SymbianAdapter::sendOutput(QObject *sender, const QString &data) +{ + if (sender) + emit output(sender->objectName() + " : ", data); + else + emit output(QString(), data); +} + +void SymbianAdapter::handleProcError(QProcess::ProcessError error) +{ + sendOutput(sender(), QString("Process Error %1").arg(error)); +} + +void SymbianAdapter::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + sendOutput(sender(), + QString("ProcessFinished %1 %2").arg(exitCode).arg(exitStatus)); +} + +void SymbianAdapter::handleProcStarted() +{ + sendOutput(sender(), QString("Process Started")); +} + +void SymbianAdapter::handleProcStateChanged(QProcess::ProcessState newState) +{ + sendOutput(sender(), QString("Process State %1").arg(newState)); +} + +void SymbianAdapter::run() +{ + sendOutput("### Starting SymbianAdapter"); + m_rfcommProc.start("rfcomm listen " + m_rfcommDevice + " 1"); + m_rfcommProc.waitForStarted(); + + connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)), + this, SLOT(handleTrkResult(trk::TrkResult))); + connect(&m_trkDevice, SIGNAL(error(QString)), + this, SLOT(handleTrkError(QString))); + + startInferior(); +} + +void SymbianAdapter::startGdb() +{ + if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) { + logMessage(QString("Unable to start the gdb server at %1: %2.") + .arg(m_gdbServerName).arg(m_gdbServer.errorString()), true); + QCoreApplication::exit(5); + return; + } + + logMessage(QString("Gdb server running on %1.\nRegister endianness: %3.") + .arg(m_gdbServerName).arg(m_registerEndianness), true); + + connect(&m_gdbServer, SIGNAL(newConnection()), + this, SLOT(handleGdbConnection())); + + logMessage("STARTING GDB"); + QStringList gdbArgs; + gdbArgs.append("--nx"); // Do not read .gdbinit file + gdbArgs.append("-i"); + gdbArgs.append("mi"); + m_gdbProc.start(QDir::currentPath() + "/cs-gdb", gdbArgs); + m_gdbProc.waitForStarted(); + + sendGdbMessage("set confirm off"); // confirm potentially dangerous operations? + sendGdbMessage("set endian little"); + sendGdbMessage("set remotebreak on"); + sendGdbMessage("set breakpoint pending on"); + sendGdbMessage("set trust-readonly-sections on"); + //sendGdbMessage("mem 0 ~0ll rw 8 cache"); + + // FIXME: "remote noack" does not seem to be supported on cs-gdb? + //sendGdbMessage("set remote noack-packet"); + + // FIXME: creates a lot of noise a la '&"putpkt: Junk: Ack " &' + // even thouhg the communication seems sane + //sendGdbMessage("set debug remote 1"); // creates l + + //sendGdbMessage("target remote " + m_gdbServerName); +// sendGdbMessage("target extended-remote " + m_gdbServerName); + //sendGdbMessage("target extended-async " + m_gdbServerName); + //sendGdbMessage("set remotecache ...") // Set cache use for remote targets + //sendGdbMessage("file filebrowseapp.sym"); +// sendGdbMessage("add-symbol-file filebrowseapp.sym " + m_baseAddress); +// sendGdbMessage("symbol-file filebrowseapp.sym"); +// sendGdbMessage("print E32Main"); +// sendGdbMessage("break E32Main"); + //sendGdbMessage("continue"); + //sendGdbMessage("info files"); + //sendGdbMessage("file filebrowseapp.sym -readnow"); + + sendGdbMessage("add-symbol-file filebrowseapp.sym " + + hexxNumber(m_session.codeseg)); + sendGdbMessage("symbol-file filebrowseapp.sym"); + + // -symbol-info-address not implemented in cs-gdb 6.4-6.8 (at least) + sendGdbMessage("info address E32Main", + GdbCB(handleInfoMainAddress)); + sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL", + GdbCB(handleInfoMainAddress)); + +#if 1 + // FIXME: Gdb based version. That's the goal + //sendGdbMessage("break E32Main"); + //sendGdbMessage("continue"); + //sendTrkMessage(0x18, TrkCB(handleContinueAfterCreateProcess), + // trkContinueMessage(), "CONTINUE"); +#else + // Directly talk to TRK. Works for now... + sendGdbMessage("break E32Main"); + sendGdbMessage("break filebrowseappui.cpp:39"); + // sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); +#endif +} + +void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback, + const QVariant &cookie) +{ + static int token = 0; + ++token; + GdbCommand data; + data.command = msg; + data.callback = callback; + data.cookie = cookie; + m_gdbCookieForToken[token] = data; + logMessage(QString("<- GDB: %1 %2").arg(token).arg(msg)); + m_gdbProc.write(QString("%1%2\n").arg(token).arg(msg).toLatin1()); +} + +void SymbianAdapter::handleGdbReadyReadStandardError() +{ + QByteArray ba = qobject_cast(sender())->readAllStandardError(); + sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba))); +} + +void SymbianAdapter::handleGdbReadyReadStandardOutput() +{ + QByteArray ba = qobject_cast(sender())->readAllStandardOutput(); + QString str = QString::fromLatin1(ba); + // FIXME: fragile. merge with gdbengine logic +#if 0 + QRegExp re(QString(".*([0-9]+)[^]done.*")); + int pos = re.indexIn(str); + if (pos == -1) { + logMessage(QString("\n-> GDB: %1 %**% %2 %**%\n").arg(str).arg(pos)); + return; + } + int token = re.cap(1).toInt(); + logMessage(QString("\n-> GDB: %1 %2##\n").arg(token).arg(QString::fromLatin1(ba))); + if (!token) + return; + GdbCommand cmd = m_gdbCookieForToken.take(token); + logMessage("FOUND CALLBACK FOR " + cmd.command); + GdbResult result; + result.data = ba; + if (!cmd.callback.isNull()) + cmd.callback(result); +#else + bool ok; + QRegExp re(QString("Symbol .._Z7E32Mainv.. is a function at address 0x(.*)\\.")); + if (re.indexIn(str) != -1) { + logMessage(QString("-> GDB MAIN BREAKPOINT: %1").arg(re.cap(1))); + uint addr = re.cap(1).toInt(&ok, 16); + sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); + return; + } + QRegExp re1(QString("Symbol .._ZN16CFileBrowseAppUi14HandleCommandLEi.. is a function at address 0x(.*)\\.")); + if (re1.indexIn(str) != -1) { + logMessage(QString("-> GDB USER BREAKPOINT: %1").arg(re1.cap(1))); + uint addr = re1.cap(1).toInt(&ok, 16); + sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); + + sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); + sendGdbMessage("target remote " + m_gdbServerName); + return; + } + logMessage(QString("-> GDB: %1").arg(str)); +#endif +} + +void SymbianAdapter::handleInfoMainAddress(const GdbResult &result) +{ + Q_UNUSED(result); +} + +void SymbianAdapter::handleSetTrkMainBreakpoint(const TrkResult &result) +{ + Q_UNUSED(result); +/* + //---TRK------------------------------------------------------ + // [80 09 00 00 00 00 0A] + const uint bpnr = extractInt(result.data.data()); + logMessage("SET MAIN BREAKPOINT " + hexxNumber(bpnr) + + stringFromArray(result.data.data())); +*/ +} + +void SymbianAdapter::handleInfoAddress(const GdbResult &result) +{ + Q_UNUSED(result); + // FIXME +} + +void SymbianAdapter::handleRfcommReadyReadStandardError() +{ + QByteArray ba = qobject_cast(sender())->readAllStandardError(); + sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba))); +} + +void SymbianAdapter::handleRfcommReadyReadStandardOutput() +{ + QByteArray ba = qobject_cast(sender())->readAllStandardOutput(); + sendOutput(sender(), QString("stdout: %1").arg(QString::fromLatin1(ba))); +} + +// +// GdbProcessBase +// + +void SymbianAdapter::start(const QString &program, const QStringList &args, + QIODevice::OpenMode mode) +{ + //m_gdbProc.start(program, args, mode); +} + +void SymbianAdapter::kill() +{ + //m_gdbProc.kill(); +} + +void SymbianAdapter::terminate() +{ + //m_gdbProc.terminate(); +} + +bool SymbianAdapter::waitForStarted(int msecs) +{ + //return m_gdbProc.waitForStarted(msecs); + return true; +} + +bool SymbianAdapter::waitForFinished(int msecs) +{ + //return m_gdbProc.waitForFinished(msecs); + return true; +} + +QProcess::ProcessState SymbianAdapter::state() const +{ + return m_gdbProc.state(); +} + +QString SymbianAdapter::errorString() const +{ + return m_gdbProc.errorString(); +} + +QByteArray SymbianAdapter::readAllStandardError() +{ + return m_gdbProc.readAllStandardError(); +} + +QByteArray SymbianAdapter::readAllStandardOutput() +{ + return m_gdbProc.readAllStandardOutput(); +} + +qint64 SymbianAdapter::write(const char *data) +{ + return m_gdbProc.write(data); +} + +void SymbianAdapter::setWorkingDirectory(const QString &dir) +{ + m_gdbProc.setWorkingDirectory(dir); +} + +void SymbianAdapter::setEnvironment(const QStringList &env) +{ + m_gdbProc.setEnvironment(env); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h new file mode 100644 index 00000000000..45c5b762c04 --- /dev/null +++ b/src/plugins/debugger/symbian/symbianadapter.h @@ -0,0 +1,247 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef DEBUGGER_SYMBIANADAPTER_H +#define DEBUGGER_SYMBIANADAPTER_H + +#include "trkutils.h" +#include "trkclient.h" +#include "../gdb/gdbprocessbase.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Debugger { +namespace Internal { + +struct GdbResult +{ + QByteArray data; +}; + +/////////////////////////////////////////////////////////////////////// +// +// SymbianAdapter +// +/////////////////////////////////////////////////////////////////////// + +class SymbianAdapter : public GdbProcessBase +{ + Q_OBJECT + +public: + typedef trk::TrkResult TrkResult; + typedef trk::TrkFunctor1 TrkCallback; + typedef trk::TrkFunctor1 GdbCallback; + + SymbianAdapter(); + ~SymbianAdapter(); + void setGdbServerName(const QString &name); + QString gdbServerIP() const; + uint gdbServerPort() const; + void setVerbose(int verbose) { m_verbose = verbose; } + void setSerialFrame(bool b) { m_serialFrame = b; } + void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; } + +public slots: + void startInferior(); + +signals: + void output(const QString &senderName, const QString &data); + +private slots: + void handleProcError(QProcess::ProcessError error); + void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus); + void handleProcStarted(); + void handleProcStateChanged(QProcess::ProcessState newState); + void run(); + void startGdb(); + +private: + friend class RunnerGui; + void connectProcess(QProcess *proc); + void sendOutput(QObject *sender, const QString &data); + void sendOutput(const QString &data) { sendOutput(0, data); } + + QString m_rfcommDevice; // /dev/rfcomm0 + QString m_gdbServerName; // 127.0.0.1:(2222+uid) + + QProcess m_gdbProc; + QProcess m_rfcommProc; + bool m_running; + +public: + // + // Implementation of GdbProcessBase + // + void start(const QString &program, const QStringList &args, + QIODevice::OpenMode mode = QIODevice::ReadWrite); + void kill(); + void terminate(); + bool waitForStarted(int msecs = 30000); + bool waitForFinished(int msecs = 30000); + QProcess::ProcessState state() const; + QString errorString() const; + QByteArray readAllStandardError(); + QByteArray readAllStandardOutput(); + qint64 write(const char *data); + void setWorkingDirectory(const QString &dir); + void setEnvironment(const QStringList &env); + + // + // TRK + // + void sendTrkMessage(byte code, + TrkCallback callback = TrkCallback(), + const QByteArray &data = QByteArray(), + const QVariant &cookie = QVariant()); + Q_SLOT void handleTrkResult(const trk::TrkResult &data); + Q_SLOT void handleTrkError(const QString &msg); + + // convenience messages + void sendTrkAck(byte token); + + void handleCpuType(const TrkResult &result); + void handleCreateProcess(const TrkResult &result); + void handleClearBreakpoint(const TrkResult &result); + void handleSignalContinue(const TrkResult &result); + void handleStop(const TrkResult &result); + void handleSupportMask(const TrkResult &result); + void handleTrkVersions(const TrkResult &result); + void handleDisconnect(const TrkResult &result); + + void handleAndReportCreateProcess(const TrkResult &result); + void handleAndReportReadRegisters(const TrkResult &result); + QByteArray memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const; + QByteArray trkContinueMessage(); + QByteArray trkReadRegisterMessage(); + QByteArray trkReadMemoryMessage(uint addr, uint len); + QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true); + void handleAndReportSetBreakpoint(const TrkResult &result); + void handleReadMemoryBuffered(const TrkResult &result); + void handleReadMemoryUnbuffered(const TrkResult &result); + void handleStepRange(const TrkResult &result); + void handleReadRegisters(const TrkResult &result); + void reportReadMemoryBuffered(const TrkResult &result); + void reportToGdb(const TrkResult &result); + + // set breakpoints behind gdb's back + void handleSetTrkBreakpoint(const TrkResult &result); + void handleSetTrkMainBreakpoint(const TrkResult &result); + + void readMemory(uint addr, uint len); + void interruptInferior(); + + trk::TrkDevice m_trkDevice; + + // + // Gdb + // + struct GdbCommand + { + GdbCommand() : flags(0), callback(GdbCallback()), callbackName(0) {} + + int flags; + GdbCallback callback; + const char *callbackName; + QString command; + QVariant cookie; + //QTime postTime; + }; + + void sendGdbMessage(const QString &msg, + GdbCallback callback = GdbCallback(), + const QVariant &cookie = QVariant()); + Q_SLOT void handleGdbConnection(); + Q_SLOT void readGdbServerCommand(); + void readGdbResponse(); + void handleGdbServerCommand(const QByteArray &cmd); + void sendGdbServerMessage(const QByteArray &msg, + const QByteArray &logNote = QByteArray()); + void sendGdbServerMessageAfterTrkResponse(const QByteArray &msg, + const QByteArray &logNote = QByteArray()); + void sendGdbServerAck(); + bool sendGdbServerPacket(const QByteArray &packet, bool doFlush); + + Q_SLOT void handleGdbReadyReadStandardError(); + Q_SLOT void handleGdbReadyReadStandardOutput(); + void logMessage(const QString &msg, bool force = false); + Q_SLOT void trkLogMessage(const QString &msg); + + void handleInfoAddress(const GdbResult &result); + void handleInfoMainAddress(const GdbResult &result); + + QTcpServer m_gdbServer; + QPointer m_gdbConnection; + QByteArray m_gdbReadBuffer; + bool m_gdbAckMode; + + QHash m_gdbCookieForToken; + + // + // Rfcomm + // + Q_SLOT void handleRfcommReadyReadStandardError(); + Q_SLOT void handleRfcommReadyReadStandardOutput(); + + // Debuggee state + Q_SLOT void executeCommand(const QString &msg); + trk::Session m_session; // global-ish data (process id, target information) + trk::Snapshot m_snapshot; // local-ish data (memory and registers) + int m_verbose; + bool m_serialFrame; + bool m_bufferedMemoryRead; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_SYMBIANADAPTER_H diff --git a/src/plugins/debugger/symbian/symbianengine.cpp b/src/plugins/debugger/symbian/symbianengine.cpp new file mode 100644 index 00000000000..11c6b03c8ad --- /dev/null +++ b/src/plugins/debugger/symbian/symbianengine.cpp @@ -0,0 +1,66 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#define QT_NO_CAST_FROM_ASCII + +#include "gdb/gdbengine.h" +#include "symbianadapter.h" + +//#include "debuggerdialogs.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace Debugger { +namespace Internal { + + +IDebuggerEngine *createSymbianEngine(DebuggerManager *parent, + QList *opts) +{ + Q_UNUSED(opts); + //opts->push_back(new GdbOptionsPage); + return new GdbEngine(parent, new SymbianAdapter); +} + +} // namespace Internal +} // namespace Debugger + + diff --git a/tests/manual/trk/trkdevicex.cpp b/src/plugins/debugger/symbian/trkclient.cpp similarity index 99% rename from tests/manual/trk/trkdevicex.cpp rename to src/plugins/debugger/symbian/trkclient.cpp index 42c7f72e175..5ae9766ac5a 100644 --- a/tests/manual/trk/trkdevicex.cpp +++ b/src/plugins/debugger/symbian/trkclient.cpp @@ -27,7 +27,7 @@ ** **************************************************************************/ -#include "trkdevicex.h" +#include "trkclient.h" #include "trkutils.h" #include @@ -35,7 +35,6 @@ #include #include #include -#include #ifdef Q_OS_WIN # include diff --git a/tests/manual/trk/trkdevicex.h b/src/plugins/debugger/symbian/trkclient.h similarity index 100% rename from tests/manual/trk/trkdevicex.h rename to src/plugins/debugger/symbian/trkclient.h diff --git a/tests/manual/trk/trkfunctor.h b/src/plugins/debugger/symbian/trkfunctor.h similarity index 98% rename from tests/manual/trk/trkfunctor.h rename to src/plugins/debugger/symbian/trkfunctor.h index 3dbd027774b..4b0d3669120 100644 --- a/tests/manual/trk/trkfunctor.h +++ b/src/plugins/debugger/symbian/trkfunctor.h @@ -27,8 +27,8 @@ ** **************************************************************************/ -#ifndef _TRK_FUNCTOR_H_ -#define _TRK_FUNCTOR_H_ +#ifndef DEBUGGER_TRK_FUNCTOR_H +#define DEBUGGER_TRK_FUNCTOR_H #include diff --git a/tests/manual/trk/trkutils.cpp b/src/plugins/debugger/symbian/trkutils.cpp similarity index 100% rename from tests/manual/trk/trkutils.cpp rename to src/plugins/debugger/symbian/trkutils.cpp diff --git a/tests/manual/trk/trkutils.h b/src/plugins/debugger/symbian/trkutils.h similarity index 99% rename from tests/manual/trk/trkutils.h rename to src/plugins/debugger/symbian/trkutils.h index 7b1709498ce..6f1b280eb85 100644 --- a/tests/manual/trk/trkutils.h +++ b/src/plugins/debugger/symbian/trkutils.h @@ -197,7 +197,6 @@ QByteArray hexNumber(uint n, int digits = 0); QByteArray hexxNumber(uint n, int digits = 0); // prepends '0x', too uint swapEndian(uint in); - } // namespace trk #endif // DEBUGGER_TRK_UTILS diff --git a/tests/manual/trk/adapter.pro b/tests/manual/trk/adapter.pro index 22f4aa3cddb..9ee1a95d8f7 100644 --- a/tests/manual/trk/adapter.pro +++ b/tests/manual/trk/adapter.pro @@ -1,14 +1,20 @@ TEMPLATE = app +DEBUGGERHOME = ../../../src/plugins/debugger/symbian + +INCLUDEPATH *= $$DEBUGGERHOME + +UTILSDIR = ../../../src/libs QT = core network win32:CONFIG+=console -HEADERS += trkutils.h \ -trkfunctor.h \ -trkdevice.h \ +HEADERS += \ + $$DEBUGGERHOME/trkutils.h \ + $$DEBUGGERHOME/trkfunctor.h \ + $$PWD/trkdevice.h \ SOURCES += \ - adapter.cpp \ - trkutils.cpp \ - trkdevice.cpp + $$DEBUGGERHOME/trkutils.cpp \ + $$PWD/trkdevice.cpp \ + $$PWD/adapter.cpp \ diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index bf55d0b6f40..4724df4d179 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -27,8 +27,7 @@ ** **************************************************************************/ -#include "trkutils.h" -#include "trkdevicex.h" +#include "symbianadapter.h" #include #include @@ -114,1627 +113,6 @@ static QByteArray dumpRegister(int n, uint value) return ba; } -#define TrkCB(s) TrkCallback(this, &Adapter::s) -#define GdbCB(s) GdbCallback(this, &Adapter::s) - -struct GdbResult -{ - QByteArray data; -}; - -/////////////////////////////////////////////////////////////////////// -// -// Adapter -// -/////////////////////////////////////////////////////////////////////// - -class Adapter : public QObject -{ - Q_OBJECT - -public: - typedef TrkFunctor1 TrkCallback; - typedef TrkFunctor1 GdbCallback; - - Adapter(); - ~Adapter(); - void setGdbServerName(const QString &name); - QString gdbServerIP() const; - uint gdbServerPort() const; - void setVerbose(int verbose) { m_verbose = verbose; } - void setSerialFrame(bool b) { m_serialFrame = b; } - void setRegisterEndianness(Endianness r) { m_registerEndianness = r; } - void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; } - -public slots: - void startInferior(); - -signals: - void output(const QString &senderName, const QString &data); - -private slots: - void handleProcError(QProcess::ProcessError error); - void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus); - void handleProcStarted(); - void handleProcStateChanged(QProcess::ProcessState newState); - void run(); - void startGdb(); - -private: - friend class RunnerGui; - void connectProcess(QProcess *proc); - void sendOutput(QObject *sender, const QString &data); - void sendOutput(const QString &data) { sendOutput(0, data); } - - QString m_rfcommDevice; // /dev/rfcomm0 - QString m_gdbServerName; // 127.0.0.1:(2222+uid) - - QProcess m_gdbProc; - QProcess m_rfcommProc; - bool m_running; - -public: - // - // TRK - // - void sendTrkMessage(byte code, - TrkCallback callback = TrkCallback(), - const QByteArray &data = QByteArray(), - const QVariant &cookie = QVariant()); - Q_SLOT void handleTrkResult(const trk::TrkResult &data); - Q_SLOT void handleTrkError(const QString &msg); - - // convenience messages - void sendTrkAck(byte token); - - void handleCpuType(const TrkResult &result); - void handleCreateProcess(const TrkResult &result); - void handleClearBreakpoint(const TrkResult &result); - void handleSignalContinue(const TrkResult &result); - void handleStop(const TrkResult &result); - void handleSupportMask(const TrkResult &result); - void handleTrkVersions(const TrkResult &result); - void handleDisconnect(const TrkResult &result); - - void handleAndReportCreateProcess(const TrkResult &result); - void handleAndReportReadRegisters(const TrkResult &result); - QByteArray memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const; - QByteArray trkContinueMessage(); - QByteArray trkReadRegisterMessage(); - QByteArray trkReadMemoryMessage(uint addr, uint len); - QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true); - void handleAndReportSetBreakpoint(const TrkResult &result); - void handleReadMemoryBuffered(const TrkResult &result); - void handleReadMemoryUnbuffered(const TrkResult &result); - void handleStepRange(const TrkResult &result); - void handleReadRegisters(const TrkResult &result); - void reportReadMemoryBuffered(const TrkResult &result); - void reportToGdb(const TrkResult &result); - - // set breakpoints behind gdb's back - void setTrkBreakpoint(const Breakpoint &bp); - void handleSetTrkBreakpoint(const TrkResult &result); - void handleSetTrkMainBreakpoint(const TrkResult &result); - - void readMemory(uint addr, uint len); - void interruptInferior(); - - TrkDevice m_trkDevice; - - // - // Gdb - // - struct GdbCommand - { - GdbCommand() : flags(0), callback(GdbCallback()), callbackName(0) {} - - int flags; - GdbCallback callback; - const char *callbackName; - QString command; - QVariant cookie; - //QTime postTime; - }; - - void sendGdbMessage(const QString &msg, - GdbCallback callback = GdbCallback(), - const QVariant &cookie = QVariant()); - Q_SLOT void handleGdbConnection(); - Q_SLOT void readGdbServerCommand(); - void readGdbResponse(); - void handleGdbServerCommand(const QByteArray &cmd); - void sendGdbServerMessage(const QByteArray &msg, - const QByteArray &logNote = QByteArray()); - void sendGdbServerMessageAfterTrkResponse(const QByteArray &msg, - const QByteArray &logNote = QByteArray()); - void sendGdbServerAck(); - bool sendGdbServerPacket(const QByteArray &packet, bool doFlush); - - Q_SLOT void handleGdbReadyReadStandardError(); - Q_SLOT void handleGdbReadyReadStandardOutput(); - void logMessage(const QString &msg, bool force = false); - Q_SLOT void trkLogMessage(const QString &msg); - - void handleInfoAddress(const GdbResult &result); - void handleInfoMainAddress(const GdbResult &result); - - QTcpServer m_gdbServer; - QPointer m_gdbConnection; - QByteArray m_gdbReadBuffer; - bool m_gdbAckMode; - - QHash m_gdbCookieForToken; - - // - // Rfcomm - // - Q_SLOT void handleRfcommReadyReadStandardError(); - Q_SLOT void handleRfcommReadyReadStandardOutput(); - - // Debuggee state - Q_SLOT void executeCommand(const QString &msg); - Session m_session; // global-ish data (process id, target information) - Snapshot m_snapshot; // local-ish data (memory and registers) - int m_verbose; - Endianness m_registerEndianness; - bool m_serialFrame; - bool m_bufferedMemoryRead; -}; - -Adapter::Adapter() -{ - m_running = false; - m_gdbAckMode = true; - m_verbose = 2; - m_registerEndianness = LittleEndian; - m_serialFrame = false; - m_bufferedMemoryRead = true; - m_rfcommDevice = "/dev/rfcomm0"; - - uid_t userId = getuid(); - m_gdbServerName = QString("127.0.0.1:%1").arg(2222 + userId); - - m_gdbProc.setObjectName("GDB PROCESS"); - connectProcess(&m_gdbProc); - connect(&m_gdbProc, SIGNAL(readyReadStandardError()), - this, SLOT(handleGdbReadyReadStandardError())); - connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), - this, SLOT(handleGdbReadyReadStandardOutput())); - - m_rfcommProc.setObjectName("RFCOMM PROCESS"); - connectProcess(&m_rfcommProc); - connect(&m_rfcommProc, SIGNAL(readyReadStandardError()), - this, SLOT(handleRfcommReadyReadStandardError())); - connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()), - this, SLOT(handleRfcommReadyReadStandardOutput())); - - if (m_verbose > 1) - m_trkDevice.setVerbose(true); - m_trkDevice.setSerialFrame(m_serialFrame); - - connect(&m_trkDevice, SIGNAL(logMessage(QString)), - this, SLOT(trkLogMessage(QString))); -} - -Adapter::~Adapter() -{ - m_gdbServer.close(); - logMessage("Shutting down.\n", true); -} - -void Adapter::trkLogMessage(const QString &msg) -{ - logMessage("TRK " + msg); -} - -void Adapter::setGdbServerName(const QString &name) -{ - m_gdbServerName = name; -} - -QString Adapter::gdbServerIP() const -{ - int pos = m_gdbServerName.indexOf(':'); - if (pos == -1) - return m_gdbServerName; - return m_gdbServerName.left(pos); -} - -uint Adapter::gdbServerPort() const -{ - int pos = m_gdbServerName.indexOf(':'); - if (pos == -1) - return 0; - return m_gdbServerName.mid(pos + 1).toUInt(); -} - -QByteArray Adapter::trkContinueMessage() -{ - QByteArray ba; - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - return ba; -} - -QByteArray Adapter::trkReadRegisterMessage() -{ - 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 Adapter::trkReadMemoryMessage(uint addr, uint len) -{ - QByteArray ba; - appendByte(&ba, 0x08); // Options, FIXME: why? - appendShort(&ba, len); - appendInt(&ba, addr); - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - return ba; -} - -void Adapter::startInferior() -{ - QString errorMessage; - if (!m_trkDevice.open(m_rfcommDevice, &errorMessage)) { - logMessage("LOOPING"); - QTimer::singleShot(1000, this, SLOT(startInferior())); - return; - } - - m_trkDevice.sendTrkInitialPing(); - sendTrkMessage(0x01); // Connect - sendTrkMessage(0x05, TrkCB(handleSupportMask)); - sendTrkMessage(0x06, TrkCB(handleCpuType)); - sendTrkMessage(0x04, TrkCB(handleTrkVersions)); // Versions - //sendTrkMessage(0x09); // Unrecognized command - //sendTrkMessage(0x4a, 0, - // "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File - //sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File - - QByteArray ba; - appendByte(&ba, 0); // ? - appendByte(&ba, 0); // ? - appendByte(&ba, 0); // ? - - QByteArray file("C:\\sys\\bin\\filebrowseapp.exe"); - appendString(&ba, file, TargetByteOrder); - sendTrkMessage(0x40, TrkCB(handleCreateProcess), ba); // Create Item - //sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(startGdbServer)); -} - -void Adapter::logMessage(const QString &msg, bool force) -{ - if (m_verbose || force) - emit output(QString(), msg); -} - -// -// Gdb -// -void Adapter::handleGdbConnection() -{ - logMessage("HANDLING GDB CONNECTION"); - - m_gdbConnection = m_gdbServer.nextPendingConnection(); - connect(m_gdbConnection, SIGNAL(disconnected()), - m_gdbConnection, SLOT(deleteLater())); - connect(m_gdbConnection, SIGNAL(readyRead()), - this, SLOT(readGdbServerCommand())); -} - -static inline QString msgGdbPacket(const QString &p) -{ - return QLatin1String("gdb: ") + p; -} - -void Adapter::readGdbServerCommand() -{ - QByteArray packet = m_gdbConnection->readAll(); - m_gdbReadBuffer.append(packet); - - logMessage("gdb: -> " + QString::fromAscii(packet)); - if (packet != m_gdbReadBuffer) - logMessage("buffer: " + m_gdbReadBuffer); - - QByteArray &ba = m_gdbReadBuffer; - while (ba.size()) { - char code = ba.at(0); - ba = ba.mid(1); - - if (code == '+') { - //logMessage("ACK"); - continue; - } - - if (code == '-') { - logMessage("NAK: Retransmission requested"); - continue; - } - - if (code == char(0x03)) { - logMessage("INTERRUPT RECEIVED"); - interruptInferior(); - continue; - } - - if (code != '$') { - logMessage("Broken package (2) " + quoteUnprintableLatin1(ba) - + hexNumber(code)); - continue; - } - - int pos = ba.indexOf('#'); - if (pos == -1) { - logMessage("Invalid checksum format in " - + quoteUnprintableLatin1(ba)); - continue; - } - - bool ok = false; - uint checkSum = ba.mid(pos + 1, 2).toUInt(&ok, 16); - if (!ok) { - logMessage("Invalid checksum format 2 in " - + quoteUnprintableLatin1(ba)); - return; - } - - //logMessage(QString("Packet checksum: %1").arg(checkSum)); - byte sum = 0; - for (int i = 0; i < pos; ++i) - sum += ba.at(i); - - if (sum != checkSum) { - logMessage(QString("ERROR: Packet checksum wrong: %1 %2 in " - + quoteUnprintableLatin1(ba)).arg(checkSum).arg(sum)); - } - - QByteArray cmd = ba.left(pos); - ba.remove(0, pos + 3); - handleGdbServerCommand(cmd); - } -} - -bool Adapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush) -{ - if (!m_gdbConnection) { - logMessage(QString::fromLatin1("Cannot write to gdb: No connection (%1)") - .arg(QString::fromLatin1(packet)), true); - return false; - } - if (m_gdbConnection->state() != QAbstractSocket::ConnectedState) { - logMessage(QString::fromLatin1("Cannot write to gdb: Not connected (%1)") - .arg(QString::fromLatin1(packet)), true); - return false; - } - if (m_gdbConnection->write(packet) == -1) { - logMessage(QString::fromLatin1("Cannot write to gdb: %1 (%2)") - .arg(m_gdbConnection->errorString()).arg(QString::fromLatin1(packet)), true); - return false; - } - if (doFlush) - m_gdbConnection->flush(); - return true; -} - -void Adapter::sendGdbServerAck() -{ - if (!m_gdbAckMode) - return; - QByteArray packet = "+"; - logMessage("gdb: <- " + packet); - sendGdbServerPacket(packet, false); -} - -void Adapter::sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote) -{ - byte sum = 0; - for (int i = 0; i != msg.size(); ++i) - sum += msg.at(i); - - char checkSum[30]; - qsnprintf(checkSum, sizeof(checkSum) - 1, "%02x ", sum); - - //logMessage(QString("Packet checksum: %1").arg(sum)); - - QByteArray packet; - packet.append("$"); - packet.append(msg); - packet.append('#'); - packet.append(checkSum); - int pad = qMax(0, 24 - packet.size()); - logMessage("gdb: <- " + packet + QByteArray(pad, ' ') + logNote); - sendGdbServerPacket(packet, true); -} - -void Adapter::sendGdbServerMessageAfterTrkResponse(const QByteArray &msg, - const QByteArray &logNote) -{ - QByteArray ba = msg + char(1) + logNote; - sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportToGdb), "", ba); // Answer gdb -} - -void Adapter::reportToGdb(const TrkResult &result) -{ - QByteArray message = result.cookie.toByteArray(); - QByteArray note; - int pos = message.lastIndexOf(char(1)); // HACK - if (pos != -1) { - note = message.mid(pos + 1); - message = message.left(pos); - } - message.replace("@CODESEG@", hexNumber(m_session.codeseg)); - message.replace("@DATASEG@", hexNumber(m_session.dataseg)); - message.replace("@PID@", hexNumber(m_session.pid)); - message.replace("@TID@", hexNumber(m_session.tid)); - sendGdbServerMessage(message, note); -} - -QByteArray Adapter::trkBreakpointMessage(uint addr, uint len, bool armMode) -{ - QByteArray ba; - appendByte(&ba, 0x82); // unused option - appendByte(&ba, armMode /*bp.mode == ArmMode*/ ? 0x00 : 0x01); - appendInt(&ba, addr); - appendInt(&ba, len); - appendInt(&ba, 0x00000001); - appendInt(&ba, m_session.pid); - appendInt(&ba, 0xFFFFFFFF); - return ba; -} - -void Adapter::handleGdbServerCommand(const QByteArray &cmd) -{ - // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html - if (0) {} - - else if (cmd == "!") { - sendGdbServerAck(); - //sendGdbServerMessage("", "extended mode not enabled"); - sendGdbServerMessage("OK", "extended mode enabled"); - } - - else if (cmd.startsWith("?")) { - logMessage(msgGdbPacket(QLatin1String("Query halted"))); - // Indicate the reason the target halted. - // The reply is the same as for step and continue. - sendGdbServerAck(); - // The command below will trigger fetching a stack trace while - // the process does not seem to be fully functional. Most notably - // the PC points to a 0x9..., which is not in "our" range - //sendGdbServerMessage("T05library:r;", "target halted (library load)"); - //sendGdbServerMessage("S05", "target halted (trap)"); - sendGdbServerMessage("S00", "target halted (trap)"); - //sendGdbServerMessage("O" + QByteArray("Starting...").toHex()); - } - - else if (cmd == "c") { - logMessage(msgGdbPacket(QLatin1String("Continue"))); - sendGdbServerAck(); - QByteArray ba; - appendByte(&ba, 0); // options - appendInt(&ba, 0); // start address - appendInt(&ba, 0); // end address - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - sendTrkMessage(0x18, TrkCallback(), ba); - } - - else if (cmd.startsWith("C")) { - logMessage(msgGdbPacket(QLatin1String("Continue with signal"))); - // C sig[;addr] Continue with signal sig (hex signal number) - //Reply: See section D.3 Stop Reply Packets, for the reply specifications. - sendGdbServerAck(); - bool ok = false; - uint signalNumber = cmd.mid(1).toInt(&ok, 16); - QByteArray ba; - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - sendTrkMessage(0x18, TrkCB(handleSignalContinue), ba, signalNumber); // Continue - } - - else if (cmd.startsWith("D")) { - sendGdbServerAck(); - sendGdbServerMessage("OK", "shutting down"); - qApp->quit(); - } - - else if (cmd == "g") { - logMessage(msgGdbPacket(QLatin1String("Read registers"))); - // Read general registers. - //sendGdbServerMessage("00000000", "read registers"); - sendGdbServerAck(); - sendTrkMessage(0x12, TrkCB(handleAndReportReadRegisters), - trkReadRegisterMessage()); - } - - else if (cmd.startsWith("Hc")) { - logMessage(msgGdbPacket(QLatin1String("Set thread & continue"))); - // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). - // for step and continue operations - //$Hc-1#09 - sendGdbServerAck(); - sendGdbServerMessage("OK", "Set current thread for step & continue"); - } - - else if (cmd.startsWith("Hg")) { - logMessage(msgGdbPacket(QLatin1String("Set thread"))); - // Set thread for subsequent operations (`m', `M', `g', `G', et.al.). - // for 'other operations. 0 - any thread - //$Hg0#df - sendGdbServerAck(); - m_session.currentThread = cmd.mid(2).toInt(0, 16); - sendGdbServerMessage("OK", "Set current thread " - + QByteArray::number(m_session.currentThread)); - } - - else if (cmd == "k") { - logMessage(msgGdbPacket(QLatin1String("kill"))); - // kill - sendGdbServerAck(); - QByteArray ba; - appendByte(&ba, 0); // ? - appendByte(&ba, 0); // Sub-command: Delete Process - appendInt(&ba, m_session.pid); - sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); // Delete Item - sendGdbServerMessageAfterTrkResponse("", "process killed"); - } - - else if (cmd.startsWith("m")) { - logMessage(msgGdbPacket(QLatin1String("Read memory"))); - // m addr,length - sendGdbServerAck(); - uint addr = 0, len = 0; - do { - const int pos = cmd.indexOf(','); - if (pos == -1) - break; - bool ok; - addr = cmd.mid(1, pos - 1).toUInt(&ok, 16); - if (!ok) - break; - len = cmd.mid(pos + 1).toUInt(&ok, 16); - if (!ok) - break; - } while (false); - if (len) { - readMemory(addr, len); - } else { - sendGdbServerMessage("E20", "Error " + cmd); - } - } - else if (cmd.startsWith("p")) { - logMessage(msgGdbPacket(QLatin1String("read register"))); - // 0xf == current instruction pointer? - //sendGdbServerMessage("0000", "current IP"); - sendGdbServerAck(); - #if 0 - A1 = 0, first integer-like argument - A4 = 3, last integer-like argument - AP = 11, - IP = 12, - SP = 13, Contains address of top of stack - LR = 14, address to return to from a function call - PC = 15, Contains program counter - F0 = 16, first floating point register - F3 = 19, last floating point argument register - F7 = 23, last floating point register - FPS = 24, floating point status register - PS = 25, Contains processor status - WR0, WMMX data registers. - WR15 = WR0 + 15, - WC0, WMMX control registers. - WCSSF = WC0 + 2, - WCASF = WC0 + 3, - WC7 = WC0 + 7, - WCGR0, WMMX general purpose registers. - WCGR3 = WCGR0 + 3, - WCGR7 = WCGR0 + 7, - NUM_REGS, - - // Other useful registers. - FP = 11, Frame register in ARM code, if used. - THUMB_FP = 7, Frame register in Thumb code, if used. - NUM_ARG_REGS = 4, - LAST_ARG = A4, - NUM_FP_ARG_REGS = 4, - LAST_FP_ARG = F3 - #endif - bool ok = false; - const uint registerNumber = cmd.mid(1).toInt(&ok, 16); - QByteArray logMsg = "Read Register"; - if (registerNumber == RegisterPSGdb) { - QByteArray ba; - appendInt(&ba, m_snapshot.registers[RegisterPSTrk], m_registerEndianness); - logMsg += dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk]); - sendGdbServerMessage(ba.toHex(), logMsg); - } else if (registerNumber < RegisterCount) { - QByteArray ba; - appendInt(&ba, m_snapshot.registers[registerNumber], m_registerEndianness); - 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 if (cmd == "qAttached") { - //$qAttached#8f - // 1: attached to an existing process - // 0: created a new process - sendGdbServerAck(); - sendGdbServerMessage("0", "new process created"); - //sendGdbServerMessage("1", "attached to existing process"); - //sendGdbServerMessage("E01", "new process created"); - } - - else if (cmd.startsWith("qC")) { - logMessage(msgGdbPacket(QLatin1String("query thread id"))); - // Return the current thread ID - //$qC#b4 - sendGdbServerAck(); - sendGdbServerMessageAfterTrkResponse("QC@TID@"); - } - - else if (cmd.startsWith("qSupported")) { - //$qSupported#37 - //$qSupported:multiprocess+#c6 - //logMessage("Handling 'qSupported'"); - sendGdbServerAck(); - if (0) - sendGdbServerMessage(QByteArray(), "nothing supported"); - else - sendGdbServerMessage( - "PacketSize=7cf;" - "QPassSignals+;" - "qXfer:libraries:read+;" - //"qXfer:auxv:read+;" - "qXfer:features:read+"); - } - - else if (cmd == "qPacketInfo") { - // happens with gdb 6.4.50.20060226-cvs / CodeSourcery - // deprecated by qSupported? - sendGdbServerAck(); - sendGdbServerMessage("", "FIXME: nothing?"); - } - - else if (cmd == "qOffsets") { - sendGdbServerAck(); - sendGdbServerMessageAfterTrkResponse("TextSeg=@CODESEG@;DataSeg=@DATASEG@"); - } - - else if (cmd == "qSymbol::") { - if (m_verbose) - logMessage(msgGdbPacket(QLatin1String("notify can handle symbol lookup"))); - // Notify the target that GDB is prepared to serve symbol lookup requests. - sendGdbServerAck(); - if (1) - sendGdbServerMessage("OK", "no further symbols needed"); - else - sendGdbServerMessage("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(), "ask for more"); - } - - else if (cmd.startsWith("qXfer:features:read:target.xml:")) { - // $qXfer:features:read:target.xml:0,7ca#46...Ack - sendGdbServerAck(); - sendGdbServerMessage("lsymbianelf"); - } - - else if (cmd == "QStartNoAckMode") { - //$qSupported#37 - //logMessage("Handling 'QStartNoAckMode'"); - sendGdbServerAck(); - sendGdbServerMessage("OK", "ack no-ack mode"); - m_gdbAckMode = false; - } - - else if (cmd.startsWith("QPassSignals")) { - // list of signals to pass directly to inferior - // $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c;#8f - // happens only if "QPassSignals+;" is qSupported - sendGdbServerAck(); - // FIXME: use the parameters - sendGdbServerMessage("OK", "passing signals accepted"); - } - - else if (cmd == "s" || cmd.startsWith("vCont;s")) { - logMessage(msgGdbPacket(QLatin1String("Step range"))); - logMessage(" from " + hexxNumber(m_snapshot.registers[RegisterPC])); - sendGdbServerAck(); - m_running = true; - QByteArray ba; - appendByte(&ba, 0x01); // options - appendInt(&ba, m_snapshot.registers[RegisterPC]); // start address - //appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address - appendInt(&ba, -1); // end address - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - sendTrkMessage(0x19, TrkCB(handleStepRange), ba, "Step range"); - // FIXME: should be triggered by "real" stop" - //sendGdbServerMessageAfterTrkResponse("S05", "target halted"); - } - - else if (cmd == "vCont?") { - // actions supported by the vCont packet - sendGdbServerAck(); - //sendGdbServerMessage("OK"); // we don't support vCont. - sendGdbServerMessage("vCont;c;C;s;S"); - } - - else if (cmd == "vCont;c") { - // vCont[;action[:thread-id]]...' - sendGdbServerAck(); - m_running = true; - sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); - } - - else if (cmd.startsWith("vKill")) { - // kill - sendGdbServerAck(); - QByteArray ba; - appendByte(&ba, 0); // Sub-command: Delete Process - appendInt(&ba, m_session.pid); - sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); // Delete Item - sendGdbServerMessageAfterTrkResponse("", "process killed"); - } - - else if (0 && cmd.startsWith("Z0,")) { - // Tell gdb we don't support software breakpoints - sendGdbServerMessage(""); - } - - else if (cmd.startsWith("Z0,") || cmd.startsWith("Z1,")) { - sendGdbServerAck(); - // Insert breakpoint - logMessage(msgGdbPacket(QLatin1String("Insert breakpoint"))); - // $Z0,786a4ccc,4#99 - const int pos = cmd.lastIndexOf(','); - bool ok = false; - const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); - const uint len = cmd.mid(pos + 1).toInt(&ok, 16); - //qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len; - logMessage(QString::fromLatin1("Inserting breakpoint at 0x%1, %2") - .arg(addr, 0, 16).arg(len)); - - //---IDE------------------------------------------------------ - // Command: 0x1B Set Break - //BreakType: 0x82 - // Options: 0x00 - // Address: 0x78674340 (2020033344) i.e + 0x00000340 - // Length: 0x00000001 (1) - // Count: 0x00000000 (0) - //ProcessID: 0x000001b5 (437) - // ThreadID: 0xffffffff (-1) - // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00 - // 00 00 01 B5 FF FF FF FF] - const QByteArray ba = trkBreakpointMessage(addr, len, m_session.pid); - sendTrkMessage(0x1B, TrkCB(handleAndReportSetBreakpoint), ba, addr); - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 09 00 00 00 00 0A] - } - - else if (cmd.startsWith("z0,") || cmd.startsWith("z1,")) { - sendGdbServerAck(); - // Remove breakpoint - logMessage(msgGdbPacket(QLatin1String("Remove breakpoint"))); - // $z0,786a4ccc,4#99 - const int pos = cmd.lastIndexOf(','); - bool ok = false; - const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16); - const uint len = cmd.mid(pos + 1).toInt(&ok, 16); - const uint bp = m_session.addressToBP[addr]; - if (bp == 0) { - logMessage(QString::fromLatin1("NO RECORDED BP AT 0x%1, %2") - .arg(addr, 0, 16).arg(len)); - } else { - //---IDE------------------------------------------------------ - // Command: 0x1C Clear Break - // [1C 25 00 00 00 0A 78 6A 43 40] - m_session.addressToBP.remove(addr); - QByteArray ba; - appendByte(&ba, 0x00); - appendShort(&ba, bp); - appendInt(&ba, addr); - sendTrkMessage(0x1C, TrkCB(handleClearBreakpoint), ba, addr); - } - } - - else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:")) { - QByteArray data = cmd.mid(1 + cmd.indexOf(':')); - // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux) - bool handled = false; - if (data.startsWith("auxv:read::")) { - const int offsetPos = data.lastIndexOf(':') + 1; - const int commaPos = data.lastIndexOf(','); - if (commaPos != -1) { - bool ok1 = false, ok2 = false; - const int offset = data.mid(offsetPos, commaPos - offsetPos) - .toInt(&ok1, 16); - const int length = data.mid(commaPos + 1).toInt(&ok2, 16); - if (ok1 && ok2) { - const QString msg = QString::fromLatin1("Read of OS auxilary " - "vector (%1, %2) not implemented.").arg(offset).arg(length); - logMessage(msgGdbPacket(msg), true); - sendGdbServerMessage("E20", msg.toLatin1()); - handled = true; - } - } - } // auxv read - if (!handled) { - const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ") - + QString::fromAscii(cmd); - logMessage(msgGdbPacket(msg), true); - sendGdbServerMessage("E20", msg.toLatin1()); - } - } // qPart/qXfer - else { - logMessage(msgGdbPacket(QLatin1String("FIXME unknown: ") - + QString::fromAscii(cmd))); - } -} - -void Adapter::executeCommand(const QString &msg) -{ - if (msg == "EI") { - sendGdbMessage("-exec-interrupt"); - } else if (msg == "C") { - sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); - } else if (msg == "R") { - sendTrkMessage(0x18, TrkCB(handleReadRegisters), - trkReadRegisterMessage(), "READ REGS"); - } else if (msg == "I") { - interruptInferior(); - } else { - logMessage("EXECUTING GDB COMMAND " + msg); - sendGdbMessage(msg); - } -} - -void Adapter::sendTrkMessage(byte code, TrkCallback callback, - const QByteArray &data, const QVariant &cookie) -{ - m_trkDevice.sendTrkMessage(code, callback, data, cookie); -} - -void Adapter::sendTrkAck(byte token) -{ - logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token))); - m_trkDevice.sendTrkAck(token); -} - -void Adapter::handleTrkError(const QString &msg) -{ - logMessage("## TRK ERROR: " + msg); -} - -void Adapter::handleTrkResult(const TrkResult &result) -{ - if (result.isDebugOutput) { - sendTrkAck(result.token); - logMessage(QLatin1String("APPLICATION OUTPUT: ") + - QString::fromAscii(result.data)); - sendGdbServerMessage("O" + result.data.toHex()); - return; - } - logMessage("READ TRK " + result.toString()); - QByteArray prefix = "READ BUF: "; - QByteArray str = result.toString().toUtf8(); - switch (result.code) { - case 0x80: // ACK - break; - case 0xff: { // NAK. This mostly means transmission error, not command failed. - QString logMsg; - QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token - << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str; - logMessage(logMsg, true); - break; - } - case 0x90: { // Notified Stopped - // 90 01 78 6a 40 40 00 00 07 23 00 00 07 24 00 00 - const char *data = result.data.data(); - const uint addr = extractInt(data); - const uint pid = extractInt(data + 4); - const uint tid = extractInt(data + 8); - logMessage(prefix + QString::fromLatin1("NOTE: PID %1/TID %2 " - "STOPPED at 0x%3").arg(pid).arg(tid).arg(addr, 0, 16)); - sendTrkAck(result.token); - if (addr) { - // Todo: Do not send off GdbMessages if a synced gdb - // query is pending, queue instead - if (m_running) { - m_running = false; - sendGdbServerMessage("S05", "Target stopped"); - } - } else { - logMessage(QLatin1String("Ignoring stop at 0")); - } - break; - } - case 0x91: { // Notify Exception (obsolete) - logMessage(prefix + "NOTE: EXCEPTION " + str); - sendTrkAck(result.token); - break; - } - case 0x92: { // - logMessage(prefix + "NOTE: INTERNAL ERROR: " + str); - sendTrkAck(result.token); - break; - } - - // target->host OS notification - case 0xa0: { // Notify Created - const char *data = result.data.data(); - const byte error = result.data.at(0); - // type: 1 byte; for dll item, this value is 2. - const 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); - 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 << '\''; - logMessage(logMsg); - // This lets gdb trigger a register update etc - //sendGdbServerMessage("T05library:r;"); - sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); - break; - } - case 0xa1: { // NotifyDeleted - const ushort itemType = extractByte(result.data.data() + 1); - const ushort len = result.data.size() > 12 - ? extractShort(result.data.data() + 10) : ushort(0); - const QString name = len - ? QString::fromAscii(result.data.mid(12, len)) : QString(); - if (!name.isEmpty()) - m_session.modules.removeAll(name); - logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3") - .arg(QString::fromAscii(prefix)) - .arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")) - .arg(name)); - sendTrkAck(result.token); - if (itemType == 0) { - sendGdbServerMessage("W00", "Process exited"); - //sendTrkMessage(0x02, TrkCB(handleDisconnect)); - } - break; - } - case 0xa2: { // NotifyProcessorStarted - logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str); - sendTrkAck(result.token); - break; - } - case 0xa6: { // NotifyProcessorStandby - logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str); - sendTrkAck(result.token); - break; - } - case 0xa7: { // NotifyProcessorReset - logMessage(prefix + "NOTE: PROCESSOR RESET: " + str); - sendTrkAck(result.token); - break; - } - default: { - logMessage(prefix + "INVALID: " + str); - break; - } - } -} - -void Adapter::handleCpuType(const TrkResult &result) -{ - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 03 00 04 00 00 04 00 00 00] - m_session.cpuMajor = result.data[1]; - m_session.cpuMinor = result.data[2]; - m_session.bigEndian = result.data[3]; - m_session.defaultTypeSize = result.data[4]; - m_session.fpTypeSize = result.data[5]; - m_session.extended1TypeSize = result.data[6]; - //m_session.extended2TypeSize = result.data[6]; - QString logMsg; - QTextStream(&logMsg) << "HANDLE CPU TYPE: CPU=" << m_session.cpuMajor << '.' - << m_session.cpuMinor << " bigEndian=" << m_session.bigEndian - << " defaultTypeSize=" << m_session.defaultTypeSize - << " fpTypeSize=" << m_session.fpTypeSize - << " extended1TypeSize=" << m_session.extended1TypeSize; - logMessage(logMsg); -} - -void Adapter::setTrkBreakpoint(const Breakpoint &bp) -{ - //---IDE------------------------------------------------------ - // Command: 0x1B Set Break - //BreakType: 0x82 - // Options: 0x00 - // Address: 0x78674340 (2020033344) i.e + 0x00000340 - // Length: 0x00000001 (1) - // Count: 0x00000000 (0) - //ProcessID: 0x000001b5 (437) - // ThreadID: 0xffffffff (-1) - // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00 - // 00 00 01 B5 FF FF FF FF] - const QByteArray ba = trkBreakpointMessage(m_session.codeseg + bp.offset, - 1, m_session.pid); - sendTrkMessage(0x1B, TrkCB(handleSetTrkBreakpoint), ba); - - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 09 00 00 00 00 0A] -} - -void Adapter::handleSetTrkBreakpoint(const TrkResult &result) -{ - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 09 00 00 00 00 0A] - const uint bpnr = extractInt(result.data.data()); - logMessage("SET BREAKPOINT " + hexxNumber(bpnr) - + stringFromArray(result.data.data())); -} - -void Adapter::handleCreateProcess(const TrkResult &result) -{ - // 40 00 00] - //logMessage(" RESULT: " + result.toString()); - // [80 08 00 00 00 01 B5 00 00 01 B6 78 67 40 00 00 40 00 00] - const char *data = result.data.data(); - m_session.pid = extractInt(data + 1); - m_session.tid = extractInt(data + 5); - m_session.codeseg = extractInt(data + 9); - m_session.dataseg = extractInt(data + 13); - - logMessage("PID: " + hexxNumber(m_session.pid)); - logMessage("TID: " + hexxNumber(m_session.tid)); - logMessage("COD: " + hexxNumber(m_session.codeseg)); - logMessage("DAT: " + hexxNumber(m_session.dataseg)); - - QByteArray ba; - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); - - startGdb(); - - -#if 0 - //---IDE------------------------------------------------------ - // Command: 0x42 Read Info - // [42 0C 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F - // 72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00] - sendTrkMessage(0x42, TrkCB(handleReadInfo), - "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " - "72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00"); - //sendTrkMessage(0x42, TrkCB(handleReadInfo), - // "00 01 00 00 00 00"); - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x20 Unspecified general OS-related error - // [80 0C 20] - - - //---IDE------------------------------------------------------ - // Command: 0x42 Read Info - // [42 0D 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F - // 72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00] - sendTrkMessage(0x42, TrkCB(handleReadInfo), - "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " - "72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00"); - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x20 Unspecified general OS-related error - // [80 0D 20] -#endif - - //sendTrkMessage(0x18, TrkCB(handleStop), - // "01 " + formatInt(m_session.pid) + formatInt(m_session.tid)); -} - -void Adapter::handleReadRegisters(const TrkResult &result) -{ - logMessage(" RESULT: " + result.toString()); - // [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...] - if (result.errorCode()) { - logMessage("ERROR: " + result.errorString()); - return; - } - const char *data = result.data.data() + 1; // Skip ok byte - for (int i = 0; i < RegisterCount; ++i) - m_snapshot.registers[i] = extractInt(data + 4 * i); -} - -void Adapter::handleAndReportReadRegisters(const TrkResult &result) -{ - handleReadRegisters(result); - QByteArray ba; - for (int i = 0; i < 16; ++i) { - const uint reg = m_registerEndianness == LittleEndian - ? swapEndian(m_snapshot.registers[i]) : m_snapshot.registers[i]; - ba += hexNumber(reg, 8); - } - QByteArray logMsg = "REGISTER CONTENTS: "; - if (m_verbose > 1) { - for (int i = 0; i < RegisterCount; ++i) { - logMsg += dumpRegister(i, m_snapshot.registers[i]); - logMsg += ' '; - } - } - sendGdbServerMessage(ba, logMsg); -} - -static inline QString msgMemoryReadError(int code, uint addr, uint len = 0) -{ - const QString lenS = len ? QString::number(len) : QLatin1String(""); - return QString::fromLatin1("Memory read error %1 at: 0x%2 %3") - .arg(code).arg(addr, 0 ,16).arg(lenS); -} - -void Adapter::handleReadMemoryBuffered(const TrkResult &result) -{ - if (extractShort(result.data.data() + 1) + 3 != result.data.size()) - logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n"); - const uint blockaddr = result.cookie.toUInt(); - if (const int errorCode = result.errorCode()) { - logMessage(msgMemoryReadError(errorCode, blockaddr)); - return; - } - const QByteArray ba = result.data.mid(3); - m_snapshot.memory.insert(blockaddr, ba); -} - -// Format log message for memory access with some smartness about registers -QByteArray Adapter::memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const -{ - QByteArray logMsg = "memory contents"; - if (m_verbose > 1) { - logMsg += " addr: " + hexxNumber(addr); - // indicate dereferencing of registers - if (len == 4) { - if (addr == m_snapshot.registers[RegisterPC]) { - logMsg += "[PC]"; - } else if (addr == m_snapshot.registers[RegisterPSTrk]) { - logMsg += "[PSTrk]"; - } else if (addr == m_snapshot.registers[RegisterSP]) { - logMsg += "[SP]"; - } else if (addr == m_snapshot.registers[RegisterLR]) { - logMsg += "[LR]"; - } else if (addr > m_snapshot.registers[RegisterSP] && - (addr - m_snapshot.registers[RegisterSP]) < 10240) { - logMsg += "[SP+"; // Stack area ...stack seems to be top-down - logMsg += QByteArray::number(addr - m_snapshot.registers[RegisterSP]); - logMsg += ']'; - } - } - logMsg += " length "; - logMsg += QByteArray::number(len); - logMsg += " :"; - logMsg += stringFromArray(ba, 16); - } - return logMsg; -} - -void Adapter::reportReadMemoryBuffered(const TrkResult &result) -{ - const qulonglong cookie = result.cookie.toULongLong(); - const uint addr = cookie >> 32; - const uint len = uint(cookie); - - // Gdb accepts less memory according to documentation. - // Send E on complete failure. - QByteArray ba; - uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize; - for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) { - const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr); - if (it == m_snapshot.memory.constEnd()) - break; - ba.append(it.value()); - } - const int previousChunkOverlap = addr % MemoryChunkSize; - if (previousChunkOverlap != 0 && ba.size() > previousChunkOverlap) - ba.remove(0, previousChunkOverlap); - if (ba.size() > int(len)) - ba.truncate(len); - - if (ba.isEmpty()) { - ba = "E20"; - sendGdbServerMessage(ba, msgMemoryReadError(32, addr, len).toLatin1()); - } else { - sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba)); - } -} - -void Adapter::handleReadMemoryUnbuffered(const TrkResult &result) -{ - //logMessage("UNBUFFERED MEMORY READ: " + stringFromArray(result.data)); - const uint blockaddr = result.cookie.toUInt(); - if (extractShort(result.data.data() + 1) + 3 != result.data.size()) - logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n"); - if (const int errorCode = result.errorCode()) { - const QByteArray ba = "E20"; - sendGdbServerMessage(ba, msgMemoryReadError(32, blockaddr).toLatin1()); - } else { - const QByteArray ba = result.data.mid(3); - sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(blockaddr, ba.size(), ba)); - } -} - -void Adapter::handleStepRange(const TrkResult &result) -{ - // [80 0f 00] - if (result.errorCode()) { - logMessage("ERROR: " + result.errorString()); - return; - } - logMessage("STEPPING FINISHED "); - //sendGdbServerMessage("S05", "Stepping finished"); -} - -void Adapter::handleAndReportSetBreakpoint(const TrkResult &result) -{ - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 09 00 00 00 00 0A] - uint bpnr = extractByte(result.data.data()); - uint addr = result.cookie.toUInt(); - m_session.addressToBP[addr] = bpnr; - logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + " " - + stringFromArray(result.data.data())); - sendGdbServerMessage("OK"); - //sendGdbServerMessage("OK"); -} - -void Adapter::handleClearBreakpoint(const TrkResult &result) -{ - logMessage("CLEAR BREAKPOINT "); - if (result.errorCode()) { - logMessage("ERROR: " + result.errorString()); - //return; - } - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 09 00 00 00 00 0A] - // FIXME: - sendGdbServerMessage("OK"); -} - -void Adapter::handleSignalContinue(const TrkResult &result) -{ - int signalNumber = result.cookie.toInt(); - logMessage(" HANDLE SIGNAL CONTINUE: " + stringFromArray(result.data)); - logMessage("NUMBER" + QString::number(signalNumber)); - sendGdbServerMessage("O" + QByteArray("Console output").toHex()); - sendGdbServerMessage("W81"); // "Process exited with result 1 -} - -void Adapter::handleSupportMask(const TrkResult &result) -{ - const char *data = result.data.data(); - QByteArray str; - for (int i = 0; i < 32; ++i) { - //str.append(" [" + formatByte(data[i]) + "]: "); - for (int j = 0; j < 8; ++j) - if (data[i] & (1 << j)) - str.append(QByteArray::number(i * 8 + j, 16)); - } - logMessage("SUPPORTED: " + str); - } - -void Adapter::handleTrkVersions(const TrkResult &result) -{ - QString logMsg; - QTextStream str(&logMsg); - str << "Versions: "; - if (result.data.size() >= 5) { - str << "Trk version " << int(result.data.at(1)) << '.' - << int(result.data.at(2)) - << ", Protocol version " << int(result.data.at(3)) - << '.' << int(result.data.at(4)); - } - logMessage(logMsg); -} - -void Adapter::handleDisconnect(const TrkResult & /*result*/) -{ - logMessage(QLatin1String("Trk disconnected"), true); -} - -void Adapter::readMemory(uint addr, uint len) -{ - Q_ASSERT(len < (2 << 16)); - - // We try to get medium-sized chunks of data from the device - if (m_verbose > 2) - logMessage(QString::fromLatin1("readMemory %1 bytes from 0x%2 blocksize=%3") - .arg(len).arg(addr, 0, 16).arg(MemoryChunkSize)); - - if (m_bufferedMemoryRead) { - uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize; - for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) { - if (!m_snapshot.memory.contains(blockaddr)) { - if (m_verbose) - logMessage(QString::fromLatin1("Requesting buffered " - "memory %1 bytes from 0x%2") - .arg(MemoryChunkSize).arg(blockaddr, 0, 16)); - sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered), - trkReadMemoryMessage(blockaddr, MemoryChunkSize), - QVariant(blockaddr)); - } - } - const qulonglong cookie = (qulonglong(addr) << 32) + len; - sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportReadMemoryBuffered), - QByteArray(), cookie); - } else { - if (m_verbose) - logMessage(QString::fromLatin1("Requesting unbuffered memory %1 " - "bytes from 0x%2").arg(len).arg(addr, 0, 16)); - sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered), - trkReadMemoryMessage(addr, len), QVariant(addr)); - } -} - -void Adapter::interruptInferior() -{ - QByteArray ba; - // stop the thread (2) or the process (1) or the whole system (0) - // We choose 2, as 1 does not seem to work. - appendByte(&ba, 2); - appendInt(&ba, m_session.pid); - appendInt(&ba, m_session.tid); // threadID: 4 bytes Variable number of bytes. - sendTrkMessage(0x1a, TrkCallback(), ba, "Interrupting..."); -} - -void Adapter::connectProcess(QProcess *proc) -{ - connect(proc, SIGNAL(error(QProcess::ProcessError)), - this, SLOT(handleProcError(QProcess::ProcessError))); - connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), - this, SLOT(handleProcFinished(int, QProcess::ExitStatus))); - connect(proc, SIGNAL(started()), - this, SLOT(handleProcStarted())); - connect(proc, SIGNAL(stateChanged(QProcess::ProcessState)), - this, SLOT(handleProcStateChanged(QProcess::ProcessState))); -} - -void Adapter::sendOutput(QObject *sender, const QString &data) -{ - if (sender) - emit output(sender->objectName() + " : ", data); - else - emit output(QString(), data); -} - -void Adapter::handleProcError(QProcess::ProcessError error) -{ - sendOutput(sender(), QString("Process Error %1").arg(error)); -} - -void Adapter::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus) -{ - sendOutput(sender(), - QString("ProcessFinished %1 %2").arg(exitCode).arg(exitStatus)); -} - -void Adapter::handleProcStarted() -{ - sendOutput(sender(), QString("Process Started")); -} - -void Adapter::handleProcStateChanged(QProcess::ProcessState newState) -{ - sendOutput(sender(), QString("Process State %1").arg(newState)); -} - -void Adapter::run() -{ - sendOutput("### Starting Adapter"); - m_rfcommProc.start("rfcomm listen " + m_rfcommDevice + " 1"); - m_rfcommProc.waitForStarted(); - - connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)), - this, SLOT(handleTrkResult(trk::TrkResult))); - connect(&m_trkDevice, SIGNAL(error(QString)), - this, SLOT(handleTrkError(QString))); - - startInferior(); -} - -void Adapter::startGdb() -{ - if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) { - logMessage(QString("Unable to start the gdb server at %1: %2.") - .arg(m_gdbServerName).arg(m_gdbServer.errorString()), true); - QCoreApplication::exit(5); - return; - } - - logMessage(QString("Gdb server running on %1.\nRegister endianness: %3.") - .arg(m_gdbServerName).arg(m_registerEndianness), true); - - connect(&m_gdbServer, SIGNAL(newConnection()), - this, SLOT(handleGdbConnection())); - - logMessage("STARTING GDB"); - QStringList gdbArgs; - gdbArgs.append("--nx"); // Do not read .gdbinit file - gdbArgs.append("-i"); - gdbArgs.append("mi"); - m_gdbProc.start(QDir::currentPath() + "/cs-gdb", gdbArgs); - m_gdbProc.waitForStarted(); - - sendGdbMessage("set confirm off"); // confirm potentially dangerous operations? - sendGdbMessage("set endian little"); - sendGdbMessage("set remotebreak on"); - sendGdbMessage("set breakpoint pending on"); - sendGdbMessage("set trust-readonly-sections on"); - //sendGdbMessage("mem 0 ~0ll rw 8 cache"); - - // FIXME: "remote noack" does not seem to be supported on cs-gdb? - //sendGdbMessage("set remote noack-packet"); - - // FIXME: creates a lot of noise a la '&"putpkt: Junk: Ack " &' - // even thouhg the communication seems sane - //sendGdbMessage("set debug remote 1"); // creates l - - //sendGdbMessage("target remote " + m_gdbServerName); -// sendGdbMessage("target extended-remote " + m_gdbServerName); - //sendGdbMessage("target extended-async " + m_gdbServerName); - //sendGdbMessage("set remotecache ...") // Set cache use for remote targets - //sendGdbMessage("file filebrowseapp.sym"); -// sendGdbMessage("add-symbol-file filebrowseapp.sym " + m_baseAddress); -// sendGdbMessage("symbol-file filebrowseapp.sym"); -// sendGdbMessage("print E32Main"); -// sendGdbMessage("break E32Main"); - //sendGdbMessage("continue"); - //sendGdbMessage("info files"); - //sendGdbMessage("file filebrowseapp.sym -readnow"); - - sendGdbMessage("add-symbol-file filebrowseapp.sym " - + hexxNumber(m_session.codeseg)); - sendGdbMessage("symbol-file filebrowseapp.sym"); - - // -symbol-info-address not implemented in cs-gdb 6.4-6.8 (at least) - sendGdbMessage("info address E32Main", - GdbCB(handleInfoMainAddress)); - sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL", - GdbCB(handleInfoMainAddress)); - -#if 1 - // FIXME: Gdb based version. That's the goal - //sendGdbMessage("break E32Main"); - //sendGdbMessage("continue"); - //sendTrkMessage(0x18, TrkCB(handleContinueAfterCreateProcess), - // trkContinueMessage(), "CONTINUE"); -#else - // Directly talk to TRK. Works for now... - sendGdbMessage("break E32Main"); - sendGdbMessage("break filebrowseappui.cpp:39"); - // sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); -#endif -} - -void Adapter::sendGdbMessage(const QString &msg, GdbCallback callback, - const QVariant &cookie) -{ - static int token = 0; - ++token; - GdbCommand data; - data.command = msg; - data.callback = callback; - data.cookie = cookie; - m_gdbCookieForToken[token] = data; - logMessage(QString("<- GDB: %1 %2").arg(token).arg(msg)); - m_gdbProc.write(QString("%1%2\n").arg(token).arg(msg).toLatin1()); -} - -void Adapter::handleGdbReadyReadStandardError() -{ - QByteArray ba = qobject_cast(sender())->readAllStandardError(); - sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba))); -} - -void Adapter::handleGdbReadyReadStandardOutput() -{ - QByteArray ba = qobject_cast(sender())->readAllStandardOutput(); - QString str = QString::fromLatin1(ba); - // FIXME: fragile. merge with gdbengine logic -#if 0 - QRegExp re(QString(".*([0-9]+)[^]done.*")); - int pos = re.indexIn(str); - if (pos == -1) { - logMessage(QString("\n-> GDB: %1 %**% %2 %**%\n").arg(str).arg(pos)); - return; - } - int token = re.cap(1).toInt(); - logMessage(QString("\n-> GDB: %1 %2##\n").arg(token).arg(QString::fromLatin1(ba))); - if (!token) - return; - GdbCommand cmd = m_gdbCookieForToken.take(token); - logMessage("FOUND CALLBACK FOR " + cmd.command); - GdbResult result; - result.data = ba; - if (!cmd.callback.isNull()) - cmd.callback(result); -#else - bool ok; - QRegExp re(QString("Symbol .._Z7E32Mainv.. is a function at address 0x(.*)\\.")); - if (re.indexIn(str) != -1) { - logMessage(QString("-> GDB MAIN BREAKPOINT: %1").arg(re.cap(1))); - uint addr = re.cap(1).toInt(&ok, 16); - sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); - return; - } - QRegExp re1(QString("Symbol .._ZN16CFileBrowseAppUi14HandleCommandLEi.. is a function at address 0x(.*)\\.")); - if (re1.indexIn(str) != -1) { - logMessage(QString("-> GDB USER BREAKPOINT: %1").arg(re1.cap(1))); - uint addr = re1.cap(1).toInt(&ok, 16); - sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); - - sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); - sendGdbMessage("target remote " + m_gdbServerName); - return; - } - logMessage(QString("-> GDB: %1").arg(str)); -#endif -} - -void Adapter::handleInfoMainAddress(const GdbResult &result) -{ - Q_UNUSED(result); -} - -void Adapter::handleSetTrkMainBreakpoint(const TrkResult &result) -{ - Q_UNUSED(result); -/* - //---TRK------------------------------------------------------ - // [80 09 00 00 00 00 0A] - const uint bpnr = extractInt(result.data.data()); - logMessage("SET MAIN BREAKPOINT " + hexxNumber(bpnr) - + stringFromArray(result.data.data())); -*/ -} - -void Adapter::handleInfoAddress(const GdbResult &result) -{ - Q_UNUSED(result); - // FIXME -} - -void Adapter::handleRfcommReadyReadStandardError() -{ - QByteArray ba = qobject_cast(sender())->readAllStandardError(); - sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba))); -} - -void Adapter::handleRfcommReadyReadStandardOutput() -{ - QByteArray ba = qobject_cast(sender())->readAllStandardOutput(); - sendOutput(sender(), QString("stdout: %1").arg(QString::fromLatin1(ba))); -} /////////////////////////////////////////////////////////////////////// // @@ -1787,12 +165,14 @@ public slots: // /////////////////////////////////////////////////////////////////////// +using namespace Debugger::Internal; + class RunnerGui : public QMainWindow { Q_OBJECT public: - RunnerGui(Adapter *adapter); + RunnerGui(SymbianAdapter *adapter); private slots: void executeStepICommand() { executeCommand("-exec-step-instruction"); } @@ -1806,7 +186,7 @@ private: void executeCommand(const QString &cmd) { m_adapter->executeCommand(cmd); } void connectAction(QAction *&, QString name, const char *slot); - Adapter *m_adapter; + SymbianAdapter *m_adapter; TextEdit m_textEdit; QToolBar m_toolBar; QAction *m_stepIAction; @@ -1817,7 +197,7 @@ private: QAction *m_continueAction; }; -RunnerGui::RunnerGui(Adapter *adapter) +RunnerGui::RunnerGui(SymbianAdapter *adapter) : m_adapter(adapter) { resize(1200, 1000); @@ -1855,7 +235,7 @@ void RunnerGui::connectAction(QAction *&action, QString name, const char *slot) int main(int argc, char *argv[]) { QApplication app(argc, argv); - Adapter adapter; + SymbianAdapter adapter; RunnerGui gui(&adapter); gui.show(); QTimer::singleShot(0, &adapter, SLOT(run())); diff --git a/tests/manual/trk/runner.pro b/tests/manual/trk/runner.pro index 4ced7ccd71a..21461da2d94 100644 --- a/tests/manual/trk/runner.pro +++ b/tests/manual/trk/runner.pro @@ -1,15 +1,21 @@ TEMPLATE = app +DEBUGGERHOME = ../../../src/plugins/debugger/symbian +INCLUDEPATH *= $$DEBUGGERHOME + QT += network win32:CONFIG+=console HEADERS += \ - trkutils.h \ - trkdevicex.h \ + $$DEBUGGERHOME/../gdb/gdbprocessbase.h \ + $$DEBUGGERHOME/trkutils.h \ + $$DEBUGGERHOME/trkclient.h \ + $$DEBUGGERHOME/symbianadapter.h \ SOURCES += \ - runner.cpp \ - trkutils.cpp \ - trkdevicex.cpp \ + $$DEBUGGERHOME/trkutils.cpp \ + $$DEBUGGERHOME/trkclient.cpp \ + $$DEBUGGERHOME/symbianadapter.cpp \ + $$PWD/runner.cpp \ diff --git a/tests/manual/trk/trklauncher.pri b/tests/manual/trk/trklauncher.pri index 3593888b861..74b37e42e3c 100644 --- a/tests/manual/trk/trklauncher.pri +++ b/tests/manual/trk/trklauncher.pri @@ -1,9 +1,15 @@ DEFINES += DEBUG_TRK=0 -INCLUDEPATH *= $$PWD -SOURCES += $$PWD/launcher.cpp \ - $$PWD/trkutils.cpp \ - $$PWD/trkdevice.cpp -HEADERS += $$PWD/trkutils.h \ - $$PWD/trkfunctor.h \ +DEBUGGERHOME = ../../../src/plugins/debugger/symbian + +INCLUDEPATH *= $$DEBUGGERHOME + +SOURCES += \ + $$DEBUGGERHOME/trkutils.cpp \ + $$PWD/trkdevice.cpp \ + $$PWD/launcher.cpp \ + +HEADERS += \ + $$DEBUGGERHOME/trkutils.h \ + $$DEBUGGERHOME/trkfunctor.h \ $$PWD/trkdevice.h \ $$PWD/launcher.h diff --git a/tests/manual/trk/trkserver.pro b/tests/manual/trk/trkserver.pro index a333dc2c363..6fbbc85c06c 100644 --- a/tests/manual/trk/trkserver.pro +++ b/tests/manual/trk/trkserver.pro @@ -1,12 +1,17 @@ TEMPLATE = app +DEBUGGERHOME = ../../../src/plugins/debugger/symbian + QT = core network win32:CONFIG+=console +INCLUDEPATH *= $$DEBUGGERHOME + + HEADERS += \ - trkutils.h + $$DEBUGGERHOME/trkutils.h SOURCES += \ - trkutils.cpp \ - trkserver.cpp + $$DEBUGGERHOME/trkutils.cpp \ + $$PWD/trkserver.cpp From 3ceecf661b55c8b270c25f37098cdd8f45a612b1 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 10 Sep 2009 08:25:56 +0200 Subject: [PATCH 21/43] debugger: fix linking new header files gdbprocessbase needs to be listed in HEADERS --- src/plugins/debugger/gdb/gdb.pri | 1 + .../debugger/symbian/symbianadapter.cpp | 30 ------------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/src/plugins/debugger/gdb/gdb.pri b/src/plugins/debugger/gdb/gdb.pri index 5154397aaec..9433d4be8d8 100644 --- a/src/plugins/debugger/gdb/gdb.pri +++ b/src/plugins/debugger/gdb/gdb.pri @@ -1,4 +1,5 @@ HEADERS += \ + $$PWD/gdbprocessbase.h \ $$PWD/gdbmi.h \ $$PWD/gdbengine.h \ $$PWD/gdboptionspage.h \ diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index 8f66b331242..5790cbf6c6a 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -33,36 +33,6 @@ #define GdbCB(s) GdbCallback(this, &SymbianAdapter::s) -/* -fetch-register p info registers -set-register P set -binary-download X load, set -read-aux-vector qXfer:auxv:read info auxv -symbol-lookup qSymbol Detecting multiple threads -attach vAttach attach -verbose-resume vCont Stepping or resuming multiple threads -run vRun run -software-breakpoint Z0 break -hardware-breakpoint Z1 hbreak -write-watchpoint Z2 watch -read-watchpoint Z3 rwatch -access-watchpoint Z4 awatch -target-features qXfer:features:read set architecture -library-info qXfer:libraries:read info sharedlibrary -memory-map qXfer:memory-map:read info mem -read-spu-object qXfer:spu:read info spu -write-spu-object qXfer:spu:write info spu -get-thread-local- -storage-address qGetTLSAddr Displaying __thread variables -supported-packets qSupported Remote communications parameters -pass-signals QPassSignals handle signal -hostio-close-packet vFile:close remote get, remote put -hostio-open-packet vFile:open remote get, remote put -hostio-pread-packet vFile:pread remote get, remote put -hostio-pwrite-packet vFile:pwrite remote get, remote put -hostio-unlink-packet vFile:unlink remote delete -*/ - using namespace trk; enum { KnownRegisters = RegisterPSGdb + 1}; From 1e186c5bf9031c5da709e9a0467b5efae6933519 Mon Sep 17 00:00:00 2001 From: Henrik Hartz Date: Thu, 10 Sep 2009 12:25:55 +0200 Subject: [PATCH 22/43] make sure symbian include is scoped --- src/plugins/debugger/debugger.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index c9be97b7260..abb71c4ad36 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -87,7 +87,7 @@ include(cdb/cdb.pri) include(gdb/gdb.pri) include(script/script.pri) include(tcf/tcf.pri) -include(symbian/symbian.pri) +symbian:include(symbian/symbian.pri) include(shared/shared.pri) OTHER_FILES += Debugger.pluginspec From 46538f6a5e4d8ec9ee0326d3024a667d7f924f5d Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 10 Sep 2009 08:38:18 +0200 Subject: [PATCH 23/43] trk: remove unneeded code --- tests/manual/trk/runner.cpp | 75 ------------------------------------- 1 file changed, 75 deletions(-) diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index 4724df4d179..00a4b9bd15e 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -30,16 +30,6 @@ #include "symbianadapter.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include @@ -49,71 +39,6 @@ #include #include -#include -#include -#include -#include - -/* -fetch-register p info registers -set-register P set -binary-download X load, set -read-aux-vector qXfer:auxv:read info auxv -symbol-lookup qSymbol Detecting multiple threads -attach vAttach attach -verbose-resume vCont Stepping or resuming multiple threads -run vRun run -software-breakpoint Z0 break -hardware-breakpoint Z1 hbreak -write-watchpoint Z2 watch -read-watchpoint Z3 rwatch -access-watchpoint Z4 awatch -target-features qXfer:features:read set architecture -library-info qXfer:libraries:read info sharedlibrary -memory-map qXfer:memory-map:read info mem -read-spu-object qXfer:spu:read info spu -write-spu-object qXfer:spu:write info spu -get-thread-local- -storage-address qGetTLSAddr Displaying __thread variables -supported-packets qSupported Remote communications parameters -pass-signals QPassSignals handle signal -hostio-close-packet vFile:close remote get, remote put -hostio-open-packet vFile:open remote get, remote put -hostio-pread-packet vFile:pread remote get, remote put -hostio-pwrite-packet vFile:pwrite remote get, remote put -hostio-unlink-packet vFile:unlink remote delete -*/ - -using namespace trk; - -enum { KnownRegisters = RegisterPSGdb + 1}; - -static const char *registerNames[KnownRegisters] = -{ - "A1", "A2", "A3", "A4", - 0, 0, 0, 0, - 0, 0, 0, "AP", - "IP", "SP", "LR", "PC", - "PSTrk", 0, 0, 0, - 0, 0, 0, 0, - 0, "PSGdb" -}; - -static QByteArray dumpRegister(int n, uint value) -{ - QByteArray ba; - ba += ' '; - if (n < KnownRegisters && registerNames[n]) { - ba += registerNames[n]; - } else { - ba += '#'; - ba += QByteArray::number(n); - } - ba += "=" + hexxNumber(value); - return ba; -} - - /////////////////////////////////////////////////////////////////////// // // RunnerGui From 058b55adc5d7c0883a42effe5199f4e07693f5bb Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 10 Sep 2009 13:09:42 +0200 Subject: [PATCH 24/43] debugger: work on trk integration --- src/plugins/debugger/cdb/cdbdebugengine.cpp | 10 ++- src/plugins/debugger/cdb/cdbdebugengine.h | 2 +- src/plugins/debugger/debuggermanager.cpp | 41 ++++++--- src/plugins/debugger/debuggermanager.h | 21 +++-- src/plugins/debugger/gdb/gdbengine.cpp | 83 +++++++++++-------- src/plugins/debugger/gdb/gdbengine.h | 7 +- src/plugins/debugger/gdb/gdbprocessbase.h | 3 +- src/plugins/debugger/idebuggerengine.h | 8 +- src/plugins/debugger/script/scriptengine.cpp | 10 ++- src/plugins/debugger/script/scriptengine.h | 2 +- src/plugins/debugger/symbian/symbian.pri | 2 + .../debugger/symbian/symbianadapter.cpp | 58 ++++++------- src/plugins/debugger/symbian/symbianadapter.h | 5 +- .../debugger/symbian/symbianengine.cpp | 13 ++- src/plugins/debugger/tcf/tcfengine.cpp | 4 +- src/plugins/debugger/tcf/tcfengine.h | 2 +- tests/manual/trk/runner.cpp | 8 +- 17 files changed, 171 insertions(+), 108 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 44c739362d4..3c6ac42e0c0 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -563,11 +563,11 @@ void CdbDebugEnginePrivate::clearDisplay() m_debuggerManagerAccess->registerHandler()->removeAll(); } -bool CdbDebugEngine::startDebugger(const QSharedPointer &sp) +void CdbDebugEngine::startDebugger(const QSharedPointer &sp) { if (m_d->m_hDebuggeeProcess) { warning(QLatin1String("Internal error: Attempt to start debugger while another process is being debugged.")); - return false; + emit startFailed(); } m_d->clearDisplay(); @@ -627,7 +627,11 @@ bool CdbDebugEngine::startDebugger(const QSharedPointer } else { warning(errorMessage); } - return rc; + + if (rc) + emit startSuccessful(); + else + emit startFailed(); } bool CdbDebugEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *errorMessage) diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h index 521b7b17201..18b66041652 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.h +++ b/src/plugins/debugger/cdb/cdbdebugengine.h @@ -62,7 +62,7 @@ public: virtual void shutdown(); virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos); - virtual bool startDebugger(const QSharedPointer &startParameters); + virtual void startDebugger(const QSharedPointer &startParameters); virtual void exitDebugger(); virtual void detachDebugger(); virtual void updateWatchData(const WatchData &data); diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index b4a5c84a7ee..9bc178ca946 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -182,9 +182,10 @@ void DebuggerStartParameters::clear() /////////////////////////////////////////////////////////////////////// static IDebuggerEngine *gdbEngine = 0; -static IDebuggerEngine *winEngine = 0; static IDebuggerEngine *scriptEngine = 0; +static IDebuggerEngine *symbianEngine = 0; static IDebuggerEngine *tcfEngine = 0; +static IDebuggerEngine *winEngine = 0; DebuggerManager::DebuggerManager() : m_startParameters(new DebuggerStartParameters), @@ -197,9 +198,10 @@ DebuggerManager::~DebuggerManager() { #define doDelete(ptr) delete ptr; ptr = 0 doDelete(gdbEngine); - doDelete(winEngine); doDelete(scriptEngine); + doDelete(symbianEngine); doDelete(tcfEngine); + doDelete(winEngine); #undef doDelete } @@ -446,6 +448,8 @@ QList DebuggerManager::initializeEngines(unsigned enabledTy QList rc; if (enabledTypeFlags & GdbEngineType) gdbEngine = createGdbEngine(this, &rc); + if (enabledTypeFlags & SymbianEngineType) + symbianEngine = createSymbianEngine(this, &rc); winEngine = createWinEngine(this, (enabledTypeFlags & CdbEngineType), &rc); if (enabledTypeFlags & ScriptEngineType) scriptEngine = createScriptEngine(this, &rc); @@ -695,9 +699,10 @@ void DebuggerManager::updateWatchData(const WatchData &data) m_engine->updateWatchData(data); } -static inline QString msgEngineNotAvailable(const char *engine) +static QString msgEngineNotAvailable(const char *engine) { - return DebuggerManager::tr("The application requires the debugger engine '%1', which is disabled.").arg(QLatin1String(engine)); + return DebuggerManager::tr("The application requires the debugger engine '%1', " + "which is disabled.").arg(QLatin1String(engine)); } static IDebuggerEngine *debuggerEngineForToolChain(ProjectExplorer::ToolChain::ToolChainType tc) @@ -739,7 +744,16 @@ static IDebuggerEngine *determineDebuggerEngine(const QString &executable, return scriptEngine; } - if (IDebuggerEngine *tce = debuggerEngineForToolChain(static_cast(toolChainType))) + if (executable.endsWith(_(".sym"))) { + if (!symbianEngine) { + *errorMessage = msgEngineNotAvailable("Symbian Engine"); + return 0; + } + return symbianEngine; + } + + if (IDebuggerEngine *tce = debuggerEngineForToolChain( + static_cast(toolChainType))) return tce; #ifndef Q_OS_WIN @@ -774,7 +788,8 @@ static IDebuggerEngine *determineDebuggerEngine(int /* pid */, int toolChainType, QString *errorMessage) { - if (IDebuggerEngine *tce = debuggerEngineForToolChain(static_cast(toolChainType))) + if (IDebuggerEngine *tce = debuggerEngineForToolChain( + static_cast(toolChainType))) return tce; #ifdef Q_OS_WIN // Preferably Windows debugger @@ -846,11 +861,15 @@ void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl, setBusyCursor(false); setStatus(DebuggerProcessStartingUp); - if (!m_engine->startDebugger(m_startParameters)) { - setStatus(DebuggerProcessNotReady); - debuggingFinished(); - return; - } + connect(m_engine, SIGNAL(startFailed()), this, SLOT(startFailed())); + m_engine->startDebugger(m_startParameters); +} + +void DebuggerManager::startFailed() +{ + disconnect(m_engine, SIGNAL(startFailed()), this, SLOT(startFailed())); + setStatus(DebuggerProcessNotReady); + debuggingFinished(); } void DebuggerManager::cleanupViews() diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index de2a192abd1..3b9622e7f4c 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -172,12 +172,18 @@ class CdbDebugEngine; struct CdbDebugEnginePrivate; // Flags for initialization -enum DebuggerEngineTypeFlags { - GdbEngineType = 0x1, - ScriptEngineType = 0x2, - CdbEngineType = 0x4, - TcfEngineType = 0x8, - AllEngineTypes = (GdbEngineType|ScriptEngineType|CdbEngineType|TcfEngineType) +enum DebuggerEngineTypeFlags +{ + GdbEngineType = 0x01, + ScriptEngineType = 0x02, + CdbEngineType = 0x04, + TcfEngineType = 0x08, + SymbianEngineType = 0x10, + AllEngineTypes = GdbEngineType + | ScriptEngineType + | CdbEngineType + | TcfEngineType + | SymbianEngineType }; // The construct below is not nice but enforces a bit of order. The @@ -324,6 +330,8 @@ public slots: void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever private slots: + void showDebuggerOutput(const QString &msg) + { showDebuggerOutput(LogDebug, msg); } void showDebuggerOutput(int channel, const QString &msg); void showDebuggerInput(int channel, const QString &msg); void showApplicationOutput(const QString &data); @@ -343,6 +351,7 @@ private slots: void attemptBreakpointSynchronization(); void reloadFullStack(); void stepByInstructionTriggered(); + void startFailed(); private: // diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 055d8adfdf2..7c1909addc3 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -180,6 +180,8 @@ void GdbEngine::initializeConnections() this, SLOT(readGdbStandardError())); connect(m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), q, SLOT(exitDebugger())); + connect(m_gdbProc, SIGNAL(started()), + this, SLOT(startDebugger2())); connect(&m_stubProc, SIGNAL(processError(QString)), this, SLOT(stubError(QString))); @@ -1440,7 +1442,8 @@ void GdbEngine::exitDebugger() if (m_gdbProc->state() == QProcess::Starting) { debugMessage(_("WAITING FOR GDB STARTUP TO SHUTDOWN: %1") .arg(m_gdbProc->state())); - m_gdbProc->waitForStarted(); + // FIXME: handle this! + //m_gdbProc->waitForStarted(); } if (m_gdbProc->state() == QProcess::Running) { debugMessage(_("WAITING FOR RUNNING GDB TO SHUTDOWN: %1") @@ -1481,8 +1484,9 @@ int GdbEngine::currentFrame() const return qq->stackHandler()->currentIndex(); } -bool GdbEngine::startDebugger(const QSharedPointer &sp) +void GdbEngine::startDebugger(const QSharedPointer &sp) { + m_startParameters = *sp; // This should be set by the constructor or in exitDebugger(). QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, initializeVariables()); @@ -1492,7 +1496,8 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) if (m_gdbProc->state() != QProcess::NotRunning) { debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc->state())); m_gdbProc->kill(); - return false; + emit startFailed(); + return; } //gdbArgs.prepend(_("--quiet")); @@ -1503,37 +1508,42 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) // nothing to do } else if (q->startMode() == StartRemote) { // Start the remote server - if (sp->serverStartScript.isEmpty()) { + if (m_startParameters.serverStartScript.isEmpty()) { q->showStatusMessage(_("No server start script given. " "Assuming server runs already.")); } else { - if (!sp->workingDir.isEmpty()) - m_uploadProc.setWorkingDirectory(sp->workingDir); - if (!sp->environment.isEmpty()) - m_uploadProc.setEnvironment(sp->environment); - m_uploadProc.start(_("/bin/sh ") + sp->serverStartScript); + if (!m_startParameters.workingDir.isEmpty()) + m_uploadProc.setWorkingDirectory(m_startParameters.workingDir); + if (!m_startParameters.environment.isEmpty()) + m_uploadProc.setEnvironment(m_startParameters.environment); + m_uploadProc.start(_("/bin/sh ") + m_startParameters.serverStartScript); m_uploadProc.waitForStarted(); } - } else if (sp->useTerminal) { + } else if (m_startParameters.useTerminal) { m_stubProc.stop(); // We leave the console open, so recycle it now. - m_stubProc.setWorkingDirectory(sp->workingDir); - m_stubProc.setEnvironment(sp->environment); - if (!m_stubProc.start(sp->executable, sp->processArgs)) - return false; // Error message for user is delivered via a signal. + m_stubProc.setWorkingDirectory(m_startParameters.workingDir); + m_stubProc.setEnvironment(m_startParameters.environment); + if (!m_stubProc.start(m_startParameters.executable, + m_startParameters.processArgs)) { + // Error message for user is delivered via a signal. + emit startFailed(); + return; + } } else { if (!m_outputCollector.listen()) { QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), tr("Cannot set up communication with child process: %1") .arg(m_outputCollector.errorString())); - return false; + emit startFailed(); + return; } gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName()); - if (!sp->workingDir.isEmpty()) - m_gdbProc->setWorkingDirectory(sp->workingDir); - if (!sp->environment.isEmpty()) - m_gdbProc->setEnvironment(sp->environment); + if (!m_startParameters.workingDir.isEmpty()) + m_gdbProc->setWorkingDirectory(m_startParameters.workingDir); + if (!m_startParameters.environment.isEmpty()) + m_gdbProc->setEnvironment(m_startParameters.environment); } #if 0 @@ -1542,13 +1552,18 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) qDebug() << "ScriptFile:" << q->settings()->m_scriptFile; qDebug() << "Environment:" << m_gdbProc->environment(); qDebug() << "Arguments:" << gdbArgs; - qDebug() << "BuildDir:" << sp->buildDir; - qDebug() << "ExeFile:" << sp->executable; + qDebug() << "BuildDir:" << m_startParameters.buildDir; + qDebug() << "ExeFile:" << m_startParameters.executable; #endif QString loc = theDebuggerStringSetting(GdbLocation); q->showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" "))); m_gdbProc->start(loc, gdbArgs); +} + +void GdbEngine::startDebugger2() +{ +#if 0 if (!m_gdbProc->waitForStarted()) { QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), tr("Cannot start debugger: %1").arg(m_gdbProc->errorString())); @@ -1556,8 +1571,10 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) m_stubProc.blockSignals(true); m_stubProc.stop(); m_stubProc.blockSignals(false); - return false; + emit startFailed(); + return; } +#endif q->showStatusMessage(tr("Gdb Running...")); @@ -1639,39 +1656,39 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) } if (q->startMode() == AttachExternal || q->startMode() == AttachCrashedExternal) { - postCommand(_("attach %1").arg(sp->attachPID), CB(handleAttach)); + postCommand(_("attach %1").arg(m_startParameters.attachPID), CB(handleAttach)); // Task 254674 does not want to remove them //qq->breakHandler()->removeAllBreakpoints(); } else if (q->startMode() == AttachCore) { - QFileInfo fi(sp->executable); + QFileInfo fi(m_startParameters.executable); QString fileName = _c('"') + fi.absoluteFilePath() + _c('"'); - QFileInfo fi2(sp->coreFile); + QFileInfo fi2(m_startParameters.coreFile); // quoting core name below fails in gdb 6.8-debian QString coreName = fi2.absoluteFilePath(); postCommand(_("-file-exec-and-symbols ") + fileName, CB(handleFileExecAndSymbols)); postCommand(_("target core ") + coreName, CB(handleTargetCore)); qq->breakHandler()->removeAllBreakpoints(); } else if (q->startMode() == StartRemote) { - postCommand(_("set architecture %1").arg(sp->remoteArchitecture)); + postCommand(_("set architecture %1").arg(m_startParameters.remoteArchitecture)); qq->breakHandler()->setAllPending(); - //QFileInfo fi(sp->executable); + //QFileInfo fi(m_startParameters.executable); //QString fileName = fi.absoluteFileName(); - QString fileName = sp->executable; + QString fileName = m_startParameters.executable; postCommand(_("-file-exec-and-symbols \"%1\"").arg(fileName), CB(handleFileExecAndSymbols)); // works only for > 6.8 postCommand(_("set target-async on"), CB(handleSetTargetAsync)); - } else if (sp->useTerminal) { + } else if (m_startParameters.useTerminal) { qq->breakHandler()->setAllPending(); } else if (q->startMode() == StartInternal || q->startMode() == StartExternal) { - QFileInfo fi(sp->executable); + QFileInfo fi(m_startParameters.executable); QString fileName = _c('"') + fi.absoluteFilePath() + _c('"'); postCommand(_("-file-exec-and-symbols ") + fileName, CB(handleFileExecAndSymbols)); //postCommand(_("file ") + fileName, handleFileExecAndSymbols); #ifdef Q_OS_MAC postCommand(_("sharedlibrary apply-load-rules all")); #endif - if (!sp->processArgs.isEmpty()) - postCommand(_("-exec-arguments ") + sp->processArgs.join(_(" "))); + if (!m_startParameters.processArgs.isEmpty()) + postCommand(_("-exec-arguments ") + m_startParameters.processArgs.join(_(" "))); #ifndef Q_OS_MAC if (!m_dumperInjectionLoad) postCommand(_("set auto-solib-add off")); @@ -1686,7 +1703,7 @@ bool GdbEngine::startDebugger(const QSharedPointer &sp) qq->breakHandler()->setAllPending(); } - return true; + emit startSuccessful(); } void GdbEngine::continueInferior() diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 88eadb4c095..c0ec3444321 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -31,6 +31,7 @@ #define DEBUGGER_GDBENGINE_H #include "idebuggerengine.h" +#include "debuggermanager.h" // only for StartParameters #include "gdbmi.h" #include "gdbprocessbase.h" #include "outputcollector.h" @@ -86,6 +87,8 @@ public: this, SIGNAL(readyReadStandardOutput())); connect(&m_proc, SIGNAL(readyReadStandardError()), this, SIGNAL(readyReadStandardError())); + connect(&m_proc, SIGNAL(started()), + this, SIGNAL(started())); connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SIGNAL(finished(int, QProcess::ExitStatus))); } @@ -133,7 +136,8 @@ private: void shutdown(); void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos); - bool startDebugger(const QSharedPointer &sp); + void startDebugger(const QSharedPointer &sp); + Q_SLOT void startDebugger2(); void exitDebugger(); void detachDebugger(); @@ -430,6 +434,7 @@ private: DebuggerManager * const q; IDebuggerManagerAccessForEngines * const qq; + DebuggerStartParameters m_startParameters; // make sure to re-initialize new members in initializeVariables(); }; diff --git a/src/plugins/debugger/gdb/gdbprocessbase.h b/src/plugins/debugger/gdb/gdbprocessbase.h index b6adfc763bb..bf5216ffe91 100644 --- a/src/plugins/debugger/gdb/gdbprocessbase.h +++ b/src/plugins/debugger/gdb/gdbprocessbase.h @@ -51,7 +51,7 @@ public: QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0; virtual void kill() = 0; virtual void terminate() = 0; - virtual bool waitForStarted(int msecs = 30000) = 0; + //virtual bool waitForStarted(int msecs = 30000) = 0; virtual bool waitForFinished(int msecs = 30000) = 0; virtual QProcess::ProcessState state() const = 0; virtual QString errorString() const = 0; @@ -63,6 +63,7 @@ public: signals: void error(QProcess::ProcessError); + void started(); void readyReadStandardOutput(); void readyReadStandardError(); void finished(int, QProcess::ExitStatus); diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h index 89ff3029319..7ae53804a23 100644 --- a/src/plugins/debugger/idebuggerengine.h +++ b/src/plugins/debugger/idebuggerengine.h @@ -55,12 +55,14 @@ class WatchData; class IDebuggerEngine : public QObject { + Q_OBJECT + public: IDebuggerEngine(QObject *parent = 0) : QObject(parent) {} virtual void shutdown() = 0; virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos) = 0; - virtual bool startDebugger(const QSharedPointer &startParameters) = 0; + virtual void startDebugger(const QSharedPointer &startParameters) = 0; virtual void exitDebugger() = 0; virtual void detachDebugger() {} virtual void updateWatchData(const WatchData &data) = 0; @@ -101,6 +103,10 @@ public: virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame &) {} virtual void setRegisterValue(int regnr, const QString &value) { Q_UNUSED(regnr); Q_UNUSED(value); } + +signals: + void startSuccessful(); + void startFailed(); }; } // namespace Internal diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp index 3f31ca421b0..45742e96798 100644 --- a/src/plugins/debugger/script/scriptengine.cpp +++ b/src/plugins/debugger/script/scriptengine.cpp @@ -217,7 +217,7 @@ void ScriptEngine::exitDebugger() qq->notifyInferiorExited(); } -bool ScriptEngine::startDebugger(const QSharedPointer &sp) +void ScriptEngine::startDebugger(const QSharedPointer &sp) { if (!m_scriptEngine) m_scriptEngine = new QScriptEngine(this); @@ -233,15 +233,17 @@ bool ScriptEngine::startDebugger(const QSharedPointer & QFileInfo fi(sp->executable); m_scriptFileName = fi.absoluteFilePath(); QFile scriptFile(m_scriptFileName); - if (!scriptFile.open(QIODevice::ReadOnly)) - return false; + if (!scriptFile.open(QIODevice::ReadOnly)) { + emit startFailed(); + return; + } QTextStream stream(&scriptFile); m_scriptContents = stream.readAll(); scriptFile.close(); attemptBreakpointSynchronization(); qq->notifyInferiorRunningRequested(); QTimer::singleShot(0, this, SLOT(runInferior())); - return true; + emit startSuccessful(); } void ScriptEngine::continueInferior() diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h index 1f82a6ed583..32e8d3fe4b1 100644 --- a/src/plugins/debugger/script/scriptengine.h +++ b/src/plugins/debugger/script/scriptengine.h @@ -75,7 +75,7 @@ private: void shutdown(); void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos); - bool startDebugger(const QSharedPointer &sp); + void startDebugger(const QSharedPointer &sp); void exitDebugger(); diff --git a/src/plugins/debugger/symbian/symbian.pri b/src/plugins/debugger/symbian/symbian.pri index 1ffb8081d4f..afc2dbf9eef 100644 --- a/src/plugins/debugger/symbian/symbian.pri +++ b/src/plugins/debugger/symbian/symbian.pri @@ -1,9 +1,11 @@ HEADERS += \ + $$PWD/trkutils.h \ $$PWD/trkclient.h \ $$PWD/symbianadapter.h \ #$$PWD/gdboptionspage.h \ SOURCES += \ + $$PWD/trkutils.cpp \ $$PWD/trkclient.cpp \ $$PWD/symbianadapter.cpp \ $$PWD/symbianengine.cpp \ diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index 5790cbf6c6a..9ade25364d7 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -104,7 +104,7 @@ SymbianAdapter::SymbianAdapter() SymbianAdapter::~SymbianAdapter() { m_gdbServer.close(); - logMessage("Shutting down.\n", true); + logMessage("Shutting down.\n"); } void SymbianAdapter::trkLogMessage(const QString &msg) @@ -193,10 +193,10 @@ void SymbianAdapter::startInferior() //sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(startGdbServer)); } -void SymbianAdapter::logMessage(const QString &msg, bool force) +void SymbianAdapter::logMessage(const QString &msg) { - if (m_verbose || force) - emit output(QString(), msg); + if (m_verbose) + emit output(msg); } // @@ -289,17 +289,17 @@ bool SymbianAdapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush) { if (!m_gdbConnection) { logMessage(QString::fromLatin1("Cannot write to gdb: No connection (%1)") - .arg(QString::fromLatin1(packet)), true); + .arg(QString::fromLatin1(packet))); return false; } if (m_gdbConnection->state() != QAbstractSocket::ConnectedState) { logMessage(QString::fromLatin1("Cannot write to gdb: Not connected (%1)") - .arg(QString::fromLatin1(packet)), true); + .arg(QString::fromLatin1(packet))); return false; } if (m_gdbConnection->write(packet) == -1) { logMessage(QString::fromLatin1("Cannot write to gdb: %1 (%2)") - .arg(m_gdbConnection->errorString()).arg(QString::fromLatin1(packet)), true); + .arg(m_gdbConnection->errorString()).arg(QString::fromLatin1(packet))); return false; } if (doFlush) @@ -720,6 +720,7 @@ void SymbianAdapter::handleGdbServerCommand(const QByteArray &cmd) if (bp == 0) { logMessage(QString::fromLatin1("NO RECORDED BP AT 0x%1, %2") .arg(addr, 0, 16).arg(len)); + sendGdbServerMessage("E00"); } else { //---IDE------------------------------------------------------ // Command: 0x1C Clear Break @@ -748,7 +749,7 @@ void SymbianAdapter::handleGdbServerCommand(const QByteArray &cmd) if (ok1 && ok2) { const QString msg = QString::fromLatin1("Read of OS auxilary " "vector (%1, %2) not implemented.").arg(offset).arg(length); - logMessage(msgGdbPacket(msg), true); + logMessage(msgGdbPacket(msg)); sendGdbServerMessage("E20", msg.toLatin1()); handled = true; } @@ -757,7 +758,7 @@ void SymbianAdapter::handleGdbServerCommand(const QByteArray &cmd) if (!handled) { const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ") + QString::fromAscii(cmd); - logMessage(msgGdbPacket(msg), true); + logMessage(msgGdbPacket(msg)); sendGdbServerMessage("E20", msg.toLatin1()); } } // qPart/qXfer @@ -820,7 +821,7 @@ void SymbianAdapter::handleTrkResult(const TrkResult &result) QString logMsg; QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str; - logMessage(logMsg, true); + logMessage(logMsg); break; } case 0x90: { // Notified Stopped @@ -1221,7 +1222,7 @@ void SymbianAdapter::handleTrkVersions(const TrkResult &result) void SymbianAdapter::handleDisconnect(const TrkResult & /*result*/) { - logMessage(QLatin1String("Trk disconnected"), true); + logMessage(QLatin1String("Trk disconnected")); } void SymbianAdapter::readMemory(uint addr, uint len) @@ -1284,9 +1285,9 @@ void SymbianAdapter::connectProcess(QProcess *proc) void SymbianAdapter::sendOutput(QObject *sender, const QString &data) { if (sender) - emit output(sender->objectName() + " : ", data); + emit output(sender->objectName() + " : " + data); else - emit output(QString(), data); + emit output(data); } void SymbianAdapter::handleProcError(QProcess::ProcessError error) @@ -1328,13 +1329,13 @@ void SymbianAdapter::startGdb() { if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) { logMessage(QString("Unable to start the gdb server at %1: %2.") - .arg(m_gdbServerName).arg(m_gdbServer.errorString()), true); + .arg(m_gdbServerName).arg(m_gdbServer.errorString())); QCoreApplication::exit(5); return; } logMessage(QString("Gdb server running on %1.\nRegister endianness: %3.") - .arg(m_gdbServerName).arg(m_registerEndianness), true); + .arg(m_gdbServerName).arg(m_registerEndianness)); connect(&m_gdbServer, SIGNAL(newConnection()), this, SLOT(handleGdbConnection())); @@ -1379,12 +1380,12 @@ void SymbianAdapter::startGdb() sendGdbMessage("symbol-file filebrowseapp.sym"); // -symbol-info-address not implemented in cs-gdb 6.4-6.8 (at least) - sendGdbMessage("info address E32Main", - GdbCB(handleInfoMainAddress)); - sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL", - GdbCB(handleInfoMainAddress)); + //sendGdbMessage("info address E32Main", + // GdbCB(handleInfoMainAddress)); + //sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL", + // GdbCB(handleInfoMainAddress)); -#if 1 +#if 0 // FIXME: Gdb based version. That's the goal //sendGdbMessage("break E32Main"); //sendGdbMessage("continue"); @@ -1392,8 +1393,11 @@ void SymbianAdapter::startGdb() // trkContinueMessage(), "CONTINUE"); #else // Directly talk to TRK. Works for now... - sendGdbMessage("break E32Main"); - sendGdbMessage("break filebrowseappui.cpp:39"); + //sendGdbMessage("break E32Main"); + sendGdbMessage("-break-insert E32Main"); + sendGdbMessage("-break-insert filebrowseappui.cpp:39"); + sendGdbMessage("target remote " + m_gdbServerName); + //sendGdbMessage("break filebrowseappui.cpp:39"); // sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); #endif } @@ -1441,6 +1445,7 @@ void SymbianAdapter::handleGdbReadyReadStandardOutput() if (!cmd.callback.isNull()) cmd.callback(result); #else +/* bool ok; QRegExp re(QString("Symbol .._Z7E32Mainv.. is a function at address 0x(.*)\\.")); if (re.indexIn(str) != -1) { @@ -1459,6 +1464,7 @@ void SymbianAdapter::handleGdbReadyReadStandardOutput() sendGdbMessage("target remote " + m_gdbServerName); return; } +*/ logMessage(QString("-> GDB: %1").arg(str)); #endif } @@ -1505,6 +1511,8 @@ void SymbianAdapter::handleRfcommReadyReadStandardOutput() void SymbianAdapter::start(const QString &program, const QStringList &args, QIODevice::OpenMode mode) { + qDebug() << "SYMBIAN START"; + run(); //m_gdbProc.start(program, args, mode); } @@ -1518,12 +1526,6 @@ void SymbianAdapter::terminate() //m_gdbProc.terminate(); } -bool SymbianAdapter::waitForStarted(int msecs) -{ - //return m_gdbProc.waitForStarted(msecs); - return true; -} - bool SymbianAdapter::waitForFinished(int msecs) { //return m_gdbProc.waitForFinished(msecs); diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h index 45c5b762c04..79c7860d5c4 100644 --- a/src/plugins/debugger/symbian/symbianadapter.h +++ b/src/plugins/debugger/symbian/symbianadapter.h @@ -95,7 +95,7 @@ public slots: void startInferior(); signals: - void output(const QString &senderName, const QString &data); + void output(const QString &msg); private slots: void handleProcError(QProcess::ProcessError error); @@ -126,7 +126,6 @@ public: QIODevice::OpenMode mode = QIODevice::ReadWrite); void kill(); void terminate(); - bool waitForStarted(int msecs = 30000); bool waitForFinished(int msecs = 30000); QProcess::ProcessState state() const; QString errorString() const; @@ -213,7 +212,7 @@ public: Q_SLOT void handleGdbReadyReadStandardError(); Q_SLOT void handleGdbReadyReadStandardOutput(); - void logMessage(const QString &msg, bool force = false); + void logMessage(const QString &msg); // triggers output() if m_verbose Q_SLOT void trkLogMessage(const QString &msg); void handleInfoAddress(const GdbResult &result); diff --git a/src/plugins/debugger/symbian/symbianengine.cpp b/src/plugins/debugger/symbian/symbianengine.cpp index 11c6b03c8ad..ef407e2c53f 100644 --- a/src/plugins/debugger/symbian/symbianengine.cpp +++ b/src/plugins/debugger/symbian/symbianengine.cpp @@ -31,6 +31,7 @@ #include "gdb/gdbengine.h" #include "symbianadapter.h" +#include "debuggermanager.h" //#include "debuggerdialogs.h" @@ -40,24 +41,20 @@ #include #include -#include -#include -#include -#include -#include -#include namespace Debugger { namespace Internal { - IDebuggerEngine *createSymbianEngine(DebuggerManager *parent, QList *opts) { Q_UNUSED(opts); //opts->push_back(new GdbOptionsPage); - return new GdbEngine(parent, new SymbianAdapter); + SymbianAdapter *adapter = new SymbianAdapter; + QObject::connect(adapter, SIGNAL(output(QString)), + parent, SLOT(showDebuggerOutput(QString))); + return new GdbEngine(parent, adapter); } } // namespace Internal diff --git a/src/plugins/debugger/tcf/tcfengine.cpp b/src/plugins/debugger/tcf/tcfengine.cpp index 0c98513b8ec..bcadf3c9540 100644 --- a/src/plugins/debugger/tcf/tcfengine.cpp +++ b/src/plugins/debugger/tcf/tcfengine.cpp @@ -220,7 +220,7 @@ void TcfEngine::exitDebugger() qq->notifyInferiorExited(); } -bool TcfEngine::startDebugger(const QSharedPointer &sp) +void TcfEngine::startDebugger(const QSharedPointer &sp) { qq->notifyInferiorRunningRequested(); const int pos = sp->remoteChannel.indexOf(QLatin1Char(':')); @@ -228,7 +228,7 @@ bool TcfEngine::startDebugger(const QSharedPointer &sp) const quint16 port = sp->remoteChannel.mid(pos + 1).toInt(); //QTimer::singleShot(0, this, SLOT(runInferior())); m_socket->connectToHost(host, port); - return true; + emit startSuccessful(); } void TcfEngine::continueInferior() diff --git a/src/plugins/debugger/tcf/tcfengine.h b/src/plugins/debugger/tcf/tcfengine.h index 3d556427bd9..4487fffd3de 100644 --- a/src/plugins/debugger/tcf/tcfengine.h +++ b/src/plugins/debugger/tcf/tcfengine.h @@ -82,7 +82,7 @@ private: void shutdown(); void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos); - bool startDebugger(const QSharedPointer &sp); + void startDebugger(const QSharedPointer &sp); void exitDebugger(); void continueInferior(); diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index 00a4b9bd15e..b43118f4b25 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -53,9 +53,9 @@ signals: void executeCommand(QString); public slots: - void handleOutput(const QString &senderName, const QString &data) + void handleOutput(const QString &str0) { - QString str = senderName + data; + QString str = str0; str.replace("\\t", QString(QChar(0x09))); str.replace("\\n", QString("\n")); append(str); @@ -137,8 +137,8 @@ RunnerGui::RunnerGui(SymbianAdapter *adapter) connectAction(m_disassIAction, "Disass Inst", SLOT(executeDisassICommand())); connectAction(m_continueAction, "Continue", SLOT(executeContinueCommand())); - connect(adapter, SIGNAL(output(QString,QString)), - &m_textEdit, SLOT(handleOutput(QString,QString))); + connect(adapter, SIGNAL(output(QString)), + &m_textEdit, SLOT(handleOutput(QString))); connect(&m_textEdit, SIGNAL(executeCommand(QString)), m_adapter, SLOT(executeCommand(QString))); } From 75a3112ac48f6813f74e9cb55cea25e3d9b716f5 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 10 Sep 2009 13:15:19 +0200 Subject: [PATCH 25/43] Revert "make sure symbian include is scoped" This reverts commit 1e186c5bf9031c5da709e9a0467b5efae6933519. The code is not symbian specific, linking error was fixed properly by adding the needed files to HEADERS. --- src/plugins/debugger/debugger.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index abb71c4ad36..c9be97b7260 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -87,7 +87,7 @@ include(cdb/cdb.pri) include(gdb/gdb.pri) include(script/script.pri) include(tcf/tcf.pri) -symbian:include(symbian/symbian.pri) +include(symbian/symbian.pri) include(shared/shared.pri) OTHER_FILES += Debugger.pluginspec From 903a50a6ef90cf4b795acab3648006e577fb0e47 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 10 Sep 2009 13:59:21 +0200 Subject: [PATCH 26/43] debugger: work on trk integration --- src/plugins/debugger/debuggermanager.cpp | 12 ++++++++---- src/plugins/debugger/symbian/symbianadapter.cpp | 16 +++++++++------- src/plugins/debugger/symbian/symbianadapter.h | 1 + src/plugins/debugger/symbian/symbianengine.cpp | 3 ++- tests/manual/trk/trklauncher.pri | 2 +- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 9bc178ca946..5222fb8c1ae 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -1355,14 +1355,18 @@ void DebuggerManager::modulesDockToggled(bool on) void DebuggerManager::showDebuggerOutput(int channel, const QString &msg) { - QTC_ASSERT(m_outputWindow, return); - m_outputWindow->showOutput(channel, msg); + if (m_outputWindow) + m_outputWindow->showOutput(channel, msg); + else + qDebug() << "OUTPUT: " << channel << msg; } void DebuggerManager::showDebuggerInput(int channel, const QString &msg) { - QTC_ASSERT(m_outputWindow, return); - m_outputWindow->showInput(channel, msg); + if (m_outputWindow) + m_outputWindow->showInput(channel, msg); + else + qDebug() << "INPUT: " << channel << msg; } diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index 9ade25364d7..b13447499f7 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -191,6 +191,7 @@ void SymbianAdapter::startInferior() appendString(&ba, file, TargetByteOrder); sendTrkMessage(0x40, TrkCB(handleCreateProcess), ba); // Create Item //sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(startGdbServer)); + emit started(); } void SymbianAdapter::logMessage(const QString &msg) @@ -1292,7 +1293,8 @@ void SymbianAdapter::sendOutput(QObject *sender, const QString &data) void SymbianAdapter::handleProcError(QProcess::ProcessError error) { - sendOutput(sender(), QString("Process Error %1").arg(error)); + sendOutput(sender(), + QString("Process Error %1: %2").arg(error).arg(errorString())); } void SymbianAdapter::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus) @@ -1511,25 +1513,25 @@ void SymbianAdapter::handleRfcommReadyReadStandardOutput() void SymbianAdapter::start(const QString &program, const QStringList &args, QIODevice::OpenMode mode) { - qDebug() << "SYMBIAN START"; + Q_UNUSED(mode); + qDebug() << "SYMBIAN START" << program << args << mode; run(); - //m_gdbProc.start(program, args, mode); } void SymbianAdapter::kill() { - //m_gdbProc.kill(); + m_gdbProc.kill(); } void SymbianAdapter::terminate() { - //m_gdbProc.terminate(); + m_gdbProc.terminate(); } bool SymbianAdapter::waitForFinished(int msecs) { - //return m_gdbProc.waitForFinished(msecs); - return true; + return m_gdbProc.waitForFinished(msecs); + //return true; } QProcess::ProcessState SymbianAdapter::state() const diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h index 79c7860d5c4..da6c0735ab3 100644 --- a/src/plugins/debugger/symbian/symbianadapter.h +++ b/src/plugins/debugger/symbian/symbianadapter.h @@ -96,6 +96,7 @@ public slots: signals: void output(const QString &msg); + void startSuccessful(); private slots: void handleProcError(QProcess::ProcessError error); diff --git a/src/plugins/debugger/symbian/symbianengine.cpp b/src/plugins/debugger/symbian/symbianengine.cpp index ef407e2c53f..cb30e78fd9d 100644 --- a/src/plugins/debugger/symbian/symbianengine.cpp +++ b/src/plugins/debugger/symbian/symbianengine.cpp @@ -52,9 +52,10 @@ IDebuggerEngine *createSymbianEngine(DebuggerManager *parent, Q_UNUSED(opts); //opts->push_back(new GdbOptionsPage); SymbianAdapter *adapter = new SymbianAdapter; + GdbEngine *engine = new GdbEngine(parent, adapter); QObject::connect(adapter, SIGNAL(output(QString)), parent, SLOT(showDebuggerOutput(QString))); - return new GdbEngine(parent, adapter); + return engine; } } // namespace Internal diff --git a/tests/manual/trk/trklauncher.pri b/tests/manual/trk/trklauncher.pri index 74b37e42e3c..69ed7630410 100644 --- a/tests/manual/trk/trklauncher.pri +++ b/tests/manual/trk/trklauncher.pri @@ -1,7 +1,7 @@ DEFINES += DEBUG_TRK=0 DEBUGGERHOME = ../../../src/plugins/debugger/symbian -INCLUDEPATH *= $$DEBUGGERHOME +INCLUDEPATH *= $$PWD $$DEBUGGERHOME SOURCES += \ $$DEBUGGERHOME/trkutils.cpp \ From 700bfa6339b9f788985d9ccc7515c6ea47c78239 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 10 Sep 2009 13:59:21 +0200 Subject: [PATCH 27/43] debugger: work on trk integration --- .../debugger/symbian/symbianadapter.cpp | 107 ++---------------- src/plugins/debugger/symbian/symbianadapter.h | 5 - tests/manual/trk/runner.cpp | 41 ++++++- 3 files changed, 47 insertions(+), 106 deletions(-) diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index b13447499f7..2184e6b7390 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -71,7 +71,7 @@ SymbianAdapter::SymbianAdapter() { m_running = false; m_gdbAckMode = true; - m_verbose = 2; + m_verbose = 0; m_serialFrame = false; m_bufferedMemoryRead = true; m_rfcommDevice = "/dev/rfcomm0"; @@ -82,9 +82,9 @@ SymbianAdapter::SymbianAdapter() m_gdbProc.setObjectName("GDB PROCESS"); connectProcess(&m_gdbProc); connect(&m_gdbProc, SIGNAL(readyReadStandardError()), - this, SLOT(handleGdbReadyReadStandardError())); + this, SIGNAL(readyReadStandardError())); connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), - this, SLOT(handleGdbReadyReadStandardOutput())); + this, SIGNAL(readyReadStandardOutput())); m_rfcommProc.setObjectName("RFCOMM PROCESS"); connectProcess(&m_rfcommProc); @@ -167,7 +167,7 @@ void SymbianAdapter::startInferior() { QString errorMessage; if (!m_trkDevice.open(m_rfcommDevice, &errorMessage)) { - logMessage("LOOPING"); + emit output("LOOPING"); QTimer::singleShot(1000, this, SLOT(startInferior())); return; } @@ -427,7 +427,6 @@ void SymbianAdapter::handleGdbServerCommand(const QByteArray &cmd) else if (cmd.startsWith("D")) { sendGdbServerAck(); sendGdbServerMessage("OK", "shutting down"); - qApp->quit(); } else if (cmd == "g") { @@ -1332,7 +1331,7 @@ void SymbianAdapter::startGdb() if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) { logMessage(QString("Unable to start the gdb server at %1: %2.") .arg(m_gdbServerName).arg(m_gdbServer.errorString())); - QCoreApplication::exit(5); + //emit startFailed(); return; } @@ -1361,47 +1360,19 @@ void SymbianAdapter::startGdb() //sendGdbMessage("set remote noack-packet"); // FIXME: creates a lot of noise a la '&"putpkt: Junk: Ack " &' - // even thouhg the communication seems sane + // even though the communication seems sane //sendGdbMessage("set debug remote 1"); // creates l - //sendGdbMessage("target remote " + m_gdbServerName); -// sendGdbMessage("target extended-remote " + m_gdbServerName); - //sendGdbMessage("target extended-async " + m_gdbServerName); - //sendGdbMessage("set remotecache ...") // Set cache use for remote targets - //sendGdbMessage("file filebrowseapp.sym"); -// sendGdbMessage("add-symbol-file filebrowseapp.sym " + m_baseAddress); -// sendGdbMessage("symbol-file filebrowseapp.sym"); -// sendGdbMessage("print E32Main"); -// sendGdbMessage("break E32Main"); - //sendGdbMessage("continue"); - //sendGdbMessage("info files"); - //sendGdbMessage("file filebrowseapp.sym -readnow"); - sendGdbMessage("add-symbol-file filebrowseapp.sym " + hexxNumber(m_session.codeseg)); sendGdbMessage("symbol-file filebrowseapp.sym"); - // -symbol-info-address not implemented in cs-gdb 6.4-6.8 (at least) - //sendGdbMessage("info address E32Main", - // GdbCB(handleInfoMainAddress)); //sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL", // GdbCB(handleInfoMainAddress)); -#if 0 - // FIXME: Gdb based version. That's the goal - //sendGdbMessage("break E32Main"); - //sendGdbMessage("continue"); - //sendTrkMessage(0x18, TrkCB(handleContinueAfterCreateProcess), - // trkContinueMessage(), "CONTINUE"); -#else - // Directly talk to TRK. Works for now... - //sendGdbMessage("break E32Main"); - sendGdbMessage("-break-insert E32Main"); sendGdbMessage("-break-insert filebrowseappui.cpp:39"); sendGdbMessage("target remote " + m_gdbServerName); - //sendGdbMessage("break filebrowseappui.cpp:39"); - // sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); -#endif + //sendGdbMessage("-exec-continue"); } void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback, @@ -1418,64 +1389,6 @@ void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback, m_gdbProc.write(QString("%1%2\n").arg(token).arg(msg).toLatin1()); } -void SymbianAdapter::handleGdbReadyReadStandardError() -{ - QByteArray ba = qobject_cast(sender())->readAllStandardError(); - sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba))); -} - -void SymbianAdapter::handleGdbReadyReadStandardOutput() -{ - QByteArray ba = qobject_cast(sender())->readAllStandardOutput(); - QString str = QString::fromLatin1(ba); - // FIXME: fragile. merge with gdbengine logic -#if 0 - QRegExp re(QString(".*([0-9]+)[^]done.*")); - int pos = re.indexIn(str); - if (pos == -1) { - logMessage(QString("\n-> GDB: %1 %**% %2 %**%\n").arg(str).arg(pos)); - return; - } - int token = re.cap(1).toInt(); - logMessage(QString("\n-> GDB: %1 %2##\n").arg(token).arg(QString::fromLatin1(ba))); - if (!token) - return; - GdbCommand cmd = m_gdbCookieForToken.take(token); - logMessage("FOUND CALLBACK FOR " + cmd.command); - GdbResult result; - result.data = ba; - if (!cmd.callback.isNull()) - cmd.callback(result); -#else -/* - bool ok; - QRegExp re(QString("Symbol .._Z7E32Mainv.. is a function at address 0x(.*)\\.")); - if (re.indexIn(str) != -1) { - logMessage(QString("-> GDB MAIN BREAKPOINT: %1").arg(re.cap(1))); - uint addr = re.cap(1).toInt(&ok, 16); - sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); - return; - } - QRegExp re1(QString("Symbol .._ZN16CFileBrowseAppUi14HandleCommandLEi.. is a function at address 0x(.*)\\.")); - if (re1.indexIn(str) != -1) { - logMessage(QString("-> GDB USER BREAKPOINT: %1").arg(re1.cap(1))); - uint addr = re1.cap(1).toInt(&ok, 16); - sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1)); - - sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE"); - sendGdbMessage("target remote " + m_gdbServerName); - return; - } -*/ - logMessage(QString("-> GDB: %1").arg(str)); -#endif -} - -void SymbianAdapter::handleInfoMainAddress(const GdbResult &result) -{ - Q_UNUSED(result); -} - void SymbianAdapter::handleSetTrkMainBreakpoint(const TrkResult &result) { Q_UNUSED(result); @@ -1488,12 +1401,6 @@ void SymbianAdapter::handleSetTrkMainBreakpoint(const TrkResult &result) */ } -void SymbianAdapter::handleInfoAddress(const GdbResult &result) -{ - Q_UNUSED(result); - // FIXME -} - void SymbianAdapter::handleRfcommReadyReadStandardError() { QByteArray ba = qobject_cast(sender())->readAllStandardError(); diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h index da6c0735ab3..0980112dce3 100644 --- a/src/plugins/debugger/symbian/symbianadapter.h +++ b/src/plugins/debugger/symbian/symbianadapter.h @@ -211,14 +211,9 @@ public: void sendGdbServerAck(); bool sendGdbServerPacket(const QByteArray &packet, bool doFlush); - Q_SLOT void handleGdbReadyReadStandardError(); - Q_SLOT void handleGdbReadyReadStandardOutput(); void logMessage(const QString &msg); // triggers output() if m_verbose Q_SLOT void trkLogMessage(const QString &msg); - void handleInfoAddress(const GdbResult &result); - void handleInfoMainAddress(const GdbResult &result); - QTcpServer m_gdbServer; QPointer m_gdbConnection; QByteArray m_gdbReadBuffer; diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index b43118f4b25..aaa3b984b47 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -107,6 +107,12 @@ private slots: void executeContinueCommand() { executeCommand("-exec-continue"); } void executeDisassICommand() { executeCommand("disass $pc $pc+4"); } + void handleReadyReadStandardError(); + void handleReadyReadStandardOutput(); + + void run(); + void started(); + private: void executeCommand(const QString &cmd) { m_adapter->executeCommand(cmd); } void connectAction(QAction *&, QString name, const char *slot); @@ -141,6 +147,13 @@ RunnerGui::RunnerGui(SymbianAdapter *adapter) &m_textEdit, SLOT(handleOutput(QString))); connect(&m_textEdit, SIGNAL(executeCommand(QString)), m_adapter, SLOT(executeCommand(QString))); + + connect(adapter, SIGNAL(readyReadStandardError()), + this, SLOT(handleReadyReadStandardError())); + connect(adapter, SIGNAL(readyReadStandardOutput()), + this, SLOT(handleReadyReadStandardOutput())); + connect(adapter, SIGNAL(started()), + this, SLOT(started())); } void RunnerGui::connectAction(QAction *&action, QString name, const char *slot) @@ -151,6 +164,31 @@ void RunnerGui::connectAction(QAction *&action, QString name, const char *slot) connect(action, SIGNAL(triggered()), this, slot); } +void RunnerGui::handleReadyReadStandardError() +{ + QByteArray ba = m_adapter->readAllStandardError(); + qDebug() << ba; + m_textEdit.handleOutput(ba); +} + +void RunnerGui::handleReadyReadStandardOutput() +{ + QByteArray ba = m_adapter->readAllStandardOutput(); + qDebug() << ba; + m_textEdit.handleOutput("-> GDB: " + ba); +} + +void RunnerGui::run() +{ + m_adapter->run(); +} + +void RunnerGui::started() +{ + qDebug() << "\nSTARTED\n"; + m_adapter->sendGdbMessage("-exec-continue"); +} + /////////////////////////////////////////////////////////////////////// // // main @@ -161,9 +199,10 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); SymbianAdapter adapter; + adapter.setVerbose(2); RunnerGui gui(&adapter); gui.show(); - QTimer::singleShot(0, &adapter, SLOT(run())); + QTimer::singleShot(0, &gui, SLOT(run())); return app.exec(); } From 648ceaed181afc58230138916ca27d79fb8870ef Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 10 Sep 2009 16:30:04 +0200 Subject: [PATCH 28/43] debugger: work on trk integration --- src/plugins/debugger/gdb/gdbengine.cpp | 17 ++++++++++++----- src/plugins/debugger/gdb/gdbengine.h | 1 + src/plugins/debugger/gdb/gdbprocessbase.h | 1 + src/plugins/debugger/symbian/symbianadapter.cpp | 15 +++++---------- src/plugins/debugger/symbian/symbianadapter.h | 3 ++- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 7c1909addc3..466c6f62766 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1563,6 +1563,8 @@ void GdbEngine::startDebugger(const QSharedPointer &sp) void GdbEngine::startDebugger2() { + qDebug() << "STARTUP, PHASE 2"; + debugMessage(_("STARTUP, PHASE 2")); #if 0 if (!m_gdbProc->waitForStarted()) { QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), @@ -1726,11 +1728,16 @@ void GdbEngine::handleStart(const GdbResultRecord &response, const QVariant &) QString msg = _(response.data.findChild("consolestreamoutput").data()); QRegExp needle(_("\\bEntry point: (0x[0-9a-f]+)\\b")); if (needle.indexIn(msg) != -1) { - //debugMessage(_("STREAM: ") + msg + " " + needle.cap(1)); - postCommand(_("tbreak *") + needle.cap(1)); - m_waitingForFirstBreakpointToBeHit = true; - qq->notifyInferiorRunningRequested(); - postCommand(_("-exec-run"), CB(handleExecRun)); + if (m_gdbProc->isAdapter()) { + postCommand(_("-exec-continue"), CB(handleExecRun)); + qq->notifyInferiorRunningRequested(); + } else { + //debugMessage(_("STREAM: ") + msg + " " + needle.cap(1)); + postCommand(_("tbreak *") + needle.cap(1)); + m_waitingForFirstBreakpointToBeHit = true; + qq->notifyInferiorRunningRequested(); + postCommand(_("-exec-run"), CB(handleExecRun)); + } } else { debugMessage(_("PARSING START ADDRESS FAILED: ") + msg); } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index c0ec3444321..1dbc285a6ee 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -106,6 +106,7 @@ public: qint64 write(const char *data) { return m_proc.write(data); } void setWorkingDirectory(const QString &dir) { m_proc.setWorkingDirectory(dir); } void setEnvironment(const QStringList &env) { m_proc.setEnvironment(env); } + bool isAdapter() const { return false; } private: QProcess m_proc; diff --git a/src/plugins/debugger/gdb/gdbprocessbase.h b/src/plugins/debugger/gdb/gdbprocessbase.h index bf5216ffe91..6c5825e6f66 100644 --- a/src/plugins/debugger/gdb/gdbprocessbase.h +++ b/src/plugins/debugger/gdb/gdbprocessbase.h @@ -60,6 +60,7 @@ public: virtual qint64 write(const char *data) = 0; virtual void setWorkingDirectory(const QString &dir) = 0; virtual void setEnvironment(const QStringList &env) = 0; + virtual bool isAdapter() const = 0; signals: void error(QProcess::ProcessError); diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index 2184e6b7390..97b0bd68851 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -71,7 +71,7 @@ SymbianAdapter::SymbianAdapter() { m_running = false; m_gdbAckMode = true; - m_verbose = 0; + m_verbose = 2; m_serialFrame = false; m_bufferedMemoryRead = true; m_rfcommDevice = "/dev/rfcomm0"; @@ -191,7 +191,6 @@ void SymbianAdapter::startInferior() appendString(&ba, file, TargetByteOrder); sendTrkMessage(0x40, TrkCB(handleCreateProcess), ba); // Create Item //sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(startGdbServer)); - emit started(); } void SymbianAdapter::logMessage(const QString &msg) @@ -1047,7 +1046,7 @@ void SymbianAdapter::handleAndReportReadRegisters(const TrkResult &result) sendGdbServerMessage(ba, logMsg); } -static inline QString msgMemoryReadError(int code, uint addr, uint len = 0) +static QString msgMemoryReadError(int code, uint addr, uint len = 0) { const QString lenS = len ? QString::number(len) : QLatin1String(""); return QString::fromLatin1("Memory read error %1 at: 0x%2 %3") @@ -1372,21 +1371,18 @@ void SymbianAdapter::startGdb() sendGdbMessage("-break-insert filebrowseappui.cpp:39"); sendGdbMessage("target remote " + m_gdbServerName); - //sendGdbMessage("-exec-continue"); + emit started(); } void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback, const QVariant &cookie) { - static int token = 0; - ++token; GdbCommand data; data.command = msg; data.callback = callback; data.cookie = cookie; - m_gdbCookieForToken[token] = data; - logMessage(QString("<- GDB: %1 %2").arg(token).arg(msg)); - m_gdbProc.write(QString("%1%2\n").arg(token).arg(msg).toLatin1()); + logMessage(QString("<- GDB: %2").arg(msg)); + m_gdbProc.write(msg.toLatin1() + "\n"); } void SymbianAdapter::handleSetTrkMainBreakpoint(const TrkResult &result) @@ -1438,7 +1434,6 @@ void SymbianAdapter::terminate() bool SymbianAdapter::waitForFinished(int msecs) { return m_gdbProc.waitForFinished(msecs); - //return true; } QProcess::ProcessState SymbianAdapter::state() const diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h index 0980112dce3..e694a1ffab3 100644 --- a/src/plugins/debugger/symbian/symbianadapter.h +++ b/src/plugins/debugger/symbian/symbianadapter.h @@ -93,6 +93,7 @@ public: public slots: void startInferior(); + void run(); signals: void output(const QString &msg); @@ -103,7 +104,6 @@ private slots: void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus); void handleProcStarted(); void handleProcStateChanged(QProcess::ProcessState newState); - void run(); void startGdb(); private: @@ -135,6 +135,7 @@ public: qint64 write(const char *data); void setWorkingDirectory(const QString &dir); void setEnvironment(const QStringList &env); + bool isAdapter() const { return true; } // // TRK From 472c8069406c17cb2304794bf300c06b53a846f9 Mon Sep 17 00:00:00 2001 From: con Date: Wed, 9 Sep 2009 18:35:25 +0200 Subject: [PATCH 29/43] Move DebuggerRunControl initialization out of ::start method. --- src/plugins/debugger/debuggerrunner.cpp | 56 ++++++++++++------------- src/plugins/debugger/debuggerrunner.h | 2 + 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 0f9b8b2d80c..75b76845e8b 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -140,39 +140,39 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, Qt::QueuedConnection); connect(this, SIGNAL(stopRequested()), m_manager, SLOT(exitDebugger())); + if (runConfiguration) { + // Enhance parameters by info from the project, but do not clobber + // arguments given in the dialogs + if (m_startParameters->executable.isEmpty()) + m_startParameters->executable = runConfiguration->executable(); + if (m_startParameters->environment.empty()) + m_startParameters->environment = runConfiguration->environment().toStringList(); + if (m_startParameters->workingDir.isEmpty()) + m_startParameters->workingDir = runConfiguration->workingDirectory(); + if (m_mode != StartExternal) + m_startParameters->processArgs = runConfiguration->commandLineArguments(); + switch (m_startParameters->toolChainType) { + case ProjectExplorer::ToolChain::UNKNOWN: + case ProjectExplorer::ToolChain::INVALID: + m_startParameters->toolChainType = runConfiguration->toolChainType(); + break; + default: + break; + } + if (const ProjectExplorer::Project *project = runConfiguration->project()) { + m_startParameters->buildDir = project->buildDirectory(project->activeBuildConfiguration()); + } + m_startParameters->useTerminal = runConfiguration->runMode() == ApplicationRunConfiguration::Console; + m_dumperLibrary = runConfiguration->dumperLibrary(); + m_dumperLibraryLocations = runConfiguration->dumperLibraryLocations(); + } } void DebuggerRunControl::start() { m_running = true; - ApplicationRunConfigurationPtr rc = - runConfiguration().objectCast(); - if (rc) { - // Enhance parameters by info from the project, but do not clobber - // arguments given in the dialogs - if (m_startParameters->executable.isEmpty()) - m_startParameters->executable = rc->executable(); - if (m_startParameters->environment.empty()) - m_startParameters->environment = rc->environment().toStringList(); - if (m_startParameters->workingDir.isEmpty()) - m_startParameters->workingDir = rc->workingDirectory(); - if (m_mode != StartExternal) - m_startParameters->processArgs = rc->commandLineArguments(); - switch (m_startParameters->toolChainType) { - case ProjectExplorer::ToolChain::UNKNOWN: - case ProjectExplorer::ToolChain::INVALID: - m_startParameters->toolChainType = rc->toolChainType(); - break; - default: - break; - } - m_manager->setQtDumperLibraryName(rc->dumperLibrary()); - m_manager->setQtDumperLibraryLocations(rc->dumperLibraryLocations()); - if (const ProjectExplorer::Project *project = rc->project()) { - m_startParameters->buildDir = project->buildDirectory(project->activeBuildConfiguration()); - } - m_startParameters->useTerminal = rc->runMode() == ApplicationRunConfiguration::Console; - } + m_manager->setQtDumperLibraryName(m_dumperLibrary); + m_manager->setQtDumperLibraryLocations(m_dumperLibraryLocations); //emit addToOutputWindow(this, tr("Debugging %1").arg(m_executable)); m_manager->startNewDebugger(this, m_startParameters); diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 0e0b0ac1e77..06a986ce9d3 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -109,6 +109,8 @@ private: const QSharedPointer m_startParameters; DebuggerManager *m_manager; bool m_running; + QString m_dumperLibrary; + QStringList m_dumperLibraryLocations; }; // A default run configuration for external executables or attaching to From 334837d776c83a28699cd1ec7a55d340a856cbe3 Mon Sep 17 00:00:00 2001 From: con Date: Wed, 9 Sep 2009 18:42:25 +0200 Subject: [PATCH 30/43] Move initialization code out of ::start method --- .../qt-s60/s60devicerunconfiguration.cpp | 42 +++++++++---------- .../qt-s60/s60devicerunconfiguration.h | 1 + 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 3488a25f49f..5bae0badb60 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -537,36 +537,34 @@ S60DeviceRunControl::S60DeviceRunControl(QSharedPointer runCon this, SLOT(signsisProcessFailed())); connect(m_signsis, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(signsisProcessFinished())); + + Qt4Project *project = qobject_cast(runConfiguration->project()); + QTC_ASSERT(project, return); + + m_serialPortName = runConfiguration->serialPortName(); + m_serialPortFriendlyName = S60Manager::instance()->serialDeviceLister()->friendlyNameForPort(m_serialPortName); + m_targetName = runConfiguration->targetName(); + m_baseFileName = runConfiguration->basePackageFilePath(); + m_workingDirectory = QFileInfo(m_baseFileName).absolutePath(); + m_qtDir = project->qtVersion(project->activeBuildConfiguration())->versionInfo().value("QT_INSTALL_DATA"); + m_useCustomSignature = (runConfiguration->signingMode() == S60DeviceRunConfiguration::SignCustom); + m_customSignaturePath = runConfiguration->customSignaturePath(); + m_customKeyPath = runConfiguration->customKeyPath(); + m_toolsDirectory = S60Manager::instance()->deviceForQtVersion( + project->qtVersion(project->activeBuildConfiguration())).toolsRoot + + "/epoc32/tools"; + m_executableFileName = lsFile(runConfiguration->executableFileName()); + const QString makesisTool = m_toolsDirectory + "/makesis.exe"; + const QString packageFile = QFileInfo(runConfiguration->packageFileName()).fileName(); } void S60DeviceRunControl::start() { - QSharedPointer rc = runConfiguration().objectCast(); - QTC_ASSERT(!rc.isNull(), return); - - Qt4Project *project = qobject_cast(rc->project()); - QTC_ASSERT(project, return); - - m_serialPortName = rc->serialPortName(); - m_serialPortFriendlyName = S60Manager::instance()->serialDeviceLister()->friendlyNameForPort(m_serialPortName); - m_targetName = rc->targetName(); - m_baseFileName = rc->basePackageFilePath(); - m_workingDirectory = QFileInfo(m_baseFileName).absolutePath(); - m_qtDir = project->qtVersion(project->activeBuildConfiguration())->versionInfo().value("QT_INSTALL_DATA"); - m_useCustomSignature = (rc->signingMode() == S60DeviceRunConfiguration::SignCustom); - m_customSignaturePath = rc->customSignaturePath(); - m_customKeyPath = rc->customKeyPath(); - emit started(); emit addToOutputWindow(this, tr("Creating %1.sisx ...").arg(QDir::toNativeSeparators(m_baseFileName))); - emit addToOutputWindow(this, tr("Executable file: %1").arg(lsFile(rc->executableFileName()))); + emit addToOutputWindow(this, tr("Executable file: %1").arg(m_executableFileName)); - m_toolsDirectory = S60Manager::instance()->deviceForQtVersion( - project->qtVersion(project->activeBuildConfiguration())).toolsRoot - + "/epoc32/tools"; - const QString makesisTool = m_toolsDirectory + "/makesis.exe"; - const QString packageFile = QFileInfo(rc->packageFileName()).fileName(); m_makesis->setWorkingDirectory(m_workingDirectory); emit addToOutputWindow(this, tr("%1 %2").arg(QDir::toNativeSeparators(makesisTool), packageFile)); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index d05b7cc8d9f..8d09f5b2bc8 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -176,6 +176,7 @@ private: QString m_baseFileName; QString m_workingDirectory; QString m_toolsDirectory; + QString m_executableFileName; QString m_qtDir; bool m_useCustomSignature; QString m_customSignaturePath; From 32e0340eab3292e4543fadf976a07cf89e10eccc Mon Sep 17 00:00:00 2001 From: con Date: Thu, 10 Sep 2009 17:02:57 +0200 Subject: [PATCH 31/43] Version bump. --- doc/qtcreator.qdoc | 4 ++-- doc/qtcreator.qdocconf | 10 +++++----- src/app/Info.plist | 4 ++-- src/plugins/bineditor/BinEditor.pluginspec | 6 +++--- src/plugins/bookmarks/Bookmarks.pluginspec | 8 ++++---- .../CMakeProjectManager.pluginspec | 10 +++++----- src/plugins/coreplugin/Core.pluginspec | 2 +- src/plugins/coreplugin/coreconstants.h | 2 +- src/plugins/cpaster/CodePaster.pluginspec | 8 ++++---- src/plugins/cppeditor/CppEditor.pluginspec | 8 ++++---- src/plugins/cpptools/CppTools.pluginspec | 8 ++++---- src/plugins/cvs/CVS.pluginspec | 10 +++++----- src/plugins/debugger/Debugger.pluginspec | 10 +++++----- src/plugins/designer/Designer.pluginspec | 6 +++--- src/plugins/duieditor/DuiEditor.pluginspec | 6 +++--- src/plugins/fakevim/FakeVim.pluginspec | 10 +++++----- src/plugins/find/Find.pluginspec | 4 ++-- .../GenericProjectManager.pluginspec | 10 +++++----- src/plugins/git/ScmGit.pluginspec | 10 +++++----- src/plugins/helloworld/HelloWorld.pluginspec | 4 ++-- src/plugins/help/Help.pluginspec | 8 ++++---- src/plugins/perforce/Perforce.pluginspec | 10 +++++----- .../projectexplorer/ProjectExplorer.pluginspec | 10 +++++----- .../qmlprojectmanager/QmlProjectManager.pluginspec | 12 ++++++------ .../qt4projectmanager/Qt4ProjectManager.pluginspec | 14 +++++++------- .../qtscripteditor/QtScriptEditor.pluginspec | 6 +++--- src/plugins/quickopen/QuickOpen.pluginspec | 4 ++-- src/plugins/regexp/RegExp.pluginspec | 4 ++-- .../resourceeditor/ResourceEditor.pluginspec | 4 ++-- src/plugins/snippets/Snippets.pluginspec | 8 ++++---- src/plugins/subversion/Subversion.pluginspec | 10 +++++----- src/plugins/texteditor/TextEditor.pluginspec | 8 ++++---- src/plugins/vcsbase/VCSBase.pluginspec | 8 ++++---- src/plugins/welcome/Welcome.pluginspec | 4 ++-- 34 files changed, 125 insertions(+), 125 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 74fc7674308..f9c62be93dc 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -5,7 +5,7 @@ \title Qt Creator Manual - \section1 Version 1.2.80 + \section1 Version 1.2.91 The goal of Qt Creator is to provide a cross-platform, complete Integrated Development Environment (IDE) to develop Qt projects. It is available for @@ -1786,7 +1786,7 @@ There are some known issues with Qt Creator. The development team is aware of those, there is no need to report them as bug. - \section1 Known Issues of Version 1.2.80 + \section1 Known Issues of Version 1.2.91 \list \o Gdb on Windows may not work if the 'Embassy \reg Security Center' software diff --git a/doc/qtcreator.qdocconf b/doc/qtcreator.qdocconf index 14d79d8f2c3..7663eb8c255 100644 --- a/doc/qtcreator.qdocconf +++ b/doc/qtcreator.qdocconf @@ -19,16 +19,16 @@ sources.fileextensions = "qtcreator.qdoc addressbook-sdk.qdoc" qhp.projects = QtCreator qhp.QtCreator.file = qtcreator.qhp -qhp.QtCreator.namespace = com.nokia.qtcreator.1280 +qhp.QtCreator.namespace = com.nokia.qtcreator.1291 qhp.QtCreator.virtualFolder = doc qhp.QtCreator.indexTitle = Qt Creator qhp.QtCreator.indexRoot = qhp.QtCreator.extraFiles = classic.css \ images/qt-logo.png \ images/qtcreator-screenshots.png -qhp.QtCreator.filterAttributes = qtcreator 1.2.80 -qhp.QtCreator.customFilters.QtCreator.name = Qt Creator 1.2.80 -qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator 1.2.80 +qhp.QtCreator.filterAttributes = qtcreator 1.2.91 +qhp.QtCreator.customFilters.QtCreator.name = Qt Creator 1.2.91 +qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator 1.2.91 # macros.qdocconf @@ -211,5 +211,5 @@ HTML.footer = "


\n" \ "\n" \ "\n" \ "\n" \ - "\n" \ + "\n" \ "
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Creator 1.2.80
Qt Creator 1.2.91
" diff --git a/src/app/Info.plist b/src/app/Info.plist index db37f1b65e9..6633f429d69 100644 --- a/src/app/Info.plist +++ b/src/app/Info.plist @@ -184,8 +184,8 @@ CFBundleIdentifier com.nokia.qtcreator CFBundleVersion - 1.2.80 + 1.2.91 CFBundleShortVersionString - 1.2.80 + 1.2.91 diff --git a/src/plugins/bineditor/BinEditor.pluginspec b/src/plugins/bineditor/BinEditor.pluginspec index 41ad4dcf0f3..7a78f5dcb49 100644 --- a/src/plugins/bineditor/BinEditor.pluginspec +++ b/src/plugins/bineditor/BinEditor.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,7 +19,7 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Binary editor component. http://qt.nokia.com - - + + diff --git a/src/plugins/bookmarks/Bookmarks.pluginspec b/src/plugins/bookmarks/Bookmarks.pluginspec index 68fef93b4bd..7e74335bd0b 100644 --- a/src/plugins/bookmarks/Bookmarks.pluginspec +++ b/src/plugins/bookmarks/Bookmarks.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Bookmarks in text editors. http://qt.nokia.com - - - + + + diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec index ae9cd238fbd..b2274b4cc8b 100644 --- a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec +++ b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. CMake support http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/coreplugin/Core.pluginspec b/src/plugins/coreplugin/Core.pluginspec index 5ef4f956652..88232587e1a 100644 --- a/src/plugins/coreplugin/Core.pluginspec +++ b/src/plugins/coreplugin/Core.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 4122b1afb51..e950f528965 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -35,7 +35,7 @@ namespace Constants { #define IDE_VERSION_MAJOR 1 #define IDE_VERSION_MINOR 2 -#define IDE_VERSION_RELEASE 80 +#define IDE_VERSION_RELEASE 91 #define STRINGIFY_INTERNAL(x) #x #define STRINGIFY(x) STRINGIFY_INTERNAL(x) diff --git a/src/plugins/cpaster/CodePaster.pluginspec b/src/plugins/cpaster/CodePaster.pluginspec index 564793e22ba..b5c583b2702 100644 --- a/src/plugins/cpaster/CodePaster.pluginspec +++ b/src/plugins/cpaster/CodePaster.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Codepaster plugin for pushing/fetching diff from server http://qt.nokia.com - - - + + + diff --git a/src/plugins/cppeditor/CppEditor.pluginspec b/src/plugins/cppeditor/CppEditor.pluginspec index f9817bfa1c3..8eee10b864c 100644 --- a/src/plugins/cppeditor/CppEditor.pluginspec +++ b/src/plugins/cppeditor/CppEditor.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. C/C++ editor component. http://qt.nokia.com - - - + + + diff --git a/src/plugins/cpptools/CppTools.pluginspec b/src/plugins/cpptools/CppTools.pluginspec index bce24e53817..9c97cd3dadb 100644 --- a/src/plugins/cpptools/CppTools.pluginspec +++ b/src/plugins/cpptools/CppTools.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Tools for analyzing C/C++ code. http://qt.nokia.com - - - + + + diff --git a/src/plugins/cvs/CVS.pluginspec b/src/plugins/cvs/CVS.pluginspec index 94e7421af52..1af1e886c44 100644 --- a/src/plugins/cvs/CVS.pluginspec +++ b/src/plugins/cvs/CVS.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. CVS integration. http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/debugger/Debugger.pluginspec b/src/plugins/debugger/Debugger.pluginspec index 23f3babcccb..a410898c925 100644 --- a/src/plugins/debugger/Debugger.pluginspec +++ b/src/plugins/debugger/Debugger.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,10 +19,10 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Debugger integration. http://qt.nokia.com - - - - + + + + Disable Cdb debugger engine diff --git a/src/plugins/designer/Designer.pluginspec b/src/plugins/designer/Designer.pluginspec index 528745a54b6..02cb944268c 100644 --- a/src/plugins/designer/Designer.pluginspec +++ b/src/plugins/designer/Designer.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Qt Designer integration. http://qt.nokia.com - + - + diff --git a/src/plugins/duieditor/DuiEditor.pluginspec b/src/plugins/duieditor/DuiEditor.pluginspec index 9400bb5bc94..8272e77dc15 100644 --- a/src/plugins/duieditor/DuiEditor.pluginspec +++ b/src/plugins/duieditor/DuiEditor.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,7 +19,7 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Editor for DUI. http://qt.nokia.com - - + + diff --git a/src/plugins/fakevim/FakeVim.pluginspec b/src/plugins/fakevim/FakeVim.pluginspec index 2f343a333d5..b494ce3435e 100644 --- a/src/plugins/fakevim/FakeVim.pluginspec +++ b/src/plugins/fakevim/FakeVim.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. VI-style keyboard navigation. http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/find/Find.pluginspec b/src/plugins/find/Find.pluginspec index e18d54902b8..9fa0b7e7ef7 100644 --- a/src/plugins/find/Find.pluginspec +++ b/src/plugins/find/Find.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,6 +19,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Provides the find widget and the hooks for find implementations. http://qt.nokia.com - + diff --git a/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec b/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec index 8f3c16125bb..2176c47e1a9 100644 --- a/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec +++ b/src/plugins/genericprojectmanager/GenericProjectManager.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Generic support http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/git/ScmGit.pluginspec b/src/plugins/git/ScmGit.pluginspec index 934ffd5e8c9..0bcbdcc24c4 100644 --- a/src/plugins/git/ScmGit.pluginspec +++ b/src/plugins/git/ScmGit.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Git integration. http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/helloworld/HelloWorld.pluginspec b/src/plugins/helloworld/HelloWorld.pluginspec index 4aaf5b9eab7..4ed6d96636b 100644 --- a/src/plugins/helloworld/HelloWorld.pluginspec +++ b/src/plugins/helloworld/HelloWorld.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,6 +19,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Hello World sample plugin. http://qt.nokia.com - + diff --git a/src/plugins/help/Help.pluginspec b/src/plugins/help/Help.pluginspec index 3c60befe91f..0009411597e 100644 --- a/src/plugins/help/Help.pluginspec +++ b/src/plugins/help/Help.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Help system. http://qt.nokia.com - - - + + + diff --git a/src/plugins/perforce/Perforce.pluginspec b/src/plugins/perforce/Perforce.pluginspec index 78c3b8edd08..cc77648b9d2 100644 --- a/src/plugins/perforce/Perforce.pluginspec +++ b/src/plugins/perforce/Perforce.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Perforce integration. http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/projectexplorer/ProjectExplorer.pluginspec b/src/plugins/projectexplorer/ProjectExplorer.pluginspec index b064c36d248..70d49c83511 100644 --- a/src/plugins/projectexplorer/ProjectExplorer.pluginspec +++ b/src/plugins/projectexplorer/ProjectExplorer.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ProjectExplorer framework that can be extended with different kind of project types. http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec b/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec index 60261b13b8f..fde164aa8d6 100644 --- a/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec +++ b/src/plugins/qmlprojectmanager/QmlProjectManager.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,10 +19,10 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Qml support http://qt.nokia.com - - - - - + + + + + diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec index 78d80c3b4f8..e9a39950cb5 100644 --- a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec +++ b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,11 +19,11 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Provides project type for Qt 4 pro files and tools. http://qt.nokia.com - - - - - - + + + + + + diff --git a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec index 6eaf3fe9f8e..2c8b772f06f 100644 --- a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec +++ b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,7 +19,7 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Editor for QtScript. http://qt.nokia.com - - + + diff --git a/src/plugins/quickopen/QuickOpen.pluginspec b/src/plugins/quickopen/QuickOpen.pluginspec index 86299f76224..db95f0097cc 100644 --- a/src/plugins/quickopen/QuickOpen.pluginspec +++ b/src/plugins/quickopen/QuickOpen.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,6 +19,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Provides the Locator widget and the hooks for QuickOpen filter implementations. http://qt.nokia.com - + diff --git a/src/plugins/regexp/RegExp.pluginspec b/src/plugins/regexp/RegExp.pluginspec index 0318e93ef8b..08081797edd 100644 --- a/src/plugins/regexp/RegExp.pluginspec +++ b/src/plugins/regexp/RegExp.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,6 +19,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Regular Expression test widget. http://qt.nokia.com - + diff --git a/src/plugins/resourceeditor/ResourceEditor.pluginspec b/src/plugins/resourceeditor/ResourceEditor.pluginspec index a3e0a0dd220..697f61c6741 100644 --- a/src/plugins/resourceeditor/ResourceEditor.pluginspec +++ b/src/plugins/resourceeditor/ResourceEditor.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,6 +19,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Editor for qrc files. http://qt.nokia.com - + diff --git a/src/plugins/snippets/Snippets.pluginspec b/src/plugins/snippets/Snippets.pluginspec index 0d3307183fe..fd4881ac94b 100644 --- a/src/plugins/snippets/Snippets.pluginspec +++ b/src/plugins/snippets/Snippets.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Code snippet plugin. http://qt.nokia.com - - - + + + diff --git a/src/plugins/subversion/Subversion.pluginspec b/src/plugins/subversion/Subversion.pluginspec index 8e7de969ad7..f8bd40f1b92 100644 --- a/src/plugins/subversion/Subversion.pluginspec +++ b/src/plugins/subversion/Subversion.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,9 +19,9 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Subversion integration. http://qt.nokia.com - - - - + + + + diff --git a/src/plugins/texteditor/TextEditor.pluginspec b/src/plugins/texteditor/TextEditor.pluginspec index b64b2b7ce20..691dd6edfa1 100644 --- a/src/plugins/texteditor/TextEditor.pluginspec +++ b/src/plugins/texteditor/TextEditor.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Text editor framework and the implementation of the basic text editor. http://qt.nokia.com - - - + + + diff --git a/src/plugins/vcsbase/VCSBase.pluginspec b/src/plugins/vcsbase/VCSBase.pluginspec index 383cd1d4be9..670df6002b9 100644 --- a/src/plugins/vcsbase/VCSBase.pluginspec +++ b/src/plugins/vcsbase/VCSBase.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,8 +19,8 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Version Control System Base Plugin http://qt.nokia.com - - - + + + diff --git a/src/plugins/welcome/Welcome.pluginspec b/src/plugins/welcome/Welcome.pluginspec index 32b0bffee50..396d0d57324 100644 --- a/src/plugins/welcome/Welcome.pluginspec +++ b/src/plugins/welcome/Welcome.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008-2009 Nokia Corporation @@ -19,6 +19,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. Default Welcome Screen Plugin http://qt.nokia.com - + From 7b596180bb675a654529536f6f2d7fbdcfa55c56 Mon Sep 17 00:00:00 2001 From: con Date: Thu, 10 Sep 2009 17:58:00 +0200 Subject: [PATCH 32/43] Missing return statement. --- src/plugins/qt4projectmanager/qtversionmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index a9b642e1312..8b8e956b037 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -1244,7 +1244,7 @@ QStringList QtVersion::debuggingHelperLibraryLocations() const { QString qtInstallData = versionInfo().value("QT_INSTALL_DATA"); if (qtInstallData.isEmpty()) - QString::null; + return QString::null; return DebuggingHelperLibrary::debuggingHelperLibraryLocations(qtInstallData); } From 65284dc0edad8fc3687873cce5e920d11555cec7 Mon Sep 17 00:00:00 2001 From: con Date: Thu, 10 Sep 2009 18:07:51 +0200 Subject: [PATCH 33/43] Oops. Compile again. --- src/plugins/qt4projectmanager/qtversionmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 8b8e956b037..55068132db0 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -1244,7 +1244,7 @@ QStringList QtVersion::debuggingHelperLibraryLocations() const { QString qtInstallData = versionInfo().value("QT_INSTALL_DATA"); if (qtInstallData.isEmpty()) - return QString::null; + return QStringList(); return DebuggingHelperLibrary::debuggingHelperLibraryLocations(qtInstallData); } From 10c2b040695cc638b52a0dd3267d8bf6bf583f35 Mon Sep 17 00:00:00 2001 From: Alp Mestan Date: Thu, 10 Sep 2009 18:17:46 +0200 Subject: [PATCH 34/43] Many additional translations Merge-request: 1461 Reviewed-by: Pierre Rossi --- share/qtcreator/translations/qtcreator_fr.ts | 279 +++++++++---------- 1 file changed, 139 insertions(+), 140 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_fr.ts b/share/qtcreator/translations/qtcreator_fr.ts index e9c3aa13957..da536e5d7a0 100644 --- a/share/qtcreator/translations/qtcreator_fr.ts +++ b/share/qtcreator/translations/qtcreator_fr.ts @@ -10681,17 +10681,17 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Save Changes - + Sauvegarder les changements The following files have unsaved changes: - + Les fichiers suivants contiennent des modifications non enregistrées: Automatically save all files before building - + Sauvegarder automatiquement tous les fichiers avant de compiler @@ -10699,12 +10699,12 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Options - + Options 0 - + 0 @@ -10712,62 +10712,63 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Add Files - + Ajouter des fichiers Add Prefix - + Ajouter un préfixe Invalid file - + Fichier invalide Copy - + Copier Skip - + ignorer ? + Passer Abort - + Abandonner The file %1 is not in a subdirectory of the resource file. Continuing will result in an invalid resource file. - + Le fichier %1 n'est pas dans un sous-dossier du fichier de ressource. Continuer résulterait en un fichier de ressource invalide. Choose copy location - + Choisir le chemin de la copie Overwrite failed - + L'écrasement a échoué Could not overwrite file %1. - + L'écrasement du fichier %1 a échoué. Copying failed - + Échec de la copie Could not copy the file to %1. - + La copie du fichier dans "%1" a échoué. @@ -10775,72 +10776,72 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Add Files... - + Ajouter des fichiers... Change Alias... - + Changer l'alias... Add Prefix... - + Ajouter un prefixe... Change Prefix... - + Changer le préfixe... Change Language... - + Changer la langue... Remove Item - + Supprimer l'élément Open file - + Ouvrir le fichier All files (*) - + Tous les fichiers (*) Change Prefix - + Changer le préfixe Input Prefix: - + Entrée du préfixe: Change Language - + Changer la langue Language: - + Langue: Change File Alias - + Changer l'alias du fichier Alias: - + Alias: @@ -10848,62 +10849,62 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Keyboard Shortcuts - + Rarccourcis clavier Filter: - + Filtre: Command - + Commande Label - + Libellé Shortcut - + Raccourci Defaults - + Restaurer Import... - + Importer... Export... - + Exporter... Key Sequence - + Combinaison de touches Shortcut: - + Raccourci: Reset - + Remise à zéro Remove - + Effacer @@ -10911,7 +10912,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Debugging Helper Build Log - + Journal de compilation de l'assistant de deboggage @@ -10919,7 +10920,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Snippets - + Extraits de code @@ -10927,7 +10928,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Snippets - + Extraits de code @@ -10935,22 +10936,22 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Start Debugger - + Lancer le débogueur Executable: - + Nom de l'exécutable: Arguments: - + Arguments: Break at 'main': - + S'arrêter sur 'main': @@ -10958,27 +10959,27 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Start Debugger - + Lancer le débogueur Host and port: - + Hôte et port: Architecture: - + Architecture: Use server start script: - + Utiliser le script de démarrage du serveur : Server start script: - + Script de démarrage du serveur : @@ -10986,32 +10987,32 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Prompt to submit - + Demander à chaque soumission Subversion Command: - + Commande Subversion: Authentication - + Identification User name: - + Nom d'utilisateur: Password: - + Mot de passe: Subversion - + Subversion @@ -11019,7 +11020,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Subversion Command - + Commande Subversion @@ -11027,12 +11028,12 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Subversion Output - + Sortie de Subversion Subversion - + Subversion @@ -11040,7 +11041,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t &Subversion - + &Subversion @@ -11055,7 +11056,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Alt+S,Alt+A - + Alt+S,Alt+A @@ -11070,72 +11071,72 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Revert - + Rétablir Revert "%1" - + Rétablir "%1" Diff Project - + Faire un diff sur le projet Diff Current File - + Faire un diff du fichier courant Diff "%1" - + Faire un diff de "%1" Alt+S,Alt+D - + Alt+S,Alt+D Commit All Files - + Faire un commit de tous les fichiers Commit Current File - + Faire un commit du fichier courant Commit "%1" - + Faire un commit de "%1" Alt+S,Alt+C - + Alt+S,Alt+C Filelog Current File - + Journal du fichier courant Filelog "%1" - + Journal du fichier "%1" Annotate Current File - + Annoter le fichier courant Annotate "%1" - + Annoter "%1" @@ -11155,12 +11156,12 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Commit - + Faire un commit Diff Selected Files - + Faire un diff sur tous les fichiers sélectionnés @@ -11175,7 +11176,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Closing Subversion Editor - Fermer l'éditeur Subversion + Fermeture de l'éditeur Subversion @@ -11185,12 +11186,12 @@ To do this, you type this shortcut and a space in the Locator entry field, and t The commit message check failed. Do you want to commit the change? - + La vérification du message de commit a échoué. Voulez-vous soumettre vos modifications ? The file has been changed. Do you want to revert it? - + Le fichier a été modifié. Voulez-vous le rétablir ? @@ -11232,8 +11233,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t %1 Executing: %2 %3 <timestamp> Executing: <executable> <arguments> - %1 Exécute : %2 %3 - + %1 Exécution de : %2 %3 @@ -11261,7 +11261,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Subversion Submit - Submit Subversion + Soumission sur Subversion @@ -11270,7 +11270,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t %1 found - %1 éléments trouvés + %1 élément(s) trouvé(s) @@ -11385,7 +11385,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t In leading white space - Espaces de début de ligne + Espaces en début de ligne @@ -11443,7 +11443,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Display &folding markers - + Affiche les marqueurs de &pliage @@ -11521,8 +11521,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t The following encodings are likely to fit: - -Les encodages suivants pourraient fonctionner : + Les encodages suivants pourraient convenir : @@ -11689,7 +11688,7 @@ Les encodages suivants pourraient fonctionner : Triggers a quick fix in this scope - + Lancer une réparation rapide dans ce contexte @@ -11707,7 +11706,7 @@ Les encodages suivants pourraient fonctionner : &Redo - + &Refaire @@ -11747,97 +11746,97 @@ Les encodages suivants pourraient fonctionner : Ctrl+E, Ctrl+W - + Ctrl+E, Ctrl+W (Un)Comment &Selection - + (Dé)Commenter la &Sélection Ctrl+/ - + Ctrl+/ Cut &Line - + Couper la &Ligne Shift+Del - + Shift+Suppr Delete &Line - + Effacer la &Ligne Collapse - + Plier Ctrl+< - + Ctrl+< Expand - + Étendre Ctrl+> - + Ctrl+> (Un)&Collapse All - + (Dé)&Plier tout Increase Font Size - + Augmenter la taille de la police Ctrl++ - + Ctrl++ Decrease Font Size - + Diminuer la taille de la police Ctrl+- - + Ctrl+- Goto Block Start - + Aller au début du bloc Ctrl+[ - + Ctrl+[ Goto Block End - + Aller à la fin du bloc Ctrl+] - + Ctrl+] @@ -11847,7 +11846,7 @@ Les encodages suivants pourraient fonctionner : Ctrl+{ - + Ctrl+{ @@ -11857,7 +11856,7 @@ Les encodages suivants pourraient fonctionner : Ctrl+} - + Ctrl+} @@ -11867,7 +11866,7 @@ Les encodages suivants pourraient fonctionner : Ctrl+U - + Ctrl+U @@ -11877,52 +11876,52 @@ Les encodages suivants pourraient fonctionner : Ctrl+Shift+U - + Ctrl+Shift+U Move Line Up - + Déplacer la ligne au-dessus Ctrl+Shift+Up - + Ctrl+Shift+Up Move Line Down - + Déplacer la ligne en-dessous Ctrl+Shift+Down - + Ctrl+Shift+Down Copy Line Up - + Copier la ligne au-dessus Ctrl+Alt+Up - + Ctrl+Alt+Up Copy Line Down - + Copier la ligne en-dessous Ctrl+Alt+Down - + Ctrl+Alt+Down <line number> - + <numéro de ligne> @@ -11956,7 +11955,7 @@ Les encodages suivants pourraient fonctionner : Search Scope contexte/portée/autre ? - Contexte de la recherche + Portée de la recherche @@ -12186,17 +12185,17 @@ Les encodages suivants pourraient fonctionner : Insert name... - Inserez nom... + Inserez le nom... Prompt to submit - + Afficher avant de soumettre Submit Message Check failed - + La vérification du message de soumission a échoué @@ -12276,7 +12275,7 @@ nom <email> alias </email> Would you like to remove this file from the version control system (%1)? Note: This might remove the local file. Voulez-vous retirer ce fichier du système de gestion de versions (%1)? -Note : Ceci risque de supprimer le fichier sur le disque. +Note : Ceci risque de supprimer le fichier du disque. @@ -12296,7 +12295,7 @@ Note : Ceci risque de supprimer le fichier sur le disque. <Description> - <Description> + <Description> @@ -12351,12 +12350,12 @@ p, li { white-space: pre-wrap; } Patch 1 - + Patch 1 Patch 2 - + Patch 2 @@ -12364,27 +12363,27 @@ p, li { white-space: pre-wrap; } main - + main Text1: - + Texte 1: N/A - + Indisponible Text2: - + Texte 2: Text3: - + Texte 3: From ead47eafa8353583bec6cb8d708a6661d88b6ad6 Mon Sep 17 00:00:00 2001 From: Alp Mestan Date: Thu, 10 Sep 2009 18:17:46 +0200 Subject: [PATCH 35/43] Translations from QuickOpen::* until the end done, many needing review though Merge-request: 1461 Reviewed-by: Pierre Rossi --- share/qtcreator/translations/qtcreator_fr.ts | 146 +++++++++---------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_fr.ts b/share/qtcreator/translations/qtcreator_fr.ts index da536e5d7a0..4df4895a89c 100644 --- a/share/qtcreator/translations/qtcreator_fr.ts +++ b/share/qtcreator/translations/qtcreator_fr.ts @@ -10266,17 +10266,17 @@ p, li { white-space: pre-wrap; } Filter Configuration - + Configuration du filtre Limit to prefix - + Limiter au préfixe Prefix: - + Préfixe: @@ -10284,36 +10284,36 @@ p, li { white-space: pre-wrap; } Generic Directory Filter - + Filtre de dossier générique Filter Configuration - + Configuration du filtre Choose a directory to add - + Choisir un répertoire à ajouter %1 filter update: 0 files - + Mise à jour du filtre %1: 0 fichiers %1 filter update: %n files - - + Mise à jour du filtre %1: %n fichier + Mise à jour du filtre %1: %n fichiers %1 filter update: canceled - + Mise à jour du filtre %1: annulée @@ -10321,12 +10321,12 @@ p, li { white-space: pre-wrap; } Name: - + Nom: File Types: - + Types de fichiers: @@ -10336,38 +10336,38 @@ p, li { white-space: pre-wrap; } Prefix: - + Préfixe: Specify a short word/abbreviation that can be used to restrict completions to files from this directory tree. To do this, you type this shortcut and a space in the Locator entry field, and then the word to search for. - + Spécifier a mot court ou une abbréviation qui peut être utilisé pour réstreindre la complétion aux fichiers de cette arborescence. Pour ce faire, entrez ce raccourci et un espace dans le champs Localisation, puis ensuite le mot à chercher. Limit to prefix - + Limiter au préfixe Add... - + Ajouter... Edit... - + Modifier... Remove - + Supprimer Directories: - + Dossiers: @@ -10375,7 +10375,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Files in file system - + Fichiers du système de fichier @@ -10383,27 +10383,27 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Filter configuration - + Configuration du filtre Prefix: - + Préfixe: Limit to prefix - + Limiter au préfixe Include hidden files - + Inclure les fichiers cachés Filter: - + Filtre: @@ -10411,7 +10411,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Open documents - + Ouvrir des documents @@ -10419,7 +10419,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Available filters - + Filtres disponibles @@ -10427,7 +10427,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Indexing - + Indexation @@ -10435,27 +10435,27 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Refresh - + Raffraîchir Configure... - + Configurer... Locate... - + Localiser... Type to locate - + Taper pour localiser <type here> - + <taper ici> @@ -10463,37 +10463,37 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Configure Filters - + Configurer les filtres Add - + Ajouter Remove - + Supprimer Edit... - + Modifier... Refresh Interval: - + Intervalle de raffraichissement: min - + min Refresh now! - + Raffraîchir maintenant! @@ -10501,7 +10501,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t %1 (Prefix: %2) - + %1 (Prefixe: %2) @@ -10509,32 +10509,32 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Configure Filters - + Configurer les filtres Add - + Ajouter Remove - + Supprimer Edit - + Modifier Refresh Interval: - + Intervalle de raffraichissement: min - + min @@ -10542,102 +10542,102 @@ To do this, you type this shortcut and a space in the Locator entry field, and t &Pattern: - + &Motif: &Escaped Pattern: - + Motif &échappé: &Pattern Syntax: - + Syntaxe du &motif: &Text: - + &Texte: Case &Sensitive - + &Sensible à la casse &Minimal - + &Minimale Index of Match: - + Index de la correspondance: Matched Length: - + Longueur de la correspondance: Regular expression v1 - + Expression régulière v1 Regular expression v2 - + Expression régulière v2 Wildcard - + Joker Fixed string - + Chaîne de caractères fixe Capture %1: - + Capture %1: Match: - + Correspondance: Regular Expression - + Expression régulière Enter pattern from code... - + Entrer un motif depuis le code... Clear patterns - + Effacer les motifs Clear texts - + Effacer les textes Enter pattern from code - + Entrer le motif depuis le code Pattern - + Motif @@ -10645,27 +10645,27 @@ To do this, you type this shortcut and a space in the Locator entry field, and t Creates a Qt Resource file (.qrc). - + Crée une fichier ressource Qt (.qrc). Qt Resource file - + Fichier de ressource Qt Qt - + Qt &Undo - + &Annuler &Redo - + &Refaire @@ -10673,7 +10673,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t untitled - + sans titre From 7f2568554d4075354fa3181726087167e5209c53 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 11 Sep 2009 09:18:26 +0200 Subject: [PATCH 36/43] "C:/foo/" is not a folder. Even on Linux :) Reviewed-by: TrustMe --- src/plugins/qt4projectmanager/qtoptionspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qtoptionspage.cpp b/src/plugins/qt4projectmanager/qtoptionspage.cpp index dea944b087b..3ffc91ad55e 100644 --- a/src/plugins/qt4projectmanager/qtoptionspage.cpp +++ b/src/plugins/qt4projectmanager/qtoptionspage.cpp @@ -325,7 +325,7 @@ static inline QString msgHtmlHelperToolTip(const QFileInfo &fi) return QtOptionsPageWidget::tr("" "" "
File:
%1
Last modified:%2
Size:%3 Bytes
"). - arg(fi.absoluteFilePath()). + arg(QDir::toNativeSeparators(fi.absoluteFilePath())). arg(fi.lastModified().toString(Qt::SystemLocaleLongDate)). arg(fi.size()); } From c9da1d954339b873cece24b2cbf5691ea492bd32 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 11 Sep 2009 08:55:16 +0200 Subject: [PATCH 37/43] debugger: code cosmetics --- src/plugins/debugger/debuggerrunner.cpp | 75 +++++++++++++------------ src/plugins/debugger/debuggerrunner.h | 31 +++++----- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 75b76845e8b..1739653b3d4 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -43,7 +43,8 @@ #include -using namespace Debugger::Internal; +namespace Debugger { +namespace Internal { using ProjectExplorer::RunConfiguration; using ProjectExplorer::RunControl; @@ -120,10 +121,10 @@ QWidget *DebuggerRunner::configurationWidget(RunConfigurationPtr runConfiguratio DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, - DebuggerStartMode mode, - const QSharedPointer &startParameters, - QSharedPointer runConfiguration) : - RunControl(runConfiguration), + DebuggerStartMode mode, + const QSharedPointer &startParameters, + QSharedPointer runConfiguration) + : RunControl(runConfiguration), m_mode(mode), m_startParameters(startParameters), m_manager(manager), @@ -140,32 +141,36 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, Qt::QueuedConnection); connect(this, SIGNAL(stopRequested()), m_manager, SLOT(exitDebugger())); - if (runConfiguration) { - // Enhance parameters by info from the project, but do not clobber - // arguments given in the dialogs - if (m_startParameters->executable.isEmpty()) - m_startParameters->executable = runConfiguration->executable(); - if (m_startParameters->environment.empty()) - m_startParameters->environment = runConfiguration->environment().toStringList(); - if (m_startParameters->workingDir.isEmpty()) - m_startParameters->workingDir = runConfiguration->workingDirectory(); - if (m_mode != StartExternal) - m_startParameters->processArgs = runConfiguration->commandLineArguments(); - switch (m_startParameters->toolChainType) { - case ProjectExplorer::ToolChain::UNKNOWN: - case ProjectExplorer::ToolChain::INVALID: - m_startParameters->toolChainType = runConfiguration->toolChainType(); - break; - default: - break; - } - if (const ProjectExplorer::Project *project = runConfiguration->project()) { - m_startParameters->buildDir = project->buildDirectory(project->activeBuildConfiguration()); - } - m_startParameters->useTerminal = runConfiguration->runMode() == ApplicationRunConfiguration::Console; - m_dumperLibrary = runConfiguration->dumperLibrary(); - m_dumperLibraryLocations = runConfiguration->dumperLibraryLocations(); + + if (!runConfiguration) + return; + + // Enhance parameters by info from the project, but do not clobber + // arguments given in the dialogs + if (m_startParameters->executable.isEmpty()) + m_startParameters->executable = runConfiguration->executable(); + if (m_startParameters->environment.empty()) + m_startParameters->environment = runConfiguration->environment().toStringList(); + if (m_startParameters->workingDir.isEmpty()) + m_startParameters->workingDir = runConfiguration->workingDirectory(); + if (m_mode != StartExternal) + m_startParameters->processArgs = runConfiguration->commandLineArguments(); + switch (m_startParameters->toolChainType) { + case ProjectExplorer::ToolChain::UNKNOWN: + case ProjectExplorer::ToolChain::INVALID: + m_startParameters->toolChainType = runConfiguration->toolChainType(); + break; + default: + break; } + if (const ProjectExplorer::Project *project = runConfiguration->project()) { + m_startParameters->buildDir = + project->buildDirectory(project->activeBuildConfiguration()); + } + m_startParameters->useTerminal = + runConfiguration->runMode() == ApplicationRunConfiguration::Console; + m_dumperLibrary = runConfiguration->dumperLibrary(); + m_dumperLibraryLocations = runConfiguration->dumperLibraryLocations(); } void DebuggerRunControl::start() @@ -173,11 +178,8 @@ void DebuggerRunControl::start() m_running = true; m_manager->setQtDumperLibraryName(m_dumperLibrary); m_manager->setQtDumperLibraryLocations(m_dumperLibraryLocations); - - //emit addToOutputWindow(this, tr("Debugging %1").arg(m_executable)); m_manager->startNewDebugger(this, m_startParameters); emit started(); - //debuggingFinished(); } void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data) @@ -187,7 +189,6 @@ void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data) void DebuggerRunControl::stop() { - //qDebug() << "DebuggerRunControl::stop"; m_running = false; emit stopRequested(); } @@ -195,13 +196,13 @@ void DebuggerRunControl::stop() void DebuggerRunControl::debuggingFinished() { m_running = false; - //qDebug() << "DebuggerRunControl::finished"; - //emit addToOutputWindow(this, tr("Debugging %1 finished").arg(m_executable)); emit finished(); } bool DebuggerRunControl::isRunning() const { - //qDebug() << "DebuggerRunControl::isRunning" << m_running; return m_running; } + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 06a986ce9d3..81f84588899 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -51,7 +51,8 @@ typedef QSharedPointer typedef QSharedPointer ApplicationRunConfigurationPtr; -class DebuggerRunner : public ProjectExplorer::IRunConfigurationRunner +class DebuggerRunner + : public ProjectExplorer::IRunConfigurationRunner { Q_OBJECT @@ -59,7 +60,7 @@ public: explicit DebuggerRunner(DebuggerManager *manager); // ProjectExplorer::IRunConfigurationRunner - virtual bool canRun(RunConfigurationPtr runConfiguration, const QString &mode); + bool canRun(RunConfigurationPtr runConfiguration, const QString &mode); virtual ProjectExplorer::RunControl *run(RunConfigurationPtr runConfiguration, const QString &mode); virtual QString displayName() const; @@ -79,15 +80,16 @@ private: }; // This is a job description -class DebuggerRunControl : public ProjectExplorer::RunControl +class DebuggerRunControl + : public ProjectExplorer::RunControl { Q_OBJECT public: - explicit DebuggerRunControl(DebuggerManager *manager, - DebuggerStartMode mode, - const QSharedPointer &sp, - ApplicationRunConfigurationPtr runConfiguration); + DebuggerRunControl(DebuggerManager *manager, + DebuggerStartMode mode, + const QSharedPointer &sp, + ApplicationRunConfigurationPtr runConfiguration); DebuggerStartMode startMode() const { return m_mode; } @@ -115,23 +117,24 @@ private: // A default run configuration for external executables or attaching to // running processes by id. -class DefaultApplicationRunConfiguration : public ProjectExplorer::ApplicationRunConfiguration +class DefaultApplicationRunConfiguration + : public ProjectExplorer::ApplicationRunConfiguration { Q_OBJECT public: explicit DefaultApplicationRunConfiguration(const QString &executable = QString()); - virtual QString executable() const { return m_executable; } - virtual RunMode runMode() const { return Gui; } - virtual QString workingDirectory() const { return QString(); } - virtual QStringList commandLineArguments() const { return QStringList(); } + virtual QString executable() const { return m_executable; } + virtual RunMode runMode() const { return Gui; } + virtual QString workingDirectory() const { return QString(); } + virtual QStringList commandLineArguments() const { return QStringList(); } virtual ProjectExplorer::Environment environment() const { return ProjectExplorer::Environment(); } - virtual QString dumperLibrary() const { return QString(); } + virtual QString dumperLibrary() const { return QString(); } virtual QStringList dumperLibraryLocations() const { return QStringList(); } virtual ProjectExplorer::ToolChain::ToolChainType toolChainType() const { return ProjectExplorer::ToolChain::UNKNOWN; } - virtual QWidget *configurationWidget() { return 0; } + virtual QWidget *configurationWidget() { return 0; } private: const QString m_executable; From 6a9886576f1f87f41845d2f225ed2f08a49b9438 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 11 Sep 2009 09:51:05 +0200 Subject: [PATCH 38/43] debugger: small refactoring in the gdbengine startup --- src/plugins/debugger/debuggerrunner.cpp | 1 - src/plugins/debugger/gdb/gdbengine.cpp | 45 ++++++++++++------------- src/plugins/debugger/gdb/gdbengine.h | 1 + 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 1739653b3d4..59e9d0e451b 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -179,7 +179,6 @@ void DebuggerRunControl::start() m_manager->setQtDumperLibraryName(m_dumperLibrary); m_manager->setQtDumperLibraryLocations(m_dumperLibraryLocations); m_manager->startNewDebugger(this, m_startParameters); - emit started(); } void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 466c6f62766..84380f20548 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -269,6 +269,7 @@ void GdbEngine::gdbProcError(QProcess::ProcessError error) "invoked program '%1' is missing, or you may have insufficient " "permissions to invoke the program.") .arg(theDebuggerStringSetting(GdbLocation)); + emitStartFailed(); break; case QProcess::Crashed: kill = false; @@ -746,10 +747,8 @@ void GdbEngine::flushCommand(GdbCommand &cmd) if (cmd.flags & EmbedToken) cmd.command = cmd.command.arg(currentToken()); - m_gdbProc->write(cmd.command.toLatin1() + "\r\n"); - //emit gdbInputAvailable(QString(), " " + currentTime()); - //emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); emit gdbInputAvailable(LogInput, cmd.command); + executeDebuggerCommand(cmd.command); } void GdbEngine::handleResultRecord(const GdbResultRecord &record) @@ -833,12 +832,12 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record) void GdbEngine::executeDebuggerCommand(const QString &command) { - if (m_gdbProc->state() == QProcess::NotRunning) { - debugMessage(_("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: ") + command); + if (m_gdbProc->state() != QProcess::Running) { + debugMessage(_("GDB PROCESS NOT RUNNING, PLAIN CMD IGNORED: ") + command); return; } - m_gdbProc->write(command.toLocal8Bit() + "\r\n"); + m_gdbProc->write(command.toLatin1() + "\r\n"); } void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &) @@ -1496,7 +1495,7 @@ void GdbEngine::startDebugger(const QSharedPointer &sp) if (m_gdbProc->state() != QProcess::NotRunning) { debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc->state())); m_gdbProc->kill(); - emit startFailed(); + emitStartFailed(); return; } @@ -1527,7 +1526,7 @@ void GdbEngine::startDebugger(const QSharedPointer &sp) if (!m_stubProc.start(m_startParameters.executable, m_startParameters.processArgs)) { // Error message for user is delivered via a signal. - emit startFailed(); + emitStartFailed(); return; } } else { @@ -1535,7 +1534,7 @@ void GdbEngine::startDebugger(const QSharedPointer &sp) QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), tr("Cannot set up communication with child process: %1") .arg(m_outputCollector.errorString())); - emit startFailed(); + emitStartFailed(); return; } gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName()); @@ -1561,23 +1560,20 @@ void GdbEngine::startDebugger(const QSharedPointer &sp) m_gdbProc->start(loc, gdbArgs); } +void GdbEngine::emitStartFailed() +{ + // QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), + // tr("Cannot start debugger: %1").arg(m_gdbProc->errorString())); + m_outputCollector.shutdown(); + m_stubProc.blockSignals(true); + m_stubProc.stop(); + m_stubProc.blockSignals(false); + emit startFailed(); +} + void GdbEngine::startDebugger2() { - qDebug() << "STARTUP, PHASE 2"; debugMessage(_("STARTUP, PHASE 2")); -#if 0 - if (!m_gdbProc->waitForStarted()) { - QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), - tr("Cannot start debugger: %1").arg(m_gdbProc->errorString())); - m_outputCollector.shutdown(); - m_stubProc.blockSignals(true); - m_stubProc.stop(); - m_stubProc.blockSignals(false); - emit startFailed(); - return; - } -#endif - q->showStatusMessage(tr("Gdb Running...")); postCommand(_("show version"), CB(handleShowVersion)); @@ -2027,7 +2023,8 @@ void GdbEngine::sendInsertBreakpoint(int index) } // The argument is simply a C-quoted version of the argument to the // non-MI "break" command, including the "original" quoting it wants. - where = _("\"\\\"") + GdbMi::escapeCString(where) + _("\\\":") + data->lineNumber + _c('"'); + where = _("\"\\\"%1\\\":%2\"") + .arg(GdbMi::escapeCString(where)).arg(data->lineNumber); } else { where = data->funcName; } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 1dbc285a6ee..e202ec987a5 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -250,6 +250,7 @@ private slots: void stubStarted(); void stubError(const QString &msg); void uploadProcError(QProcess::ProcessError error); + void emitStartFailed(); private: int terminationIndex(const QByteArray &buffer, int &length); From 06900dc4750b5b4669b104c05f42052fa23b0a9d Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 11 Sep 2009 10:56:45 +0200 Subject: [PATCH 39/43] debugger: refactoring in the trk adapter --- .../debugger/symbian/symbianadapter.cpp | 181 ++++++------------ src/plugins/debugger/symbian/symbianadapter.h | 23 +-- tests/manual/trk/runner.cpp | 25 ++- 3 files changed, 96 insertions(+), 133 deletions(-) diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index 97b0bd68851..667bc6bf574 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -79,19 +79,31 @@ SymbianAdapter::SymbianAdapter() uid_t userId = getuid(); m_gdbServerName = QString("127.0.0.1:%1").arg(2222 + userId); - m_gdbProc.setObjectName("GDB PROCESS"); - connectProcess(&m_gdbProc); connect(&m_gdbProc, SIGNAL(readyReadStandardError()), this, SIGNAL(readyReadStandardError())); connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), this, SIGNAL(readyReadStandardOutput())); + connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(handleGdbError(QProcess::ProcessError))); + connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(handleGdbFinished(int, QProcess::ExitStatus))); + connect(&m_gdbProc, SIGNAL(started()), + this, SLOT(handleGdbStarted())); + connect(&m_gdbProc, SIGNAL(stateChanged(QProcess::ProcessState)), + this, SLOT(handleGdbStateChanged(QProcess::ProcessState))); - m_rfcommProc.setObjectName("RFCOMM PROCESS"); - connectProcess(&m_rfcommProc); connect(&m_rfcommProc, SIGNAL(readyReadStandardError()), this, SLOT(handleRfcommReadyReadStandardError())); connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()), this, SLOT(handleRfcommReadyReadStandardOutput())); + connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(handleRfcommError(QProcess::ProcessError))); + connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(handleRfcommFinished(int, QProcess::ExitStatus))); + connect(&m_gdbProc, SIGNAL(started()), + this, SLOT(handleRfcommStarted())); + connect(&m_gdbProc, SIGNAL(stateChanged(QProcess::ProcessState)), + this, SLOT(handleRfcommStateChanged(QProcess::ProcessState))); if (m_verbose > 1) m_trkDevice.setVerbose(true); @@ -946,17 +958,6 @@ void SymbianAdapter::handleCpuType(const TrkResult &result) logMessage(logMsg); } -void SymbianAdapter::handleSetTrkBreakpoint(const TrkResult &result) -{ - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x00 - // [80 09 00 00 00 00 0A] - const uint bpnr = extractInt(result.data.data()); - logMessage("SET BREAKPOINT " + hexxNumber(bpnr) - + stringFromArray(result.data.data())); -} - void SymbianAdapter::handleCreateProcess(const TrkResult &result) { // 40 00 00] @@ -978,39 +979,6 @@ void SymbianAdapter::handleCreateProcess(const TrkResult &result) appendInt(&ba, m_session.tid); startGdb(); - - -#if 0 - //---IDE------------------------------------------------------ - // Command: 0x42 Read Info - // [42 0C 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F - // 72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00] - sendTrkMessage(0x42, TrkCB(handleReadInfo), - "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " - "72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00"); - //sendTrkMessage(0x42, TrkCB(handleReadInfo), - // "00 01 00 00 00 00"); - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x20 Unspecified general OS-related error - // [80 0C 20] - - - //---IDE------------------------------------------------------ - // Command: 0x42 Read Info - // [42 0D 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F - // 72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00] - sendTrkMessage(0x42, TrkCB(handleReadInfo), - "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " - "72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00"); - //---TRK------------------------------------------------------ - // Command: 0x80 Acknowledge - // Error: 0x20 Unspecified general OS-related error - // [80 0D 20] -#endif - - //sendTrkMessage(0x18, TrkCB(handleStop), - // "01 " + formatInt(m_session.pid) + formatInt(m_session.tid)); } void SymbianAdapter::handleReadRegisters(const TrkResult &result) @@ -1269,53 +1237,37 @@ void SymbianAdapter::interruptInferior() sendTrkMessage(0x1a, TrkCallback(), ba, "Interrupting..."); } -void SymbianAdapter::connectProcess(QProcess *proc) +void SymbianAdapter::handleGdbError(QProcess::ProcessError error) { - connect(proc, SIGNAL(error(QProcess::ProcessError)), - this, SLOT(handleProcError(QProcess::ProcessError))); - connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), - this, SLOT(handleProcFinished(int, QProcess::ExitStatus))); - connect(proc, SIGNAL(started()), - this, SLOT(handleProcStarted())); - connect(proc, SIGNAL(stateChanged(QProcess::ProcessState)), - this, SLOT(handleProcStateChanged(QProcess::ProcessState))); + emit output(QString("GDB: Process Error %1: %2").arg(error).arg(errorString())); } -void SymbianAdapter::sendOutput(QObject *sender, const QString &data) +void SymbianAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus) { - if (sender) - emit output(sender->objectName() + " : " + data); - else - emit output(data); + emit output(QString("GDB: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus)); } -void SymbianAdapter::handleProcError(QProcess::ProcessError error) +void SymbianAdapter::handleGdbStarted() { - sendOutput(sender(), - QString("Process Error %1: %2").arg(error).arg(errorString())); + emit output(QString("GDB: Process Started")); + emit started(); } -void SymbianAdapter::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus) +void SymbianAdapter::handleGdbStateChanged(QProcess::ProcessState newState) { - sendOutput(sender(), - QString("ProcessFinished %1 %2").arg(exitCode).arg(exitStatus)); -} - -void SymbianAdapter::handleProcStarted() -{ - sendOutput(sender(), QString("Process Started")); -} - -void SymbianAdapter::handleProcStateChanged(QProcess::ProcessState newState) -{ - sendOutput(sender(), QString("Process State %1").arg(newState)); + emit output(QString("GDB: Process State %1").arg(newState)); } void SymbianAdapter::run() { - sendOutput("### Starting SymbianAdapter"); + emit output("### Starting SymbianAdapter"); m_rfcommProc.start("rfcomm listen " + m_rfcommDevice + " 1"); m_rfcommProc.waitForStarted(); + + if (m_rfcommProc.state() != QProcess::Running) { + emit finished(-44, QProcess::CrashExit); + return; + } connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleTrkResult(trk::TrkResult))); @@ -1330,7 +1282,7 @@ void SymbianAdapter::startGdb() if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) { logMessage(QString("Unable to start the gdb server at %1: %2.") .arg(m_gdbServerName).arg(m_gdbServer.errorString())); - //emit startFailed(); + emit finished(-45, QProcess::CrashExit); return; } @@ -1346,32 +1298,6 @@ void SymbianAdapter::startGdb() gdbArgs.append("-i"); gdbArgs.append("mi"); m_gdbProc.start(QDir::currentPath() + "/cs-gdb", gdbArgs); - m_gdbProc.waitForStarted(); - - sendGdbMessage("set confirm off"); // confirm potentially dangerous operations? - sendGdbMessage("set endian little"); - sendGdbMessage("set remotebreak on"); - sendGdbMessage("set breakpoint pending on"); - sendGdbMessage("set trust-readonly-sections on"); - //sendGdbMessage("mem 0 ~0ll rw 8 cache"); - - // FIXME: "remote noack" does not seem to be supported on cs-gdb? - //sendGdbMessage("set remote noack-packet"); - - // FIXME: creates a lot of noise a la '&"putpkt: Junk: Ack " &' - // even though the communication seems sane - //sendGdbMessage("set debug remote 1"); // creates l - - sendGdbMessage("add-symbol-file filebrowseapp.sym " - + hexxNumber(m_session.codeseg)); - sendGdbMessage("symbol-file filebrowseapp.sym"); - - //sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL", - // GdbCB(handleInfoMainAddress)); - - sendGdbMessage("-break-insert filebrowseappui.cpp:39"); - sendGdbMessage("target remote " + m_gdbServerName); - emit started(); } void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback, @@ -1385,28 +1311,41 @@ void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback, m_gdbProc.write(msg.toLatin1() + "\n"); } -void SymbianAdapter::handleSetTrkMainBreakpoint(const TrkResult &result) -{ - Q_UNUSED(result); -/* - //---TRK------------------------------------------------------ - // [80 09 00 00 00 00 0A] - const uint bpnr = extractInt(result.data.data()); - logMessage("SET MAIN BREAKPOINT " + hexxNumber(bpnr) - + stringFromArray(result.data.data())); -*/ -} +// +// GdbProcessBase +// void SymbianAdapter::handleRfcommReadyReadStandardError() { - QByteArray ba = qobject_cast(sender())->readAllStandardError(); - sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba))); + QByteArray ba = m_rfcommProc.readAllStandardError(); + emit output(QString("RFCONN stderr: %1").arg(QString::fromLatin1(ba))); } void SymbianAdapter::handleRfcommReadyReadStandardOutput() { - QByteArray ba = qobject_cast(sender())->readAllStandardOutput(); - sendOutput(sender(), QString("stdout: %1").arg(QString::fromLatin1(ba))); + QByteArray ba = m_rfcommProc.readAllStandardOutput(); + emit output(QString("RFCONN stdout: %1").arg(QString::fromLatin1(ba))); +} + + +void SymbianAdapter::handleRfcommError(QProcess::ProcessError error) +{ + emit output(QString("RFCOMM: Process Error %1: %2").arg(error).arg(errorString())); +} + +void SymbianAdapter::handleRfcommFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + emit output(QString("RFCOMM: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus)); +} + +void SymbianAdapter::handleRfcommStarted() +{ + emit output(QString("RFCOMM: Process Started")); +} + +void SymbianAdapter::handleRfcommStateChanged(QProcess::ProcessState newState) +{ + emit output(QString("RFCOMM: Process State %1").arg(newState)); } // diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h index e694a1ffab3..ed508d91289 100644 --- a/src/plugins/debugger/symbian/symbianadapter.h +++ b/src/plugins/debugger/symbian/symbianadapter.h @@ -85,11 +85,13 @@ public: SymbianAdapter(); ~SymbianAdapter(); void setGdbServerName(const QString &name); + QString gdbServerName() const { return m_gdbServerName; } QString gdbServerIP() const; uint gdbServerPort() const; void setVerbose(int verbose) { m_verbose = verbose; } void setSerialFrame(bool b) { m_serialFrame = b; } void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; } + trk::Session &session() { return m_session; } public slots: void startInferior(); @@ -98,19 +100,13 @@ public slots: signals: void output(const QString &msg); void startSuccessful(); + void startFailed(); private slots: - void handleProcError(QProcess::ProcessError error); - void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus); - void handleProcStarted(); - void handleProcStateChanged(QProcess::ProcessState newState); void startGdb(); private: friend class RunnerGui; - void connectProcess(QProcess *proc); - void sendOutput(QObject *sender, const QString &data); - void sendOutput(const QString &data) { sendOutput(0, data); } QString m_rfcommDevice; // /dev/rfcomm0 QString m_gdbServerName; // 127.0.0.1:(2222+uid) @@ -174,10 +170,6 @@ public: void reportReadMemoryBuffered(const TrkResult &result); void reportToGdb(const TrkResult &result); - // set breakpoints behind gdb's back - void handleSetTrkBreakpoint(const TrkResult &result); - void handleSetTrkMainBreakpoint(const TrkResult &result); - void readMemory(uint addr, uint len); void interruptInferior(); @@ -212,6 +204,11 @@ public: void sendGdbServerAck(); bool sendGdbServerPacket(const QByteArray &packet, bool doFlush); + Q_SLOT void handleGdbError(QProcess::ProcessError error); + Q_SLOT void handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus); + Q_SLOT void handleGdbStarted(); + Q_SLOT void handleGdbStateChanged(QProcess::ProcessState newState); + void logMessage(const QString &msg); // triggers output() if m_verbose Q_SLOT void trkLogMessage(const QString &msg); @@ -227,6 +224,10 @@ public: // Q_SLOT void handleRfcommReadyReadStandardError(); Q_SLOT void handleRfcommReadyReadStandardOutput(); + Q_SLOT void handleRfcommError(QProcess::ProcessError error); + Q_SLOT void handleRfcommFinished(int exitCode, QProcess::ExitStatus exitStatus); + Q_SLOT void handleRfcommStarted(); + Q_SLOT void handleRfcommStateChanged(QProcess::ProcessState newState); // Debuggee state Q_SLOT void executeCommand(const QString &msg); diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp index aaa3b984b47..059eac4f946 100755 --- a/tests/manual/trk/runner.cpp +++ b/tests/manual/trk/runner.cpp @@ -186,7 +186,30 @@ void RunnerGui::run() void RunnerGui::started() { qDebug() << "\nSTARTED\n"; - m_adapter->sendGdbMessage("-exec-continue"); + executeCommand("set confirm off"); // confirm potentially dangerous operations? + executeCommand("set endian little"); + executeCommand("set remotebreak on"); + executeCommand("set breakpoint pending on"); + executeCommand("set trust-readonly-sections on"); + //executeCommand("mem 0 ~0ll rw 8 cache"); + + // FIXME: "remote noack" does not seem to be supported on cs-gdb? + //executeCommand("set remote noack-packet"); + + // FIXME: creates a lot of noise a la '&"putpkt: Junk: Ack " &' + // even though the communication seems sane + //executeCommand("set debug remote 1"); // creates l + + executeCommand("add-symbol-file filebrowseapp.sym " + + trk::hexxNumber(m_adapter->session().codeseg)); + executeCommand("symbol-file filebrowseapp.sym"); + + //executeCommand("info address CFileBrowseAppUi::HandleCommandL", + // GdbCB(handleInfoMainAddress)); + + executeCommand("-break-insert filebrowseappui.cpp:39"); + executeCommand("target remote " + m_adapter->gdbServerName()); + executeCommand("-exec-continue"); } /////////////////////////////////////////////////////////////////////// From 7f54f9d339a195717cdbec7f17b20110f1680175 Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Fri, 11 Sep 2009 11:19:33 +0200 Subject: [PATCH 40/43] Wrap completion box list when navigating with up/down arrow keys. Reviewed-by: Thorbjorn Lindeijer --- src/plugins/texteditor/completionwidget.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/plugins/texteditor/completionwidget.cpp b/src/plugins/texteditor/completionwidget.cpp index 91b05cd7a2e..c656500f072 100644 --- a/src/plugins/texteditor/completionwidget.cpp +++ b/src/plugins/texteditor/completionwidget.cpp @@ -156,7 +156,17 @@ bool CompletionWidget::event(QEvent *e) closeList(currentIndex()); return true; case Qt::Key_Up: + if (currentIndex().row() == 0) { + setCurrentIndex(model()->index(model()->rowCount()-1, 0)); + return true; + } + forwardKeys = false; + break; case Qt::Key_Down: + if (currentIndex().row() == model()->rowCount()-1) { + setCurrentIndex(model()->index(0, 0)); + return true; + } case Qt::Key_Enter: case Qt::Key_PageDown: case Qt::Key_PageUp: From 17f9204bbadb5a145883f6ff84cf61fa2f7bfca2 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 11 Sep 2009 12:30:53 +0200 Subject: [PATCH 41/43] debugger: refactoring in the gdbengine --- src/plugins/debugger/debuggermanager.h | 1 + src/plugins/debugger/gdb/gdbengine.cpp | 72 +++++++++++-------- src/plugins/debugger/gdb/gdbengine.h | 7 ++ src/plugins/debugger/gdb/gdbprocessbase.h | 4 ++ .../debugger/symbian/symbianadapter.cpp | 18 ++++- src/plugins/debugger/symbian/symbianadapter.h | 1 + tests/manual/trk/runner.pro | 2 + 7 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 3b9622e7f4c..e857f7bdb82 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -430,6 +430,7 @@ private: BreakpointData *findBreakpoint(const QString &fileName, int lineNumber); void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos); + // FIXME: Remove engine-specific state QSharedPointer m_startParameters; DebuggerRunControl *m_runControl; QString m_dumperLib; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 84380f20548..02e84fd6a94 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -138,6 +138,20 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record) return out.mid(pos + 3); } +/////////////////////////////////////////////////////////////////////// +// +// GdbProcess +// +/////////////////////////////////////////////////////////////////////// + +void GdbProcess::attach(GdbEngine *engine) const +{ + QFileInfo fi(engine->startParameters().executable); + QString fileName = fi.absoluteFilePath(); + engine->postCommand(_("-file-exec-and-symbols ") + fileName, + &GdbEngine::handleFileExecAndSymbols, "handleFileExecAndSymbols"); +} + /////////////////////////////////////////////////////////////////////// // // GdbEngine @@ -1678,26 +1692,28 @@ void GdbEngine::startDebugger2() } else if (m_startParameters.useTerminal) { qq->breakHandler()->setAllPending(); } else if (q->startMode() == StartInternal || q->startMode() == StartExternal) { - QFileInfo fi(m_startParameters.executable); - QString fileName = _c('"') + fi.absoluteFilePath() + _c('"'); - postCommand(_("-file-exec-and-symbols ") + fileName, CB(handleFileExecAndSymbols)); - //postCommand(_("file ") + fileName, handleFileExecAndSymbols); - #ifdef Q_OS_MAC - postCommand(_("sharedlibrary apply-load-rules all")); - #endif - if (!m_startParameters.processArgs.isEmpty()) - postCommand(_("-exec-arguments ") + m_startParameters.processArgs.join(_(" "))); - #ifndef Q_OS_MAC - if (!m_dumperInjectionLoad) - postCommand(_("set auto-solib-add off")); - postCommand(_("info target"), CB(handleStart)); - #else - // On MacOS, breaking in at the entry point wreaks havoc. - postCommand(_("tbreak main")); - m_waitingForFirstBreakpointToBeHit = true; - qq->notifyInferiorRunningRequested(); - postCommand(_("-exec-run"), CB(handleExecRun)); - #endif + m_gdbProc->attach(this); + if (m_gdbProc->isAdapter()) { + qq->notifyInferiorRunningRequested(); + postCommand(_("-exec-continue"), CB(handleExecContinue)); + } else { + #ifdef Q_OS_MAC + postCommand(_("sharedlibrary apply-load-rules all")); + #endif + if (!m_startParameters.processArgs.isEmpty()) + postCommand(_("-exec-arguments ") + m_startParameters.processArgs.join(_(" "))); + #ifdef Q_OS_MAC + // On MacOS, breaking in at the entry point wreaks havoc. + postCommand(_("tbreak main")); + m_waitingForFirstBreakpointToBeHit = true; + qq->notifyInferiorRunningRequested(); + postCommand(_("-exec-run"), CB(handleExecRun)); + #else + if (!m_dumperInjectionLoad) + postCommand(_("set auto-solib-add off")); + postCommand(_("info target"), CB(handleStart)); + #endif + } qq->breakHandler()->setAllPending(); } @@ -1724,16 +1740,11 @@ void GdbEngine::handleStart(const GdbResultRecord &response, const QVariant &) QString msg = _(response.data.findChild("consolestreamoutput").data()); QRegExp needle(_("\\bEntry point: (0x[0-9a-f]+)\\b")); if (needle.indexIn(msg) != -1) { - if (m_gdbProc->isAdapter()) { - postCommand(_("-exec-continue"), CB(handleExecRun)); - qq->notifyInferiorRunningRequested(); - } else { - //debugMessage(_("STREAM: ") + msg + " " + needle.cap(1)); - postCommand(_("tbreak *") + needle.cap(1)); - m_waitingForFirstBreakpointToBeHit = true; - qq->notifyInferiorRunningRequested(); - postCommand(_("-exec-run"), CB(handleExecRun)); - } + //debugMessage(_("STREAM: ") + msg + " " + needle.cap(1)); + postCommand(_("tbreak *") + needle.cap(1)); + m_waitingForFirstBreakpointToBeHit = true; + qq->notifyInferiorRunningRequested(); + postCommand(_("-exec-run"), CB(handleExecRun)); } else { debugMessage(_("PARSING START ADDRESS FAILED: ") + msg); } @@ -1771,7 +1782,6 @@ void GdbEngine::handleAttach(const GdbResultRecord &, const QVariant &) void GdbEngine::handleSetTargetAsync(const GdbResultRecord &record, const QVariant &) { if (record.resultClass == GdbResultDone) { - //postCommand(_("info target"), handleStart); qq->notifyInferiorRunningRequested(); postCommand(_("target remote %1").arg(q->startParameters()->remoteChannel), CB(handleTargetRemote)); diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index e202ec987a5..53ae548e277 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -107,6 +107,7 @@ public: void setWorkingDirectory(const QString &dir) { m_proc.setWorkingDirectory(dir); } void setEnvironment(const QStringList &env) { m_proc.setEnvironment(env); } bool isAdapter() const { return false; } + void attach(GdbEngine *engine) const; private: QProcess m_proc; @@ -126,6 +127,11 @@ signals: void applicationOutputAvailable(const QString &output); private: + friend class GdbProcess; + friend class SymbianAdapter; + + const DebuggerStartParameters &startParameters() const + { return m_startParameters; } // // IDebuggerEngine implementation // @@ -206,6 +212,7 @@ public: // otherwise the Qt flag macros are unhappy }; Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag) + private: typedef void (GdbEngine::*GdbCommandCallback)(const GdbResultRecord &record, const QVariant &cookie); diff --git a/src/plugins/debugger/gdb/gdbprocessbase.h b/src/plugins/debugger/gdb/gdbprocessbase.h index 6c5825e6f66..71483cd2ee5 100644 --- a/src/plugins/debugger/gdb/gdbprocessbase.h +++ b/src/plugins/debugger/gdb/gdbprocessbase.h @@ -36,6 +36,8 @@ namespace Debugger { namespace Internal { +class GdbEngine; + // GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter. // In the GdbProcess case it's just a wrapper around a QProcess running // gdb, in the Adapter case it's the interface to the gdb process in @@ -62,6 +64,8 @@ public: virtual void setEnvironment(const QStringList &env) = 0; virtual bool isAdapter() const = 0; + virtual void attach(GdbEngine *engine) const = 0; + signals: void error(QProcess::ProcessError); void started(); diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index 667bc6bf574..c5ff3dc2b24 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -28,9 +28,11 @@ **************************************************************************/ #include "symbianadapter.h" +#ifndef STANDALONE_RUNNER +#include "gdb/gdbengine.h" +#endif #define TrkCB(s) TrkCallback(this, &SymbianAdapter::s) -#define GdbCB(s) GdbCallback(this, &SymbianAdapter::s) using namespace trk; @@ -1307,7 +1309,7 @@ void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback, data.command = msg; data.callback = callback; data.cookie = cookie; - logMessage(QString("<- GDB: %2").arg(msg)); + logMessage(QString("<- ADAPTER TO GDB: %2").arg(msg)); m_gdbProc.write(msg.toLatin1() + "\n"); } @@ -1410,5 +1412,17 @@ void SymbianAdapter::setEnvironment(const QStringList &env) m_gdbProc.setEnvironment(env); } +void SymbianAdapter::attach(GdbEngine *engine) const +{ +#ifdef STANDALONE_RUNNER +#else + QString fileName = engine->startParameters().executable; + engine->postCommand(_("add-symbol-file \"%1\" %2").arg(fileName) + .arg(m_session.codeseg)); + engine->postCommand(_("symbol-file \"%1\"").arg(fileName)); + engine->postCommand(_("target remote ") + gdbServerName()); +#endif +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h index ed508d91289..713692d44fa 100644 --- a/src/plugins/debugger/symbian/symbianadapter.h +++ b/src/plugins/debugger/symbian/symbianadapter.h @@ -132,6 +132,7 @@ public: void setWorkingDirectory(const QString &dir); void setEnvironment(const QStringList &env); bool isAdapter() const { return true; } + void attach(GdbEngine *engine) const; // // TRK diff --git a/tests/manual/trk/runner.pro b/tests/manual/trk/runner.pro index 21461da2d94..20240eb1f73 100644 --- a/tests/manual/trk/runner.pro +++ b/tests/manual/trk/runner.pro @@ -4,6 +4,8 @@ TEMPLATE = app DEBUGGERHOME = ../../../src/plugins/debugger/symbian INCLUDEPATH *= $$DEBUGGERHOME +DEFINES += STANDALONE_RUNNER + QT += network win32:CONFIG+=console From 8213e5bda734852dbd9ecc308695ffb65aa87a6f Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 11 Sep 2009 13:05:37 +0200 Subject: [PATCH 42/43] debugger: work on trk. Something's visible in Locals&Watchers now! --- src/plugins/debugger/gdb/gdbengine.cpp | 12 +++++++++++- src/plugins/debugger/symbian/symbianadapter.cpp | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 02e84fd6a94..452e9908ec4 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1078,7 +1078,6 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) return; } - //MAC: bool isFirstStop = data.findChild("bkptno").data() == "1"; //!MAC: startSymbolName == data.findChild("frame").findChild("func") if (m_waitingForFirstBreakpointToBeHit) { @@ -1292,6 +1291,15 @@ void GdbEngine::handleAsyncOutput2(const GdbMi &data) } } + // FIXME: Hack, remove as soon as we get real stack traces. + if (m_gdbProc->isAdapter()) { + StackFrame f; + f.file = QString::fromLocal8Bit(fullName.data()); + f.line = frame.findChild("line").data().toInt(); + f.address = _(frame.findChild("addr").data()); + q->gotoLocation(f, true); + } + // // Stack // @@ -2051,6 +2059,8 @@ void GdbEngine::sendInsertBreakpoint(int index) // cmd += "-c " + data->condition + " "; #else QString cmd = _("-break-insert -f "); + if (m_gdbProc->isAdapter()) + cmd = _("-break-insert "); //if (!data->condition.isEmpty()) // cmd += _("-c ") + data->condition + ' '; #endif diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp index c5ff3dc2b24..212e1d5e18e 100644 --- a/src/plugins/debugger/symbian/symbianadapter.cpp +++ b/src/plugins/debugger/symbian/symbianadapter.cpp @@ -1421,6 +1421,7 @@ void SymbianAdapter::attach(GdbEngine *engine) const .arg(m_session.codeseg)); engine->postCommand(_("symbol-file \"%1\"").arg(fileName)); engine->postCommand(_("target remote ") + gdbServerName()); + engine->attemptBreakpointSynchronization(); #endif } From 1a0134a9de7d168288a8dbc0d1f157794314d90a Mon Sep 17 00:00:00 2001 From: con Date: Fri, 11 Sep 2009 14:37:17 +0200 Subject: [PATCH 43/43] Use systems preferred language on Mac. And ensure that the menu items don't vanish from the application menu when they are translated. --- src/app/app.pro | 2 +- src/app/main.cpp | 38 ++++++++++++++++++++++++++- src/plugins/coreplugin/mainwindow.cpp | 9 +++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/app/app.pro b/src/app/app.pro index 69f5aa6fdce..b1830edff2f 100644 --- a/src/app/app.pro +++ b/src/app/app.pro @@ -17,7 +17,7 @@ win32 { } else:macx { CONFIG(debug, debug|release):LIBS *= -lExtensionSystem_debug -lAggregation_debug else:LIBS *= -lExtensionSystem -lAggregation - + LIBS += -framework CoreFoundation ICON = qtcreator.icns QMAKE_INFO_PLIST = Info.plist FILETYPES.files = profile.icns prifile.icns diff --git a/src/app/main.cpp b/src/app/main.cpp index 599459eb05c..f6a0dc45b3c 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -48,6 +48,20 @@ #ifdef Q_OS_MAC # include +# include + +// Helper function CoreFoundation -> Qt +static QString stringFromCFString(CFStringRef value) { + QString retVal; + CFIndex maxLength = 2 * CFStringGetLength(value) + 1/*zero term*/; // max UTF8 + char *cstring = new char[maxLength]; + if (CFStringGetCString(CFStringRef(value), cstring, maxLength, kCFStringEncodingUTF8)) { + retVal = QString::fromUtf8(cstring); + } + delete cstring; + return retVal; +} + #endif enum { OptionIndent = 4, DescriptionIndent = 24 }; @@ -216,7 +230,29 @@ int main(int argc, char **argv) QTranslator translator; QTranslator qtTranslator; - const QString &locale = QLocale::system().name(); + QString locale = QLocale::system().name(); +#ifdef Q_OS_MAC + // because QLocale's system locale is basically useless on the Mac. + // Try to get the real system setting via core foundation + CFLocaleRef maclocale = CFLocaleCopyCurrent(); + CFTypeRef value = CFLocaleGetValue(maclocale, kCFLocaleLanguageCode); + QString preferredLanguage = stringFromCFString(CFStringRef(value)); + if (!preferredLanguage.isEmpty()) + locale = preferredLanguage; + CFRelease(maclocale); + CFArrayRef languages = (CFArrayRef)CFPreferencesCopyValue( + CFSTR("AppleLanguages"), + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); +// CFShow(languages); + if (CFArrayGetCount(languages) > 0) { + QString preferredLanguage = stringFromCFString(CFStringRef(CFArrayGetValueAtIndex(languages, 0))); + if (!preferredLanguage.isEmpty()) + locale = preferredLanguage; + } + CFRelease(languages); +#endif const QString &creatorTrPath = QCoreApplication::applicationDirPath() + QLatin1String(SHARE_PATH "/translations"); if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) { diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index e42d5c03423..af8576b8ac4 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -160,7 +160,7 @@ MainWindow::MainWindow() : QCoreApplication::setOrganizationName(QLatin1String("Nokia")); QSettings::setDefaultFormat(QSettings::IniFormat); QString baseName = qApp->style()->objectName(); -#ifdef Q_WS_X11 +#ifdef Q_WS_X11 if (baseName == QLatin1String("windows")) { // Sometimes we get the standard windows 95 style as a fallback // e.g. if we are running on a KDE4 desktop @@ -325,7 +325,7 @@ bool MainWindow::init(QString *errorMessage) void MainWindow::modeChanged(Core::IMode *mode) { - if (mode == m_outputMode) { + if (mode == m_outputMode) { int idx = OutputPaneManager::instance()->m_widgetComboBox->itemData(OutputPaneManager::instance()->m_widgetComboBox->currentIndex()).toInt(); IOutputPane *out = OutputPaneManager::instance()->m_pageMap.value(idx); if (out && out->canFocus()) @@ -678,6 +678,7 @@ void MainWindow::registerDefaultActions() cmd = am->registerAction(m_optionsAction, Constants::OPTIONS, m_globalContext); #ifdef Q_WS_MAC cmd->setDefaultKeySequence(QKeySequence("Ctrl+,")); + cmd->action()->setMenuRole(QAction::PreferencesRole); #endif mtools->addAction(cmd, Constants::G_DEFAULT_THREE); connect(m_optionsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog())); @@ -735,7 +736,11 @@ void MainWindow::registerDefaultActions() cmd = am->registerAction(tmpaction, Constants::ABOUT_QTCREATOR, m_globalContext); mhelp->addAction(cmd, Constants::G_HELP_ABOUT); tmpaction->setEnabled(true); +#ifdef Q_WS_MAC + cmd->action()->setMenuRole(QAction::ApplicationSpecificRole); +#endif connect(tmpaction, SIGNAL(triggered()), this, SLOT(aboutQtCreator())); + //About Plugins Action tmpaction = new QAction(tr("About &Plugins..."), this); cmd = am->registerAction(tmpaction, Constants::ABOUT_PLUGINS, m_globalContext);