src/etc/lldb_providers.py PYTHON 1,643 lines View on github.com → Search inside
1from __future__ import annotations23import sys4from enum import Flag, auto5from typing import TYPE_CHECKING, Dict, Generator, List, Optional67from lldb import (8    SBData,9    SBError,10    eBasicTypeChar32,11    eBasicTypeDouble,12    eBasicTypeFloat,13    eBasicTypeHalf,14    eBasicTypeLong,15    eBasicTypeLongLong,16    eBasicTypeShort,17    eBasicTypeSignedChar,18    eBasicTypeUnsignedChar,19    eBasicTypeUnsignedLong,20    eBasicTypeUnsignedLongLong,21    eBasicTypeUnsignedShort,22    eFormatChar,23    eTypeIsInteger,24)25from rust_types import is_tuple_fields2627if TYPE_CHECKING:28    from lldb import SBProcess, SBTarget, SBType, SBTypeStaticField, SBValue2930# from lldb.formatters import Logger3132####################################################################################################33# This file contains two kinds of pretty-printers: summary and synthetic.34#35# Important classes from LLDB module:36#   SBValue: the value of a variable, a register, or an expression37#   SBType:  the data type; each SBValue has a corresponding SBType38#39# Summary provider is a function with the type `(SBValue, dict) -> str`.40#   The first parameter is the object encapsulating the actual variable being displayed;41#   The second parameter is an internal support parameter used by LLDB, and you should not touch it.42#43# Synthetic children is the way to provide a children-based representation of the object's value.44# Synthetic provider is a class that implements the following interface:45#46#     class SyntheticChildrenProvider:47#         def __init__(self, SBValue, dict)48#         def num_children(self)49#         def get_child_index(self, str)50#         def get_child_at_index(self, int)51#         def update(self)52#         def has_children(self)53#         def get_value(self)54#55#56# You can find more information and examples here:57#   1. https://lldb.llvm.org/varformats.html58#   2. https://lldb.llvm.org/use/python-reference.html59#   3. https://github.com/llvm/llvm-project/blob/llvmorg-8.0.1/lldb/www/python_reference/lldb.formatters.cpp-pysrc.html60#   4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa61####################################################################################################6263PY3 = sys.version_info[0] == 3646566class LLDBFeature(Flag):67    """Used to track which features we rely on and whether or not we can access them. The global68    `lldb_providers.FEATURE_FLAGS` is initialized in `lldb_lookup.__lldb_init_module` and is69    expected not to change after that point.7071    This is used rather than `debugger.GetVersionString` because Apple's fork of LLDB (used for72    xcode) uses a non-standard versioning scheme that has no relation to LLVM's.73    """7475    StaticFields = auto()76    """Added in LLDB 18. Adds functions to `SBType` the inspection of a struct's static fields."""77    TypeRecognizers = auto()78    """Added in LLDB 19. Callback-based type matching for synthetic/summary providers."""79    Float128 = auto()80    """Added in LLDB 22.1. Adds builtin support for Float 128's, including an `eBasicTypeFloat128`,81    a formatter, and handlers in `TypeSystemClang`"""828384def detect_features() -> LLDBFeature:85    import lldb8687    features = LLDBFeature(0)8889    # Most feature checks should be possible via simple "does this API exist at all" checks.90    if getattr(lldb.SBType, "GetStaticFieldWithName", None) is not None:91        features |= LLDBFeature.StaticFields92    if getattr(lldb, "eFormatterMatchCallback", None) is not None:93        features |= LLDBFeature.TypeRecognizers94    if getattr(lldb, "eBasicTypeFloat128", None) is not None:95        features |= LLDBFeature.Float1289697    return features9899100FEATURE_FLAGS: LLDBFeature = detect_features()101102103class LLDBOpaque:104    """105    An marker type for use in type hints to denote LLDB bookkeeping variables. Values marked with106    this type should never be used except when passing as an argument to an LLDB function.107    """108109110class ValueBuilder:111    def __init__(self, valobj: SBValue):112        self.valobj = valobj113        process = valobj.GetProcess()114        self.endianness = process.GetByteOrder()115        self.pointer_size = process.GetAddressByteSize()116117    def from_int(self, name: str, value: int) -> SBValue:118        type = self.valobj.GetType().GetBasicType(eBasicTypeLong)119        data = SBData.CreateDataFromSInt64Array(120            self.endianness,121            self.pointer_size,122            [value],123        )124        return self.valobj.CreateValueFromData(name, data, type)125126    def from_uint(self, name: str, value: int) -> SBValue:127        type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong)128        data = SBData.CreateDataFromUInt64Array(129            self.endianness,130            self.pointer_size,131            [value],132        )133        return self.valobj.CreateValueFromData(name, data, type)134135136def unwrap_unique_or_non_null(unique_or_nonnull: SBValue) -> SBValue:137    # BACKCOMPAT: rust 1.32138    # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067139    # BACKCOMPAT: rust 1.60140    # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f141    ptr = unique_or_nonnull.GetChildMemberWithName("pointer")142    return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0)143144145def unwrap_scalar_wrappers(wrapper: SBValue) -> SBValue:146    while (wrapper.type.GetTypeFlags() & eTypeIsInteger) == 0:147        wrapper = wrapper.GetChildAtIndex(0)148    return wrapper149150151class DefaultSyntheticProvider:152    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):153        # logger = Logger.Logger()154        # logger >> "Default synthetic provider for " + str(valobj.GetName())155        self.valobj = valobj156        self.is_ptr = valobj.GetType().IsPointerType()157158    def num_children(self) -> int:159        return self.valobj.GetNumChildren()160161    def get_child_index(self, name: str) -> int:162        return self.valobj.GetIndexOfChildWithName(name)163164    def get_child_at_index(self, index: int) -> Optional[SBValue]:165        return self.valobj.GetChildAtIndex(index)166167    def update(self):168        pass169170    def has_children(self) -> bool:171        return self.valobj.MightHaveChildren()172173    def get_value(self):174        return self.valobj.value175176177class EmptySyntheticProvider:178    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):179        # logger = Logger.Logger()180        # logger >> "[EmptySyntheticProvider] for " + str(valobj.GetName())181        self.valobj = valobj182183    def num_children(self) -> int:184        return 0185186    def get_child_index(self, name: str) -> int:187        return -1188189    def get_child_at_index(self, index: int) -> Optional[SBValue]:190        return None191192    def update(self):193        pass194195    def has_children(self) -> bool:196        return False197198199MSVC_STR_NAMES: List[str] = [200    "ref$<str$>",201    "ref_mut$<str$>",202    "ptr_const$<str$>",203    "ptr_mut$<str$>",204]205206207def get_template_args(type_name: str) -> Generator[str, None, None]:208    """209    Takes a type name `T<A, tuple$<B, C>, D>` and returns a list of its generic args210    `["A", "tuple$<B, C>", "D"]`.211212    Always returns an empty generator for `&str`, `&mut str`, `*const str`, and `*mut str`213214    Strips off `enum2$<>` wrapper from enum types before checking for template args215216    String-based replacement for LLDB's `SBType.template_args`, as LLDB is currently unable to217    populate this field for targets with PDB debug info. Also useful for manually altering the type218    name of generics (e.g. `Vec<ref$<str$> >` -> `Vec<&str>`).219220    Each element of the returned list can be looked up for its `SBType` value via221    `SBTarget.FindFirstType()`222    """223    if type_name in MSVC_STR_NAMES:224        return225226    if type_name.startswith(("enum2$<", "slice2$<")):227        # remove the prefix and the trailing ">"228        type_name = type_name.split("<", 1)[0][:-1].strip()229230    level = 0231    start = 0232    for i, c in enumerate(type_name):233        if c == "<":234            level += 1235            if level == 1:236                start = i + 1237        elif c == ">":238            level -= 1239            if level == 0:240                yield type_name[start:i].strip()241        elif c == "," and level == 1:242            yield type_name[start:i].strip()243            start = i + 1244245246MSVC_PTR_PREFIX = ("ref$<", "ref_mut$<", "ptr_const$<", "ptr_mut$<")247248PRIMITIVE_TYPES: Dict[str, int] = {249    "u8": eBasicTypeUnsignedChar,250    "u16": eBasicTypeUnsignedShort,251    "u32": eBasicTypeUnsignedLong,252    "u64": eBasicTypeUnsignedLongLong,253    "i8": eBasicTypeSignedChar,254    "i16": eBasicTypeShort,255    "i32": eBasicTypeLong,256    "i64": eBasicTypeLongLong,257    "f16": eBasicTypeHalf,258    "f32": eBasicTypeFloat,259    "f64": eBasicTypeDouble,260    "char": eBasicTypeChar32,261}262263264def resolve_msvc_template_arg(arg_name: str, target: SBTarget) -> SBType:265    """266    RECURSIVE when arrays or references are nested (e.g. `ref$<ref$<u8> >`, `array$<ref$<u8> >`)267268    Takes the template arg's name (likely from `get_template_args`) and finds/creates its269    corresponding SBType.270271    For non-reference/pointer/array types this is identical to calling272    `target.FindFirstType(arg_name)`273274    LLDB internally interprets refs, pointers, and arrays C-style (`&u8` -> `u8 *`,275    `*const u8` -> `u8 *`, `[u8; 5]` -> `u8 [5]`). Looking up these names still doesn't work in the276    current version of LLDB, so instead the types are generated via `base_type.GetPointerType()` and277    `base_type.GetArrayType()`, which bypass the PDB file and ask clang directly for the type node.278    """279280    result = target.FindFirstType(arg_name)281282    if result.IsValid():283        return result284285    if arg_name in MSVC_STR_NAMES:286        return target.FindFirstType(arg_name)287288    # As of LLDB 22, finding primitives based on `FindFirstType` with their rust name no longer289    # works. Instead, we can look them up by their `eBasicType` equivalent. For usize and isize,290    # we convert them to their bit-sized counterpart before the lookup291    if arg_name == "isize" or arg_name == "usize":292        equivalent = f"{arg_name[0]}{target.GetAddressByteSize() * 8}"293        return target.GetBasicType(PRIMITIVE_TYPES[equivalent])294295    if (basic_type := PRIMITIVE_TYPES.get(arg_name)) is not None:296        return target.GetBasicType(basic_type)297298    if arg_name == "f128" and LLDBFeature.Float128 in FEATURE_FLAGS:299        from lldb import eBasicTypeFloat128300301        return target.GetBasicType(eBasicTypeFloat128)302303    for prefix in MSVC_PTR_PREFIX:304        if arg_name.startswith(prefix):305            arg_name = arg_name[len(prefix) : -1].strip()306307            result = resolve_msvc_template_arg(arg_name, target)308            return result.GetPointerType()309310    if arg_name.startswith("slice2$<"):311        arg_name = arg_name[len("slice2$<") : -1].strip()312        return resolve_msvc_template_arg(arg_name, target)313314    if arg_name.startswith("array$<"):315        template_args = get_template_args(arg_name)316317        element_name = next(template_args)318        length = next(template_args)319320        result = resolve_msvc_template_arg(element_name, target)321322        return result.GetArrayType(int(length))323324    return result325326327def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:328    # structs need the field name before the field value329    output = (330        f"{valobj.GetChildAtIndex(i).GetName()}:{child}"331        for i, child in enumerate(aggregate_field_summary(valobj, _dict))332    )333334    return "{" + ", ".join(output) + "}"335336337def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):338    return "(" + ", ".join(aggregate_field_summary(valobj, _dict)) + ")"339340341def aggregate_field_summary(valobj: SBValue, _dict) -> Generator[str, None, None]:342    for i in range(0, valobj.GetNumChildren()):343        child: SBValue = valobj.GetChildAtIndex(i)344        summary = child.summary345        if summary is None:346            summary = child.value347            if summary is None:348                if is_tuple_fields(child.GetType().fields):349                    summary = TupleSummaryProvider(child, _dict)350                else:351                    summary = StructSummaryProvider(child, _dict)352        yield summary353354355def SizeSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:356    return "size=" + str(valobj.GetNumChildren())357358359def vec_to_string(vec: SBValue) -> str:360    length = vec.GetNumChildren()361    chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)]362    return (363        bytes(chars).decode(errors="replace")364        if PY3365        else "".join(chr(char) for char in chars)366    )367368369def read_string(370    process: SBProcess, address: int, length: int, error: Optional[SBError] = None371) -> str:372    """Reads a string from running process's memory. If `error` is passed in, it will be passed373    to the `SBProcess.ReadMemory` call, and will reflect any errors after the function is called.374375    If any error or exception occurs, a placeholder byte array of the form "<error: [reason]>" will376    be returned instead."""377378    if error is None:379        error = SBError()380    try:381        data = process.ReadMemory(address, length, error)382        if error.Success():383            return '"' + data.decode("utf-8", "replace") + '"'384        else:385            return f"<error: {error.GetCString()}>"386    except Exception as e:387        print(f"Unable to generate String summary: {e.__cause__}")388        return "<error: Unable to read memory>"389390391def StdStringSummaryProvider(valobj: SBValue, dict: LLDBOpaque):392    inner_vec = (393        valobj.GetNonSyntheticValue()394        .GetChildMemberWithName("vec")395        .GetNonSyntheticValue()396    )397398    pointer = (399        inner_vec.GetChildMemberWithName("buf")400        .GetChildMemberWithName("inner")401        .GetChildMemberWithName("ptr")402        .GetChildMemberWithName("pointer")403        .GetChildMemberWithName("pointer")404    )405406    length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned()407    capacity = (408        inner_vec.GetChildMemberWithName("buf")409        .GetChildMemberWithName("cap")410        .GetValueAsUnsigned()411    )412413    if length <= 0:414        return '""'415416    no_hi_bit_max: int = 1 << ((pointer.GetByteSize() * 8) - 1)417    # technically length isn't a NoHighBit<usize>, but length should always be <= capacity418    if length >= no_hi_bit_max or capacity >= no_hi_bit_max:419        return "<error: invalid len/capacity>"420    if pointer.GetValueAsUnsigned() == 0:421        return "<error: String pointer is null>"422423    process = pointer.GetProcess()424425    return read_string(process, pointer.GetValueAsAddress(), length)426427428def StdOsStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:429    inner_vec = valobj.GetNonSyntheticValue().GetChildAtIndex(0).GetChildAtIndex(0)430431    is_windows = inner_vec.GetTypeName().endswith("Wtf8Buf")432433    if is_windows:434        inner_vec = inner_vec.GetChildAtIndex(0)435436    pointer = (437        inner_vec.GetChildMemberWithName("buf")438        .GetChildMemberWithName("inner")439        .GetChildMemberWithName("ptr")440        .GetChildMemberWithName("pointer")441        .GetChildMemberWithName("pointer")442    )443444    length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned()445    capacity = (446        inner_vec.GetChildMemberWithName("buf")447        .GetChildMemberWithName("cap")448        .GetValueAsUnsigned()449    )450451    if length <= 0:452        return '""'453454    no_hi_bit_max: int = 1 << ((pointer.GetByteSize() * 8) - 1)455    # technically length isn't a NoHighBit<usize>, but length should always be <= capacity456    if length >= no_hi_bit_max or capacity >= no_hi_bit_max:457        return "<error: invalid len/capacity>"458    if pointer.GetValueAsUnsigned() == 0:459        return "<error: OsString pointer is null>"460461    process = pointer.GetProcess()462463    return read_string(process, pointer.GetValueAsAddress(), length)464465466def StdStrSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:467    # logger = Logger.Logger()468    # logger >> "[StdStrSummaryProvider] for " + str(valobj.GetName())469470    # the code below assumes non-synthetic value, this makes sure the assumption holds471    valobj = valobj.GetNonSyntheticValue()472473    length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned()474    if length == 0:475        return '""'476477    data_ptr = valobj.GetChildMemberWithName("data_ptr")478479    start = data_ptr.GetValueAsUnsigned()480    error = SBError()481    process = data_ptr.GetProcess()482    data = process.ReadMemory(start, length, error)483    data = data.decode(encoding="UTF-8") if PY3 else data484    return '"%s"' % data485486487def StdPathBufSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:488    # logger = Logger.Logger()489    # logger >> "[StdPathBufSummaryProvider] for " + str(valobj.GetName())490    return StdOsStringSummaryProvider(valobj.GetChildMemberWithName("inner"), _dict)491492493def StdPathSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:494    # logger = Logger.Logger()495    # logger >> "[StdPathSummaryProvider] for " + str(valobj.GetName())496    length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned()497    if length == 0:498        return '""'499500    data_ptr = valobj.GetChildMemberWithName("data_ptr")501502    start = data_ptr.GetValueAsUnsigned()503    process = data_ptr.GetProcess()504505    return read_string(process, start, length)506507508def sequence_formatter(output: str, valobj: SBValue, _dict: LLDBOpaque):509    length: int = valobj.GetNumChildren()510511    long: bool = False512    for i in range(0, length):513        if len(output) > 32:514            long = True515            break516517        child: SBValue = valobj.GetChildAtIndex(i)518519        summary = child.summary520        if summary is None:521            summary = child.value522            if summary is None:523                summary = "{...}"524        output += f"{summary}, "525    if long:526        output = f"(len: {length}) " + output + "..."527    else:528        output = output[:-2]529530    return output531532533class StructSyntheticProvider:534    """Pretty-printer for structs and struct enum variants"""535536    def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_variant: bool = False):537        # logger = Logger.Logger()538        self.valobj = valobj539        self.is_variant = is_variant540        self.type = valobj.GetType()541        self.fields = {}542543        if is_variant:544            self.fields_count = self.type.GetNumberOfFields() - 1545            real_fields = self.type.fields[1:]546        else:547            self.fields_count = self.type.GetNumberOfFields()548            real_fields = self.type.fields549550        for number, field in enumerate(real_fields):551            self.fields[field.name] = number552553    def num_children(self) -> int:554        return self.fields_count555556    def get_child_index(self, name: str) -> int:557        return self.fields.get(name, -1)558559    def get_child_at_index(self, index: int) -> Optional[SBValue]:560        if self.is_variant:561            field = self.type.GetFieldAtIndex(index + 1)562        else:563            field = self.type.GetFieldAtIndex(index)564        return self.valobj.GetChildMemberWithName(field.name)565566    def update(self):567        # type: () -> None568        pass569570    def has_children(self) -> bool:571        return True572573574class StdStringSyntheticProvider:575    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):576        self.valobj = valobj577        ptr_size = valobj.GetTarget().GetAddressByteSize() * 8578        self.no_hi_bit_max = 1 << (ptr_size - 1)579580        self.update()581582    def update(self):583        inner_vec = self.valobj.GetChildMemberWithName("vec").GetNonSyntheticValue()584        self.data_ptr = (585            inner_vec.GetChildMemberWithName("buf")586            .GetChildMemberWithName("inner")587            .GetChildMemberWithName("ptr")588            .GetChildMemberWithName("pointer")589            .GetChildMemberWithName("pointer")590        )591592        self.capacity = (593            inner_vec.GetChildMemberWithName("buf")594            .GetChildMemberWithName("cap")595            .GetValueAsUnsigned()596        )597598        # As of 4/18/2026, LLDB cannot accurately determine the difference between Some("") and None599        # this just makes sure we're not trying to access data when the string is clearly in an600        # invalid state.601        if (602            self.capacity >= self.no_hi_bit_max603            or self.data_ptr.GetValueAsUnsigned() == 0604        ):605            self.capacity = 0606            self.length = 0607        else:608            self.length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned()609610        self.element_type = self.data_ptr.GetType().GetPointeeType()611612    def has_children(self) -> bool:613        return True614615    def num_children(self) -> int:616        return self.length617618    def get_child_index(self, name: str) -> int:619        index = name.lstrip("[").rstrip("]")620        if index.isdigit():621            return int(index)622623        return -1624625    def get_child_at_index(self, index: int) -> Optional[SBValue]:626        if not 0 <= index < self.length:627            return None628        start = self.data_ptr.GetValueAsUnsigned()629        address = start + index630        element = self.data_ptr.CreateValueFromAddress(631            f"[{index}]", address, self.element_type632        )633        element.SetFormat(eFormatChar)634        return element635636637class MSVCStrSyntheticProvider:638    _name_map: Dict[str, str] = {639        "ref$<str$>": "&str",640        "ref_mut$<str$>": "&mut str",641        "ptr_const$<str$>": "*const str",642        "ptr_mut$<str$>": "*mut str",643    }644    __slots__ = ["data_ptr", "length", "valobj"]645646    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):647        self.valobj = valobj648        self.update()649650    def update(self):651        self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr")652        self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned()653654    def has_children(self) -> bool:655        return True656657    def num_children(self) -> int:658        return self.length659660    def get_child_index(self, name: str) -> int:661        index = name.lstrip("[").rstrip("]")662        if index.isdigit():663            return int(index)664665        return -1666667    def get_child_at_index(self, index: int) -> Optional[SBValue]:668        if not 0 <= index < self.length:669            return None670        start = self.data_ptr.GetValueAsUnsigned()671        address = start + index672        element = self.data_ptr.CreateValueFromAddress(673            f"[{index}]", address, self.data_ptr.GetType().GetPointeeType()674        )675        return element676677    def get_type_name(self):678        name = self.valobj.GetTypeName()679680        if (type_name := self._name_map.get(name)) is not None:681            return type_name682        elif name.startswith("alloc::boxed::Box<str$"):683            return "Box<str>"684        else:685            return name686687688def _getVariantName(variant: SBValue) -> str:689    """690    Since the enum variant's type name is in the form `TheEnumName::TheVariantName$Variant`,691    we can extract `TheVariantName` from it for display purpose.692    """693    s = variant.GetType().GetName()694    if not s.endswith("$Variant"):695        return ""696697    # trim off path and "$Variant"698    # len("$Variant") == 8699    return s.rsplit("::", 1)[1][:-8]700701702class ClangEncodedEnumProvider:703    """Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""704705    valobj: SBValue706    variant: SBValue707    value: SBValue708709    DISCRIMINANT_MEMBER_NAME = "$discr$"710    VALUE_MEMBER_NAME = "value"711712    __slots__ = ("valobj", "variant", "value")713714    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):715        self.valobj = valobj716        self.update()717718    def has_children(self) -> bool:719        return self.value.MightHaveChildren()720721    def num_children(self) -> int:722        return self.value.GetNumChildren()723724    def get_child_index(self, name: str) -> int:725        return self.value.GetIndexOfChildWithName(name)726727    def get_child_at_index(self, index: int) -> Optional[SBValue]:728        return self.value.GetChildAtIndex(index)729730    def update(self):731        all_variants = self.valobj.GetChildAtIndex(0)732        index = self._getCurrentVariantIndex(all_variants)733        self.variant = all_variants.GetChildAtIndex(index)734        self.value = self.variant.GetChildMemberWithName(735            ClangEncodedEnumProvider.VALUE_MEMBER_NAME736        )737        if (synth := self.value.GetSyntheticValue()).IsValid():738            self.value = synth739740    def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:741        default_index = 0742        for i in range(all_variants.GetNumChildren()):743            variant = all_variants.GetChildAtIndex(i)744            discr = variant.GetChildMemberWithName(745                ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME746            )747            if discr.IsValid():748                discr_unsigned_value = discr.GetValueAsUnsigned()749                if variant.GetName() == f"$variant${discr_unsigned_value}":750                    return i751            else:752                default_index = i753        return default_index754755756def ClangEncodedEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:757    if valobj.TypeIsPointerType():758        valobj = valobj.Dereference()759    enum_synth = ClangEncodedEnumProvider(valobj.GetNonSyntheticValue(), _dict)760    variant = enum_synth.variant761    name = _getVariantName(variant)762763    if valobj.GetNumChildren() == 0:764        return name765766    child_name: str = valobj.GetChildAtIndex(0).name767    if child_name == "0" or child_name == "__0":768        # enum variant is a tuple struct769        return name + TupleSummaryProvider(valobj, _dict)770    else:771        # enum variant is a regular struct772        return name + StructSummaryProvider(valobj, _dict)773774775class MSVCEnumSyntheticProvider:776    """777    Synthetic provider for sum-type enums on MSVC. For a detailed explanation of the internals,778    see:779780    https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs781    """782783    valobj: SBValue784    variant: SBValue785    value: SBValue786787    __slots__ = ["valobj", "variant", "value"]788789    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):790        self.valobj = valobj791        # This allows the summary provider to still print something792        # even if we can't find the variant for whatever reason793        self.variant = valobj794        self.value = valobj795        self.update()796797    def update(self):798        tag: SBValue = self.valobj.GetChildMemberWithName("tag")799800        if tag.IsValid():801            tag: int = tag.GetValueAsUnsigned()802            for child in self.valobj.GetNonSyntheticValue().children:803                if not child.name.startswith("variant"):804                    continue805806                variant_type: SBType = child.GetType()807                try:808                    exact: SBTypeStaticField = variant_type.GetStaticFieldWithName(809                        "DISCR_EXACT"810                    )811                except AttributeError:812                    # LLDB versions prior to 19.0.0 do not have the `SBTypeGetStaticField` API.813                    # With current DI generation there's not a great way to provide a "best effort"814                    # evaluation either, so we just return the object itself with no further815                    # attempts to inspect the type information816                    self.variant = self.valobj817                    self.value = self.valobj818                    return819820                if exact.IsValid():821                    discr: int = exact.GetConstantValue(822                        self.valobj.target823                    ).GetValueAsUnsigned()824                    if tag == discr:825                        self.variant = child826                        self.value = child.GetChildMemberWithName("value")827                        if (synth := self.value.GetSyntheticValue()).IsValid():828                            self.value = synth829830                        return831                else:  # if invalid, DISCR must be a range832                    begin: int = (833                        variant_type.GetStaticFieldWithName("DISCR_BEGIN")834                        .GetConstantValue(self.valobj.target)835                        .GetValueAsUnsigned()836                    )837                    end: int = (838                        variant_type.GetStaticFieldWithName("DISCR_END")839                        .GetConstantValue(self.valobj.target)840                        .GetValueAsUnsigned()841                    )842843                    # begin isn't necessarily smaller than end, so we must test for both cases844                    if begin < end:845                        if begin <= tag <= end:846                            self.variant = child847                            self.value = child.GetChildMemberWithName("value")848                            if (synth := self.value.GetSyntheticValue()).IsValid():849                                self.value = synth850851                            return852                    else:853                        if tag >= begin or tag <= end:854                            self.variant = child855                            self.value = child.GetChildMemberWithName("value")856                            if (synth := self.value.GetSyntheticValue()).IsValid():857                                self.value = synth858859                            return860        else:  # if invalid, tag is a 128 bit value861            tag_lo: int = self.valobj.GetChildMemberWithName(862                "tag128_lo"863            ).GetValueAsUnsigned()864            tag_hi: int = self.valobj.GetChildMemberWithName(865                "tag128_hi"866            ).GetValueAsUnsigned()867868            tag: int = (tag_hi << 64) | tag_lo869870            for child in self.valobj.GetNonSyntheticValue().children:871                if not child.name.startswith("variant"):872                    continue873874                variant_type: SBType = child.GetType()875                exact_lo: SBTypeStaticField = variant_type.GetStaticFieldWithName(876                    "DISCR128_EXACT_LO"877                )878879                if exact_lo.IsValid():880                    exact_lo: int = exact_lo.GetConstantValue(881                        self.valobj.target882                    ).GetValueAsUnsigned()883                    exact_hi: int = (884                        variant_type.GetStaticFieldWithName("DISCR128_EXACT_HI")885                        .GetConstantValue(self.valobj.target)886                        .GetValueAsUnsigned()887                    )888889                    discr: int = (exact_hi << 64) | exact_lo890                    if tag == discr:891                        self.variant = child892                        self.value = child.GetChildMemberWithName("value")893                        if (synth := self.value.GetSyntheticValue()).IsValid():894                            self.value = synth895                        return896                else:  # if invalid, DISCR must be a range897                    begin_lo: int = (898                        variant_type.GetStaticFieldWithName("DISCR128_BEGIN_LO")899                        .GetConstantValue(self.valobj.target)900                        .GetValueAsUnsigned()901                    )902                    begin_hi: int = (903                        variant_type.GetStaticFieldWithName("DISCR128_BEGIN_HI")904                        .GetConstantValue(self.valobj.target)905                        .GetValueAsUnsigned()906                    )907908                    end_lo: int = (909                        variant_type.GetStaticFieldWithName("DISCR128_END_LO")910                        .GetConstantValue(self.valobj.target)911                        .GetValueAsUnsigned()912                    )913                    end_hi: int = (914                        variant_type.GetStaticFieldWithName("DISCR128_END_HI")915                        .GetConstantValue(self.valobj.target)916                        .GetValueAsUnsigned()917                    )918919                    begin = (begin_hi << 64) | begin_lo920                    end = (end_hi << 64) | end_lo921922                    # begin isn't necessarily smaller than end, so we must test for both cases923                    if begin < end:924                        if begin <= tag <= end:925                            self.variant = child926                            self.value = child.GetChildMemberWithName("value")927                        if (synth := self.value.GetSyntheticValue()).IsValid():928                            self.value = synth929                            return930                    else:931                        if tag >= begin or tag <= end:932                            self.variant = child933                            self.value = child.GetChildMemberWithName("value")934                        if (synth := self.value.GetSyntheticValue()).IsValid():935                            self.value = synth936                            return937938    def num_children(self) -> int:939        return self.value.GetNumChildren()940941    def get_child_index(self, name: str) -> int:942        return self.value.GetIndexOfChildWithName(name)943944    def get_child_at_index(self, index: int) -> Optional[SBValue]:945        return self.value.GetChildAtIndex(index)946947    def has_children(self) -> bool:948        return self.value.MightHaveChildren()949950    def get_type_name(self) -> str:951        name = self.valobj.GetTypeName()952        # remove "enum2$<", str.removeprefix() is python 3.9+953        name = name[7:]954955        # MSVC misinterprets ">>" as a shift operator, so spaces are inserted by rust to956        # avoid that957        if name.endswith(" >"):958            name = name[:-2]959        elif name.endswith(">"):960            name = name[:-1]961962        return name963964965def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:966    if valobj.TypeIsPointerType():967        valobj = valobj.Dereference()968    enum_synth = MSVCEnumSyntheticProvider(valobj.GetNonSyntheticValue(), _dict)969    variant_names: SBType = valobj.target.FindFirstType(970        f"{enum_synth.valobj.GetTypeName()}::VariantNames"971    )972    try:973        name_idx = (974            enum_synth.variant.GetType()975            .GetStaticFieldWithName("NAME")976            .GetConstantValue(valobj.target)977            .GetValueAsUnsigned()978        )979    except AttributeError:980        # LLDB versions prior to 19 do not have the `SBTypeGetStaticField` API, and have no way981        # to determine the value based on the tag field.982        tag: SBValue = valobj.GetChildMemberWithName("tag")983984        if tag.IsValid():985            discr: int = tag.GetValueAsUnsigned()986            return "".join(["{tag = ", str(tag.unsigned), "}"])987        else:988            tag_lo: int = valobj.GetChildMemberWithName(989                "tag128_lo"990            ).GetValueAsUnsigned()991            tag_hi: int = valobj.GetChildMemberWithName(992                "tag128_hi"993            ).GetValueAsUnsigned()994995            discr: int = (tag_hi << 64) | tag_lo996997        return "".join(["{tag = ", str(discr), "}"])998999    name: str = variant_names.enum_members[name_idx].name10001001    if enum_synth.num_children() == 0:1002        return name10031004    child_name: str = enum_synth.value.GetChildAtIndex(0).name1005    if child_name == "0" or child_name == "__0":1006        # enum variant is a tuple struct1007        return name + TupleSummaryProvider(enum_synth.value, _dict)1008    else:1009        # enum variant is a regular struct1010        return name + StructSummaryProvider(enum_synth.value, _dict)101110121013class TupleSyntheticProvider:1014    """Pretty-printer for tuples and tuple enum variants"""10151016    def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_variant: bool = False):1017        # logger = Logger.Logger()1018        self.valobj = valobj1019        self.is_variant = is_variant1020        self.type = valobj.GetType()10211022        if is_variant:1023            self.size = self.type.GetNumberOfFields() - 11024        else:1025            self.size = self.type.GetNumberOfFields()10261027    def num_children(self) -> int:1028        return self.size10291030    def get_child_index(self, name: str) -> int:1031        if name.isdigit():1032            return int(name)1033        else:1034            return -110351036    def get_child_at_index(self, index: int) -> Optional[SBValue]:1037        if self.is_variant:1038            field = self.type.GetFieldAtIndex(index + 1)1039        else:1040            field = self.type.GetFieldAtIndex(index)1041        element = self.valobj.GetChildMemberWithName(field.name)1042        return self.valobj.CreateValueFromData(1043            str(index), element.GetData(), element.GetType()1044        )10451046    def update(self):1047        pass10481049    def has_children(self) -> bool:1050        return True105110521053class MSVCTupleSyntheticProvider:1054    __slots__ = ["valobj"]10551056    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):1057        self.valobj = valobj10581059    def num_children(self) -> int:1060        return self.valobj.GetNumChildren()10611062    def get_child_index(self, name: str) -> int:1063        return self.valobj.GetIndexOfChildWithName(name)10641065    def get_child_at_index(self, index: int) -> Optional[SBValue]:1066        child: SBValue = self.valobj.GetChildAtIndex(index)1067        offset = self.valobj.GetType().GetFieldAtIndex(index).byte_offset1068        return self.valobj.CreateChildAtOffset(str(index), offset, child.GetType())10691070    def update(self):1071        pass10721073    def has_children(self) -> bool:1074        return self.valobj.MightHaveChildren()10751076    def get_type_name(self) -> str:1077        name = self.valobj.GetTypeName()1078        # remove "tuple$<" and ">", str.removeprefix and str.removesuffix require python 3.9+1079        name = name[7:-1].strip()1080        return "(" + name + ")"108110821083class StdVecSyntheticProvider:1084    """Pretty-printer for alloc::vec::Vec<T>10851086    struct Vec<T> { buf: RawVec<T>, len: usize }1087    rust 1.75: struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }1088    rust 1.76: struct RawVec<T> { ptr: Unique<T>, cap: Cap(usize), ... }1089    rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... }1090    rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }1091    rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }1092    struct NonZero<T>(T)1093    struct NonNull<T> { pointer: *const T }1094    """10951096    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):1097        # logger = Logger.Logger()1098        # logger >> "[StdVecSyntheticProvider] for " + str(valobj.GetName())1099        self.valobj = valobj1100        self.element_type = None1101        ptr_size = valobj.GetTarget().GetAddressByteSize() * 81102        self.no_hi_bit_max = 1 << (ptr_size - 1)1103        self.update()11041105    def num_children(self) -> int:1106        return self.length11071108    def get_child_index(self, name: str) -> int:1109        index = name.lstrip("[").rstrip("]")1110        if index.isdigit():1111            return int(index)1112        else:1113            return -111141115    def get_child_at_index(self, index: int) -> Optional[SBValue]:1116        start = self.data_ptr.GetValueAsUnsigned()1117        address = start + index * self.element_type_size1118        element = self.data_ptr.CreateValueFromAddress(1119            "[%s]" % index, address, self.element_type1120        )1121        return element11221123    def update(self):1124        buf: SBValue = self.valobj.GetChildMemberWithName("buf")1125        self.data_ptr = unwrap_unique_or_non_null(1126            buf.GetChildMemberWithName("inner").GetChildMemberWithName("ptr")1127        )11281129        capacity: int = buf.GetChildMemberWithName("cap").GetValueAsUnsigned()11301131        if capacity >= self.no_hi_bit_max or self.data_ptr.GetValueAsUnsigned() == 0:1132            self.capacity = 01133            self.length = 01134        else:1135            self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()11361137        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)11381139        if not self.element_type.IsValid():1140            arg_name = next(get_template_args(self.valobj.GetTypeName()))11411142            self.element_type = resolve_msvc_template_arg(arg_name, self.valobj.target)11431144        self.element_type_size = self.element_type.GetByteSize()11451146    def has_children(self) -> bool:1147        return True114811491150class StdSliceSyntheticProvider:1151    __slots__ = ["valobj", "length", "data_ptr", "element_type", "element_size"]11521153    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):1154        self.valobj = valobj1155        self.update()11561157    def num_children(self) -> int:1158        return self.length11591160    def get_child_index(self, name: str) -> int:1161        index = name.lstrip("[").rstrip("]")1162        if index.isdigit():1163            return int(index)1164        else:1165            return -111661167    def get_child_at_index(self, index: int) -> Optional[SBValue]:1168        start = self.data_ptr.GetValueAsUnsigned()1169        address = start + index * self.element_size1170        element = self.data_ptr.CreateValueFromAddress(1171            "[%s]" % index, address, self.element_type1172        )1173        return element11741175    def update(self):1176        self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned()1177        self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr")11781179        self.element_type = self.data_ptr.GetType().GetPointeeType()1180        self.element_size = self.element_type.GetByteSize()11811182    def has_children(self) -> bool:1183        return True118411851186class MSVCStdSliceSyntheticProvider(StdSliceSyntheticProvider):1187    type_name: Optional[str] = None11881189    def get_type_name(self) -> str:1190        if self.type_name is not None:1191            return self.type_name11921193        name = self.valobj.GetTypeName()11941195        if name.startswith("ref_mut"):1196            name = name[len("ref_mut$<slice2$<") :].rstrip("> ")1197            self.type_name = f"&mut [{name}]"1198        elif name.startswith("ref"):1199            name = name[len("ref$<slice2$<") :].rstrip("> ")1200            self.type_name = f"&[{name}]"1201        elif name.startswith("ptr_mut"):1202            name = name[len("ptr_mut$<slice2$<") :].rstrip("> ")1203            self.type_name = f"*mut [{name}]"1204        elif name.startswith("ptr_const"):1205            name = name[len("ptr_const$<slice2$<") :].rstrip("> ")1206            self.type_name = f"*const [{name}]"1207        elif name.startswith("alloc::boxed::Box"):1208            prefix_len = len("alloc::boxed::Box<slice2$<")1209            suffix_len = len(">,alloc::alloc::Global>")1210            if name.endswith(",alloc::alloc::Global>"):1211                name = name[prefix_len : len(name) - suffix_len]12121213                self.type_name = f"Box<[{name}]>"1214            else:1215                [element_name, alloc_name] = name[prefix_len:].split(">", 1)12161217                name = f"{element_name}{alloc_name}"12181219                # alloc name contains the trailing ">", so we don't need to add it1220                self.type_name = f"Box<[{element_name}]{alloc_name}"1221        else:1222            self.type_name = name12231224        return self.type_name122512261227def StdSliceSummaryProvider(valobj, dict):1228    output = sequence_formatter("[", valobj, dict)1229    output += "]"1230    return output123112321233class StdVecDequeSyntheticProvider:1234    """Pretty-printer for alloc::collections::vec_deque::VecDeque<T>12351236    struct VecDeque<T> { head: WrappedIndex, len: usize, buf: RawVec<T> }1237    """12381239    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):1240        # logger = Logger.Logger()1241        # logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName())1242        self.valobj = valobj1243        self.element_type = None1244        self.update()12451246    def num_children(self) -> int:1247        return self.size12481249    def get_child_index(self, name: str) -> int:1250        index = name.lstrip("[").rstrip("]")1251        if index.isdigit() and int(index) < self.size:1252            return int(index)1253        else:1254            return -112551256    def get_child_at_index(self, index: int) -> Optional[SBValue]:1257        start = self.data_ptr.GetValueAsUnsigned()1258        address = start + ((index + self.head) % self.cap) * self.element_type_size1259        element = self.data_ptr.CreateValueFromAddress(1260            "[%s]" % index, address, self.element_type1261        )1262        return element12631264    def update(self):1265        head = self.valobj.GetChildMemberWithName("head")1266        # BACKCOMPAT: rust 1.951267        if head.GetType().num_fields == 1:1268            head = head.GetChildAtIndex(0)1269        self.head = head.GetValueAsUnsigned()1270        self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()1271        self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName(1272            "inner"1273        )1274        cap = self.buf.GetChildMemberWithName("cap")1275        if cap.GetType().num_fields == 1:1276            cap = cap.GetChildAtIndex(0)1277        self.cap = cap.GetValueAsUnsigned()12781279        self.data_ptr = unwrap_unique_or_non_null(1280            self.buf.GetChildMemberWithName("ptr")1281        )12821283        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)12841285        if not self.element_type.IsValid():1286            arg_name = next(get_template_args(self.valobj.GetTypeName()))12871288            self.element_type = resolve_msvc_template_arg(arg_name, self.valobj.target)12891290        self.element_type_size = self.element_type.GetByteSize()12911292    def has_children(self) -> bool:1293        return True129412951296# BACKCOMPAT: rust 1.351297class StdOldHashMapSyntheticProvider:1298    """Pretty-printer for std::collections::hash::map::HashMap<K, V, S>12991300    struct HashMap<K, V, S> {..., table: RawTable<K, V>, ... }1301    struct RawTable<K, V> { capacity_mask: usize, size: usize, hashes: TaggedHashUintPtr, ... }1302    """13031304    def __init__(self, valobj: SBValue, _dict: LLDBOpaque, show_values: bool = True):1305        self.valobj = valobj1306        self.show_values = show_values1307        self.update()13081309    def num_children(self) -> int:1310        return self.size13111312    def get_child_index(self, name: str) -> int:1313        index = name.lstrip("[").rstrip("]")1314        if index.isdigit():1315            return int(index)1316        else:1317            return -113181319    def get_child_at_index(self, index: int) -> Optional[SBValue]:1320        # logger = Logger.Logger()1321        start = self.data_ptr.GetValueAsUnsigned() & ~113221323        # See `libstd/collections/hash/table.rs:raw_bucket_at1324        hashes = self.hash_uint_size * self.capacity1325        align = self.pair_type_size1326        # See `libcore/alloc.rs:padding_needed_for`1327        len_rounded_up = (1328            (1329                (((hashes + align) % self.modulo - 1) % self.modulo)1330                & ~((align - 1) % self.modulo)1331            )1332            % self.modulo1333            - hashes1334        ) % self.modulo1335        # len_rounded_up = ((hashes + align - 1) & ~(align - 1)) - hashes13361337        pairs_offset = hashes + len_rounded_up1338        pairs_start = start + pairs_offset13391340        table_index = self.valid_indices[index]1341        idx = table_index & self.capacity_mask1342        address = pairs_start + idx * self.pair_type_size1343        element = self.data_ptr.CreateValueFromAddress(1344            "[%s]" % index, address, self.pair_type1345        )1346        if self.show_values:1347            return element1348        else:1349            key = element.GetChildAtIndex(0)1350            return self.valobj.CreateValueFromData(1351                "[%s]" % index, key.GetData(), key.GetType()1352            )13531354    def update(self):1355        # logger = Logger.Logger()13561357        self.table = self.valobj.GetChildMemberWithName("table")  # type: SBValue1358        self.size = self.table.GetChildMemberWithName("size").GetValueAsUnsigned()1359        self.hashes = self.table.GetChildMemberWithName("hashes")1360        self.hash_uint_type = self.hashes.GetType()1361        self.hash_uint_size = self.hashes.GetType().GetByteSize()1362        self.modulo = 2**self.hash_uint_size1363        self.data_ptr = self.hashes.GetChildAtIndex(0).GetChildAtIndex(0)13641365        self.capacity_mask = self.table.GetChildMemberWithName(1366            "capacity_mask"1367        ).GetValueAsUnsigned()1368        self.capacity = (self.capacity_mask + 1) % self.modulo13691370        marker = self.table.GetChildMemberWithName("marker").GetType()  # type: SBType1371        self.pair_type = marker.template_args[0]1372        self.pair_type_size = self.pair_type.GetByteSize()13731374        self.valid_indices = []1375        for idx in range(self.capacity):1376            address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size1377            hash_uint = self.data_ptr.CreateValueFromAddress(1378                "[%s]" % idx, address, self.hash_uint_type1379            )1380            hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0)1381            if hash_ptr.GetValueAsUnsigned() != 0:1382                self.valid_indices.append(idx)13831384        # logger >> "Valid indices: {}".format(str(self.valid_indices))13851386    def has_children(self) -> bool:1387        return True138813891390class StdHashMapSyntheticProvider:1391    """Pretty-printer for hashbrown's HashMap"""13921393    def __init__(self, valobj: SBValue, _dict: LLDBOpaque, show_values: bool = True):1394        self.valobj = valobj1395        self.show_values = show_values1396        self.update()13971398    def num_children(self) -> int:1399        return self.size14001401    def get_child_index(self, name: str) -> int:1402        index = name.lstrip("[").rstrip("]")1403        if index.isdigit():1404            return int(index)1405        else:1406            return -114071408    def get_child_at_index(self, index: int) -> Optional[SBValue]:1409        pairs_start = self.data_ptr.GetValueAsUnsigned()1410        idx = self.valid_indices[index]1411        if self.new_layout:1412            idx = -(idx + 1)1413        address = pairs_start + idx * self.pair_type_size1414        element = self.data_ptr.CreateValueFromAddress(1415            "[%s]" % index, address, self.pair_type1416        )14171418        if self.show_values:1419            return element1420        else:1421            key = element.GetChildAtIndex(0)1422            return self.valobj.CreateValueFromData(1423                "[%s]" % index, key.GetData(), key.GetType()1424            )14251426    def update(self):1427        table = self.table()1428        inner_table = table.GetChildMemberWithName("table")14291430        capacity = (1431            inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 11432        )1433        ctrl = inner_table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)14341435        self.size = inner_table.GetChildMemberWithName("items").GetValueAsUnsigned()14361437        self.pair_type = table.GetType().GetTemplateArgumentType(0)14381439        if not self.pair_type.IsValid():1440            arg_name = next(get_template_args(table.GetTypeName()))14411442            self.pair_type = resolve_msvc_template_arg(arg_name, self.valobj.target)14431444        if self.pair_type.IsTypedefType():1445            self.pair_type = self.pair_type.GetTypedefedType()1446        self.pair_type_size = self.pair_type.GetByteSize()14471448        self.new_layout = not inner_table.GetChildMemberWithName("data").IsValid()1449        if self.new_layout:1450            self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType())1451        else:1452            self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(1453                01454            )14551456        u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar)1457        u8_type_size = (1458            self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()1459        )14601461        self.valid_indices = []1462        for idx in range(capacity):1463            address = ctrl.GetValueAsUnsigned() + idx * u8_type_size1464            value = ctrl.CreateValueFromAddress(1465                "ctrl[%s]" % idx, address, u8_type1466            ).GetValueAsUnsigned()1467            is_present = value & 128 == 01468            if is_present:1469                self.valid_indices.append(idx)14701471    def table(self) -> SBValue:1472        if self.show_values:1473            hashbrown_hashmap = self.valobj.GetChildMemberWithName("base")1474        else:1475            # BACKCOMPAT: rust 1.471476            # HashSet wraps either std HashMap or hashbrown::HashSet, which both1477            # wrap hashbrown::HashMap, so either way we "unwrap" twice.1478            hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0)1479        return hashbrown_hashmap.GetChildMemberWithName("table")14801481    def has_children(self) -> bool:1482        return True148314841485def StdRcSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:1486    strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned()1487    weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned()1488    return "strong={}, weak={}".format(strong, weak)148914901491class StdRcSyntheticProvider:1492    """Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T>14931494    struct Rc<T> { ptr: NonNull<RcInner<T>>, ... }1495    rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> }1496    rust 1.33.0: struct NonNull<T> { pointer: *const T }1497    struct NonZero<T>(T)1498    struct RcInner<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }14991500    struct Arc<T> { ptr: NonNull<ArcInner<T>>, ... }1501    struct ArcInner<T> { strong: atomic::Atomic<usize>, weak: atomic::Atomic<usize>, data: T }1502    """15031504    def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_atomic: bool = False):1505        self.valobj = valobj15061507        self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr"))15081509        self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value")15101511        self.strong = unwrap_scalar_wrappers(self.ptr.GetChildMemberWithName("strong"))1512        self.weak = unwrap_scalar_wrappers(self.ptr.GetChildMemberWithName("weak"))15131514        self.value_builder = ValueBuilder(valobj)15151516        self.update()15171518    def num_children(self) -> int:1519        # Actually there are 3 children, but only the `value` should be shown as a child1520        return 115211522    def get_child_index(self, name: str) -> int:1523        if name == "value":1524            return 01525        if name == "strong":1526            return 11527        if name == "weak":1528            return 21529        return -115301531    def get_child_at_index(self, index: int) -> Optional[SBValue]:1532        if index == 0:1533            return self.value1534        if index == 1:1535            return self.value_builder.from_uint("strong", self.strong_count)1536        if index == 2:1537            return self.value_builder.from_uint("weak", self.weak_count)15381539        return None15401541    def update(self):1542        self.strong_count = self.strong.GetValueAsUnsigned()1543        self.weak_count = self.weak.GetValueAsUnsigned() - 115441545    def has_children(self) -> bool:1546        return True154715481549class StdCellSyntheticProvider:1550    """Pretty-printer for std::cell::Cell"""15511552    def __init__(self, valobj: SBValue, _dict: LLDBOpaque):1553        self.valobj = valobj1554        self.value = valobj.GetChildMemberWithName("value").GetChildAtIndex(0)15551556    def num_children(self) -> int:1557        return 115581559    def get_child_index(self, name: str) -> int:1560        if name == "value":1561            return 01562        return -115631564    def get_child_at_index(self, index: int) -> Optional[SBValue]:1565        if index == 0:1566            return self.value1567        return None15681569    def update(self):1570        pass15711572    def has_children(self) -> bool:1573        return True157415751576def StdRefSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:1577    borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned()1578    return (1579        "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)1580    )158115821583class StdRefSyntheticProvider:1584    """Pretty-printer for std::cell::Ref, std::cell::RefMut, and std::cell::RefCell"""15851586    def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_cell: bool = False):1587        self.valobj = valobj15881589        borrow = valobj.GetChildMemberWithName("borrow")1590        value = valobj.GetChildMemberWithName("value")1591        if is_cell:1592            self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName(1593                "value"1594            )1595            self.value = value.GetChildMemberWithName("value")1596        else:1597            self.borrow = (1598                borrow.GetChildMemberWithName("borrow")1599                .GetChildMemberWithName("value")1600                .GetChildMemberWithName("value")1601            )1602            self.value = value.Dereference()16031604        self.value_builder = ValueBuilder(valobj)16051606        self.update()16071608    def num_children(self) -> int:1609        # Actually there are 2 children, but only the `value` should be shown as a child1610        return 116111612    def get_child_index(self, name: str) -> int:1613        if name == "value":1614            return 01615        if name == "borrow":1616            return 11617        return -116181619    def get_child_at_index(self, index: int) -> Optional[SBValue]:1620        if index == 0:1621            return self.value1622        if index == 1:1623            return self.value_builder.from_int("borrow", self.borrow_count)1624        return None16251626    def update(self):1627        self.borrow_count = self.borrow.GetValueAsSigned()16281629    def has_children(self) -> bool:1630        return True163116321633def StdNonZeroNumberSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:1634    inner = valobj.GetChildAtIndex(0)1635    inner_inner = inner.GetChildAtIndex(0)16361637    # FIXME: Avoid printing as character literal,1638    #        see https://github.com/llvm/llvm-project/issues/65076.1639    if inner_inner.GetTypeName() in ["char", "unsigned char"]:1640        return str(inner_inner.GetValueAsSigned())1641    else:1642        return inner_inner.GetValue()

