feat(debug): enhance type hinting in gdb and Python debug visualizers
This commit is contained in:
@@ -158,13 +158,19 @@ def _append_field(fields_out, name, value, is_pointer=False, type_hint=None):
|
||||
|
||||
def _process_member(label, member_val, node_id, fields_out, edges, nodes, visited, type_hint=None):
|
||||
member_type = member_val.type.strip_typedefs()
|
||||
# Every field gets a type hint, not just ones a wrapper (pretty-printer
|
||||
# or Rust-enum-variant) has already labeled -- a plain `int`/`char *`
|
||||
# member is just as worth showing as one that came out of an unwrapped
|
||||
# std::optional. The caller's type_hint (a wrapper name) still wins when
|
||||
# present, since that's more informative than the leaf's own raw type.
|
||||
own_type_hint = type_hint or _type_name(member_type)
|
||||
|
||||
if member_type.code == gdb.TYPE_CODE_PTR:
|
||||
try:
|
||||
ptr_int = int(member_val)
|
||||
except gdb.error:
|
||||
ptr_int = 0
|
||||
_append_field(fields_out, label, _addr_str(ptr_int), is_pointer=True, type_hint=type_hint)
|
||||
_append_field(fields_out, label, _addr_str(ptr_int), is_pointer=True, type_hint=own_type_hint)
|
||||
if ptr_int:
|
||||
edges.append((node_id, _addr_str(ptr_int), label))
|
||||
_visit_pointer(member_val, ptr_int, nodes, edges, visited)
|
||||
@@ -199,7 +205,7 @@ def _process_member(label, member_val, node_id, fields_out, edges, nodes, visite
|
||||
_append_field(fields_out, label, _format_scalar(member_val), type_hint=wrapper_name)
|
||||
return
|
||||
|
||||
_append_field(fields_out, label, _format_scalar(member_val), type_hint=type_hint)
|
||||
_append_field(fields_out, label, _format_scalar(member_val), type_hint=own_type_hint)
|
||||
|
||||
|
||||
def _describe_struct(val, node_id, nodes, edges, visited):
|
||||
@@ -217,7 +223,7 @@ def _describe_struct(val, node_id, nodes, edges, visited):
|
||||
else:
|
||||
for leaf_label, leaf_val in leaves:
|
||||
_process_member(leaf_label, leaf_val, node_id, fields_out, edges, nodes, visited, wrapper_name)
|
||||
nodes[node_id] = fields_out
|
||||
nodes[node_id] = {"fields": fields_out, "type": wrapper_name}
|
||||
return
|
||||
|
||||
t = val.type.strip_typedefs()
|
||||
@@ -230,7 +236,7 @@ def _describe_struct(val, node_id, nodes, edges, visited):
|
||||
continue
|
||||
_process_member(f.name, member_val, node_id, fields_out, edges, nodes, visited)
|
||||
|
||||
nodes[node_id] = fields_out
|
||||
nodes[node_id] = {"fields": fields_out, "type": _type_name(t)}
|
||||
|
||||
|
||||
def _visit_pointer(ptr_val, ptr_int, nodes, edges, visited):
|
||||
@@ -269,14 +275,16 @@ def _visit_pointer(ptr_val, ptr_int, nodes, edges, visited):
|
||||
text = text[:500] + "…"
|
||||
except (gdb.error, UnicodeDecodeError):
|
||||
text = _format_scalar(ptr_val.dereference())
|
||||
nodes[node_id] = [{"name": "value", "value": text, "isPointer": False}]
|
||||
leaf_fields = []
|
||||
_append_field(leaf_fields, "value", text, type_hint=_type_name(pointee_type))
|
||||
nodes[node_id] = {"fields": leaf_fields, "type": _type_name(ptr_val.type.strip_typedefs())}
|
||||
else:
|
||||
if node_id in nodes:
|
||||
return # already described (richly or otherwise) via another path
|
||||
pointee = ptr_val.dereference()
|
||||
nodes[node_id] = [
|
||||
{"name": "value", "value": _format_scalar(pointee), "isPointer": False}
|
||||
]
|
||||
leaf_fields = []
|
||||
_append_field(leaf_fields, "value", _format_scalar(pointee), type_hint=_type_name(pointee_type))
|
||||
nodes[node_id] = {"fields": leaf_fields, "type": _type_name(ptr_val.type.strip_typedefs())}
|
||||
|
||||
|
||||
def _walk_primary_root(root_val, nodes, edges, visited):
|
||||
@@ -297,9 +305,9 @@ def _walk_primary_root(root_val, nodes, edges, visited):
|
||||
_describe_struct(root_val, node_id, nodes, edges, visited)
|
||||
return node_id
|
||||
else:
|
||||
nodes["root"] = [
|
||||
{"name": "value", "value": _format_scalar(root_val), "isPointer": False}
|
||||
]
|
||||
leaf_fields = []
|
||||
_append_field(leaf_fields, "value", _format_scalar(root_val), type_hint=_type_name(t))
|
||||
nodes["root"] = {"fields": leaf_fields, "type": _type_name(t)}
|
||||
return None
|
||||
|
||||
|
||||
@@ -424,7 +432,12 @@ def build_graph_json(root_val, watched_roots):
|
||||
continue
|
||||
_add_named_root(sym.name, val, "global", nodes, edges, visited, roots, skip_addrs)
|
||||
|
||||
nodes_json = [{"id": nid, "fields": fields} for nid, fields in nodes.items()]
|
||||
nodes_json = [
|
||||
{"id": nid, "fields": node["fields"], "type": node["type"]}
|
||||
if node.get("type")
|
||||
else {"id": nid, "fields": node["fields"]}
|
||||
for nid, node in nodes.items()
|
||||
]
|
||||
edges_json = [
|
||||
{"from": src, "to": dst, "label": label}
|
||||
for (src, dst, label) in edges
|
||||
|
||||
Reference in New Issue
Block a user