
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




