use direct providers when possible

This commit is contained in:
Walnut
2025-10-10 05:42:40 -05:00
parent 9e39de94c4
commit b17670d3de
4 changed files with 179 additions and 152 deletions
+50 -46
View File
@@ -1,81 +1,85 @@
# LLDB iterates through these in reverse order to discover summaries/synthetics that means the top
# of the list can be "overwritten" by items lower on the list. Be careful when reordering items.
# Forces test-compliant formatting to all other types
type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
# Std String
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
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
type synthetic add -l lldb_lookup.StdSliceSyntheticProvider -x "^&(mut )?str$" --category Rust
type summary add -F lldb_lookup.StdStrSummaryProvider -e -x -h "^&(mut )?str$" --category Rust
## MSVC
type synthetic add -l lldb_lookup.MSVCStrSyntheticProvider -x "^ref(_mut)?\$<str\$>$" --category Rust
type summary add -F lldb_lookup.StdStrSummaryProvider -e -h -x "^ref(_mut)?\$<str\$>$" --category Rust
# Array
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?\\[.+\\]$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
# Slice
# Array/Slice
type synthetic add -l lldb_lookup.StdSliceSyntheticProvider -x "^&(mut )?\\[.+\\]$" --category Rust
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
## MSVC
type synthetic add -l lldb_lookup.MSVCStdSliceSyntheticProvider -x "^ref(_mut)?\$<slice2\$<.+> >" --category Rust
type summary add -F lldb_lookup.StdSliceSummaryProvider -e -x -h "^ref(_mut)?\$<slice2\$<.+> >" --category Rust
# OsString
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
type summary add -F lldb_lookup.StdOsStringSummaryProvider -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
# Vec
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
type synthetic add -l lldb_lookup.StdVecSyntheticProvider -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
# VecDeque
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
# BTreeSet
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
# BTreeMap
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
type synthetic add -l lldb_lookup.StdVecDequeSyntheticProvider -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
# HashMap
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
type synthetic add -l lldb_lookup.classify_hashmap -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
# HashSet
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
type synthetic add -l lldb_lookup.classify_hashset -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
type summary add -F lldb_lookup.SizeSummaryProvider -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
# Rc
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
type synthetic add -l lldb_lookup.StdRcSyntheticProvider -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
type summary add -F lldb_lookup.StdRcSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
# Arc
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
type synthetic add -l lldb_lookup.arc_synthetic -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
type summary add -F lldb_lookup.StdRcSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
# Cell
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
type synthetic add -l lldb_lookup.StdCellSyntheticProvider -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
# RefCell
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
type synthetic add -l lldb_lookup.StdRefSyntheticProvider -x "^(core::([a-z_]+::)+)Ref(Cell|Mut)?<.+>$" --category Rust
type summary add -F lldb_lookup.StdRefSummaryProvider -e -x -h "^(core::([a-z_]+::)+)Ref(Cell|Mut)?<.+>$" --category Rust
# NonZero
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
type summary add -F lldb_lookup.StdNonZeroNumberSummaryProvider -e -x -h "^(core::([a-z_]+::)+)NonZero(<.+>|I\d{0,3}|U\d{0,3})$" --category Rust
# PathBuf
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::([a-z_]+::)+)PathBuf$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::([a-z_]+::)+)PathBuf$" --category Rust
type summary add -F lldb_lookup.StdPathBufSummaryProvider -e -x -h "^(std::([a-z_]+::)+)PathBuf$" --category Rust
# Path
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
type summary add -F lldb_lookup.StdPathSummaryProvider -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
# Enum
# type summary add -F lldb_lookup.ClangEncodedEnumSummaryProvider -e -h "lldb_lookup.is_sum_type_enum" --recognizer-function --category Rust
## MSVC
type synthetic add -l lldb_lookup.MSVCEnumSyntheticProvider -x "^enum2\$<.+>$" --category Rust
type summary add -F lldb_lookup.MSVCEnumSummaryProvider -e -x -h "^enum2\$<.+>$" --category Rust
## MSVC Variants
type synthetic add -l lldb_lookup.synthetic_lookup -x "^enum2\$<.+>::.*$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^enum2\$<.+>::.*$" --category Rust
# Tuple
type synthetic add -l lldb_lookup.synthetic_lookup -x "^\(.*\)$" --category Rust
type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^\(.*\)$" --category Rust
type synthetic add -l lldb_lookup.TupleSyntheticProvider -x "^\(.*\)$" --category Rust
## MSVC
type synthetic add -l lldb_lookup.MSVCTupleSyntheticProvider -x "^tuple\$<.+>$" --category Rust
type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^tuple\$<.+>$" --category Rust
type category enable Rust
+75 -86
View File
@@ -1,10 +1,35 @@
from __future__ import annotations
from typing import Dict
from typing import List
import lldb
from lldb_providers import *
from rust_types import RustType, classify_struct, classify_union
from rust_types import (
ENUM_DISR_FIELD_NAME,
ENUM_LLDB_ENCODED_VARIANTS,
RustType,
classify_union,
is_tuple_fields,
)
####################################################################################################
# This file contains lookup functions that associate rust types with their synthetic/summary
# providers.
#
# LLDB caches the results of the the commands in `lldb_commands`, but that caching is "shallow". It
# purely associates the type with the function given, whether it is a regular function or a class
# constructor. If the function makes decisions about what type of SyntheticProvider to return, that
# processing is done **each time a value of that type is encountered**.
#
# To reiterate, inspecting a `vec![T; 100_000]` will call `T`'s lookup function/constructor 100,000
# times. This can lead to significant delays in value visualization if the lookup logic is complex.
#
# As such, lookup functions should be kept as minimal as possible. LLDB technically expects a
# SyntheticProvider class constructor. If you can provide just a class constructor, that should be
# preferred. If extra processing must be done, try to keep it as minimal and as targeted as possible
# (see: `classify_hashmap()` vs `classify_hashset()`).
####################################################################################################
# BACKCOMPAT: rust 1.35
@@ -12,70 +37,64 @@ def is_hashbrown_hashmap(hash_map: lldb.SBValue) -> bool:
return len(hash_map.type.fields) == 1
def classify_rust_type(type: lldb.SBType) -> RustType:
if type.IsPointerType():
type = type.GetPointeeType()
def classify_hashmap(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
if is_hashbrown_hashmap(valobj):
return StdHashMapSyntheticProvider(valobj, _dict)
else:
return StdOldHashMapSyntheticProvider(valobj, _dict)
def classify_hashset(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
hash_map = valobj.GetChildAtIndex(0)
if is_hashbrown_hashmap(hash_map):
return StdHashMapSyntheticProvider(valobj, _dict, show_values=False)
else:
return StdOldHashMapSyntheticProvider(hash_map, _dict, show_values=False)
def arc_synthetic(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
return StdRcSyntheticProvider(valobj, _dict, is_atomic=True)
def classify_rust_type(type: lldb.SBType, is_msvc: bool) -> RustType:
if type.IsPointerType():
return RustType.Indirection
# there is a bit of code duplication here because we don't want to check all of the standard
# library regexes since LLDB handles that for us
type_class = type.GetTypeClass()
if type_class == lldb.eTypeClassStruct:
return classify_struct(type.name, type.fields)
fields: List[lldb.SBTypeMember] = type.fields
if len(fields) == 0:
return RustType.Empty
# <<variant>> is emitted by GDB while LLDB(18.1+) emits "$variants$"
if (
fields[0].name == ENUM_DISR_FIELD_NAME
or fields[0].name == ENUM_LLDB_ENCODED_VARIANTS
):
return RustType.Enum
if is_tuple_fields(fields):
return RustType.Tuple
return RustType.Struct
if type_class == lldb.eTypeClassUnion:
# If we're debugging msvc, sum-type enums should have been caught by the regex in lldb
# commands since they all start with "enum2$<"
if is_msvc:
return RustType.Union
return classify_union(type.fields)
return RustType.Other
def summary_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> str:
"""Returns the summary provider for the given value"""
rust_type = classify_rust_type(valobj.GetType())
if rust_type == RustType.StdString:
return StdStringSummaryProvider(valobj, _dict)
if rust_type == RustType.StdOsString:
return StdOsStringSummaryProvider(valobj, _dict)
if rust_type == RustType.StdStr:
return StdStrSummaryProvider(valobj, _dict)
if rust_type == RustType.StdVec:
return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.StdVecDeque:
return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.StdSlice:
return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.StdHashMap:
return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.StdHashSet:
return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.StdRc:
return StdRcSummaryProvider(valobj, _dict)
if rust_type == RustType.StdArc:
return StdRcSummaryProvider(valobj, _dict)
if rust_type == RustType.StdRef:
return StdRefSummaryProvider(valobj, _dict)
if rust_type == RustType.StdRefMut:
return StdRefSummaryProvider(valobj, _dict)
if rust_type == RustType.StdRefCell:
return StdRefSummaryProvider(valobj, _dict)
if rust_type == RustType.StdNonZeroNumber:
return StdNonZeroNumberSummaryProvider(valobj, _dict)
if rust_type == RustType.StdPathBuf:
return StdPathBufSummaryProvider(valobj, _dict)
if rust_type == RustType.StdPath:
return StdPathSummaryProvider(valobj, _dict)
return ""
def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
"""Returns the synthetic provider for the given value"""
rust_type = classify_rust_type(valobj.GetType())
is_msvc = valobj.GetTarget().GetTriple().endswith("msvc")
rust_type = classify_rust_type(valobj.GetType(), is_msvc)
if rust_type == RustType.Struct:
if rust_type == RustType.Struct or rust_type == RustType.Union:
return StructSyntheticProvider(valobj, _dict)
if rust_type == RustType.StructVariant:
return StructSyntheticProvider(valobj, _dict, is_variant=True)
@@ -112,37 +131,7 @@ def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
)
return ClangEncodedEnumProvider(valobj, _dict)
if rust_type == RustType.StdVec:
return StdVecSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdVecDeque:
return StdVecDequeSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdSlice or rust_type == RustType.StdStr:
return StdSliceSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdHashMap:
if is_hashbrown_hashmap(valobj):
return StdHashMapSyntheticProvider(valobj, _dict)
else:
return StdOldHashMapSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdHashSet:
hash_map = valobj.GetChildAtIndex(0)
if is_hashbrown_hashmap(hash_map):
return StdHashMapSyntheticProvider(valobj, _dict, show_values=False)
else:
return StdOldHashMapSyntheticProvider(hash_map, _dict, show_values=False)
if rust_type == RustType.StdRc:
return StdRcSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdArc:
return StdRcSyntheticProvider(valobj, _dict, is_atomic=True)
if rust_type == RustType.StdCell:
return StdCellSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdRef:
return StdRefSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdRefMut:
return StdRefSyntheticProvider(valobj, _dict)
if rust_type == RustType.StdRefCell:
return StdRefSyntheticProvider(valobj, _dict, is_cell=True)
if rust_type == RustType.Indirection:
return IndirectionSyntheticProvider(valobj, _dict)
return DefaultSyntheticProvider(valobj, _dict)
+33
View File
@@ -102,11 +102,14 @@ class DefaultSyntheticProvider:
# logger = Logger.Logger()
# logger >> "Default synthetic provider for " + str(valobj.GetName())
self.valobj = valobj
self.is_ptr = valobj.GetType().IsPointerType()
def num_children(self) -> int:
return self.valobj.GetNumChildren()
def get_child_index(self, name: str) -> int:
if self.is_ptr and name == "$$dereference$$":
return self.valobj.Dereference().GetSyntheticValue()
return self.valobj.GetIndexOfChildWithName(name)
def get_child_at_index(self, index: int) -> SBValue:
@@ -118,6 +121,36 @@ class DefaultSyntheticProvider:
def has_children(self) -> bool:
return self.valobj.MightHaveChildren()
def get_value(self):
return self.valobj.value
class IndirectionSyntheticProvider:
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
self.valobj = valobj
def num_children(self) -> int:
return 1
def get_child_index(self, name: str) -> int:
if self.is_ptr and name == "$$dereference$$":
return 0
return -1
def get_child_at_index(self, index: int) -> SBValue:
if index == 0:
return self.valobj.Dereference().GetSyntheticValue()
return None
def update(self):
pass
def has_children(self) -> bool:
return True
def get_value(self):
return self.valobj.value
class EmptySyntheticProvider:
def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
+21 -20
View File
@@ -15,27 +15,28 @@ class RustType(Enum):
SingletonEnum = 8
RegularEnum = 9
CompressedEnum = 10
RegularUnion = 11
Union = 11
Indirection = 12
StdString = 12
StdOsString = 13
StdStr = 14
StdSlice = 15
StdVec = 16
StdVecDeque = 17
StdBTreeSet = 18
StdBTreeMap = 19
StdHashMap = 20
StdHashSet = 21
StdRc = 22
StdArc = 23
StdCell = 24
StdRef = 25
StdRefMut = 26
StdRefCell = 27
StdNonZeroNumber = 28
StdPath = 29
StdPathBuf = 30
StdString = 13
StdOsString = 14
StdStr = 15
StdSlice = 16
StdVec = 17
StdVecDeque = 18
StdBTreeSet = 19
StdBTreeMap = 20
StdHashMap = 21
StdHashSet = 22
StdRc = 23
StdArc = 24
StdCell = 25
StdRef = 26
StdRefMut = 27
StdRefCell = 28
StdNonZeroNumber = 29
StdPath = 30
StdPathBuf = 31
STD_STRING_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)String$")