Skip to content

Commit 2e8e618

Browse files
committed
use direct providers when possible
1 parent ca24813 commit 2e8e618

File tree

4 files changed

+177
-149
lines changed

4 files changed

+177
-149
lines changed

src/etc/lldb_commands

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,85 @@
1+
# LLDB iterates through these in reverse order to discover summaries/synthetics that means the top
2+
# of the list can be "overwritten" by items lower on the list. Be careful when reordering items.
3+
14
# Forces test-compliant formatting to all other types
25
type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
3-
type summary add -F _ -e -x -h "^.*$" --category Rust
6+
47
# Std String
58
type synthetic add -l lldb_lookup.StdStringSyntheticProvider -x "^(alloc::([a-z_]+::)+)String$" --category Rust
6-
type summary add -F lldb_lookup.StdStringSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
9+
type summary add -F lldb_lookup.StdStringSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
10+
711
# Std str
8-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?str$" --category Rust
9-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust
12+
type synthetic add -l lldb_lookup.StdSliceSyntheticProvider -x "^&(mut )?str$" --category Rust
13+
type summary add -F lldb_lookup.StdStrSummaryProvider -e -x -h "^&(mut )?str$" --category Rust
14+
1015
## MSVC
1116
type synthetic add -l lldb_lookup.MSVCStrSyntheticProvider -x "^ref(_mut)?\$<str\$>$" --category Rust
1217
type summary add -F lldb_lookup.StdStrSummaryProvider -e -h -x "^ref(_mut)?\$<str\$>$" --category Rust
13-
# Array
14-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?\\[.+\\]$" --category Rust
15-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
16-
# Slice
18+
19+
# Array/Slice
20+
type synthetic add -l lldb_lookup.StdSliceSyntheticProvider -x "^&(mut )?\\[.+\\]$" --category Rust
21+
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
22+
1723
## MSVC
1824
type synthetic add -l lldb_lookup.MSVCStdSliceSyntheticProvider -x "^ref(_mut)?\$<slice2\$<.+> >" --category Rust
1925
type summary add -F lldb_lookup.StdSliceSummaryProvider -e -x -h "^ref(_mut)?\$<slice2\$<.+> >" --category Rust
26+
2027
# OsString
21-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
22-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
28+
type summary add -F lldb_lookup.StdOsStringSummaryProvider -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
29+
2330
# Vec
24-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
25-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
31+
type synthetic add -l lldb_lookup.StdVecSyntheticProvider -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
32+
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
33+
2634
# VecDeque
27-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
28-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
29-
# BTreeSet
30-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
31-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
32-
# BTreeMap
33-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
34-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
35+
type synthetic add -l lldb_lookup.StdVecDequeSyntheticProvider -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
36+
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
37+
3538
# HashMap
36-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
37-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
39+
type synthetic add -l lldb_lookup.classify_hashmap -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
40+
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
41+
3842
# HashSet
39-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
40-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
43+
type synthetic add -l lldb_lookup.classify_hashset -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
44+
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
45+
4146
# Rc
42-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
43-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
47+
type synthetic add -l lldb_lookup.StdRcSyntheticProvider -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
48+
type summary add -F lldb_lookup.StdRcSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
49+
4450
# Arc
45-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
46-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
51+
type synthetic add -l lldb_lookup.arc_synthetic -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
52+
type summary add -F lldb_lookup.StdRcSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
53+
4754
# Cell
48-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
49-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
55+
type synthetic add -l lldb_lookup.StdCellSyntheticProvider -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
56+
5057
# RefCell
51-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
52-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
53-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
54-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
55-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
56-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
58+
type synthetic add -l lldb_lookup.StdRefSyntheticProvider -x "^(core::([a-z_]+::)+)Ref(Cell|Mut)?<.+>$" --category Rust
59+
type summary add -F lldb_lookup.StdRefSummaryProvider -e -x -h "^(core::([a-z_]+::)+)Ref(Cell|Mut)?<.+>$" --category Rust
60+
5761
# NonZero
58-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
59-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
60-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
61-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
62+
type summary add -F lldb_lookup.StdNonZeroNumberSummaryProvider -e -x -h "^(core::([a-z_]+::)+)NonZero(<.+>|I\d{0,3}|U\d{0,3})$" --category Rust
63+
6264
# PathBuf
63-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::([a-z_]+::)+)PathBuf$" --category Rust
64-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::([a-z_]+::)+)PathBuf$" --category Rust
65+
type summary add -F lldb_lookup.StdPathBufSummaryProvider -e -x -h "^(std::([a-z_]+::)+)PathBuf$" --category Rust
66+
6567
# Path
66-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
67-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
68+
type summary add -F lldb_lookup.StdPathSummaryProvider -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
69+
6870
# Enum
6971
## MSVC
7072
type synthetic add -l lldb_lookup.MSVCEnumSyntheticProvider -x "^enum2\$<.+>$" --category Rust
7173
type summary add -F lldb_lookup.MSVCEnumSummaryProvider -e -x -h "^enum2\$<.+>$" --category Rust
74+
7275
## MSVC Variants
7376
type synthetic add -l lldb_lookup.synthetic_lookup -x "^enum2\$<.+>::.*$" --category Rust
74-
type summary add -F lldb_lookup.summary_lookup -e -x -h "^enum2\$<.+>::.*$" --category Rust
77+
7578
# Tuple
76-
type synthetic add -l lldb_lookup.synthetic_lookup -x "^\(.*\)$" --category Rust
79+
type synthetic add -l lldb_lookup.TupleSyntheticProvider -x "^\(.*\)$" --category Rust
80+
7781
## MSVC
7882
type synthetic add -l lldb_lookup.MSVCTupleSyntheticProvider -x "^tuple\$<.+>$" --category Rust
7983
type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^tuple\$<.+>$" --category Rust
84+
8085
type category enable Rust

