forked from qt-creator/qt-creator
From https://issuetracker.google.com/issues/240007217#comment17 "Some a background on the technical aspect of SEGVs: Android Runtime (ART) uses SEGV for various internal purposes (it triggers a SEGV and handles it without crashing the app, the app doesn't know it happened). When the native debugger is connected, the debugger must intercept all SEGV signals. When running the debugger on Android API level 27 and newer, we make the debugger skip these SEGV signals (i.e., forward them to be handled by ART), because we know how to handle real SEGV signals inside ART. For older Android versions (26 or older), we did not have this support, so the debugger stops at every SEGV (i.e., it cannot know if the signal is a real crash or an ART-internal thing)." Arguably, this should be caught by the LLDB Android platform bits, but... Task-number: QTCREATORBUG-30759 Task-number: QTCREATORBUG-29928 Task-number: QTCREATORBUG-30080 Change-Id: I8cabe4a0675c596a9617520aff0d62ad11321f0e Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Cristian Adam <cristian.adam@qt.io> Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
NOTE:
While the primary intention of this pretty printing implementation is
to provide what Qt Creator needs, it can sometimes be used in plain
GDB and LLDB sessions, too.
This features is provided as-is. There is no guarantee this works in any
way outside Qt Creator, this setup is not officially supported.
Bugreports or (better!) patches are welcome.
With
python import sys
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