1
1
from __future__ import annotations
2
2
import re
3
3
import sys
4
- from typing import List , TYPE_CHECKING
4
+ from typing import List , TYPE_CHECKING , Generator
5
5
6
6
from lldb import (
7
7
SBData ,
13
13
)
14
14
15
15
if TYPE_CHECKING :
16
- from lldb import SBValue , SBType , SBTypeStaticField
16
+ from lldb import SBValue , SBType , SBTypeStaticField , SBTarget
17
17
18
18
# from lldb.formatters import Logger
19
19
@@ -133,14 +133,14 @@ def has_children(self) -> bool:
133
133
return False
134
134
135
135
136
- def get_template_args (type_name : str ) -> list [str ]:
136
+ def get_template_args (type_name : str ) -> Generator [str , None , None ]:
137
137
"""
138
138
Takes a type name `T<A, tuple$<B, C>, D>` and returns a list of its generic args
139
139
`["A", "tuple$<B, C>", "D"]`.
140
140
141
141
String-based replacement for LLDB's `SBType.template_args`, as LLDB is currently unable to
142
142
populate this field for targets with PDB debug info. Also useful for manually altering the type
143
- name of generics (e.g. `Vec<ref$<str$>` -> `Vec<&str>`).
143
+ name of generics (e.g. `Vec<ref$<str$> > ` -> `Vec<&str>`).
144
144
145
145
Each element of the returned list can be looked up for its `SBType` value via
146
146
`SBTarget.FindFirstType()`
@@ -156,11 +156,55 @@ def get_template_args(type_name: str) -> list[str]:
156
156
elif c == ">" :
157
157
level -= 1
158
158
if level == 0 :
159
- params . append ( type_name [start :i ].strip () )
159
+ yield type_name [start :i ].strip ()
160
160
elif c == "," and level == 1 :
161
- params . append ( type_name [start :i ].strip () )
161
+ yield type_name [start :i ].strip ()
162
162
start = i + 1
163
- return params
163
+
164
+
165
+ MSVC_PTR_PREFIX : List [str ] = ["ref$<" , "ref_mut$<" , "ptr_const$<" , "ptr_mut$<" ]
166
+
167
+
168
+ def resolve_msvc_template_arg (arg_name : str , target : SBTarget ) -> SBType :
169
+ """
170
+ RECURSIVE when arrays or references are nested (e.g. `ref$<ref$<u8> >`, `array$<ref$<u8> >`)
171
+
172
+ Takes the template arg's name (likely from `get_template_args`) and finds/creates its
173
+ corresponding SBType.
174
+
175
+ For non-reference/pointer/array types this is identical to calling
176
+ `target.FindFirstType(arg_name)`
177
+
178
+ LLDB internally interprets refs, pointers, and arrays C-style (`&u8` -> `u8 *`,
179
+ `*const u8` -> `u8 *`, `[u8; 5]` -> `u8 [5]`). Looking up these names still doesn't work in the
180
+ current version of LLDB, so instead the types are generated via `base_type.GetPointerType()` and
181
+ `base_type.GetArrayType()`, which bypass the PDB file and ask clang directly for the type node.
182
+ """
183
+ result = target .FindFirstType (arg_name )
184
+
185
+ if result .IsValid ():
186
+ return result
187
+
188
+ for prefix in MSVC_PTR_PREFIX :
189
+ if arg_name .startswith (prefix ):
190
+ arg_name = arg_name [len (prefix ) : - 1 ].strip ()
191
+
192
+ result = resolve_msvc_template_arg (arg_name , target )
193
+ return result .GetPointerType ()
194
+
195
+ if arg_name .startswith ("array$<" ):
196
+ arg_name = arg_name [7 :- 1 ].strip ()
197
+
198
+ template_args = get_template_args (arg_name )
199
+
200
+ element_name = next (template_args )
201
+ length = next (template_args )
202
+
203
+ result = resolve_msvc_template_arg (element_name , target )
204
+
205
+ return result .GetArrayType (int (length ))
206
+
207
+ return result
164
208
165
209
166
210
def SizeSummaryProvider (valobj : SBValue , _dict : LLDBOpaque ) -> str :
@@ -808,6 +852,7 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
808
852
# logger = Logger.Logger()
809
853
# logger >> "[StdVecSyntheticProvider] for " + str(valobj.GetName())
810
854
self .valobj = valobj
855
+ self .element_type = None
811
856
self .update ()
812
857
813
858
def num_children (self ) -> int :
@@ -841,8 +886,9 @@ def update(self):
841
886
self .element_type = self .valobj .GetType ().GetTemplateArgumentType (0 )
842
887
843
888
if not self .element_type .IsValid ():
844
- element_name = get_template_args (self .valobj .GetTypeName ())[0 ]
845
- self .element_type = self .valobj .target .FindFirstType (element_name )
889
+ arg_name = next (get_template_args (self .valobj .GetTypeName ()))
890
+
891
+ self .element_type = resolve_msvc_template_arg (arg_name , self .valobj .target )
846
892
847
893
self .element_type_size = self .element_type .GetByteSize ()
848
894
@@ -918,6 +964,7 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
918
964
# logger = Logger.Logger()
919
965
# logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName())
920
966
self .valobj = valobj
967
+ self .element_type = None
921
968
self .update ()
922
969
923
970
def num_children (self ) -> int :
@@ -954,6 +1001,12 @@ def update(self):
954
1001
)
955
1002
956
1003
self .element_type = self .valobj .GetType ().GetTemplateArgumentType (0 )
1004
+
1005
+ if not self .element_type .IsValid ():
1006
+ arg_name = next (get_template_args (self .valobj .GetTypeName ()))
1007
+
1008
+ self .element_type = resolve_msvc_template_arg (arg_name , self .valobj .target )
1009
+
957
1010
self .element_type_size = self .element_type .GetByteSize ()
958
1011
959
1012
def has_children (self ) -> bool :
@@ -1081,6 +1134,7 @@ def get_child_at_index(self, index: int) -> SBValue:
1081
1134
element = self .data_ptr .CreateValueFromAddress (
1082
1135
"[%s]" % index , address , self .pair_type
1083
1136
)
1137
+
1084
1138
if self .show_values :
1085
1139
return element
1086
1140
else :
@@ -1100,14 +1154,12 @@ def update(self):
1100
1154
1101
1155
self .size = inner_table .GetChildMemberWithName ("items" ).GetValueAsUnsigned ()
1102
1156
1103
- template_args = table .type . template_args
1157
+ self . pair_type = table .GetType (). GetTemplateArgumentType ( 0 )
1104
1158
1105
- if template_args is None :
1106
- type_name = table .GetTypeName ()
1107
- args = get_template_args (type_name )
1108
- self .pair_type = self .valobj .target .FindFirstType (args [0 ])
1109
- else :
1110
- self .pair_type = template_args [0 ]
1159
+ if not self .pair_type .IsValid ():
1160
+ arg_name = next (get_template_args (table .GetTypeName ()))
1161
+
1162
+ self .pair_type = resolve_msvc_template_arg (arg_name , self .valobj .target )
1111
1163
1112
1164
if self .pair_type .IsTypedefType ():
1113
1165
self .pair_type = self .pair_type .GetTypedefedType ()
0 commit comments