src/etc/lldb_lookup.py

Lines changed: 71 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,100 @@
11
from __future__ import annotations
2-
from typing import Dict
2+
from typing import List
3+
34

45
import lldb
56

67
from lldb_providers import *
7-
from rust_types import RustType, classify_struct, classify_union
8+
from rust_types import (
9+
ENUM_DISR_FIELD_NAME,
10+
ENUM_LLDB_ENCODED_VARIANTS,
11+
RustType,
12+
classify_union,
13+
is_tuple_fields,
14+
)
15+
16+
####################################################################################################
17+
# This file contains lookup functions that associate rust types with their synthetic/summary
18+
# providers.
19+
#
20+
# LLDB caches the results of the the commands in `lldb_commands`, but that caching is "shallow". It
21+
# purely associates the type with the function given, whether it is a regular function or a class
22+
# constructor. If the function makes decisions about what type of SyntheticProvider to return, that
23+
# processing is done **each time a value of that type is encountered**.
24+
#
25+
# To reiterate, inspecting a `vec![T; 100_000]` will call `T`'s lookup function/constructor 100,000
26+
# times. This can lead to significant delays in value visualization if the lookup logic is complex.
27+
#
28+
# As such, lookup functions should be kept as minimal as possible. LLDB technically expects a
29+
# SyntheticProvider class constructor. If you can provide just a class constructor, that should be
30+
# preferred. If extra processing must be done, try to keep it as minimal and as targeted as possible
31+
# (see: `classify_hashmap()` vs `classify_hashset()`).
32+
####################################################################################################
833

934

1035
# BACKCOMPAT: rust 1.35
1136
def is_hashbrown_hashmap(hash_map: lldb.SBValue) -> bool:
1237
return len(hash_map.type.fields) == 1
1338

1439

