diff options
| author | Walnut <39544927+Walnut356@users.noreply.github.com> | 2025-01-10 22:02:45 -0600 |
|---|---|---|
| committer | Walnut <39544927+Walnut356@users.noreply.github.com> | 2025-01-10 22:02:45 -0600 |
| commit | 4f595334f5771b28d85c46f29859d2e48af270b5 (patch) | |
| tree | b1c0dbe5173d6d69323d65559ec31b329100df5e | |
| parent | 2b8ff7534a085271d3803cfd9401ef3ec9112563 (diff) | |
| download | rust-4f595334f5771b28d85c46f29859d2e48af270b5.tar.gz rust-4f595334f5771b28d85c46f29859d2e48af270b5.zip | |
add alternate inner type lookup for vec/string for missing template args
| -rw-r--r-- | src/etc/lldb_commands | 4 | ||||
| -rw-r--r-- | src/etc/lldb_providers.py | 89 |
2 files changed, 86 insertions, 7 deletions
diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands index e2c30acfc85..5f24d0da047 100644 --- a/src/etc/lldb_commands +++ b/src/etc/lldb_commands @@ -1,8 +1,8 @@ # Forces test-compliant formatting to all other types type summary add -F _ -e -x -h "^.*$" --category Rust # Std String -type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)String$" --category Rust -type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust +type synthetic add -l lldb_lookup.StdStringSyntheticProvider -x "^(alloc::([a-z_]+::)+)String$" --category Rust +type summary add -F lldb_lookup.StdStringSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust # Std str type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?str$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index b1bf6f9b06c..063db7abb3c 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -9,6 +9,7 @@ from lldb import ( eBasicTypeLong, eBasicTypeUnsignedLong, eBasicTypeUnsignedChar, + eFormatChar, ) # from lldb.formatters import Logger @@ -143,11 +144,32 @@ def vec_to_string(vec: SBValue) -> str: ) -def StdStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: - # logger = Logger.Logger() - # logger >> "[StdStringSummaryProvider] for " + str(valobj.GetName()) - vec = valobj.GetChildAtIndex(0) - return '"%s"' % vec_to_string(vec) +def StdStringSummaryProvider(valobj, dict): + inner_vec = ( + valobj.GetNonSyntheticValue() + .GetChildMemberWithName("vec") + .GetNonSyntheticValue() + ) + + pointer = ( + inner_vec.GetChildMemberWithName("buf") + .GetChildMemberWithName("inner") + .GetChildMemberWithName("ptr") + .GetChildMemberWithName("pointer") + .GetChildMemberWithName("pointer") + ) + + length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned() + + if length <= 0: + return "" + error = SBError() + process = pointer.GetProcess() + data = process.ReadMemory(pointer.GetValueAsUnsigned(), length, error) + if error.Success(): + return '"' + data.decode("utf8", "replace") + '"' + else: + raise Exception("ReadMemory error: %s", error.GetCString()) def StdOsStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: @@ -266,6 +288,48 @@ class StructSyntheticProvider: return True +class StdStringSyntheticProvider: + def __init__(self, valobj: SBValue, _dict: LLDBOpaque): + self.valobj = valobj + self.update() + + def update(self): + inner_vec = self.valobj.GetChildMemberWithName("vec").GetNonSyntheticValue() + self.data_ptr = ( + inner_vec.GetChildMemberWithName("buf") + .GetChildMemberWithName("inner") + .GetChildMemberWithName("ptr") + .GetChildMemberWithName("pointer") + .GetChildMemberWithName("pointer") + ) + self.length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned() + self.element_type = self.data_ptr.GetType().GetPointeeType() + + def has_children(self) -> bool: + return True + + def num_children(self) -> int: + return self.length + + def get_child_index(self, name: str) -> int: + index = name.lstrip("[").rstrip("]") + if index.isdigit(): + return int(index) + + return -1 + + def get_child_at_index(self, index: int) -> SBValue: + if not 0 <= index < self.length: + return None + start = self.data_ptr.GetValueAsUnsigned() + address = start + index + element = self.data_ptr.CreateValueFromAddress( + f"[{index}]", address, self.element_type + ) + element.SetFormat(eFormatChar) + return element + + class MSVCStrSyntheticProvider: __slots__ = ["valobj", "data_ptr", "length"] @@ -699,6 +763,21 @@ class StdVecSyntheticProvider: ) self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) + + if not self.element_type.IsValid(): + # annoyingly, vec's constituent type isn't guaranteed to be contained anywhere useful. + # Some functions have it, but those functions only exist in binary when they're used. + # that means it's time for string-based garbage. + + # acquire the first generic parameter via its type name + _, _, end = self.valobj.GetTypeName().partition("<") + element_name, _, _ = end.partition(",") + + # this works even for built-in rust types like `u32` because internally it's just a + # `typedef` i really REALLY wish there was a better way to do this, but at the moment + # LLDB flat out ignores template parameters due to piggybacking off of TypeSystemClang. + self.element_type = self.valobj.target.FindFirstType(element_name) + self.element_type_size = self.element_type.GetByteSize() def has_children(self) -> bool: |
