Working on lldb data formatting some more
This commit is contained in:
@@ -1,6 +1,13 @@
|
|||||||
|
|
||||||
import lldb, signal, sys, time
|
import lldb, signal, sys, time
|
||||||
import lldb.formatters.Logger
|
import lldb.formatters.Logger
|
||||||
|
import codelldb.value
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
#
|
||||||
|
# Store pointers to some important types and globals.
|
||||||
|
#
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
|
||||||
_FNameEntryType = None
|
_FNameEntryType = None
|
||||||
@@ -9,6 +16,28 @@ _FUObjectItemType = None
|
|||||||
_GNameBlocksDebug = None
|
_GNameBlocksDebug = None
|
||||||
_GObjectArrayForDebugVisualizers = 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
|
# A forwarding synth provider is a provider that
|
||||||
@@ -952,157 +981,36 @@ def UObjectSummaryProvider(valobj, dict):
|
|||||||
# return 'expired'
|
# return 'expired'
|
||||||
# return Object.Dereference().GetSummary() or ('0x%x' % addr)
|
# 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).
|
|
||||||
|
|
||||||
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):
|
|
||||||
sbv = self._Value__sbvalue
|
|
||||||
if sbv.GetType().IsPointerType():
|
|
||||||
sbv = sbv.Dereference()
|
|
||||||
child = sbv.GetChildMemberWithName(name)
|
|
||||||
if not child.IsValid():
|
|
||||||
for i in range(sbv.GetNumChildren()):
|
|
||||||
c = sbv.GetChildAtIndex(i)
|
|
||||||
if c.GetName() == name:
|
|
||||||
child = c
|
|
||||||
break
|
|
||||||
if not child.IsValid():
|
|
||||||
raise AttributeError("Attribute '%s' is not defined" % name)
|
|
||||||
return Value(child)
|
|
||||||
Value.__getattr__ = __getattr__
|
|
||||||
|
|
||||||
_patch_codelldb_value()
|
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
#
|
#
|
||||||
# FV
|
# The getattr which is built in to codelldb.value.Value
|
||||||
|
# fails to fetch synthetic values. Monkey-patch it.
|
||||||
#
|
#
|
||||||
#############################################################
|
##############################################################
|
||||||
|
|
||||||
|
def _value_getattr(self, name):
|
||||||
|
sbv = self._Value__sbvalue
|
||||||
|
if sbv.GetType().IsPointerType():
|
||||||
|
sbv = sbv.Dereference()
|
||||||
|
child = sbv.GetChildMemberWithName(name)
|
||||||
|
if not child.IsValid():
|
||||||
|
for i in range(sbv.GetNumChildren()):
|
||||||
|
c = sbv.GetChildAtIndex(i)
|
||||||
|
if c.GetName() == name:
|
||||||
|
child = c
|
||||||
|
break
|
||||||
|
if not child.IsValid():
|
||||||
|
raise AttributeError("Attribute '%s' is not defined" % name)
|
||||||
|
return codelldb.value.Value(child)
|
||||||
|
|
||||||
def fv(expr):
|
codelldb.value.Value.__getattr__ = _value_getattr
|
||||||
"""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
|
# The standard repr for SBValue will recurse infinitely if
|
||||||
# provide useful synth providers for smart pointers
|
# you provide useful synth providers for smart pointers.
|
||||||
|
# Monkey-patch it.
|
||||||
#
|
#
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
@@ -1126,3 +1034,44 @@ def _sbvalue_display(v):
|
|||||||
|
|
||||||
lldb.SBValue.__repr__ = _sbvalue_repr
|
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")
|
||||||
|
|||||||
Reference in New Issue
Block a user