15-
def classify_rust_type(type: lldb.SBType) -> RustType:
16-
if type.IsPointerType():
17-
type = type.GetPointeeType()
18-
19-
type_class = type.GetTypeClass()
20-
if type_class == lldb.eTypeClassStruct:
21-
return classify_struct(type.name, type.fields)
22-
if type_class == lldb.eTypeClassUnion:
23-
return classify_union(type.fields)
40+
def classify_hashmap(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
41+
if is_hashbrown_hashmap(valobj):
42+
return StdHashMapSyntheticProvider(valobj, _dict)
43+
else:
44+
return StdOldHashMapSyntheticProvider(valobj, _dict)
2445

25-
return RustType.Other
2646

47+
def classify_hashset(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
48+
hash_map = valobj.GetChildAtIndex(0)
49+
if is_hashbrown_hashmap(hash_map):
50+
return StdHashMapSyntheticProvider(valobj, _dict, show_values=False)
51+
else:
52+
return StdOldHashMapSyntheticProvider(hash_map, _dict, show_values=False)
2753

28-
def summary_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> str:
29-
"""Returns the summary provider for the given value"""
30-
rust_type = classify_rust_type(valobj.GetType())
3154

32-
if rust_type == RustType.StdString:
33-
return StdStringSummaryProvider(valobj, _dict)
34-
if rust_type == RustType.StdOsString:
35-
return StdOsStringSummaryProvider(valobj, _dict)
36-
if rust_type == RustType.StdStr:
37-
return StdStrSummaryProvider(valobj, _dict)
55+
def arc_synthetic(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
56+
return StdRcSyntheticProvider(valobj, _dict, is_atomic=True)
3857

39-
if rust_type == RustType.StdVec:
40-
return SizeSummaryProvider(valobj, _dict)
41-
if rust_type == RustType.StdVecDeque:
42-
return SizeSummaryProvider(valobj, _dict)
43-
if rust_type == RustType.StdSlice:
44-
return SizeSummaryProvider(valobj, _dict)
4558

46-
if rust_type == RustType.StdHashMap:
47-
return SizeSummaryProvider(valobj, _dict)
48-
if rust_type == RustType.StdHashSet:
49-
return SizeSummaryProvider(valobj, _dict)
59+
def classify_rust_type(type: lldb.SBType, is_msvc: bool) -> RustType:
60+
if type.IsPointerType():
61+
return RustType.Indirection
5062

51-
if rust_type == RustType.StdRc:
52-
return StdRcSummaryProvider(valobj, _dict)
53-
if rust_type == RustType.StdArc:
54-
return StdRcSummaryProvider(valobj, _dict)
63+
# there is a bit of code duplication here because we don't want to check all of the standard
64+
# library regexes since LLDB handles that for us
65+
type_class = type.GetTypeClass()
66+
if type_class == lldb.eTypeClassStruct:
67+
fields: List[lldb.SBTypeMember] = type.fields
68+
if len(fields) == 0:
69+
return RustType.Empty
5570

56-
if rust_type == RustType.StdRef:
57-
return StdRefSummaryProvider(valobj, _dict)
58-
if rust_type == RustType.StdRefMut:
59-
return StdRefSummaryProvider(valobj, _dict)
60-
if rust_type == RustType.StdRefCell:
61-
return StdRefSummaryProvider(valobj, _dict)
71+
# <<variant>> is emitted by GDB while LLDB(18.1+) emits "$variants$"
72+
if (
73+
fields[0].name == ENUM_DISR_FIELD_NAME
74+
or fields[0].name == ENUM_LLDB_ENCODED_VARIANTS
75+
):
76+
return RustType.Enum
6277

63-
if rust_type == RustType.StdNonZeroNumber:
64-
return StdNonZeroNumberSummaryProvider(valobj, _dict)
78+
if is_tuple_fields(fields):
79+
return RustType.Tuple
6580

66-
if rust_type == RustType.StdPathBuf:
67-
return StdPathBufSummaryProvider(valobj, _dict)
68-
if rust_type == RustType.StdPath:
69-
return StdPathSummaryProvider(valobj, _dict)
81+
return RustType.Struct
82+
if type_class == lldb.eTypeClassUnion:
83+
# If we're debugging msvc, sum-type enums should have been caught by the regex in lldb
84+
# commands since they all start with "enum2$<"
85+
if is_msvc:
86+
return RustType.Union
87+
return classify_union(type.fields)
7088

71-
return ""
89+
return RustType.Other
7290

7391

7492
def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
7593
"""Returns the synthetic provider for the given value"""
76-
rust_type = classify_rust_type(valobj.GetType())
94+
is_msvc = valobj.GetTarget().GetTriple().endswith("msvc")
95+
rust_type = classify_rust_type(valobj.GetType(), is_msvc)
7796

78-
if rust_type == RustType.Struct:
97+
if rust_type == RustType.Struct or rust_type == RustType.Union:
7998
return StructSyntheticProvider(valobj, _dict)
8099
if rust_type == RustType.StructVariant:
81100
return StructSyntheticProvider(valobj, _dict, is_variant=True)
@@ -92,37 +111,7 @@ def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
92111
return synthetic_lookup(valobj.GetChildAtIndex(0), _dict)
93112
if rust_type == RustType.Enum:
94113
return ClangEncodedEnumProvider(valobj, _dict)
95-
if rust_type == RustType.StdVec:
96-
return StdVecSyntheticProvider(valobj, _dict)
97-
if rust_type == RustType.StdVecDeque:
98-
return StdVecDequeSyntheticProvider(valobj, _dict)
99-
if rust_type == RustType.StdSlice or rust_type == RustType.StdStr:
100-
return StdSliceSyntheticProvider(valobj, _dict)
101-
102-
if rust_type == RustType.StdHashMap:
103-
if is_hashbrown_hashmap(valobj):
104-
return StdHashMapSyntheticProvider(valobj, _dict)
105-
else:
106-
return StdOldHashMapSyntheticProvider(valobj, _dict)
107-
if rust_type == RustType.StdHashSet:
108-
hash_map = valobj.GetChildAtIndex(0)
109-
if is_hashbrown_hashmap(hash_map):
110-
return StdHashMapSyntheticProvider(valobj, _dict, show_values=False)
111-
else:
112-
return StdOldHashMapSyntheticProvider(hash_map, _dict, show_values=False)
113-
114-
if rust_type == RustType.StdRc:
115-
return StdRcSyntheticProvider(valobj, _dict)
116-
if rust_type == RustType.StdArc:
117-
return StdRcSyntheticProvider(valobj, _dict, is_atomic=True)
118-
119-
if rust_type == RustType.StdCell:
120-
return StdCellSyntheticProvider(valobj, _dict)
121-
if rust_type == RustType.StdRef:
122-
return StdRefSyntheticProvider(valobj, _dict)
123-
if rust_type == RustType.StdRefMut:
124-
return StdRefSyntheticProvider(valobj, _dict)
125-
if rust_type == RustType.StdRefCell:
126-
return StdRefSyntheticProvider(valobj, _dict, is_cell=True)
114+
if rust_type == RustType.Indirection:
115+
return IndirectionSyntheticProvider(valobj, _dict)
127116

128117
return DefaultSyntheticProvider(valobj, _dict)

src/etc/lldb_providers.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,14 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
9393
# logger = Logger.Logger()
9494
# logger >> "Default synthetic provider for " + str(valobj.GetName())
9595
self.valobj = valobj
96+
self.is_ptr = valobj.GetType().IsPointerType()
9697

9798
def num_children(self) -> int:
9899
return self.valobj.GetNumChildren()
99100

100101
def get_child_index(self, name: str) -> int:
102+
if self.is_ptr and name == "$$dereference$$":
103+
return self.valobj.Dereference().GetSyntheticValue()
101104
return self.valobj.GetIndexOfChildWithName(name)
102105

103106
def get_child_at_index(self, index: int) -> SBValue:
@@ -109,6 +112,36 @@ def update(self):
109112
def has_children(self) -> bool:
110113
return self.valobj.MightHaveChildren()
111114

115+
def get_value(self):
116+
return self.valobj.value
117+
118+
119+
class IndirectionSyntheticProvider:
120+
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
121+
self.valobj = valobj
122+
123+
def num_children(self) -> int:
124+
return 1
125+
126+
def get_child_index(self, name: str) -> int:
127+
if self.is_ptr and name == "$$dereference$$":
128+
return 0
129+
return -1
130+
131+
def get_child_at_index(self, index: int) -> SBValue:
132+
if index == 0:
133+
return self.valobj.Dereference().GetSyntheticValue()
134+
return None
135+
136+
def update(self):
137+
pass
138+
139+
def has_children(self) -> bool:
140+
return True
141+
142+
def get_value(self):
143+
return self.valobj.value
144+
112145

113146
class EmptySyntheticProvider:
114147
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):

0 commit comments

Comments
 (0)