Code quality findings 100

Ensure functions have docstrings for documentation
missing-docstring
# def num_children(self)
Ensure functions have docstrings for documentation
missing-docstring
# def get_child_index(self, str)
Ensure functions have docstrings for documentation
missing-docstring
# def get_child_at_index(self, int)
Ensure functions have docstrings for documentation
missing-docstring
# def update(self)
Ensure functions have docstrings for documentation
missing-docstring
# def has_children(self)
Ensure functions have docstrings for documentation
missing-docstring
# def get_value(self)
Ensure functions have docstrings for documentation
missing-docstring
def detect_features() -> LLDBFeature:
Ensure functions have docstrings for documentation
missing-docstring
def from_int(self, name: str, value: int) -> SBValue:
Ensure functions have docstrings for documentation
missing-docstring
def from_uint(self, name: str, value: int) -> SBValue:
Ensure functions have docstrings for documentation
missing-docstring
def unwrap_unique_or_non_null(unique_or_nonnull: SBValue) -> SBValue:
Ensure functions have docstrings for documentation
missing-docstring
def unwrap_scalar_wrappers(wrapper: SBValue) -> SBValue:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def get_value(self):
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):
Ensure functions have docstrings for documentation
missing-docstring
def aggregate_field_summary(valobj: SBValue, _dict) -> Generator[str, None, None]:
Ensure functions have docstrings for documentation
missing-docstring
def SizeSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def vec_to_string(vec: SBValue) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def read_string(
Use logging module for better control and configurability
print-statement
print(f"Unable to generate String summary: {e.__cause__}")
Ensure functions have docstrings for documentation
missing-docstring
def StdStringSummaryProvider(valobj: SBValue, dict: LLDBOpaque):
Ensure functions have docstrings for documentation
missing-docstring
def StdOsStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def StdStrSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def StdPathBufSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def StdPathSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def sequence_formatter(output: str, valobj: SBValue, _dict: LLDBOpaque):
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def get_type_name(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def ClangEncodedEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def get_type_name(self) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def get_type_name(self) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def get_type_name(self) -> str:
Ensure functions have docstrings for documentation
missing-docstring
def StdSliceSummaryProvider(valobj, dict):
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:
Ensure functions have docstrings for documentation
missing-docstring
def update(self):
Ensure functions have docstrings for documentation
missing-docstring
def has_children(self) -> bool:
Ensure functions have docstrings for documentation
missing-docstring
def num_children(self) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_index(self, name: str) -> int:
Ensure functions have docstrings for documentation
missing-docstring
def get_child_at_index(self, index: int) -> Optional[SBValue]:

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.