Working on lldb data formatting some more

This commit is contained in:
2026-04-20 08:42:36 -04:00
parent f3e1daf4fe
commit 4c1eebab96

View File

@@ -1,6 +1,13 @@
import lldb, signal, sys, time
import lldb.formatters.Logger
import codelldb.value
############################################################
#
# Store pointers to some important types and globals.
#
############################################################
_FNameEntryType = None
@@ -9,6 +16,28 @@ _FUObjectItemType = None
_GNameBlocksDebug = None
_GObjectArrayForDebugVisualizers = None
def _init_globals(target):
global _FNameEntryType, _FNameEntryStride, _FUObjectItemType
global _GNameBlocksDebug, _GObjectArrayForDebugVisualizers
_FNameEntryType = target.FindFirstType('FNameEntry')
if not _FNameEntryType.IsValid():
print('UEDataFormatter: FNameEntry type not found')
_FNameEntryStride = _FNameEntryType.GetByteAlign()
_FUObjectItemType = target.FindFirstType('FUObjectItem')
if not _FUObjectItemType.IsValid():
print('UEDataFormatter: FUObjectItem type not found')
_GNameBlocksDebug = target.FindFirstGlobalVariable('GNameBlocksDebug')
if not _GNameBlocksDebug.IsValid():
print('UEDataFormatter: GNameBlocksDebug not found')
_GObjectArrayForDebugVisualizers = target.FindFirstGlobalVariable('GObjectArrayForDebugVisualizers')
if not _GObjectArrayForDebugVisualizers.IsValid():
print('UEDataFormatter: GObjectArrayForDebugVisualizers not found')
############################################################
#
# A forwarding synth provider is a provider that
@@ -952,83 +981,15 @@ def UObjectSummaryProvider(valobj, dict):
# return 'expired'
# return Object.Dereference().GetSummary() or ('0x%x' % addr)
def __lldb_init_module(debugger, dict):
print("Running lldb_init_module")
debugger.HandleCommand('type category delete UEDataFormatters')
global _FNameEntryType, _FNameEntryStride, _FUObjectItemType
global _GNameBlocksDebug, _GObjectArrayForDebugVisualizers
target = debugger.GetSelectedTarget()
_FNameEntryType = target.FindFirstType('FNameEntry')
_FNameEntryStride = _FNameEntryType.GetByteAlign()
_FUObjectItemType = target.FindFirstType('FUObjectItem')
_GNameBlocksDebug = target.FindFirstGlobalVariable('GNameBlocksDebug')
if not _GNameBlocksDebug.IsValid():
print('UEDataFormatter: GNameBlocksDebug not found')
_GObjectArrayForDebugVisualizers = target.FindFirstGlobalVariable('GObjectArrayForDebugVisualizers')
if not _GObjectArrayForDebugVisualizers.IsValid():
print('UEDataFormatter: GObjectArrayForDebugVisualizers not found')
debugger.HandleCommand('type summary add -F UEDataFormatter.UEFStringSummaryProvider -e FString -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.UEFNameSummaryProvider -e FName -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TObjectPtrSynthProvider -x "^TObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TObjectPtrSummaryProvider -e -x "^TObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TStrongObjectPtrSynthProvider -x "^TStrongObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TStrongObjectPtrSummaryProvider -e -x "^TStrongObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TSharedPtrSynthProvider -x "^TSharedPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TSharedPtrSummaryProvider -e -x "^TSharedPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TSharedPtrSynthProvider -x "^TSharedRef<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TSharedPtrSummaryProvider -e -x "^TSharedRef<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TWeakPtrSynthProvider -x "^TWeakPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TWeakPtrSummaryProvider -e -x "^TWeakPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TWeakObjectPtrSynthProvider -x "^TWeakObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TWeakObjectPtrSummaryProvider -e -x "^TWeakObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TWeakObjectPtrSynthProvider -x "^FWeakObjectPtr$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TWeakObjectPtrSummaryProvider -e FWeakObjectPtr -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.UObjectSynthProvider UObject -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.UObjectSummaryProvider -e UObject -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEUObjectBaseSummaryProvider -e UObjectBase -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEFFieldClassSummaryProvider -e FFieldClass -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEFFieldSummaryProvider -e FField -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEFWeakObjectPtrSummaryProvider -e FWeakObjectPtr -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UETWeakObjectPtrSynthProvider -x "TWeakObjectPtr<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UETWeakObjectPtrSynthProvider -x "TAutoWeakObjectPtr<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEArraySynthProvider -x "TArray<.+,.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEArraySummaryProvider -e -x "TArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEBitArraySynthProvider -x "TBitArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEBitArraySummaryProvider -e -x "TBitArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UESparseArraySynthProvider -x "TSparseArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UESparseArraySummaryProvider -e -x "TSparseArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEChunkedArraySynthProvider -x "TChunkedArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEChunkedArraySummaryProvider -e -x "TChunkedArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UESetSynthProvider -x "TSet<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UESetSummaryProvider -e -x "TSet<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEMapSynthProvider -x "TMap<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEMapSummaryProvider -e -x "TMap<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEMapSynthProvider -x "TMapBase<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEMapSummaryProvider -e -x "TMapBase<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UETObjectPtrSynthProvider -x "^TObjectPtr<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UETObjectPtrSummaryProvider -e -x "^TObjectPtr<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UETSharedPtrSynthProvider -x "^TSharedPtr<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UETSharedPtrSummaryProvider -e -x "^TSharedPtr<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UETSharedPtrSynthProvider -x "^TSharedRef<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UETSharedPtrSummaryProvider -e -x "^TSharedRef<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UETWeakPtrSynthProvider -x "^TWeakPtr<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UETWeakPtrSummaryProvider -e -x "^TWeakPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand("type category enable UEDataFormatters")
def _patch_codelldb_value():
"""Patch codelldb.value.Value with Unreal-friendly navigation:
- __getattr__ auto-derefs pointers and falls back to iterating
children by GetName() (so base classes like 'UWidget' resolve).
##############################################################
#
# The getattr which is built in to codelldb.value.Value
# fails to fetch synthetic values. Monkey-patch it.
#
##############################################################
This affects every /se and /py expression that uses Value — strictly
more forgiving than the stock behavior (paths that used to fail now
succeed), but it IS a global behavior change.
"""
try:
from codelldb.value import Value
except ImportError:
return
def __getattr__(self, name):
def _value_getattr(self, name):
sbv = self._Value__sbvalue
if sbv.GetType().IsPointerType():
sbv = sbv.Dereference()
@@ -1041,68 +1002,15 @@ def _patch_codelldb_value():
break
if not child.IsValid():
raise AttributeError("Attribute '%s' is not defined" % name)
return Value(child)
Value.__getattr__ = __getattr__
return codelldb.value.Value(child)
_patch_codelldb_value()
codelldb.value.Value.__getattr__ = _value_getattr
##############################################################
#
# FV
#
#############################################################
def fv(expr):
"""Evaluate a Python-syntax expression against the current frame's variables.
Every frame variable is pre-wrapped in a codelldb Value and placed in
the eval globals, so e.g. fv("Widget.Object.SCompoundWidget") walks via
the (patched) Value.__getattr__, fv("Arr[3].Field") works via
Value.__getitem__, and arithmetic/comparisons work via Value's dunders.
Usage in Watch: /py fv("Widget.Object.SCompoundWidget.SWidget")
"""
from codelldb.value import Value
frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
eval_globals = {}
for var in frame.GetVariables(True, True, True, True):
name = var.GetName()
if var.IsValid() and name:
eval_globals[name] = Value(var)
try:
result = eval(expr, eval_globals, {})
except Exception as e:
return "<%s: %s>" % (type(e).__name__, e)
if isinstance(result, Value):
return Value.unwrap(result)
return result
def fv2():
frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
top = frame.FindVariable('Top')
if not top.IsValid():
return
widget = top.GetChildMemberWithName('Widget')
if not widget.IsValid():
return
uwidget = FindNamedChild(widget, 'UWidget')
if not uwidget.IsValid():
return
return uwidget
def FindNamedChild(value, name):
for i in range(value.GetNumChildren()):
child = value.GetChildAtIndex(i)
if child.IsValid() and child.GetName() == name:
return child
return lldb.SBValue()
##############################################################
#
# The standard repr for SBValue will recurse infinitely if you
# provide useful synth providers for smart pointers
# The standard repr for SBValue will recurse infinitely if
# you provide useful synth providers for smart pointers.
# Monkey-patch it.
#
##############################################################
@@ -1126,3 +1034,44 @@ def _sbvalue_display(v):
lldb.SBValue.__repr__ = _sbvalue_repr
##############################################################
#
# Module Initialization
#
#############################################################
def __lldb_init_module(debugger, dict):
print("Running lldb_init_module")
_init_globals(debugger.GetSelectedTarget())
debugger.HandleCommand('type category delete UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.UEFStringSummaryProvider -e FString -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.UEFNameSummaryProvider -e FName -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TObjectPtrSynthProvider -x "^TObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TObjectPtrSummaryProvider -e -x "^TObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TStrongObjectPtrSynthProvider -x "^TStrongObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TStrongObjectPtrSummaryProvider -e -x "^TStrongObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TSharedPtrSynthProvider -x "^TSharedPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TSharedPtrSummaryProvider -e -x "^TSharedPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TSharedPtrSynthProvider -x "^TSharedRef<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TSharedPtrSummaryProvider -e -x "^TSharedRef<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TWeakPtrSynthProvider -x "^TWeakPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TWeakPtrSummaryProvider -e -x "^TWeakPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TWeakObjectPtrSynthProvider -x "^TWeakObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TWeakObjectPtrSummaryProvider -e -x "^TWeakObjectPtr<.+>$" -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.TWeakObjectPtrSynthProvider -x "^FWeakObjectPtr$" -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.TWeakObjectPtrSummaryProvider -e FWeakObjectPtr -w UEDataFormatters')
debugger.HandleCommand('type synthetic add -l UEDataFormatter.UObjectSynthProvider UObject -w UEDataFormatters')
debugger.HandleCommand('type summary add -F UEDataFormatter.UObjectSummaryProvider -e UObject -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEArraySynthProvider -x "TArray<.+,.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEArraySummaryProvider -e -x "TArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEBitArraySynthProvider -x "TBitArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEBitArraySummaryProvider -e -x "TBitArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UESparseArraySynthProvider -x "TSparseArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UESparseArraySummaryProvider -e -x "TSparseArray<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UESetSynthProvider -x "TSet<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UESetSummaryProvider -e -x "TSet<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEMapSynthProvider -x "TMap<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEMapSummaryProvider -e -x "TMap<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type synthetic add -l UEDataFormatter.UEMapSynthProvider -x "TMapBase<.+>$" -w UEDataFormatters')
# debugger.HandleCommand('type summary add -F UEDataFormatter.UEMapSummaryProvider -e -x "TMapBase<.+>$" -w UEDataFormatters')
debugger.HandleCommand("type category enable UEDataFormatters")