More work on getting lldb data formatters in better shape.
This commit is contained in:
@@ -1,34 +1,78 @@
|
||||
# Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
# /*=============================================================================
|
||||
# LLDB Data Formatters for Unreal Types
|
||||
# =============================================================================*/
|
||||
|
||||
import lldb
|
||||
import lldb, signal, sys, time
|
||||
import lldb.formatters.Logger
|
||||
import faulthandler
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
|
||||
# Uncomment the line below to have the data formatters emit debug logging
|
||||
# lldb.formatters.Logger._lldb_formatters_debug_level=1
|
||||
|
||||
# What documentation there is for parsing values in LLDB can be found here:
|
||||
# https://lldb.llvm.org/python_reference/index.html
|
||||
# https://lldb.llvm.org/python_reference/lldb.SBValue-class.html
|
||||
|
||||
# To install:
|
||||
# 1) Open Terminal and run:
|
||||
# touch ~/.lldbinit
|
||||
# open ~/.lldbinit
|
||||
# 2) Add the following text to .lldbini and save - modifying the path as appropriate:
|
||||
# settings set target.inline-breakpoint-strategy always
|
||||
# command script import "/Path/To/Epic/UE/Engine/Extras/LLDBDataFormatters/UEDataFormatter.py"
|
||||
# 3) Restart Xcode
|
||||
|
||||
_FNameEntryType = None
|
||||
_FNameEntryStride = 2
|
||||
_FNameEntryStride = None
|
||||
_FUObjectItemType = None
|
||||
_GNameBlocksDebug = None
|
||||
_GObjectArrayForDebugVisualizers = None
|
||||
|
||||
############################################################
|
||||
#
|
||||
# A forwarding synth provider is a provider that
|
||||
# forwards all child lookups to a different SBValue.
|
||||
#
|
||||
############################################################
|
||||
|
||||
class ForwardingSynthProvider:
|
||||
def __init__(self, valobj, dict):
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
|
||||
def num_children(self):
|
||||
return self.forward_to.GetNumChildren()
|
||||
|
||||
def get_child_index(self, name):
|
||||
return self.forward_to.GetIndexOfChildWithName(name)
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
return self.forward_to.GetChildAtIndex(index)
|
||||
|
||||
def update(self):
|
||||
self.forward_to = lldb.SBValue()
|
||||
|
||||
def has_children(self):
|
||||
return self.forward_to.IsValid() and self.forward_to.MightHaveChildren()
|
||||
|
||||
############################################################
|
||||
#
|
||||
# A Stored synth provider is an synth provider that
|
||||
# just stores an array of children.
|
||||
#
|
||||
############################################################
|
||||
|
||||
class StoredSynthProvider:
|
||||
def __init__(self, valobj, dict):
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
|
||||
def num_children(self):
|
||||
return len(self.children)
|
||||
|
||||
def get_child_index(self, name):
|
||||
for i, child in enumerate(self.children):
|
||||
if child.GetName() == name:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
if 0 <= index < len(self.children):
|
||||
return self.children[index]
|
||||
return lldb.SBValue()
|
||||
|
||||
def update(self):
|
||||
self.children = []
|
||||
|
||||
def has_children(self):
|
||||
return len(self.children) > 0
|
||||
|
||||
############################################################
|
||||
#
|
||||
# Provider for FString
|
||||
#
|
||||
############################################################
|
||||
|
||||
def UEFStringSummaryProvider(valobj, dict):
|
||||
target = valobj.GetTarget()
|
||||
@@ -53,6 +97,11 @@ def UEFStringSummaryProvider(valobj, dict):
|
||||
if summary and summary.startswith('u"'): return summary[1:]
|
||||
return summary
|
||||
|
||||
############################################################
|
||||
#
|
||||
# Provider for FName
|
||||
#
|
||||
############################################################
|
||||
|
||||
def UEFNameSummaryProvider(valobj, dict):
|
||||
target = valobj.GetTarget()
|
||||
@@ -64,8 +113,7 @@ def UEFNameSummaryProvider(valobj, dict):
|
||||
block_idx = index >> 16
|
||||
entry_offset = (index & 0xFFFF) * _FNameEntryStride
|
||||
|
||||
gname_var = target.FindFirstGlobalVariable('GNameBlocksDebug')
|
||||
gname_ptr = gname_var.GetValueAsUnsigned(0)
|
||||
gname_ptr = _GNameBlocksDebug.GetValueAsUnsigned(0)
|
||||
|
||||
error = lldb.SBError()
|
||||
block_addr = process.ReadPointerFromMemory(gname_ptr + block_idx * target.GetAddressByteSize(), error)
|
||||
@@ -92,27 +140,11 @@ def UEFNameSummaryProvider(valobj, dict):
|
||||
if number > 0: return '%s_%d' % (name, number - 1)
|
||||
return name
|
||||
|
||||
|
||||
class ForwardingSynthProvider:
|
||||
def __init__(self, valobj, dict):
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
|
||||
def num_children(self):
|
||||
return self.forward_to.GetNumChildren()
|
||||
|
||||
def get_child_index(self, name):
|
||||
return self.forward_to.GetIndexOfChildWithName(name)
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
return self.forward_to.GetChildAtIndex(index)
|
||||
|
||||
def update(self):
|
||||
self.forward_to = lldb.SBValue()
|
||||
|
||||
def has_children(self):
|
||||
return self.forward_to.MightHaveChildren()
|
||||
|
||||
############################################################
|
||||
#
|
||||
# Providers for TObjectPtr
|
||||
#
|
||||
############################################################
|
||||
|
||||
class TObjectPtrSynthProvider(ForwardingSynthProvider):
|
||||
def update(self):
|
||||
@@ -124,115 +156,172 @@ class TObjectPtrSynthProvider(ForwardingSynthProvider):
|
||||
self.forward_to = debug_ptr.Dereference()
|
||||
|
||||
def TObjectPtrSummaryProvider(valobj, dict):
|
||||
debug_ptr = valobj.GetChildMemberWithName('DebugPtr')
|
||||
debug_ptr = valobj.GetNonSyntheticValue().GetChildMemberWithName('DebugPtr')
|
||||
addr = debug_ptr.GetValueAsUnsigned(0)
|
||||
if addr == 0: return 'nullptr'
|
||||
if addr & 1: return 'unresolved'
|
||||
return '{...}'
|
||||
|
||||
############################################################
|
||||
#
|
||||
# Providers for TStrongObjectPtr
|
||||
#
|
||||
############################################################
|
||||
|
||||
class TSharedPtrSynthProvider:
|
||||
def __init__(self, valobj, dict):
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
|
||||
def num_children(self):
|
||||
return 1
|
||||
|
||||
def has_children(self):
|
||||
return true
|
||||
|
||||
def get_child_index(self, name):
|
||||
if name == 'Object': return 0
|
||||
return -1
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
if index == 0: return self.object
|
||||
return lldb.SBValue()
|
||||
|
||||
class TStrongObjectPtrSynthProvider(ForwardingSynthProvider):
|
||||
def update(self):
|
||||
self.object = self.valobj.GetChildMemberWithName('Object')
|
||||
obj = self.valobj.GetChildMemberWithName('Object')
|
||||
addr = obj.GetValueAsUnsigned(0)
|
||||
if addr == 0:
|
||||
self.forward_to = lldb.SBValue()
|
||||
else:
|
||||
self.forward_to = obj.Dereference()
|
||||
|
||||
|
||||
def TSharedPtrSummaryProvider(valobj, dict):
|
||||
obj = valobj.GetChildMemberWithName('Object')
|
||||
def TStrongObjectPtrSummaryProvider(valobj, dict):
|
||||
obj = valobj.GetNonSyntheticValue().GetChildMemberWithName('Object')
|
||||
addr = obj.GetValueAsUnsigned(0)
|
||||
if addr == 0: return 'nullptr'
|
||||
return '{...}'
|
||||
|
||||
############################################################
|
||||
#
|
||||
# Providers for TWeakObjectPtr
|
||||
#
|
||||
############################################################
|
||||
|
||||
# def UEUObjectBaseSummaryProvider(valobj,dict):
|
||||
# Name = valobj.GetChildMemberWithName('NamePrivate')
|
||||
# return Name.GetSummary()
|
||||
def _resolve_weak_object_ptr(valobj):
|
||||
obj_index = valobj.GetChildMemberWithName('ObjectIndex').GetValueAsSigned(0)
|
||||
serial_num = valobj.GetChildMemberWithName('ObjectSerialNumber').GetValueAsSigned(0)
|
||||
if serial_num == 0 or obj_index < 0: return None
|
||||
chunk_idx = obj_index >> 16 # NumElementsPerChunk = 65536
|
||||
item_idx = obj_index & 0xFFFF
|
||||
objects = _GObjectArrayForDebugVisualizers.Dereference().GetChildMemberWithName('Objects') # FUObjectItem**
|
||||
chunk = objects.GetChildAtIndex(chunk_idx, lldb.eDynamicDontRunTarget, True) # FUObjectItem*
|
||||
item = chunk.GetChildAtIndex(item_idx, lldb.eDynamicDontRunTarget, True) # FUObjectItem
|
||||
actual_serial = item.GetChildMemberWithName('SerialNumber').GetValueAsSigned(0)
|
||||
if actual_serial != serial_num: return None
|
||||
return item.GetChildMemberWithName('Object')
|
||||
|
||||
# def UEFFieldClassSummaryProvider(valobj,dict):
|
||||
# Name = valobj.GetChildMemberWithName('Name')
|
||||
# return Name.GetSummary()
|
||||
class TWeakObjectPtrSynthProvider(ForwardingSynthProvider):
|
||||
def update(self):
|
||||
obj_ptr = _resolve_weak_object_ptr(self.valobj)
|
||||
if obj_ptr is None or obj_ptr.GetValueAsUnsigned(0) == 0:
|
||||
self.forward_to = lldb.SBValue()
|
||||
else:
|
||||
self.forward_to = obj_ptr.Dereference()
|
||||
|
||||
# def UEFFieldSummaryProvider(valobj,dict):
|
||||
# Name = valobj.GetChildMemberWithName('NamePrivate')
|
||||
# return Name.GetSummary()
|
||||
def TWeakObjectPtrSummaryProvider(valobj, dict):
|
||||
raw = valobj.GetNonSyntheticValue()
|
||||
serial_num = raw.GetChildMemberWithName('ObjectSerialNumber').GetValueAsSigned(0)
|
||||
if serial_num == 0: return 'nullptr'
|
||||
if _resolve_weak_object_ptr(raw) is None: return 'expired'
|
||||
return '{...}'
|
||||
|
||||
# class UETWeakObjectPtrSynthProvider:
|
||||
############################################################
|
||||
#
|
||||
# Providers for TSharedPtr
|
||||
#
|
||||
############################################################
|
||||
|
||||
# def __init__(self, valobj, dict):
|
||||
# logger = lldb.formatters.Logger.Logger()
|
||||
# self.valobj = valobj
|
||||
class TSharedPtrSynthProvider(ForwardingSynthProvider):
|
||||
def update(self):
|
||||
obj = self.valobj.GetChildMemberWithName('Object')
|
||||
addr = obj.GetValueAsUnsigned(0)
|
||||
if addr == 0:
|
||||
self.forward_to = lldb.SBValue()
|
||||
else:
|
||||
self.forward_to = obj.Dereference()
|
||||
|
||||
# def num_children(self):
|
||||
# logger = lldb.formatters.Logger.Logger()
|
||||
# return 1
|
||||
def TSharedPtrSummaryProvider(valobj, dict):
|
||||
obj = valobj.GetNonSyntheticValue().GetChildMemberWithName('Object')
|
||||
addr = obj.GetValueAsUnsigned(0)
|
||||
if addr == 0: return 'nullptr'
|
||||
return '{...}'
|
||||
|
||||
# def get_child_index(self,name):
|
||||
# logger = lldb.formatters.Logger.Logger()
|
||||
# return 0
|
||||
############################################################
|
||||
#
|
||||
# Providers for TWeakPtr
|
||||
#
|
||||
############################################################
|
||||
|
||||
# def get_child_at_index(self,index):
|
||||
# logger = lldb.formatters.Logger.Logger()
|
||||
# logger >> "Retrieving child %s" % index
|
||||
# if self.ObjectSerialNumberVal >= 1:
|
||||
# Expr = 'GObjectArrayForDebugVisualizers->Objects[%s][%s].SerialNumber == %s' % (int(self.ObjectIndexVal/65536), self.ObjectIndexVal%65536, self.ObjectSerialNumberVal)
|
||||
# Val = self.valobj.CreateValueFromExpression("%s" % self.ObjectIndexVal, Expr)
|
||||
# Value = Val.GetValueAsUnsigned(0)
|
||||
# if Value != 0:
|
||||
# Expr = 'GObjectArrayForDebugVisualizers->Objects[%s][%s].Object' % (int(self.ObjectIndexVal/65536), self.ObjectIndexVal%65536)
|
||||
# return self.valobj.CreateValueFromExpression('Object', Expr)
|
||||
# else:
|
||||
# Expr = '(void*)0xDEADBEEF'
|
||||
# return self.valobj.CreateValueFromExpression('Object', Expr)
|
||||
def _resolve_weak_ptr(valobj):
|
||||
"""Returns (object SBValue, is_expired).
|
||||
valobj must be the raw (non-synthetic) TWeakPtr."""
|
||||
weak_ref = valobj.GetChildMemberWithName('WeakReferenceCount')
|
||||
ref_ctrl_ptr_val = weak_ref.GetChildMemberWithName('ReferenceController')
|
||||
if ref_ctrl_ptr_val.GetValueAsUnsigned(0) == 0: return None, False
|
||||
shared_count_field = ref_ctrl_ptr_val.Dereference().GetChildMemberWithName('SharedReferenceCount')
|
||||
if shared_count_field.GetValueAsSigned(0) <= 0: return None, True
|
||||
obj = valobj.GetChildMemberWithName('Object')
|
||||
return obj, False
|
||||
|
||||
# Expr = 'nullptr'
|
||||
# return self.valobj.CreateValueFromExpression('Object', Expr)
|
||||
class TWeakPtrSynthProvider(ForwardingSynthProvider):
|
||||
def update(self):
|
||||
obj, expired = _resolve_weak_ptr(self.valobj)
|
||||
if obj is None or obj.GetValueAsUnsigned(0) == 0:
|
||||
self.forward_to = lldb.SBValue()
|
||||
else:
|
||||
self.forward_to = obj.Dereference()
|
||||
|
||||
# def update(self):
|
||||
# logger = lldb.formatters.Logger.Logger()
|
||||
# try:
|
||||
# self.ObjectSerialNumber = self.valobj.GetChildMemberWithName('ObjectSerialNumber')
|
||||
# self.ObjectSerialNumberVal = self.ObjectSerialNumber.GetValueAsSigned(0)
|
||||
# self.ObjectIndex = self.valobj.GetChildMemberWithName('ObjectIndex')
|
||||
# self.ObjectIndexVal = self.ObjectIndex.GetValueAsSigned(0)
|
||||
# except:
|
||||
# pass
|
||||
def TWeakPtrSummaryProvider(valobj, dict):
|
||||
obj, expired = _resolve_weak_ptr(valobj.GetNonSyntheticValue())
|
||||
if expired: return 'expired'
|
||||
if obj is None: return 'nullptr'
|
||||
return '{...}'
|
||||
|
||||
# def has_children(self):
|
||||
# return True
|
||||
############################################################
|
||||
#
|
||||
# Providers for TUniquePtr
|
||||
#
|
||||
############################################################
|
||||
|
||||
# def UEFWeakObjectPtrSummaryProvider(valobj,dict):
|
||||
# ObjectSerialNumber = valobj.GetChildMemberWithName('ObjectSerialNumber')
|
||||
# ObjectSerialNumberVal = ObjectSerialNumber.GetValueAsSigned(0)
|
||||
# if ObjectSerialNumberVal < 1:
|
||||
# return 'object=nullptr'
|
||||
# ObjectIndex = valobj.GetChildMemberWithName('ObjectIndex')
|
||||
# ObjectIndexVal = ObjectIndex.GetValueAsSigned(0)
|
||||
# Expr = 'GObjectArrayForDebugVisualizers->Objects[%s][%s].SerialNumber == %s' % (int(ObjectIndexVal/65536), ObjectIndexVal%65536, ObjectSerialNumberVal)
|
||||
# Val = valobj.CreateValueFromExpression('%s' % ObjectIndexVal, Expr)
|
||||
# ValRef = Val.GetValueAsUnsigned(0)
|
||||
# if ValRef == 0:
|
||||
# return 'object=STALE'
|
||||
# else:
|
||||
# Expr = 'GObjectArrayForDebugVisualizers->Objects[%s][%s].Object' % (int(ObjectIndexVal/65536), ObjectIndexVal%65536)
|
||||
# Val = valobj.CreateValueFromExpression("%s" % ObjectIndexVal, Expr)
|
||||
# return 'object=' + Val.GetValue()
|
||||
class TUniquePtrSynthProvider(ForwardingSynthProvider):
|
||||
def update(self):
|
||||
ptr = self.valobj.GetChildMemberWithName('Ptr')
|
||||
addr = ptr.GetValueAsUnsigned(0)
|
||||
if addr == 0:
|
||||
self.forward_to = lldb.SBValue()
|
||||
else:
|
||||
self.forward_to = ptr.Dereference()
|
||||
|
||||
def TUniquePtrSummaryProvider(valobj, dict):
|
||||
ptr = valobj.GetNonSyntheticValue().GetChildMemberWithName('Ptr')
|
||||
addr = ptr.GetValueAsUnsigned(0)
|
||||
if addr == 0: return 'nullptr'
|
||||
return '{...}'
|
||||
|
||||
############################################################
|
||||
#
|
||||
# Providers for UObject
|
||||
#
|
||||
############################################################
|
||||
|
||||
class UObjectSynthProvider(StoredSynthProvider):
|
||||
def update(self):
|
||||
self.children = []
|
||||
raw = self.valobj
|
||||
target = raw.GetTarget()
|
||||
debug_ptr = raw.GetChildMemberWithName('ClassPrivate') \
|
||||
.GetChildMemberWithName('ObjectPtr') \
|
||||
.GetChildMemberWithName('DebugPtr')
|
||||
class_val = target.CreateValueFromAddress(
|
||||
'Class', lldb.SBAddress(debug_ptr.GetLoadAddress(), target), debug_ptr.GetType())
|
||||
self.children.append(class_val)
|
||||
name_field = raw.GetChildMemberWithName('NamePrivate')
|
||||
name_val = target.CreateValueFromAddress(
|
||||
'Name', lldb.SBAddress(name_field.GetLoadAddress(), target), name_field.GetType())
|
||||
self.children.append(name_val)
|
||||
|
||||
def UObjectSummaryProvider(valobj, dict):
|
||||
raw = valobj.GetNonSyntheticValue()
|
||||
class_debug_ptr = raw.GetChildMemberWithName('ClassPrivate') \
|
||||
.GetChildMemberWithName('ObjectPtr') \
|
||||
.GetChildMemberWithName('DebugPtr')
|
||||
class_addr = class_debug_ptr.GetValueAsUnsigned(0)
|
||||
if not class_addr:
|
||||
return 'null'
|
||||
return UEFNameSummaryProvider(
|
||||
class_debug_ptr.Dereference().GetChildMemberWithName('NamePrivate'), dict)
|
||||
|
||||
# class UEChunkedArraySynthProvider:
|
||||
|
||||
@@ -864,20 +953,39 @@ def TSharedPtrSummaryProvider(valobj, dict):
|
||||
# return Object.Dereference().GetSummary() or ('0x%x' % addr)
|
||||
|
||||
def __lldb_init_module(debugger, dict):
|
||||
global _FNameEntryType, _FNameEntryStride
|
||||
_FNameEntryType = debugger.GetSelectedTarget().FindFirstType('FNameEntry')
|
||||
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 summary add -F UEDataFormatter.UEUObjectBaseSummaryProvider -e UObject -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.UEUObjectBaseSummaryProvider -e UObjectBaseUtility -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')
|
||||
@@ -938,6 +1046,13 @@ def _patch_codelldb_value():
|
||||
|
||||
_patch_codelldb_value()
|
||||
|
||||
##############################################################
|
||||
#
|
||||
# FV
|
||||
#
|
||||
#############################################################
|
||||
|
||||
|
||||
def fv(expr):
|
||||
"""Evaluate a Python-syntax expression against the current frame's variables.
|
||||
|
||||
@@ -984,10 +1099,13 @@ def FindNamedChild(value, name):
|
||||
return lldb.SBValue()
|
||||
|
||||
|
||||
##############################################################
|
||||
#
|
||||
# The standard repr for SBValue will recurse infinitely if you
|
||||
# provide useful synth providers for smart pointers. This won't.
|
||||
# provide useful synth providers for smart pointers
|
||||
#
|
||||
##############################################################
|
||||
|
||||
def _sbvalue_repr(self):
|
||||
n = self.GetNumChildren()
|
||||
if n == 0: return _sbvalue_display(self)
|
||||
@@ -1008,6 +1126,3 @@ def _sbvalue_display(v):
|
||||
|
||||
lldb.SBValue.__repr__ = _sbvalue_repr
|
||||
|
||||
import builtins
|
||||
builtins.fv = fv
|
||||
builtins.fv2 = fv2
|
||||
|
||||
Reference in New Issue
Block a user