Commit c736cc3c authored by hjk's avatar hjk

debugger: use 'maint print msymbols' to extract Qt's namespace

still racy
parent c1228d0c
......@@ -615,7 +615,7 @@ void BreakHandler::setMarkerFileAndLine(BreakpointId id,
const QString &fileName, int lineNumber)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
QTC_ASSERT(it != m_storage.end(), qDebug() << id; return);
if (it->response.fileName == fileName && it->response.lineNumber == lineNumber)
return;
it->response.fileName = fileName;
......@@ -628,23 +628,23 @@ void BreakHandler::setMarkerFileAndLine(BreakpointId id,
BreakpointState BreakHandler::state(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return BreakpointDead);
QTC_ASSERT(it != m_storage.end(), qDebug() << id; return BreakpointDead);
return it->state;
}
DebuggerEngine *BreakHandler::engine(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return 0);
QTC_ASSERT(it != m_storage.end(), qDebug() << id; return 0);
return it->engine;
}
void BreakHandler::setEngine(BreakpointId id, DebuggerEngine *value)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
QTC_ASSERT(it->state == BreakpointNew, /**/);
QTC_ASSERT(!it->engine, return);
QTC_ASSERT(it != m_storage.end(), qDebug() << id; return);
QTC_ASSERT(it->state == BreakpointNew, qDebug() << id);
QTC_ASSERT(!it->engine, qDebug() << id; return);
it->engine = value;
it->state = BreakpointInsertRequested;
it->response = BreakpointResponse();
......@@ -687,7 +687,7 @@ void BreakHandler::setState(BreakpointId id, BreakpointState state)
{
Iterator it = m_storage.find(id);
//qDebug() << "BREAKPOINT STATE TRANSITION" << id << it->state << state;
QTC_ASSERT(it != m_storage.end(), return);
QTC_ASSERT(it != m_storage.end(), qDebug() << id; return);
QTC_ASSERT(isAllowedTransition(it->state, state),
qDebug() << "UNEXPECTED BREAKPOINT STATE TRANSITION"
<< it->state << state);
......@@ -963,7 +963,7 @@ const BreakpointResponse &BreakHandler::response(BreakpointId id) const
{
static BreakpointResponse dummy;
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return dummy);
QTC_ASSERT(it != m_storage.end(), qDebug() << id; return dummy);
return it->response;
}
......
......@@ -78,13 +78,10 @@ using namespace Debugger::Internal;
using namespace ProjectExplorer;
using namespace TextEditor;
//#define DEBUG_STATE 1
#if DEBUG_STATE
# define SDEBUG(s) qDebug() << s
#else
# define SDEBUG(s)
#endif
# define XSDEBUG(s) qDebug() << s
enum { debug = 0 };
#define SDEBUG(s) if (!debug) {} else qDebug() << s;
#define XSDEBUG(s) qDebug() << s
///////////////////////////////////////////////////////////////////////
......
......@@ -244,7 +244,7 @@ public:
bool isMasterEngine() const;
DebuggerEngine *masterEngine() const;
virtual bool prepareForQmlBreak() { return false; }
virtual bool prepareForQmlBreak(bool /*on*/) { return false; }
virtual void handlePrepareForQmlBreak() {}
signals:
......
......@@ -39,6 +39,10 @@
#include "debuggercore.h"
#include "debuggerstringutils.h"
#include <QDir>
#include <QFile>
#include <QTemporaryFile>
#include <utils/qtcassert.h>
namespace Debugger {
......@@ -94,8 +98,41 @@ void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &respon
void AbstractPlainGdbAdapter::runEngine()
{
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
m_engine->postCommand("print QString", CB(handleNamespaceExtraction));
m_engine->postCommand("-exec-run", GdbEngine::RunRequest, CB(handleExecRun));
QString fileName;
{
QTemporaryFile symbols(QDir::tempPath() + "/gdb_ns_");
symbols.open();
fileName = symbols.fileName();
}
m_engine->postCommand("maint print msymbols " + fileName.toLocal8Bit(),
CB(handleNamespaceExtraction1), fileName);
//m_engine->postCommand("print QString", CB(handleNamespaceExtraction));
}
void AbstractPlainGdbAdapter::handleNamespaceExtraction1(const GdbResponse &response)
{
QFile file(response.cookie.toString());
file.open(QIODevice::ReadOnly);
QByteArray ba = file.readAll();
int pos = ba.indexOf("7QString9fromAscii");
int pos1 = pos - 1;
while (pos1 > 0 && ba.at(pos1) != 'N' && ba.at(pos1) > '@')
--pos1;
++pos1;
QByteArray ns = ba.mid(pos1, pos - pos1);
qDebug() << "NAMESPACE: " << ns;
if (!ns.isEmpty())
m_engine->setQtNamespace(ns + "::");
if (m_engine->isSlaveEngine()) {
for (int i = 1; i <= 8; ++i) {
m_engine->postCommand("-break-insert -f '" + m_engine->qtNamespace()
+ "QScript::qScriptBreaker" + QByteArray::number(i) + "'",
CB(handleFindScriptBreaker), i);
}
} else {
doRunEngine();
}
file.remove();
}
void AbstractPlainGdbAdapter::handleNamespaceExtraction(const GdbResponse &response)
......@@ -106,10 +143,60 @@ void AbstractPlainGdbAdapter::handleNamespaceExtraction(const GdbResponse &respo
const int posQString = ba.indexOf("QString");
const int posNs = ba.lastIndexOf('(', posQString) + 1;
const QByteArray ns = ba.mid(posNs, posQString - posNs);
//qDebug() << "BA: " << response.toString() << ba << posQString << posNs << ns;
if (!ns.isEmpty())
m_engine->setQtNamespace(ns);
}
if (m_engine->isSlaveEngine()) {
for (int i = 1; i <= 8; ++i) {
m_engine->postCommand("-break-insert -f '" + m_engine->qtNamespace()
+ "QScript::qScriptBreaker" + QByteArray::number(i) + "'",
CB(handleFindScriptBreaker), i);
}
} else {
doRunEngine();
}
}
void AbstractPlainGdbAdapter::handleFindScriptBreaker(const GdbResponse &response)
{
//QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
if (response.resultClass == GdbResultDone) {
const int qmlBpType = response.cookie.toInt();
// 20^done,bkpt={number="2",type="breakpoint",disp="keep",enabled="y",
// addr="<PENDING>",pending="'myns::QScript::qScriptBreaker'"
const GdbMi bkpt = response.data.findChild("bkpt");
const GdbMi number = bkpt.findChild("number");
const int bpnr = number.data().toInt();
m_engine->addQmlBreakpointNumber(qmlBpType, bpnr);
//m_engine->postCommand("disable " + number.data());
switch (qmlBpType) {
case 5:
m_engine->postCommand("enable " + number.data());
m_engine->postCommand("command " + number.data() +
//"\necho \"STEP NOW\"\nfinish\nend")
"\nup"
"\necho \"YYY\""
"\ntbreak"
"\ncommands"
"\necho \"XXX\""
"\nstep"
"\nend"
"\ncontinue"
"\nend");
break;
default:
//m_engine->postCommand("command " + number.data() +
// "\nfinish\nend");
break;
}
}
if (response.cookie.toInt() == 8)
doRunEngine();
}
void AbstractPlainGdbAdapter::doRunEngine()
{
m_engine->postCommand("-exec-run", GdbEngine::RunRequest, CB(handleExecRun));
}
void AbstractPlainGdbAdapter::handleExecRun(const GdbResponse &response)
......
......@@ -53,14 +53,17 @@ public:
protected:
void handleInfoTarget(const GdbResponse &response);
void handleNamespaceExtraction(const GdbResponse &response);
void handleNamespaceExtraction1(const GdbResponse &response);
private:
virtual QByteArray execFilePath() const = 0;
virtual bool infoTargetNecessary() const = 0;
virtual QByteArray toLocalEncoding(const QString &s) const = 0;
virtual QString fromLocalEncoding(const QByteArray &b) const = 0;
virtual QByteArray toLocalEncoding(const QString &str) const = 0;
virtual QString fromLocalEncoding(const QByteArray &ba) const = 0;
void handleExecRun(const GdbResponse &response);
void handleFileExecAndSymbols(const GdbResponse &response);
void handleFindScriptBreaker(const GdbResponse &response);
void doRunEngine();
};
} // namespace Debugger
......
......@@ -200,6 +200,7 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters,
m_pendingBreakpointRequests = 0;
m_commandsDoneCallback = 0;
m_stackNeeded = false;
m_preparedForQmlBreak = false;
invalidateSourcesList();
m_gdbAdapter = createAdapter();
......@@ -1166,6 +1167,14 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
const int lineNumber = frame.findChild("line").data().toInt();
QString fullName = QString::fromUtf8(frame.findChild("fullname").data());
// QML single stepping: *stopped,reason="function-finished",
// frame={addr="0x00f1678e",func="myns::QScript::FunctionWrapper::proxyCall"
// ,args=[{name="exec",value="0xb71f10b0"}
// ,{name="callee",value="0xb7184480"},{name="thisObject",value="..."}
//const bool wasQmlStep = reason == "function-finished"
// && frame.findChild("func").data().endsWith("::FunctionWrapper::proxyCall");
if (fullName.isEmpty())
fullName = QString::fromUtf8(frame.findChild("file").data());
......@@ -1244,6 +1253,16 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
}
#endif
/*
if (wasQmlStep) {
qDebug() << "GOT IT";
notifyInferiorStopOk();
notifyInferiorRunRequested();
postCommand("-exec-step", RunRequest, CB(handleExecuteContinue));
return;
}
*/
handleStop0(data);
}
......@@ -2311,6 +2330,9 @@ void GdbEngine::handleBreakList(const GdbMi &table)
foreach (const GdbMi &bkpt, bkpts) {
BreakpointResponse needle;
needle.number = bkpt.findChild("number").data().toInt();
// FIXME: Performance.
if (m_qmlBreakpointNumbers.values().contains(needle.number))
continue;
BreakpointId id = breakHandler()->findSimilarBreakpoint(needle);
if (id != BreakpointId(-1)) {
updateBreakpointDataFromOutput(id, bkpt);
......@@ -2494,7 +2516,6 @@ void GdbEngine::handleInfoLine(const GdbResponse &response)
}
}
bool GdbEngine::stateAcceptsBreakpointChanges() const
{
switch (state()) {
......@@ -4513,11 +4534,10 @@ void GdbEngine::handleRemoteSetupFailed(const QString &message)
m_gdbAdapter->handleRemoteSetupFailed(message);
}
bool GdbEngine::prepareForQmlBreak()
bool GdbEngine::prepareForQmlBreak(bool on)
{
QTC_ASSERT(isSlaveEngine(), return false);
postCommand("-break-insert -t qscriptfunction.cpp:82",
NeedsStop, CB(handleQmlBreakpoint));
m_preparedForQmlBreak = on;
return true;
}
......@@ -4530,6 +4550,11 @@ void GdbEngine::handleQmlBreakpoint(const GdbResponse &response)
masterEngine()->handlePrepareForQmlBreak();
}
void GdbEngine::addQmlBreakpointNumber(int type, int nr)
{
qDebug() << "ADD SPECIAL QML BREAKPOINT, TYPE: " << type << "NR: " << nr;
m_qmlBreakpointNumbers[type] = nr;
}
//
// Factory
......
......@@ -519,9 +519,6 @@ private: ////////// View & Data Stuff //////////
void setLocals(const QList<GdbMi> &locals);
void handleStackListArgumentsClassic(const GdbResponse &response);
bool prepareForQmlBreak();
void handleQmlBreakpoint(const GdbResponse &response);
QSet<QByteArray> m_processedNames;
//
......@@ -553,6 +550,16 @@ private: ////////// View & Data Stuff //////////
bool m_stackNeeded;
int m_currentThreadId;
//
// Qml
//
void addQmlBreakpointNumber(int type /* 1-8 */, int nr);
QHash<int, int> m_qmlBreakpointNumbers;
bool m_preparedForQmlBreak;
bool prepareForQmlBreak(bool on);
void handleQmlBreakpoint(const GdbResponse &response);
// HACK:
StackFrame m_targetFrame;
QByteArray m_currentThread;
......
......@@ -10,6 +10,10 @@
namespace Debugger {
namespace Internal {
enum { debug = 0 };
#define EDEBUG(s) do { if (debug) qDebug() << s; } while (0)
const int ConnectionWaitTimeMs = 5000;
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &,
......@@ -66,7 +70,7 @@ QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp)
d->m_activeEngine = d->m_cppEngine;
if (1) {
if (0) {
setStateDebugging(true);
d->m_cppEngine->setStateDebugging(true);
d->m_qmlEngine->setStateDebugging(true);
......@@ -216,10 +220,8 @@ void QmlCppEngine::executeStep()
{
if (d->m_activeEngine == d->m_qmlEngine) {
QTC_ASSERT(d->m_cppEngine->state() == InferiorRunOk, /**/);
if (d->m_cppEngine->prepareForQmlBreak())
return; // Wait for call back.
d->m_cppEngine->prepareForQmlBreak(true);
}
notifyInferiorRunRequested();
d->m_activeEngine->executeStep();
}
......@@ -262,8 +264,8 @@ void QmlCppEngine::executeReturn()
void QmlCppEngine::continueInferior()
{
qDebug() << "\nMASTER CONTINUE INFERIOR"
<< d->m_cppEngine->state() << d->m_qmlEngine->state();
EDEBUG("\nMASTER CONTINUE INFERIOR"
<< d->m_cppEngine->state() << d->m_qmlEngine->state());
notifyInferiorRunRequested();
if (d->m_cppEngine->state() == InferiorStopOk) {
d->m_cppEngine->continueInferior();
......@@ -278,12 +280,12 @@ void QmlCppEngine::continueInferior()
void QmlCppEngine::interruptInferior()
{
qDebug() << "\nMASTER INTERRUPT INFERIOR";
EDEBUG("\nMASTER INTERRUPT INFERIOR");
}
void QmlCppEngine::requestInterruptInferior()
{
qDebug() << "\nMASTER REQUEST INTERUPT INFERIOR";
EDEBUG("\nMASTER REQUEST INTERUPT INFERIOR");
DebuggerEngine::requestInterruptInferior();
d->m_cppEngine->requestInterruptInferior();
}
......@@ -305,7 +307,7 @@ void QmlCppEngine::executeJumpToLine(const QString &fileName, int lineNumber)
void QmlCppEngine::executeDebuggerCommand(const QString &command)
{
d->m_activeEngine->executeDebuggerCommand(command);
d->m_cppEngine->executeDebuggerCommand(command);
}
void QmlCppEngine::frameUp()
......@@ -322,67 +324,67 @@ void QmlCppEngine::frameDown()
void QmlCppEngine::setupEngine()
{
qDebug() << "\nMASTER SETUP ENGINE";
EDEBUG("\nMASTER SETUP ENGINE");
d->m_qmlEngine->setupSlaveEngine();
d->m_cppEngine->setupSlaveEngine();
}
void QmlCppEngine::notifyEngineRunAndInferiorRunOk()
{
qDebug() << "\nMASTER NOTIFY ENGINE RUN AND INFERIOR RUN OK";
EDEBUG("\nMASTER NOTIFY ENGINE RUN AND INFERIOR RUN OK");
DebuggerEngine::notifyEngineRunAndInferiorRunOk();
}
void QmlCppEngine::notifyInferiorRunOk()
{
qDebug() << "\nMASTER NOTIFY INFERIOR RUN OK";
EDEBUG("\nMASTER NOTIFY INFERIOR RUN OK");
DebuggerEngine::notifyInferiorRunOk();
}
void QmlCppEngine::notifyInferiorSpontaneousStop()
{
qDebug() << "\nMASTER SPONTANEOUS STOP OK";
EDEBUG("\nMASTER SPONTANEOUS STOP OK");
DebuggerEngine::notifyInferiorSpontaneousStop();
}
void QmlCppEngine::notifyInferiorShutdownOk()
{
qDebug() << "\nMASTER INFERIOR SHUTDOWN OK";
EDEBUG("\nMASTER INFERIOR SHUTDOWN OK");
DebuggerEngine::notifyInferiorShutdownOk();
}
void QmlCppEngine::setupInferior()
{
qDebug() << "\nMASTER SETUP INFERIOR";
EDEBUG("\nMASTER SETUP INFERIOR");
d->m_qmlEngine->setupSlaveInferior();
d->m_cppEngine->setupSlaveInferior();
}
void QmlCppEngine::runEngine()
{
qDebug() << "\nMASTER RUN ENGINE";
EDEBUG("\nMASTER RUN ENGINE");
d->m_qmlEngine->runSlaveEngine();
d->m_cppEngine->runSlaveEngine();
}
void QmlCppEngine::shutdownInferior()
{
qDebug() << "\nMASTER SHUTDOWN INFERIOR";
EDEBUG("\nMASTER SHUTDOWN INFERIOR");
d->m_qmlEngine->quitDebugger();
}
void QmlCppEngine::shutdownEngine()
{
qDebug() << "\nMASTER SHUTDOWN ENGINE";
EDEBUG("\nMASTER SHUTDOWN ENGINE");
d->m_qmlEngine->shutdownSlaveEngine();
d->m_cppEngine->shutdownSlaveEngine();
}
void QmlCppEngine::setState(DebuggerState newState, bool forced)
{
qDebug() << "SET MASTER STATE: " << newState;
qDebug() << " CPP STATE: " << d->m_cppEngine->state();
qDebug() << " QML STATE: " << d->m_qmlEngine->state();
EDEBUG("SET MASTER STATE: " << newState);
EDEBUG(" CPP STATE: " << d->m_cppEngine->state());
EDEBUG(" QML STATE: " << d->m_qmlEngine->state());
DebuggerEngine::setState(newState, forced);
}
......@@ -392,9 +394,9 @@ void QmlCppEngine::slaveEngineStateChanged
DebuggerEngine *otherEngine = slaveEngine == d->m_cppEngine
? d->m_qmlEngine : d->m_cppEngine;
qDebug() << "GOT SLAVE STATE: " << slaveEngine << newState;
qDebug() << " OTHER ENGINE: " << otherEngine << otherEngine->state();
qDebug() << " COMBINED ENGINE: " << this << state() << isDying();
EDEBUG("GOT SLAVE STATE: " << slaveEngine << newState);
EDEBUG(" OTHER ENGINE: " << otherEngine << otherEngine->state());
EDEBUG(" COMBINED ENGINE: " << this << state() << isDying());
switch (newState) {
......@@ -413,7 +415,7 @@ void QmlCppEngine::slaveEngineStateChanged
if (otherEngine->state() == EngineSetupOk)
notifyEngineSetupOk();
else
qDebug() << "... WAITING FOR OTHER ENGINE SETUP...";
EDEBUG("... WAITING FOR OTHER ENGINE SETUP...");
break;
......@@ -428,7 +430,7 @@ void QmlCppEngine::slaveEngineStateChanged
if (otherEngine->state() == InferiorSetupOk)
notifyInferiorSetupOk();
else
qDebug() << "... WAITING FOR OTHER INFERIOR SETUP...";
EDEBUG("... WAITING FOR OTHER INFERIOR SETUP...");
break;
......@@ -454,13 +456,13 @@ void QmlCppEngine::slaveEngineStateChanged
else if (otherEngine->state() == InferiorRunOk)
notifyEngineRunAndInferiorStopOk();
else
qDebug() << "... WAITING FOR OTHER INFERIOR RUN";
EDEBUG("... WAITING FOR OTHER INFERIOR RUN");
} else {
if (otherEngine->state() == InferiorRunOk) {
qDebug() << "PLANNED INFERIOR RUN";
EDEBUG("PLANNED INFERIOR RUN");
notifyInferiorRunOk();
} else {
qDebug() << " **** INFERIOR RUN NOT OK ****";
EDEBUG(" **** INFERIOR RUN NOT OK ****");
}
}
break;
......@@ -475,7 +477,7 @@ void QmlCppEngine::slaveEngineStateChanged
case InferiorStopOk:
if (isDying()) {
qDebug() << "... AN INFERIOR STOPPED DURING SHUTDOWN ";
EDEBUG("... AN INFERIOR STOPPED DURING SHUTDOWN ");
} else {
if (slaveEngine != d->m_activeEngine) {
QString engineName = slaveEngine == d->m_cppEngine
......@@ -484,12 +486,12 @@ void QmlCppEngine::slaveEngineStateChanged
d->m_activeEngine = slaveEngine;
}
if (otherEngine->state() == InferiorShutdownOk) {
qDebug() << "... STOPP ";
EDEBUG("... STOPP ");
} else if (state() == InferiorStopRequested) {
qDebug() << "... AN INFERIOR STOPPED EXPECTEDLY";
EDEBUG("... AN INFERIOR STOPPED EXPECTEDLY");
notifyInferiorStopOk();
} else {
qDebug() << "... AN INFERIOR STOPPED UNEXPECTEDLY";
EDEBUG("... AN INFERIOR STOPPED UNEXPECTEDLY");
notifyInferiorSpontaneousStop();
}
}
......@@ -531,7 +533,7 @@ void QmlCppEngine::slaveEngineStateChanged
if (otherEngine->state() == EngineShutdownOk)
; // Wait for DebuggerFinished.
else
qDebug() << "... WAITING FOR OTHER ENGINE SHUTDOWN...";
EDEBUG("... WAITING FOR OTHER ENGINE SHUTDOWN...");
break;
......@@ -539,21 +541,21 @@ void QmlCppEngine::slaveEngineStateChanged
if (otherEngine->state() == DebuggerFinished)
notifyEngineShutdownOk();
else
qDebug() << "... WAITING FOR OTHER DEBUGGER TO FINISH...";
EDEBUG("... WAITING FOR OTHER DEBUGGER TO FINISH...");
break;
}
}
void QmlCppEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
{
//qDebug() << "MASETER REMOTE SETUP DONE";
EDEBUG("MASTER REMOTE SETUP DONE");
d->m_qmlEngine->handleRemoteSetupDone(gdbServerPort, qmlPort);
d->m_cppEngine->handleRemoteSetupDone(gdbServerPort, qmlPort);
}
void QmlCppEngine::handleRemoteSetupFailed(const QString &message)
{
//qDebug() << "MASETER REMOTE SETUP FAILED";
EDEBUG("MASTER REMOTE SETUP FAILED");
d->m_qmlEngine->handleRemoteSetupFailed(message);
d->m_cppEngine->handleRemoteSetupFailed(message);
}
......
......@@ -735,8 +735,21 @@ void testQList()
#endif
}
namespace A {
namespace B {
struct SomeType
{
SomeType(int a) : a(a) {}
int a;
};
} // namespace B
} // namespace A
void testQMap()
{
#if 0
QMap<uint, QStringList> ggl;
ggl[11] = QStringList() << "11";
ggl[22] = QStringList() << "22";
......@@ -745,8 +758,9 @@ void testQMap()
T ggt;
ggt[11] = QStringList() << "11";
ggt[22] = QStringList() << "22";
#endif
#if 1
#if 0
QMap<uint, float> gg0;
gg0[11] = 11.0;
gg0[22] = 22.0;
......@@ -768,6 +782,18 @@ void testQMap()
map.insert("Welt", QPointer<QObject>(&ob));
map.insert(".", QPointer<QObject>(&ob));
#endif
#if 1
QList<A::B::SomeType *> x;
x.append(new A::B::SomeType(1));
x.append(new A::B::SomeType(2));
x.append(new A::B::SomeType(3));
QMap<QString, QList<A::B::SomeType *> > mlt;
mlt["foo"] = x;
mlt["bar"] = x;
mlt["1"] = x;
mlt["2"] = x;