1import sys 2 3from lldb import SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \ 4 eBasicTypeUnsignedChar 5 6# from lldb.formatters import Logger 7 8#################################################################################################### 9# This file contains two kinds of pretty-printers: summary and synthetic. 10# 11# Important classes from LLDB module: 12# SBValue: the value of a variable, a register, or an expression 13# SBType: the data type; each SBValue has a corresponding SBType 14# 15# Summary provider is a function with the type `(SBValue, dict) -> str`. 16# The first parameter is the object encapsulating the actual variable being displayed; 17# The second parameter is an internal support parameter used by LLDB, and you should not touch it. 18# 19# Synthetic children is the way to provide a children-based representation of the object's value. 20# Synthetic provider is a class that implements the following interface: 21# 22# class SyntheticChildrenProvider: 23# def __init__(self, SBValue, dict) 24# def num_children(self) 25# def get_child_index(self, str) 26# def get_child_at_index(self, int) 27# def update(self) 28# def has_children(self) 29# def get_value(self) 30# 31# 32# You can find more information and examples here: 33# 1. https://lldb.llvm.org/varformats.html 34# 2. https://lldb.llvm.org/use/python-reference.html 35# 3. https://lldb.llvm.org/python_reference/lldb.formatters.cpp.libcxx-pysrc.html 36# 4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa 37#################################################################################################### 38 39PY3 = sys.version_info[0] == 3 40 41 42class ValueBuilder: 43 def __init__(self, valobj): 44 # type: (SBValue) -> ValueBuilder 45 self.valobj = valobj 46 process = valobj.GetProcess() 47 self.endianness = process.GetByteOrder() 48 self.pointer_size = process.GetAddressByteSize() 49 50 def from_int(self, name, value): 51 # type: (str, int) -> SBValue 52 type = self.valobj.GetType().GetBasicType(eBasicTypeLong) 53 data = SBData.CreateDataFromSInt64Array(self.endianness, self.pointer_size, [value]) 54 return self.valobj.CreateValueFromData(name, data, type) 55 56 def from_uint(self, name, value): 57 # type: (str, int) -> SBValue 58 type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong) 59 data = SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [value]) 60 return self.valobj.CreateValueFromData(name, data, type) 61 62 63def unwrap_unique_or_non_null(unique_or_nonnull): 64 # BACKCOMPAT: rust 1.32 65 # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067 66 # BACKCOMPAT: rust 1.60 67 # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f 68 ptr = unique_or_nonnull.GetChildMemberWithName("pointer") 69 return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0) 70 71 72class DefaultSyntheticProvider: 73 def __init__(self, valobj, dict): 74 # type: (SBValue, dict) -> DefaultSyntheticProvider 75 # logger = Logger.Logger() 76 # logger >> "Default synthetic provider for " + str(valobj.GetName()) 77 self.valobj = valobj 78 79 def num_children(self): 80 # type: () -> int 81 return self.valobj.GetNumChildren() 82 83 def get_child_index(self, name): 84 # type: (str) -> int 85 return self.valobj.GetIndexOfChildWithName(name) 86 87 def get_child_at_index(self, index): 88 # type: (int) -> SBValue 89 return self.valobj.GetChildAtIndex(index) 90 91 def update(self): 92 # type: () -> None 93 pass 94 95 def has_children(self): 96 # type: () -> bool 97 return self.valobj.MightHaveChildren() 98 99 100class EmptySyntheticProvider: 101 def __init__(self, valobj, dict): 102 # type: (SBValue, dict) -> EmptySyntheticProvider 103 # logger = Logger.Logger() 104 # logger >> "[EmptySyntheticProvider] for " + str(valobj.GetName()) 105 self.valobj = valobj 106 107 def num_children(self): 108 # type: () -> int 109 return 0 110 111 def get_child_index(self, name): 112 # type: (str) -> int 113 return None 114 115 def get_child_at_index(self, index): 116 # type: (int) -> SBValue 117 return None 118 119 def update(self): 120 # type: () -> None 121 pass 122 123 def has_children(self): 124 # type: () -> bool 125 return False 126 127 128def SizeSummaryProvider(valobj, dict): 129 # type: (SBValue, dict) -> str 130 return 'size=' + str(valobj.GetNumChildren()) 131 132 133def vec_to_string(vec): 134 length = vec.GetNumChildren() 135 chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)] 136 return bytes(chars).decode(errors='replace') if PY3 else "".join(chr(char) for char in chars) 137 138 139def StdStringSummaryProvider(valobj, dict): 140 # type: (SBValue, dict) -> str 141 # logger = Logger.Logger() 142 # logger >> "[StdStringSummaryProvider] for " + str(valobj.GetName()) 143 vec = valobj.GetChildAtIndex(0) 144 return '"%s"' % vec_to_string(vec) 145 146 147def StdOsStringSummaryProvider(valobj, dict): 148 # type: (SBValue, dict) -> str 149 # logger = Logger.Logger() 150 # logger >> "[StdOsStringSummaryProvider] for " + str(valobj.GetName()) 151 buf = valobj.GetChildAtIndex(0).GetChildAtIndex(0) 152 is_windows = "Wtf8Buf" in buf.type.name 153 vec = buf.GetChildAtIndex(0) if is_windows else buf 154 return '"%s"' % vec_to_string(vec) 155 156 157def StdStrSummaryProvider(valobj, dict): 158 # type: (SBValue, dict) -> str 159 # logger = Logger.Logger() 160 # logger >> "[StdStrSummaryProvider] for " + str(valobj.GetName()) 161 162 length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned() 163 if length == 0: 164 return '""' 165 166 data_ptr = valobj.GetChildMemberWithName("data_ptr") 167 168 start = data_ptr.GetValueAsUnsigned() 169 error = SBError() 170 process = data_ptr.GetProcess() 171 data = process.ReadMemory(start, length, error) 172 data = data.decode(encoding='UTF-8') if PY3 else data 173 return '"%s"' % data 174 175 176class StructSyntheticProvider: 177 """Pretty-printer for structs and struct enum variants""" 178 179 def __init__(self, valobj, dict, is_variant=False): 180 # type: (SBValue, dict, bool) -> StructSyntheticProvider 181 # logger = Logger.Logger() 182 self.valobj = valobj 183 self.is_variant = is_variant 184 self.type = valobj.GetType() 185 self.fields = {} 186 187 if is_variant: 188 self.fields_count = self.type.GetNumberOfFields() - 1 189 real_fields = self.type.fields[1:] 190 else: 191 self.fields_count = self.type.GetNumberOfFields() 192 real_fields = self.type.fields 193 194 for number, field in enumerate(real_fields): 195 self.fields[field.name] = number 196 197 def num_children(self): 198 # type: () -> int 199 return self.fields_count 200 201 def get_child_index(self, name): 202 # type: (str) -> int 203 return self.fields.get(name, -1) 204 205 def get_child_at_index(self, index): 206 # type: (int) -> SBValue 207 if self.is_variant: 208 field = self.type.GetFieldAtIndex(index + 1) 209 else: 210 field = self.type.GetFieldAtIndex(index) 211 return self.valobj.GetChildMemberWithName(field.name) 212 213 def update(self): 214 # type: () -> None 215 pass 216 217 def has_children(self): 218 # type: () -> bool 219 return True 220 221 222class TupleSyntheticProvider: 223 """Pretty-printer for tuples and tuple enum variants""" 224 225 def __init__(self, valobj, dict, is_variant=False): 226 # type: (SBValue, dict, bool) -> TupleSyntheticProvider 227 # logger = Logger.Logger() 228 self.valobj = valobj 229 self.is_variant = is_variant 230 self.type = valobj.GetType() 231 232 if is_variant: 233 self.size = self.type.GetNumberOfFields() - 1 234 else: 235 self.size = self.type.GetNumberOfFields() 236 237 def num_children(self): 238 # type: () -> int 239 return self.size 240 241 def get_child_index(self, name): 242 # type: (str) -> int 243 if name.isdigit(): 244 return int(name) 245 else: 246 return -1 247 248 def get_child_at_index(self, index): 249 # type: (int) -> SBValue 250 if self.is_variant: 251 field = self.type.GetFieldAtIndex(index + 1) 252 else: 253 field = self.type.GetFieldAtIndex(index) 254 element = self.valobj.GetChildMemberWithName(field.name) 255 return self.valobj.CreateValueFromData(str(index), element.GetData(), element.GetType()) 256 257 def update(self): 258 # type: () -> None 259 pass 260 261 def has_children(self): 262 # type: () -> bool 263 return True 264 265 266class StdVecSyntheticProvider: 267 """Pretty-printer for alloc::vec::Vec<T> 268 269 struct Vec<T> { buf: RawVec<T>, len: usize } 270 struct RawVec<T> { ptr: Unique<T>, cap: usize, ... } 271 rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... } 272 rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... } 273 rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... } 274 struct NonZero<T>(T) 275 struct NonNull<T> { pointer: *const T } 276 """ 277 278 def __init__(self, valobj, dict): 279 # type: (SBValue, dict) -> StdVecSyntheticProvider 280 # logger = Logger.Logger() 281 # logger >> "[StdVecSyntheticProvider] for " + str(valobj.GetName()) 282 self.valobj = valobj 283 self.update() 284 285 def num_children(self): 286 # type: () -> int 287 return self.length 288 289 def get_child_index(self, name): 290 # type: (str) -> int 291 index = name.lstrip('[').rstrip(']') 292 if index.isdigit(): 293 return int(index) 294 else: 295 return -1 296 297 def get_child_at_index(self, index): 298 # type: (int) -> SBValue 299 start = self.data_ptr.GetValueAsUnsigned() 300 address = start + index * self.element_type_size 301 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type) 302 return element 303 304 def update(self): 305 # type: () -> None 306 self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() 307 self.buf = self.valobj.GetChildMemberWithName("buf") 308 309 self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr")) 310 311 self.element_type = self.data_ptr.GetType().GetPointeeType() 312 self.element_type_size = self.element_type.GetByteSize() 313 314 def has_children(self): 315 # type: () -> bool 316 return True 317 318 319class StdSliceSyntheticProvider: 320 def __init__(self, valobj, dict): 321 self.valobj = valobj 322 self.update() 323 324 def num_children(self): 325 # type: () -> int 326 return self.length 327 328 def get_child_index(self, name): 329 # type: (str) -> int 330 index = name.lstrip('[').rstrip(']') 331 if index.isdigit(): 332 return int(index) 333 else: 334 return -1 335 336 def get_child_at_index(self, index): 337 # type: (int) -> SBValue 338 start = self.data_ptr.GetValueAsUnsigned() 339 address = start + index * self.element_type_size 340 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type) 341 return element 342 343 def update(self): 344 # type: () -> None 345 self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned() 346 self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr") 347 348 self.element_type = self.data_ptr.GetType().GetPointeeType() 349 self.element_type_size = self.element_type.GetByteSize() 350 351 def has_children(self): 352 # type: () -> bool 353 return True 354 355 356class StdVecDequeSyntheticProvider: 357 """Pretty-printer for alloc::collections::vec_deque::VecDeque<T> 358 359 struct VecDeque<T> { head: usize, len: usize, buf: RawVec<T> } 360 """ 361 362 def __init__(self, valobj, dict): 363 # type: (SBValue, dict) -> StdVecDequeSyntheticProvider 364 # logger = Logger.Logger() 365 # logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName()) 366 self.valobj = valobj 367 self.update() 368 369 def num_children(self): 370 # type: () -> int 371 return self.size 372 373 def get_child_index(self, name): 374 # type: (str) -> int 375 index = name.lstrip('[').rstrip(']') 376 if index.isdigit() and int(index) < self.size: 377 return int(index) 378 else: 379 return -1 380 381 def get_child_at_index(self, index): 382 # type: (int) -> SBValue 383 start = self.data_ptr.GetValueAsUnsigned() 384 address = start + ((index + self.head) % self.cap) * self.element_type_size 385 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type) 386 return element 387 388 def update(self): 389 # type: () -> None 390 self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned() 391 self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() 392 self.buf = self.valobj.GetChildMemberWithName("buf") 393 self.cap = self.buf.GetChildMemberWithName("cap").GetValueAsUnsigned() 394 395 self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr")) 396 397 self.element_type = self.data_ptr.GetType().GetPointeeType() 398 self.element_type_size = self.element_type.GetByteSize() 399 400 def has_children(self): 401 # type: () -> bool 402 return True 403 404 405# BACKCOMPAT: rust 1.35 406class StdOldHashMapSyntheticProvider: 407 """Pretty-printer for std::collections::hash::map::HashMap<K, V, S> 408 409 struct HashMap<K, V, S> {..., table: RawTable<K, V>, ... } 410 struct RawTable<K, V> { capacity_mask: usize, size: usize, hashes: TaggedHashUintPtr, ... } 411 """ 412 413 def __init__(self, valobj, dict, show_values=True): 414 # type: (SBValue, dict, bool) -> StdOldHashMapSyntheticProvider 415 self.valobj = valobj 416 self.show_values = show_values 417 self.update() 418 419 def num_children(self): 420 # type: () -> int 421 return self.size 422 423 def get_child_index(self, name): 424 # type: (str) -> int 425 index = name.lstrip('[').rstrip(']') 426 if index.isdigit(): 427 return int(index) 428 else: 429 return -1 430 431 def get_child_at_index(self, index): 432 # type: (int) -> SBValue 433 # logger = Logger.Logger() 434 start = self.data_ptr.GetValueAsUnsigned() & ~1 435 436 # See `libstd/collections/hash/table.rs:raw_bucket_at 437 hashes = self.hash_uint_size * self.capacity 438 align = self.pair_type_size 439 # See `libcore/alloc.rs:padding_needed_for` 440 len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~( 441 (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo 442 # len_rounded_up = ((hashes + align - 1) & ~(align - 1)) - hashes 443 444 pairs_offset = hashes + len_rounded_up 445 pairs_start = start + pairs_offset 446 447 table_index = self.valid_indices[index] 448 idx = table_index & self.capacity_mask 449 address = pairs_start + idx * self.pair_type_size 450 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type) 451 if self.show_values: 452 return element 453 else: 454 key = element.GetChildAtIndex(0) 455 return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType()) 456 457 def update(self): 458 # type: () -> None 459 # logger = Logger.Logger() 460 461 self.table = self.valobj.GetChildMemberWithName("table") # type: SBValue 462 self.size = self.table.GetChildMemberWithName("size").GetValueAsUnsigned() 463 self.hashes = self.table.GetChildMemberWithName("hashes") 464 self.hash_uint_type = self.hashes.GetType() 465 self.hash_uint_size = self.hashes.GetType().GetByteSize() 466 self.modulo = 2 ** self.hash_uint_size 467 self.data_ptr = self.hashes.GetChildAtIndex(0).GetChildAtIndex(0) 468 469 self.capacity_mask = self.table.GetChildMemberWithName("capacity_mask").GetValueAsUnsigned() 470 self.capacity = (self.capacity_mask + 1) % self.modulo 471 472 marker = self.table.GetChildMemberWithName("marker").GetType() # type: SBType 473 self.pair_type = marker.template_args[0] 474 self.pair_type_size = self.pair_type.GetByteSize() 475 476 self.valid_indices = [] 477 for idx in range(self.capacity): 478 address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size 479 hash_uint = self.data_ptr.CreateValueFromAddress("[%s]" % idx, address, 480 self.hash_uint_type) 481 hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0) 482 if hash_ptr.GetValueAsUnsigned() != 0: 483 self.valid_indices.append(idx) 484 485 # logger >> "Valid indices: {}".format(str(self.valid_indices)) 486 487 def has_children(self): 488 # type: () -> bool 489 return True 490 491 492class StdHashMapSyntheticProvider: 493 """Pretty-printer for hashbrown's HashMap""" 494 495 def __init__(self, valobj, dict, show_values=True): 496 # type: (SBValue, dict, bool) -> StdHashMapSyntheticProvider 497 self.valobj = valobj 498 self.show_values = show_values 499 self.update() 500 501 def num_children(self): 502 # type: () -> int 503 return self.size 504 505 def get_child_index(self, name): 506 # type: (str) -> int 507 index = name.lstrip('[').rstrip(']') 508 if index.isdigit(): 509 return int(index) 510 else: 511 return -1 512 513 def get_child_at_index(self, index): 514 # type: (int) -> SBValue 515 pairs_start = self.data_ptr.GetValueAsUnsigned() 516 idx = self.valid_indices[index] 517 if self.new_layout: 518 idx = -(idx + 1) 519 address = pairs_start + idx * self.pair_type_size 520 element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type) 521 if self.show_values: 522 return element 523 else: 524 key = element.GetChildAtIndex(0) 525 return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType()) 526 527 def update(self): 528 # type: () -> None 529 table = self.table() 530 inner_table = table.GetChildMemberWithName("table") 531 532 capacity = inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1 533 ctrl = inner_table.GetChildMemberWithName("ctrl").GetChildAtIndex(0) 534 535 self.size = inner_table.GetChildMemberWithName("items").GetValueAsUnsigned() 536 self.pair_type = table.type.template_args[0] 537 if self.pair_type.IsTypedefType(): 538 self.pair_type = self.pair_type.GetTypedefedType() 539 self.pair_type_size = self.pair_type.GetByteSize() 540 541 self.new_layout = not inner_table.GetChildMemberWithName("data").IsValid() 542 if self.new_layout: 543 self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType()) 544 else: 545 self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(0) 546 547 u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar) 548 u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize() 549 550 self.valid_indices = [] 551 for idx in range(capacity): 552 address = ctrl.GetValueAsUnsigned() + idx * u8_type_size 553 value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address, 554 u8_type).GetValueAsUnsigned() 555 is_present = value & 128 == 0 556 if is_present: 557 self.valid_indices.append(idx) 558 559 def table(self): 560 # type: () -> SBValue 561 if self.show_values: 562 hashbrown_hashmap = self.valobj.GetChildMemberWithName("base") 563 else: 564 # BACKCOMPAT: rust 1.47 565 # HashSet wraps either std HashMap or hashbrown::HashSet, which both 566 # wrap hashbrown::HashMap, so either way we "unwrap" twice. 567 hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0) 568 return hashbrown_hashmap.GetChildMemberWithName("table") 569 570 def has_children(self): 571 # type: () -> bool 572 return True 573 574 575def StdRcSummaryProvider(valobj, dict): 576 # type: (SBValue, dict) -> str 577 strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned() 578 weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned() 579 return "strong={}, weak={}".format(strong, weak) 580 581 582class StdRcSyntheticProvider: 583 """Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T> 584 585 struct Rc<T> { ptr: NonNull<RcBox<T>>, ... } 586 rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> } 587 rust 1.33.0: struct NonNull<T> { pointer: *const T } 588 struct NonZero<T>(T) 589 struct RcBox<T> { strong: Cell<usize>, weak: Cell<usize>, value: T } 590 struct Cell<T> { value: UnsafeCell<T> } 591 struct UnsafeCell<T> { value: T } 592 593 struct Arc<T> { ptr: NonNull<ArcInner<T>>, ... } 594 struct ArcInner<T> { strong: atomic::AtomicUsize, weak: atomic::AtomicUsize, data: T } 595 struct AtomicUsize { v: UnsafeCell<usize> } 596 """ 597 598 def __init__(self, valobj, dict, is_atomic=False): 599 # type: (SBValue, dict, bool) -> StdRcSyntheticProvider 600 self.valobj = valobj 601 602 self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr")) 603 604 self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value") 605 606 self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex( 607 0).GetChildMemberWithName("value") 608 self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex( 609 0).GetChildMemberWithName("value") 610 611 self.value_builder = ValueBuilder(valobj) 612 613 self.update() 614 615 def num_children(self): 616 # type: () -> int 617 # Actually there are 3 children, but only the `value` should be shown as a child 618 return 1 619 620 def get_child_index(self, name): 621 # type: (str) -> int 622 if name == "value": 623 return 0 624 if name == "strong": 625 return 1 626 if name == "weak": 627 return 2 628 return -1 629 630 def get_child_at_index(self, index): 631 # type: (int) -> SBValue 632 if index == 0: 633 return self.value 634 if index == 1: 635 return self.value_builder.from_uint("strong", self.strong_count) 636 if index == 2: 637 return self.value_builder.from_uint("weak", self.weak_count) 638 639 return None 640 641 def update(self): 642 # type: () -> None 643 self.strong_count = self.strong.GetValueAsUnsigned() 644 self.weak_count = self.weak.GetValueAsUnsigned() - 1 645 646 def has_children(self): 647 # type: () -> bool 648 return True 649 650 651class StdCellSyntheticProvider: 652 """Pretty-printer for std::cell::Cell""" 653 654 def __init__(self, valobj, dict): 655 # type: (SBValue, dict) -> StdCellSyntheticProvider 656 self.valobj = valobj 657 self.value = valobj.GetChildMemberWithName("value").GetChildAtIndex(0) 658 659 def num_children(self): 660 # type: () -> int 661 return 1 662 663 def get_child_index(self, name): 664 # type: (str) -> int 665 if name == "value": 666 return 0 667 return -1 668 669 def get_child_at_index(self, index): 670 # type: (int) -> SBValue 671 if index == 0: 672 return self.value 673 return None 674 675 def update(self): 676 # type: () -> None 677 pass 678 679 def has_children(self): 680 # type: () -> bool 681 return True 682 683 684def StdRefSummaryProvider(valobj, dict): 685 # type: (SBValue, dict) -> str 686 borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned() 687 return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow) 688 689 690class StdRefSyntheticProvider: 691 """Pretty-printer for std::cell::Ref, std::cell::RefMut, and std::cell::RefCell""" 692 693 def __init__(self, valobj, dict, is_cell=False): 694 # type: (SBValue, dict, bool) -> StdRefSyntheticProvider 695 self.valobj = valobj 696 697 borrow = valobj.GetChildMemberWithName("borrow") 698 value = valobj.GetChildMemberWithName("value") 699 if is_cell: 700 self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName("value") 701 self.value = value.GetChildMemberWithName("value") 702 else: 703 self.borrow = borrow.GetChildMemberWithName("borrow").GetChildMemberWithName( 704 "value").GetChildMemberWithName("value") 705 self.value = value.Dereference() 706 707 self.value_builder = ValueBuilder(valobj) 708 709 self.update() 710 711 def num_children(self): 712 # type: () -> int 713 # Actually there are 2 children, but only the `value` should be shown as a child 714 return 1 715 716 def get_child_index(self, name): 717 if name == "value": 718 return 0 719 if name == "borrow": 720 return 1 721 return -1 722 723 def get_child_at_index(self, index): 724 # type: (int) -> SBValue 725 if index == 0: 726 return self.value 727 if index == 1: 728 return self.value_builder.from_int("borrow", self.borrow_count) 729 return None 730 731 def update(self): 732 # type: () -> None 733 self.borrow_count = self.borrow.GetValueAsSigned() 734 735 def has_children(self): 736 # type: () -> bool 737 return True 738 739 740def StdNonZeroNumberSummaryProvider(valobj, _dict): 741 # type: (SBValue, dict) -> str 742 objtype = valobj.GetType() 743 field = objtype.GetFieldAtIndex(0) 744 element = valobj.GetChildMemberWithName(field.name) 745 return element.GetValue() 746