From 9787522ef66a22e4b59f14ddd18c2929ab6b888a Mon Sep 17 00:00:00 2001 From: jyelon Date: Tue, 21 Apr 2026 01:00:45 -0400 Subject: [PATCH] UE Data formatters done. --- .../Source/UEWingman/Handlers/Test_TMaps.h | 2 + tools/UEDataFormatter.py | 99 ++++++++++++++++--- 2 files changed, 87 insertions(+), 14 deletions(-) diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Test_TMaps.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Test_TMaps.h index bc399635..459a6b33 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Test_TMaps.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Test_TMaps.h @@ -50,6 +50,8 @@ public: Sparse.Add(TEXT("delta")); Sparse.RemoveAt(BetaIdx); + TTuple Tuple(1, TEXT("hello"), 3.14f, true, FName("world")); + // Set a breakpoint on the following line to inspect Map, Bits, and Sparse. WingOut::Stdout.Printf(TEXT("Test_TMaps: Map has %d entries, Bits has %d bits, Sparse has %d entries.\n"), Map.Num(), Bits.Num(), Sparse.Num()); diff --git a/tools/UEDataFormatter.py b/tools/UEDataFormatter.py index 49169fbe..ab20cdc3 100644 --- a/tools/UEDataFormatter.py +++ b/tools/UEDataFormatter.py @@ -45,6 +45,10 @@ def _init_globals(target): # ############################################################ +def TryGetSyntheticValue(v): + s = v.GetSyntheticValue() + return s if s.IsValid() else v + class ForwardingSynthProvider: def __init__(self, valobj, dict): self.valobj = valobj @@ -213,7 +217,7 @@ class TObjectPtrSynthProvider(ForwardingSynthProvider): if addr == 0 or addr & 1: # null or unresolved handle (odd address) self.forward_to = lldb.SBValue() else: - self.forward_to = debug_ptr.Dereference() + self.forward_to = TryGetSyntheticValue(debug_ptr.Dereference()) def TObjectPtrSummaryProvider(valobj, dict): debug_ptr = valobj.GetNonSyntheticValue().GetChildMemberWithName('DebugPtr') @@ -235,7 +239,7 @@ class TStrongObjectPtrSynthProvider(ForwardingSynthProvider): if addr == 0: self.forward_to = lldb.SBValue() else: - self.forward_to = obj.Dereference() + self.forward_to = TryGetSyntheticValue(obj.Dereference()) def TStrongObjectPtrSummaryProvider(valobj, dict): obj = valobj.GetNonSyntheticValue().GetChildMemberWithName('Object') @@ -268,7 +272,7 @@ class TWeakObjectPtrSynthProvider(ForwardingSynthProvider): if obj_ptr is None or obj_ptr.GetValueAsUnsigned(0) == 0: self.forward_to = lldb.SBValue() else: - self.forward_to = obj_ptr.Dereference() + self.forward_to = TryGetSyntheticValue(obj_ptr.Dereference()) def TWeakObjectPtrSummaryProvider(valobj, dict): raw = valobj.GetNonSyntheticValue() @@ -290,7 +294,7 @@ class TSharedPtrSynthProvider(ForwardingSynthProvider): if addr == 0: self.forward_to = lldb.SBValue() else: - self.forward_to = obj.Dereference() + self.forward_to = TryGetSyntheticValue(obj.Dereference()) def TSharedPtrSummaryProvider(valobj, dict): obj = valobj.GetNonSyntheticValue().GetChildMemberWithName('Object') @@ -321,7 +325,7 @@ class TWeakPtrSynthProvider(ForwardingSynthProvider): if obj is None or obj.GetValueAsUnsigned(0) == 0: self.forward_to = lldb.SBValue() else: - self.forward_to = obj.Dereference() + self.forward_to = TryGetSyntheticValue(obj.Dereference()) def TWeakPtrSummaryProvider(valobj, dict): obj, expired = _resolve_weak_ptr(valobj.GetNonSyntheticValue()) @@ -342,7 +346,7 @@ class TUniquePtrSynthProvider(ForwardingSynthProvider): if addr == 0: self.forward_to = lldb.SBValue() else: - self.forward_to = ptr.Dereference() + self.forward_to = TryGetSyntheticValue(ptr.Dereference()) def TUniquePtrSummaryProvider(valobj, dict): ptr = valobj.GetNonSyntheticValue().GetChildMemberWithName('Ptr') @@ -532,6 +536,76 @@ def TSparseArraySummaryProvider(valobj, dict): num_free = raw.GetChildMemberWithName('NumFreeIndices').GetValueAsSigned(0) return 'size=%d' % (array_num - num_free) +############################################################ +# +# Provider for TSet +# +############################################################ + +class TSetSynthProvider(ForwardingSynthProvider): + def update(self): + self.forward_to = TryGetSyntheticValue(self.valobj.GetChildMemberWithName('Elements')) + +def TSetSummaryProvider(valobj, dict): + elements = valobj.GetNonSyntheticValue().GetChildMemberWithName('Elements') + return TSparseArraySummaryProvider(elements, dict) + +############################################################ +# +# Provider for TMap / TMultiMap +# +############################################################ + +class TMapSynthProvider(ForwardingSynthProvider): + def update(self): + self.forward_to = TryGetSyntheticValue(self.valobj.GetChildMemberWithName('Pairs').GetNonSyntheticValue().GetChildMemberWithName('Elements')) + +def TMapSummaryProvider(valobj, dict): + pairs = valobj.GetNonSyntheticValue().GetChildMemberWithName('Pairs') + elements = pairs.GetNonSyntheticValue().GetChildMemberWithName('Elements') + return TSparseArraySummaryProvider(elements, dict) + +############################################################ +# +# Provider for TTuple +# +############################################################ + +def _tuple_child_name(index): + if index == 0: return 'Key' + if index == 1: return 'Value' + return 'Value%d' % index + +class TTupleSynthProvider(StoredSynthProvider): + def update(self): + self.children = [] + raw = self.valobj.GetNonSyntheticValue() + target = raw.GetTarget() + container = raw + first = raw.GetChildAtIndex(0) + if first.IsValid() and 'TTupleBase<' in (first.GetType().GetName() or ''): + container = first + n = container.GetNumChildren() + for i in range(n): + base = container.GetChildAtIndex(i) + field = base.GetChildAtIndex(0) + if not field.IsValid(): continue + child = target.CreateValueFromAddress( + _tuple_child_name(i), + lldb.SBAddress(field.GetLoadAddress(), target), + field.GetType()) + self.children.append(child) + +############################################################ +# +# Provider for TSetElement +# +############################################################ + +class TSetElementSynthProvider(ForwardingSynthProvider): + def update(self): + self.forward_to = TryGetSyntheticValue(self.valobj.GetChildMemberWithName('Value')) + ############################################################## # # The getattr which is built in to codelldb.value.Value @@ -618,6 +692,11 @@ def __lldb_init_module(debugger, dict): _register_provider(cat, '^TArray<.+>$', summary_fn='TArraySummaryProvider', synth_cls='TArraySynthProvider') _register_provider(cat, '^TBitArray<.+>$', summary_fn='TBitArraySummaryProvider', synth_cls='TBitArraySynthProvider') _register_provider(cat, '^TSparseArray<.+>$', summary_fn='TSparseArraySummaryProvider', synth_cls='TSparseArraySynthProvider') + _register_provider(cat, '^TSetElement<.+>$', synth_cls='TSetElementSynthProvider') + _register_provider(cat, '^TTuple<.+>$', synth_cls='TTupleSynthProvider') + _register_provider(cat, '^TSet<.+>$', summary_fn='TSetSummaryProvider', synth_cls='TSetSynthProvider') + _register_provider(cat, '^TMap<.+>$', summary_fn='TMapSummaryProvider', synth_cls='TMapSynthProvider') + _register_provider(cat, '^TMultiMap<.+>$', summary_fn='TMapSummaryProvider', synth_cls='TMapSynthProvider') _register_provider(cat, '^UObject$', summary_fn='UObjectSummaryProvider', synth_cls='UObjectSynthProvider') for class_name in ( @@ -627,11 +706,3 @@ def __lldb_init_module(debugger, dict): _register_provider(cat, '^%s$' % class_name, summary_fn='UObjectSummaryProvider') cat.SetEnabled(True) - -def counttypes(): - # Count all class types. - target = lldb.debugger.GetSelectedTarget() - count = 0 - for module in target.module_iter(): - count += module.GetTypes(lldb.eTypeClassClass).GetSize() - print('UEDataFormatter: %d class types found' % count)