add Qt Creator dumper for PIP types and PINetworkAddress GDB printer
This commit is contained in:
@@ -8,3 +8,4 @@ CMakeLists.txt.user*
|
|||||||
/build*
|
/build*
|
||||||
/AGENTS.md
|
/AGENTS.md
|
||||||
/plans
|
/plans
|
||||||
|
__pycache__
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ PIP ships a GDB pretty-printer script, `tools/gdb/pip_pp.py`, that makes the bas
|
|||||||
| \a PISet<T> | `{3, 5}` |
|
| \a PISet<T> | `{3, 5}` |
|
||||||
| \a PIPair<K,V> | `{"k", 7}` |
|
| \a PIPair<K,V> | `{"k", 7}` |
|
||||||
| \a PIVariant | `PIVariant(pivInt, 4 bytes)` |
|
| \a PIVariant | `PIVariant(pivInt, 4 bytes)` |
|
||||||
|
| \a PINetworkAddress | `192.168.1.10:8080` |
|
||||||
|
|
||||||
Nested containers are printed recursively, e.g. `PIVector<PIString>` prints as `{"a", "bb"}`.
|
Nested containers are printed recursively, e.g. `PIVector<PIString>` prints as `{"a", "bb"}`.
|
||||||
Pointers to the covered types show the address and the content:
|
Pointers to the covered types show the address and the content:
|
||||||
@@ -62,6 +63,27 @@ add-auto-load-safe-path <root_dir>
|
|||||||
The stub is installed only for shared builds; for static builds
|
The stub is installed only for shared builds; for static builds
|
||||||
use the manual `source` command.
|
use the manual `source` command.
|
||||||
|
|
||||||
|
\section qtcreator Qt Creator
|
||||||
|
|
||||||
|
Qt Creator's Variables/Expressions views do not use GDB
|
||||||
|
pretty-printers; they run their own Python dumper. PIP provides the
|
||||||
|
dumper module `tools/qtcreator/pip_types.py`, which covers the same
|
||||||
|
types as `pip_pp.py`. To enable it:
|
||||||
|
|
||||||
|
1. Open the debugger settings (Qt Creator -> Settings -> Debugger).
|
||||||
|
2. Switch to the "Variables and expressions" tab.
|
||||||
|
3. In the "Extra dumper file" field (tooltip: "Path to a Python file
|
||||||
|
containing additional data dumpers"), enter the path to the file:
|
||||||
|
|
||||||
|
\code
|
||||||
|
/path/to/pip/tools/qtcreator/pip_types.py
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
After that PIString, PIVector<T>, PIMap<K,V> and the other types from
|
||||||
|
the table above show their content in the Variables/Expressions views.
|
||||||
|
No changes to the GDB setup (`.gdbinit`, auto-load stub) are needed for
|
||||||
|
Qt Creator; those keep working for the command-line GDB.
|
||||||
|
|
||||||
\section verifying Verifying the installation
|
\section verifying Verifying the installation
|
||||||
|
|
||||||
A check script builds a demo with all covered types and asserts the expected
|
A check script builds a demo with all covered types and asserts the expected
|
||||||
@@ -88,6 +110,7 @@ tools/gdb/test/test_pp.sh build_linux
|
|||||||
| \a PISet<T> | `{3, 5}` |
|
| \a PISet<T> | `{3, 5}` |
|
||||||
| \a PIPair<K,V> | `{"k", 7}` |
|
| \a PIPair<K,V> | `{"k", 7}` |
|
||||||
| \a PIVariant | `PIVariant(pivInt, 4 bytes)` |
|
| \a PIVariant | `PIVariant(pivInt, 4 bytes)` |
|
||||||
|
| \a PINetworkAddress | `192.168.1.10:8080` |
|
||||||
|
|
||||||
Вложенные контейнеры выводятся рекурсивно, например `PIVector<PIString>`
|
Вложенные контейнеры выводятся рекурсивно, например `PIVector<PIString>`
|
||||||
выводится как `{"a", "bb"}`. Указатели на поддерживаемые типы показывают
|
выводится как `{"a", "bb"}`. Указатели на поддерживаемые типы показывают
|
||||||
|
|||||||
+21
-1
@@ -3,7 +3,8 @@ GDB pretty-printers for the PIP (Platform-Independent Primitives) library.
|
|||||||
|
|
||||||
Covered types:
|
Covered types:
|
||||||
PIString, PIByteArray, PIChar, PIVector<T>, PIDeque<T>,
|
PIString, PIByteArray, PIChar, PIVector<T>, PIDeque<T>,
|
||||||
PIStringList, PIMap<K,V>, PISet<T>, PIPair<K,V>, PIVariant
|
PIStringList, PIMap<K,V>, PISet<T>, PIPair<K,V>, PIVariant,
|
||||||
|
PINetworkAddress
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
@@ -248,6 +249,24 @@ class _PIPairPrinter(_Printer):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class _PINetworkAddressPrinter(_Printer):
|
||||||
|
"""PINetworkAddress: union {uint ip_; uchar ip_b[4]}; ushort port_.
|
||||||
|
|
||||||
|
The IP bytes are stored in ip_b[0..3] in octet order, so they are
|
||||||
|
printed as-is (no byte-swap, works for any endianness).
|
||||||
|
Printed as "i.i.i.i:p".
|
||||||
|
"""
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
try:
|
||||||
|
# Mask against a signed char type: octets must be 0..255.
|
||||||
|
b = [int(self._val["ip_b"][i]) & 0xFF for i in range(4)]
|
||||||
|
port = int(self._val["port_"])
|
||||||
|
return self._prefix + "%d.%d.%d.%d:%d" % (b[0], b[1], b[2], b[3], port)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class _PIVariantPrinter(_Printer):
|
class _PIVariantPrinter(_Printer):
|
||||||
"""PIVariant: PIByteArray _content (serialized), Type _type (enum).
|
"""PIVariant: PIByteArray _content (serialized), Type _type (enum).
|
||||||
|
|
||||||
@@ -282,6 +301,7 @@ _PATTERNS = [
|
|||||||
(re.compile(r"^PISet<.*>$"), lambda v, p: _PISetPrinter(v, p)),
|
(re.compile(r"^PISet<.*>$"), lambda v, p: _PISetPrinter(v, p)),
|
||||||
(re.compile(r"^PIPair<.*>$"), lambda v, p: _PIPairPrinter(v, p)),
|
(re.compile(r"^PIPair<.*>$"), lambda v, p: _PIPairPrinter(v, p)),
|
||||||
(re.compile(r"^PIVariant$"), lambda v, p: _PIVariantPrinter(v, p)),
|
(re.compile(r"^PIVariant$"), lambda v, p: _PIVariantPrinter(v, p)),
|
||||||
|
(re.compile(r"^PINetworkAddress$"), lambda v, p: _PINetworkAddressPrinter(v, p)),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "pibytearray.h"
|
#include "pibytearray.h"
|
||||||
#include "pichar.h"
|
#include "pichar.h"
|
||||||
#include "pimap.h"
|
#include "pimap.h"
|
||||||
|
#include "pinetworkaddress.h"
|
||||||
#include "pipair.h"
|
#include "pipair.h"
|
||||||
#include "piset.h"
|
#include "piset.h"
|
||||||
#include "pistring.h"
|
#include "pistring.h"
|
||||||
@@ -28,6 +29,8 @@ static PIString * ptr_str = 0;
|
|||||||
static PIString * ptr_null = 0;
|
static PIString * ptr_null = 0;
|
||||||
static PIChar chr_a;
|
static PIChar chr_a;
|
||||||
static PIChar chr_cyr;
|
static PIChar chr_cyr;
|
||||||
|
static PINetworkAddress addr;
|
||||||
|
static PINetworkAddress addr_null;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct PPInit {
|
struct PPInit {
|
||||||
@@ -58,6 +61,8 @@ struct PPInit {
|
|||||||
chr_a = PIChar('a');
|
chr_a = PIChar('a');
|
||||||
chr_cyr = PIChar((char16_t)0x043C);
|
chr_cyr = PIChar((char16_t)0x043C);
|
||||||
|
|
||||||
|
addr = PINetworkAddress(PIString("192.168.1.10"), 8080);
|
||||||
|
|
||||||
str_esc = "a\"b\\c\nd\te";
|
str_esc = "a\"b\\c\nd\te";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ OUT="$(gdb -batch -nx \
|
|||||||
-ex "print pair_str_int" \
|
-ex "print pair_str_int" \
|
||||||
-ex "print var_int" \
|
-ex "print var_int" \
|
||||||
-ex "print var_invalid" \
|
-ex "print var_invalid" \
|
||||||
|
-ex "print addr" \
|
||||||
|
-ex "print addr_null" \
|
||||||
-ex "print ptr_str" \
|
-ex "print ptr_str" \
|
||||||
-ex "print *ptr_str" \
|
-ex "print *ptr_str" \
|
||||||
"${WORK}/demo_pp" 2>&1)"
|
"${WORK}/demo_pp" 2>&1)"
|
||||||
@@ -102,6 +104,8 @@ check '^\$[0-9]+ = \{"one", "two"\}$' "PIStringList"
|
|||||||
check '^\$[0-9]+ = \{"k", 7\}$' "PIPair"
|
check '^\$[0-9]+ = \{"k", 7\}$' "PIPair"
|
||||||
check '^\$[0-9]+ = PIVariant\(pivInt, 4 bytes\)$' "PIVariant typed"
|
check '^\$[0-9]+ = PIVariant\(pivInt, 4 bytes\)$' "PIVariant typed"
|
||||||
check '^\$[0-9]+ = PIVariant\(pivInvalid, 0 bytes\)$' "PIVariant invalid"
|
check '^\$[0-9]+ = PIVariant\(pivInvalid, 0 bytes\)$' "PIVariant invalid"
|
||||||
|
check '^\$[0-9]+ = 192\.168\.1\.10:8080$' "PINetworkAddress"
|
||||||
|
check '^\$[0-9]+ = 0\.0\.0\.0:0$' "PINetworkAddress null"
|
||||||
check '^\$[0-9]+ = \(PIString \*\) 0x[0-9a-f]+ "hello"$' "pointer to PIString"
|
check '^\$[0-9]+ = \(PIString \*\) 0x[0-9a-f]+ "hello"$' "pointer to PIString"
|
||||||
check '^\$[0-9]+ = "hello"$' "dereferenced pointer"
|
check '^\$[0-9]+ = "hello"$' "dereferenced pointer"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,286 @@
|
|||||||
|
# Data dumpers for the PIP (Platform-Independent Primitives) library.
|
||||||
|
#
|
||||||
|
# Makes the Qt Creator Variables/Expressions views show the content of the
|
||||||
|
# basic PIP types instead of their raw internals (the Qt Creator dumper
|
||||||
|
# does not use GDB pretty-printers, it needs its own dumpers; this module
|
||||||
|
# mirrors tools/gdb/pip_pp.py):
|
||||||
|
#
|
||||||
|
# PIString -> hello
|
||||||
|
# PIByteArray -> {0x48, 0x65, 0x6c, 0x6c, 0x6f}
|
||||||
|
# PIChar -> 'a' or U+043m
|
||||||
|
# PIVector<T> -> [1, 2, 3]
|
||||||
|
# PIDeque<T> -> [1, 2, 3]
|
||||||
|
# PIStringList -> ["one", "two"]
|
||||||
|
# PIMap<K, V> -> {k: v}
|
||||||
|
# PISet<T> -> [3, 5]
|
||||||
|
# PIPair<K, V> -> (k, v)
|
||||||
|
# PIVariant -> PIVariant(pivInt, 4 bytes)
|
||||||
|
# PINetworkAddress -> 192.168.1.10:8080
|
||||||
|
#
|
||||||
|
# Enable: Qt Creator -> Settings -> Debugger -> "Variables and expressions"
|
||||||
|
# tab -> "Extra dumper file" -> point to this file.
|
||||||
|
#
|
||||||
|
# Requirements: the executable and the PIP library are built with debug
|
||||||
|
# information (-g). All dumpers are read-only and defensive: on any error
|
||||||
|
# they fall back to the default (raw) member expansion.
|
||||||
|
|
||||||
|
from dumper import Children, SubItem
|
||||||
|
|
||||||
|
# Maximum number of elements printed per container (matches pip_pp.py).
|
||||||
|
_MAX_ELEMENTS = 32
|
||||||
|
# Absolute safety cap: never try to read more elements than this
|
||||||
|
# (protects against corrupted size fields).
|
||||||
|
_MAX_READ = 10000000
|
||||||
|
# Maximum string/bytearray elements read for the display value.
|
||||||
|
_MAX_DISPLAY_UNITS = 4096
|
||||||
|
|
||||||
|
|
||||||
|
def _utf16Text(units):
|
||||||
|
"""Build a plain text string from a list of UTF-16 code units."""
|
||||||
|
out = []
|
||||||
|
i = 0
|
||||||
|
n = len(units)
|
||||||
|
while i < n:
|
||||||
|
u = units[i]
|
||||||
|
# Combine surrogate pairs.
|
||||||
|
if 0xD800 <= u <= 0xDBFF and i + 1 < n and 0xDC00 <= units[i + 1] <= 0xDFFF:
|
||||||
|
u = 0x10000 + ((u - 0xD800) << 10) + (units[i + 1] - 0xDC00)
|
||||||
|
i += 2
|
||||||
|
else:
|
||||||
|
i += 1
|
||||||
|
if 0 <= u <= 0x10FFFF:
|
||||||
|
out.append(chr(u))
|
||||||
|
else:
|
||||||
|
out.append("\ufffd")
|
||||||
|
return "".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def _dequeUnits(dvalue):
|
||||||
|
"""Read UTF-16 units from a PIDeque<PIChar> value, or None on error."""
|
||||||
|
size = int(dvalue['pid_size'])
|
||||||
|
if size < 0 or size > _MAX_READ:
|
||||||
|
return None
|
||||||
|
if size == 0:
|
||||||
|
return []
|
||||||
|
data = dvalue['pid_data']
|
||||||
|
start = int(dvalue['pid_start'])
|
||||||
|
if start < 0:
|
||||||
|
return None
|
||||||
|
return [int(data[start + i]['ch']) for i in range(min(size, _MAX_DISPLAY_UNITS))]
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIString(d, value):
|
||||||
|
"""PIString: PIDeque<PIChar> d + cache members. Printed as plain text."""
|
||||||
|
try:
|
||||||
|
size = int(value['d']['pid_size'])
|
||||||
|
units = _dequeUnits(value['d'])
|
||||||
|
if units is not None:
|
||||||
|
text = _utf16Text(units)
|
||||||
|
if size > _MAX_DISPLAY_UNITS:
|
||||||
|
text += "..."
|
||||||
|
# Hex-encode with the utf8 tag so the raw text (quotes,
|
||||||
|
# backslashes, control chars) never appears unescaped in the
|
||||||
|
# dumper protocol stream.
|
||||||
|
d.putValue(d.hexencode(text), "utf8", length=len(text))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIByteArray(d, value):
|
||||||
|
"""PIByteArray: PIDeque<uchar> d. Printed as a hex byte list."""
|
||||||
|
try:
|
||||||
|
size = int(value['d']['pid_size'])
|
||||||
|
if 0 <= size <= _MAX_READ:
|
||||||
|
if size == 0:
|
||||||
|
d.putValue('{}')
|
||||||
|
else:
|
||||||
|
dvalue = value['d']
|
||||||
|
data = dvalue['pid_data']
|
||||||
|
start = int(dvalue['pid_start'])
|
||||||
|
lim = min(size, _MAX_ELEMENTS)
|
||||||
|
items = ['0x%02x' % int(data[start + i]) for i in range(lim)]
|
||||||
|
tail = '' if size <= _MAX_ELEMENTS else ', ... (%d total)' % size
|
||||||
|
d.putValue('{%s%s}' % (', '.join(items), tail))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIChar(d, value):
|
||||||
|
"""PIChar: single UTF-16 code unit (ushort ch)."""
|
||||||
|
try:
|
||||||
|
ch = int(value['ch'])
|
||||||
|
if 0x20 <= ch <= 0x7E and ch not in (0x22, 0x5C):
|
||||||
|
d.putValue("'%s'" % chr(ch))
|
||||||
|
else:
|
||||||
|
d.putValue('U+%04x' % ch)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PINetworkAddress(d, value):
|
||||||
|
"""PINetworkAddress: union {uint ip_; uchar ip_b[4]}; ushort port_.
|
||||||
|
|
||||||
|
The IP bytes are stored in ip_b[0..3] in octet order, so they are
|
||||||
|
printed as-is (no byte-swap, works for any endianness).
|
||||||
|
Printed as "i.i.i.i:p".
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
# Mask against a signed char type: octets must be 0..255.
|
||||||
|
b = [int(value['ip_b'][i]) & 0xFF for i in range(4)]
|
||||||
|
except Exception:
|
||||||
|
ip = int(value['ip_'])
|
||||||
|
if d.byteorder == 'big':
|
||||||
|
b = [(ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
|
||||||
|
(ip >> 8) & 0xFF, ip & 0xFF]
|
||||||
|
else:
|
||||||
|
b = [ip & 0xFF, (ip >> 8) & 0xFF,
|
||||||
|
(ip >> 16) & 0xFF, (ip >> 24) & 0xFF]
|
||||||
|
port = int(value['port_'])
|
||||||
|
d.putValue('%d.%d.%d.%d:%d' % (b[0], b[1], b[2], b[3], port))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIVector(d, value):
|
||||||
|
"""PIVector<T>: T* piv_data, size_t piv_size, size_t piv_rsize."""
|
||||||
|
try:
|
||||||
|
inner = value.type[0]
|
||||||
|
size = int(value['piv_size'])
|
||||||
|
if 0 <= size <= _MAX_READ:
|
||||||
|
d.putItemCount(size)
|
||||||
|
d.putPlotData(int(value['piv_data']), size, inner)
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def _dequeDump(d, value, inner):
|
||||||
|
"""Dump a PIDeque<T>-layout value with the given element type."""
|
||||||
|
size = int(value['pid_size'])
|
||||||
|
start = int(value['pid_start'])
|
||||||
|
if 0 <= size <= _MAX_READ and 0 <= start:
|
||||||
|
d.putItemCount(size)
|
||||||
|
d.putPlotData(int(value['pid_data']) + start * inner.size(), size, inner)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIDeque(d, value):
|
||||||
|
"""PIDeque<T>: T* pid_data, size_t pid_size, size_t pid_rsize, size_t pid_start."""
|
||||||
|
try:
|
||||||
|
if _dequeDump(d, value, value.type[0]):
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIStringList(d, value):
|
||||||
|
"""PIStringList: derived from PIDeque<PIString>."""
|
||||||
|
try:
|
||||||
|
if _dequeDump(d, value, d.createType('PIString')):
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIMap(d, value):
|
||||||
|
"""PIMap<K, V>: PIVector<V> pim_content + PIDeque<MapIndex> pim_index."""
|
||||||
|
try:
|
||||||
|
index = value['pim_index']
|
||||||
|
size = int(index['pid_size'])
|
||||||
|
if not (0 <= size <= _MAX_READ):
|
||||||
|
raise ValueError('bad size')
|
||||||
|
d.putItemCount(size)
|
||||||
|
if d.isExpanded():
|
||||||
|
start = int(index['pid_start'])
|
||||||
|
entryType = index.type[0]
|
||||||
|
entrySize = entryType.size()
|
||||||
|
indexBase = int(index['pid_data'])
|
||||||
|
content = value['pim_content']
|
||||||
|
valueType = content.type[0]
|
||||||
|
valueBase = int(content['piv_data'])
|
||||||
|
with Children(d, size, maxNumChild=1000):
|
||||||
|
for i in d.childRange():
|
||||||
|
entry = d.createValueFromAddress(
|
||||||
|
indexBase + (start + i) * entrySize, entryType)
|
||||||
|
key = entry['key']
|
||||||
|
val = d.createValueFromAddress(
|
||||||
|
valueBase + int(entry['index']) * valueType.size(),
|
||||||
|
valueType)
|
||||||
|
d.putPairItem(i, (key, val), 'key', 'value')
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PISet(d, value):
|
||||||
|
"""PISet<T>: derived from PIMap<T, uchar>. Printed as the key list."""
|
||||||
|
try:
|
||||||
|
index = value['pim_index']
|
||||||
|
size = int(index['pid_size'])
|
||||||
|
if not (0 <= size <= _MAX_READ):
|
||||||
|
raise ValueError('bad size')
|
||||||
|
d.putItemCount(size)
|
||||||
|
if d.isExpanded():
|
||||||
|
start = int(index['pid_start'])
|
||||||
|
entryType = index.type[0]
|
||||||
|
entrySize = entryType.size()
|
||||||
|
indexBase = int(index['pid_data'])
|
||||||
|
with Children(d, size, maxNumChild=1000):
|
||||||
|
for i in d.childRange():
|
||||||
|
entry = d.createValueFromAddress(
|
||||||
|
indexBase + (start + i) * entrySize, entryType)
|
||||||
|
d.putSubItem(i, entry['key'])
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIPair(d, value):
|
||||||
|
"""PIPair<K, V>: public first, second members."""
|
||||||
|
try:
|
||||||
|
with Children(d):
|
||||||
|
first = d.putSubItem('first', value['first'])
|
||||||
|
second = d.putSubItem('second', value['second'])
|
||||||
|
d.putValue('(%s, %s)' % (
|
||||||
|
first.value if first.encoding is None else '...',
|
||||||
|
second.value if second.encoding is None else '...'))
|
||||||
|
except Exception:
|
||||||
|
d.putPlainChildren(value)
|
||||||
|
|
||||||
|
|
||||||
|
def _enumName(d, value):
|
||||||
|
"""Name of an enum value (e.g. 'pivInt'), or its number on failure."""
|
||||||
|
try:
|
||||||
|
import gdb
|
||||||
|
ival = int(value)
|
||||||
|
etype = gdb.lookup_type(d.type_name(value.typeid))
|
||||||
|
if etype.code != gdb.TYPE_CODE_ENUM:
|
||||||
|
return str(ival)
|
||||||
|
name = str(gdb.Value(ival).cast(etype))
|
||||||
|
return name.split('::')[-1] if '::' in name else name
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
return str(int(value))
|
||||||
|
except Exception:
|
||||||
|
return '?'
|
||||||
|
|
||||||
|
|
||||||
|
def qdump__PIVariant(d, value):
|
||||||
|
"""PIVariant: PIByteArray _content (serialized) + Type _type (enum)."""
|
||||||
|
try:
|
||||||
|
nbytes = int(value['_content']['d']['pid_size'])
|
||||||
|
d.putValue('PIVariant(%s, %d bytes)' % (_enumName(d, value['_type']), nbytes))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
d.putPlainChildren(value)
|
||||||
Reference in New Issue
Block a user