diff --git a/share/qtcreator/gdbmacros/pdumper.py b/share/qtcreator/gdbmacros/pdumper.py new file mode 100644 index 0000000000000000000000000000000000000000..9086951e2b9699cd150554082df66350d2be447a --- /dev/null +++ b/share/qtcreator/gdbmacros/pdumper.py @@ -0,0 +1,144 @@ + +import pdb; +import sys; +import linecache + + +class qdebug: + def __init__(self, + options = Null, + expanded = Null, + typeformats = Null, + individualformats = Null, + watchers = Null): + self.options = options + self.expanded = expanded + self.typeformats = typeformats + self.individualformats = individualformats + self.watchers = watchers + self.doit() + + def put(self, value): + sys.stdout.write(value) + + def putField(self, name, value): + self.put('%s="%s",' % (name, value)) + + def putItemCount(self, count): + self.put('value="<%s items>",' % count) + + def putEllipsis(self): + self.put('{name="<incomplete>",value="",type="",numchild="0"},') + + def cleanType(self, type): + t = str(type) + if t.startswith("<type '") and t.endswith("'>"): + t = t[7:-2] + return t + + def putType(self, type, priority = 0): + self.putField("type", self.cleanType(type)) + + def putAddress(self, addr): + self.put('addr="%s",' % cleanAddress(addr)) + + def putNumChild(self, numchild): + self.put('numchild="%s",' % numchild) + + def putValue(self, value, encoding = None, priority = 0): + self.putField("value", value) + + def putName(self, name): + self.put('name="%s",' % name) + + def isExpanded(self, item): + #warn("IS EXPANDED: %s in %s" % (item.iname, self.expandedINames)) + if item.iname is None: + raise "Illegal iname 'None'" + if item.iname.startswith("None"): + raise "Illegal iname '%s'" % item.iname + #warn(" --> %s" % (item.iname in self.expandedINames)) + return item.iname in self.expandedINames + + def isExpandedIName(self, iname): + return iname in self.expandedINames + + def itemFormat(self, item): + format = self.formats.get(str(cleanAddress(item.value.address))) + if format is None: + format = self.typeformats.get(stripClassTag(str(item.value.type))) + return format + + def dumpFrame(self, frame): + for var in frame.f_locals.keys(): + if var == "__file__": + continue + #if var == "__name__": + # continue + if var == "__package__": + continue + if var == "qdebug": + continue + if var != '__builtins__': + value = frame.f_locals[var] + self.dumpValue(value, var, "local.%s" % var) + + def dumpValue(self, value, name, iname): + t = type(value) + tt = self.cleanType(t) + if tt == "module" or tt == "function": + return + if tt == "list": + self.warn("LIST: %s" % dir(value)) + self.put("{") + self.putField("iname", iname) + self.putName(name) + self.putType(tt) + self.putValue(value) + self.put("children=[") + for i in xrange(len(value)): + self.dumpValue(value[i], str(i), "%s.%d" % (iname, i)) + self.put("]") + self.put("},") + elif tt != "module" and tt != "function": + self.put("{") + self.putField("iname", iname) + self.putName(name) + self.putType(tt) + self.putValue(value) + self.put("},") + + + def warn(self, msg): + self.putField("warning", msg) + + def doit(self): + # Trigger error to get a backtrace. + frame = None + #self.warn("frame: %s" % frame) + try: + raise ZeroDivisionError + except ZeroDivisionError: + frame = sys.exc_info()[2].tb_frame.f_back + + limit = 30 + n = 0 + isActive = False + while frame is not None and n < limit: + #self.warn("frame: %s" % frame.f_locals.keys()) + lineno = frame.f_lineno + code = frame.f_code + filename = code.co_filename + name = code.co_name + if isActive: + linecache.checkcache(filename) + line = linecache.getline(filename, lineno, frame.f_globals) + self.dumpFrame(frame) + if name == "<module>": + isActive = False + if name == "trace_dispatch": + isActive = True + frame = frame.f_back + n = n + 1 + + sys.stdout.flush() diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 05c0a0d9c35fda7de0a798dd0239b65fec5c25ee..6bbfe4974399ba84ca79a4e69e6efd3fb94d8593 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -57,6 +57,7 @@ SOURCES += breakhandler.cpp \ debuggerplugin.cpp \ debuggerrunner.cpp \ debuggertooltip.cpp \ + idebuggerengine.cpp \ moduleshandler.cpp \ moduleswindow.cpp \ outputcollector.cpp \ diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index c1bc7b57f0e5fe147fdef0a27d45a54ce1aa36d9..2093e54346ff13fd6f1169d76370ca25d47bb276 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -141,11 +141,6 @@ private: ////////// Gdb Process Management ////////// void handleInferiorShutdown(const GdbResponse &response); void handleGdbExit(const GdbResponse &response); - void showDebuggerInput(int channel, const QString &msg) - { m_manager->showDebuggerInput(channel, msg); } - void showDebuggerOutput(int channel, const QString &msg) - { m_manager->showDebuggerOutput(channel, msg); } - private slots: void handleGdbFinished(int, QProcess::ExitStatus status); void handleGdbError(QProcess::ProcessError error); diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index 112b172d73f888b5108facee359367f3e53fea52..3edf26905ac4ef280b50aafecee4efa69da03528 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -55,10 +55,9 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList) //m_toolTipExpression.clear(); WatchHandler *handler = m_manager->watchHandler(); - QByteArray expanded = handler->formatRequests(); - if (expanded.isEmpty()) - expanded.append("defaults,"); - expanded.chop(1); + QByteArray expanded = "expanded:" + handler->expansionRequests() + ' '; + expanded += "typeformats:" + handler->typeFormatRequests() + ' '; + expanded += "formats:" + handler->individualFormatRequests(); QByteArray watchers; if (!m_toolTipExpression.isEmpty()) diff --git a/src/plugins/debugger/idebuggerengine.cpp b/src/plugins/debugger/idebuggerengine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de8d7eefe1af2fc83511919a7069f91021dbd153 --- /dev/null +++ b/src/plugins/debugger/idebuggerengine.cpp @@ -0,0 +1,71 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 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 "idebuggerengine.h" +#include "debuggermanager.h" + + +namespace Debugger { +namespace Internal { + +void IDebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *, + quint64 addr, quint64 length) +{ + Q_UNUSED(addr); + Q_UNUSED(length); +} + +void IDebuggerEngine::setRegisterValue(int regnr, const QString &value) +{ + Q_UNUSED(regnr); + Q_UNUSED(value); +} + +bool IDebuggerEngine::checkConfiguration(int toolChain, + QString *errorMessage, QString *settingsPage) const +{ + Q_UNUSED(toolChain); + Q_UNUSED(errorMessage); + Q_UNUSED(settingsPage); + return true; +} + +void IDebuggerEngine::showDebuggerInput(int channel, const QString &msg) +{ + m_manager->showDebuggerInput(channel, msg); +} + +void IDebuggerEngine::showDebuggerOutput(int channel, const QString &msg) +{ + m_manager->showDebuggerOutput(channel, msg); +} + +} // namespace Internal +} // namespace Debugger + diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h index 3cf48f5a14fdf6d41f39705cbecd6329b78c34b7..f093376325397069ee98c06ecaa20368dcf06988 100644 --- a/src/plugins/debugger/idebuggerengine.h +++ b/src/plugins/debugger/idebuggerengine.h @@ -113,18 +113,23 @@ public: virtual void reloadFullStack() = 0; virtual void watchPoint(const QPoint &) {} - virtual void fetchMemory(MemoryViewAgent *, QObject *, quint64 addr, quint64 length) - { Q_UNUSED(addr); Q_UNUSED(length); } + virtual void fetchMemory(MemoryViewAgent *, QObject *, + quint64 addr, quint64 length); virtual void fetchDisassembler(DisassemblerViewAgent *) {} - virtual void setRegisterValue(int regnr, const QString &value) - { Q_UNUSED(regnr); Q_UNUSED(value); } - + virtual void setRegisterValue(int regnr, const QString &value); virtual void addOptionPages(QList<Core::IOptionsPage*> *) const {} virtual unsigned debuggerCapabilities() const { return 0; } - virtual bool checkConfiguration(int /* toolChain */, QString * /* errorMessage */, QString * /* settingsPage */ = 0) const { return true; } + + virtual bool checkConfiguration(int toolChain, + QString *errorMessage, QString *settingsPage = 0) const; virtual bool isSynchroneous() const { return false; } virtual QString qtNamespace() const { return QString(); } + + // Convenience + void showDebuggerInput(int channel, const QString &msg); + void showDebuggerOutput(int channel, const QString &msg); + protected: void showStatusMessage(const QString &msg, int timeout = -1); DebuggerState state() const; diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index e4a3bb61ab699dd394492e2c3ade4feabcac3ad8..b4cfd13f26e6acdb9fa1fc4eb606508c17283e1d 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -1390,13 +1390,11 @@ int WatchHandler::format(const QByteArray &iname) const return result; } -QByteArray WatchHandler::formatRequests() const +QByteArray WatchHandler::expansionRequests() const { QByteArray ba; //m_locals->formatRequests(&ba, m_locals->m_root); //m_watchers->formatRequests(&ba, m_watchers->m_root); - - ba.append("expanded:"); if (!m_expandedINames.isEmpty()) { QSetIterator<QByteArray> jt(m_expandedINames); while (jt.hasNext()) { @@ -1406,9 +1404,12 @@ QByteArray WatchHandler::formatRequests() const } ba.chop(1); } - ba.append(' '); + return ba; +} - ba.append("typeformats:"); +QByteArray WatchHandler::typeFormatRequests() const +{ + QByteArray ba; if (!m_typeFormats.isEmpty()) { QHashIterator<QString, int> it(m_typeFormats); while (it.hasNext()) { @@ -1420,9 +1421,12 @@ QByteArray WatchHandler::formatRequests() const } ba.chop(1); } - ba.append(' '); + return ba; +} - ba.append("formats:"); +QByteArray WatchHandler::individualFormatRequests() const +{ + QByteArray ba; if (!m_individualFormats.isEmpty()) { QHashIterator<QByteArray, int> it(m_individualFormats); while (it.hasNext()) { @@ -1434,8 +1438,6 @@ QByteArray WatchHandler::formatRequests() const } ba.chop(1); } - ba.append(' '); - return ba; } diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 38bb85c87d43e06f6991aeb0cf1ea2200da9d57c..8890dee507956f5af85a4aed221b48c74f76c52e 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -173,7 +173,10 @@ public: QStringList watchedExpressions() const; QHash<QByteArray, int> watcherNames() const { return m_watcherNames; } - QByteArray formatRequests() const; + + QByteArray expansionRequests() const; + QByteArray typeFormatRequests() const; + QByteArray individualFormatRequests() const; static QString watcherEditPlaceHolder(); int format(const QByteArray &iname) const; diff --git a/tests/manual/gdbdebugger/python/math.py b/tests/manual/gdbdebugger/python/math.py index 5b8fbcce4496e483eb8a663d3667bca2ff51f761..63f3b2a7d52d987beb37d360bee54a7d668daaf6 100644 --- a/tests/manual/gdbdebugger/python/math.py +++ b/tests/manual/gdbdebugger/python/math.py @@ -4,6 +4,7 @@ def square(a): return a def cube(a): + l = [1, 2, 4] x = square(a) x = x * a x = x + 1