forked from qt-creator/qt-creator
While the primary intention of this pretty printing implementation is to provide what Qt Creator needs, it can be used in a plain GDB and LLDB session, too. With python sys.path.insert(1, '<path/to/qtcreator>/share/qtcreator/debugger/') python from gdbbridge import * in .gdbinit there is a new "GDB command", called "pp". With code like int main(int argc, char *argv[]) { QString ss = "Hello"; QApplication app(argc, argv); app.setObjectName(ss); // break here } the "pp" command can be used as follows: (gdb) pp app app = [ <QGuiApplication> = {"Hello"} staticMetaObject = <QMetaObject> = {""} [parent] = <QObject *> = {"0x0"} [children] = <QObjectList> = {"<3 items>"} [properties] = "<>0 items>" [methods] = "<6 items>" [signals] = "<1 items>" ],<QApplication> = {"Hello"} (gdb) pp app [properties],[children] app = [ <QGuiApplication> = {"Hello"} staticMetaObject = <QMetaObject> = {""} [parent] = <QObject *> = {"0x0"} [children] = [ <QObject> = {""} <QObject> = {""} <QObject> = {"fusion"} ],<QObjectList> = {"<3 items>"} [properties] = [ windowIcon = <QVariant (QIcon)> = {""} cursorFlashTime = <QVariant (int)> = {"1000"} doubleClickInterval = <QVariant (int)> = {"400"} keyboardInputInterval = <QVariant (int)> = {"400"} wheelScrollLines = <QVariant (int)> = {"3"} globalStrut = <QVariant (QSize)> = {"(0, 0)"} startDragTime = <QVariant (int)> = {"500"} startDragDistance = <QVariant (int)> = {"10"} styleSheet = <QVariant (QString)> = {""} autoSipEnabled = <QVariant (bool)> = {"true"} ],"<10 items>" [methods] = "<6 items>" [signals] = "<1 items>" ],<QApplication> = {"Hello"} (gdb) pp ss ss = <QString> = {"Hello"} Or for LLDB (.lldbinit or directly in the LLDB interpreter): command script import <path/to/qtcreator>/share/qtcreator/debugger/lldbbridge.py This will add LLDB summary providers for all the Qt types in a new type category named 'Qt'. In order to hook a new debugger backend into this "common pretty printing system", the backend should expose a Python API containing at least the following: class Value: name() -> string # Name of this thing or None type() -> Type # Type of this value asBytes() -> bytes # Memory contents of this object, or None address() -> int # Address of this object, or None dereference() -> Value # Dereference if value is pointer, # remove reference if value is reference. hasChildren() -> bool # Whether this object has subobjects. expand() -> bool # Make sure that children are accessible. nativeDebuggerValue() -> string # Dumper value returned from the debugger childFromName(string name) -> Value # (optional) childFromField(Field field) -> Value # (optional) childFromIndex(int position) -> Value # (optional) class Type: name() -> string # Full name of this type bitsize() -> int # Size of type in bits code() -> TypeCodeTypedef | TypeCodeStruct | TypeCodeVoid | TypeCodeIntegral | TypeCodeFloat | TypeCodeEnum | TypeCodePointer | TypeCodeArray | TypeCodeComplex | TypeCodeReference | TypeCodeFunction | TypeCodeMemberPointer | TypeCodeUnresolvable unqualified() -> Type # Type without const/volatile target() -> Type # Type dereferenced if it is a pointer type, element if array etc stripTypedef() -> Type # Type with typedefs removed fields() -> [ Fields ] # List of fields (member and base classes) of this type templateArgument(int pos, bool numeric) -> Type or int # (optional) class Field: name() -> string # Name of member, None for anonymous items isBaseClass() -> bool # Whether this is a base class or normal member type() -> Type # Type of this member parentType() -> Type # Type of class this member belongs to bitsize() -> int # Size of member in bits bitpos() -> int # Offset of member in parent type in bits parseAndEvaluate(string: expr) -> Value # or None if not possible. lookupType(string: name) -> Type # or None if not possible. listOfLocals() -> [ Value ] # List of items currently in scope. readRawMemory(ULONG64 address, ULONG size) -> bytes # Read a block of data from the virtual address space