|
9 | 9 | eBasicTypeLong,
|
10 | 10 | eBasicTypeUnsignedLong,
|
11 | 11 | eBasicTypeUnsignedChar,
|
| 12 | + eFormatChar, |
12 | 13 | )
|
13 | 14 |
|
14 | 15 | # from lldb.formatters import Logger
|
@@ -143,11 +144,32 @@ def vec_to_string(vec: SBValue) -> str:
|
143 | 144 | )
|
144 | 145 |
|
145 | 146 |
|
146 |
| -def StdStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: |
147 |
| - # logger = Logger.Logger() |
148 |
| - # logger >> "[StdStringSummaryProvider] for " + str(valobj.GetName()) |
149 |
| - vec = valobj.GetChildAtIndex(0) |
150 |
| - return '"%s"' % vec_to_string(vec) |
| 147 | +def StdStringSummaryProvider(valobj, dict): |
| 148 | + inner_vec = ( |
| 149 | + valobj.GetNonSyntheticValue() |
| 150 | + .GetChildMemberWithName("vec") |
| 151 | + .GetNonSyntheticValue() |
| 152 | + ) |
| 153 | + |
| 154 | + pointer = ( |
| 155 | + inner_vec.GetChildMemberWithName("buf") |
| 156 | + .GetChildMemberWithName("inner") |
| 157 | + .GetChildMemberWithName("ptr") |
| 158 | + .GetChildMemberWithName("pointer") |
| 159 | + .GetChildMemberWithName("pointer") |
| 160 | + ) |
| 161 | + |
| 162 | + length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned() |
| 163 | + |
| 164 | + if length <= 0: |
| 165 | + return "" |
| 166 | + error = SBError() |
| 167 | + process = pointer.GetProcess() |
| 168 | + data = process.ReadMemory(pointer.GetValueAsUnsigned(), length, error) |
| 169 | + if error.Success(): |
| 170 | + return '"' + data.decode("utf8", "replace") + '"' |
| 171 | + else: |
| 172 | + raise Exception("ReadMemory error: %s", error.GetCString()) |
151 | 173 |
|
152 | 174 |
|
153 | 175 | def StdOsStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
|
@@ -266,6 +288,48 @@ def has_children(self) -> bool:
|
266 | 288 | return True
|
267 | 289 |
|
268 | 290 |
|
| 291 | +class StdStringSyntheticProvider: |
| 292 | + def __init__(self, valobj: SBValue, _dict: LLDBOpaque): |
| 293 | + self.valobj = valobj |
| 294 | + self.update() |
| 295 | + |
| 296 | + def update(self): |
| 297 | + inner_vec = self.valobj.GetChildMemberWithName("vec").GetNonSyntheticValue() |
| 298 | + self.data_ptr = ( |
| 299 | + inner_vec.GetChildMemberWithName("buf") |
| 300 | + .GetChildMemberWithName("inner") |
| 301 | + .GetChildMemberWithName("ptr") |
| 302 | + .GetChildMemberWithName("pointer") |
| 303 | + .GetChildMemberWithName("pointer") |
| 304 | + ) |
| 305 | + self.length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned() |
| 306 | + self.element_type = self.data_ptr.GetType().GetPointeeType() |
| 307 | + |
| 308 | + def has_children(self) -> bool: |
| 309 | + return True |
| 310 | + |
| 311 | + def num_children(self) -> int: |
| 312 | + return self.length |
| 313 | + |
| 314 | + def get_child_index(self, name: str) -> int: |
| 315 | + index = name.lstrip("[").rstrip("]") |
| 316 | + if index.isdigit(): |
| 317 | + return int(index) |
| 318 | + |
| 319 | + return -1 |
| 320 | + |
| 321 | + def get_child_at_index(self, index: int) -> SBValue: |
| 322 | + if not 0 <= index < self.length: |
| 323 | + return None |
| 324 | + start = self.data_ptr.GetValueAsUnsigned() |
| 325 | + address = start + index |
| 326 | + element = self.data_ptr.CreateValueFromAddress( |
| 327 | + f"[{index}]", address, self.element_type |
| 328 | + ) |
| 329 | + element.SetFormat(eFormatChar) |
| 330 | + return element |
| 331 | + |
| 332 | + |
269 | 333 | class MSVCStrSyntheticProvider:
|
270 | 334 | __slots__ = ["valobj", "data_ptr", "length"]
|
271 | 335 |
|
@@ -699,6 +763,21 @@ def update(self):
|
699 | 763 | )
|
700 | 764 |
|
701 | 765 | self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
|
| 766 | + |
| 767 | + if not self.element_type.IsValid(): |
| 768 | + # annoyingly, vec's constituent type isn't guaranteed to be contained anywhere useful. |
| 769 | + # Some functions have it, but those functions only exist in binary when they're used. |
| 770 | + # that means it's time for string-based garbage. |
| 771 | + |
| 772 | + # acquire the first generic parameter via its type name |
| 773 | + _, _, end = self.valobj.GetTypeName().partition("<") |
| 774 | + element_name, _, _ = end.partition(",") |
| 775 | + |
| 776 | + # this works even for built-in rust types like `u32` because internally it's just a |
| 777 | + # `typedef` i really REALLY wish there was a better way to do this, but at the moment |
| 778 | + # LLDB flat out ignores template parameters due to piggybacking off of TypeSystemClang. |
| 779 | + self.element_type = self.valobj.target.FindFirstType(element_name) |
| 780 | + |
702 | 781 | self.element_type_size = self.element_type.GetByteSize()
|
703 | 782 |
|
704 | 783 | def has_children(self) -> bool:
|
|
0 commit comments