diff options
| -rw-r--r-- | source/core/core_lldb.py | 92 | ||||
| -rw-r--r-- | typings/README.md | 5 | ||||
| -rw-r--r-- | typings/lldb.pyi | 408 |
3 files changed, 459 insertions, 46 deletions
diff --git a/source/core/core_lldb.py b/source/core/core_lldb.py index 25a829675..05ba0a4db 100644 --- a/source/core/core_lldb.py +++ b/source/core/core_lldb.py @@ -4,7 +4,7 @@ To use it, add the following line to your ~/.lldbinit file: command script import /path/to/source/core/core_lldb.py """ -import lldb # type: ignore[import] +import lldb # Set to True to enable the logger ENABLE_LOGGING = True @@ -16,7 +16,7 @@ def log(msg): lldb.formatters.Logger.Logger() >> msg -def make_string(F, L): +def make_string(F: lldb.SBData, L: int) -> str: strval = "" G = F.uint8 for X in range(L): @@ -28,17 +28,17 @@ def make_string(F, L): # Return the pointer to the data in a Slang::RefPtr -def get_ref_pointer(valobj): +def get_ref_pointer(valobj: lldb.SBValue) -> lldb.SBValue: return valobj.GetNonSyntheticValue().GetChildMemberWithName("pointer") # Check if a pointer is nullptr -def is_nullptr(valobj): +def is_nullptr(valobj: lldb.SBValue) -> bool: return valobj.GetValueAsUnsigned(0) == 0 # Slang::String summary -def String_summary(valobj, dict): +def String_summary(valobj: lldb.SBValue, dict) -> str: buffer_ptr = get_ref_pointer(valobj.GetChildMemberWithName("m_buffer")) if is_nullptr(buffer_ptr): return '""' @@ -49,7 +49,7 @@ def String_summary(valobj, dict): # Slang::UnownedStringSlice summary -def UnownedStringSlice_summary(valobj, dict): +def UnownedStringSlice_summary(valobj: lldb.SBValue, dict) -> str: begin = valobj.GetChildMemberWithName("m_begin") end = valobj.GetChildMemberWithName("m_end") length = end.GetValueAsUnsigned(0) - begin.GetValueAsUnsigned(0) @@ -60,8 +60,8 @@ def UnownedStringSlice_summary(valobj, dict): # Slang::RefPtr synthetic provider -class RefPtr_synthetic: - def __init__(self, valobj, dict): +class RefPtr_synthetic(lldb.SBSyntheticValueProvider): + def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): @@ -71,14 +71,14 @@ class RefPtr_synthetic: return len(self.children) def get_child_index(self, name): - for index in range(self.num_children()): - if self.children[index].GetName() == name: - return index + for idx in range(self.num_children()): + if self.children[idx].GetName() == name: + return idx return -1 - def get_child_at_index(self, index): - if index >= 0 and index < self.num_children(): - return self.children[index] + def get_child_at_index(self, idx): + if idx >= 0 and idx < self.num_children(): + return self.children[idx] else: return None @@ -92,7 +92,7 @@ class RefPtr_synthetic: # Slang::RefPtr summary -def RefPtr_summary(valobj, dict): +def RefPtr_summary(valobj: lldb.SBValue, dict) -> str: pointer = valobj.GetNonSyntheticValue().GetChildMemberWithName("pointer") if is_nullptr(pointer): return "nullptr" @@ -102,8 +102,8 @@ def RefPtr_summary(valobj, dict): # Slang::ComPtr synthetic provider -class ComPtr_synthetic: - def __init__(self, valobj, dict): +class ComPtr_synthetic(lldb.SBSyntheticValueProvider): + def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): @@ -113,14 +113,14 @@ class ComPtr_synthetic: return len(self.children) def get_child_index(self, name): - for index in range(self.num_children()): - if self.children[index].GetName() == name: - return index + for idx in range(self.num_children()): + if self.children[idx].GetName() == name: + return idx return -1 - def get_child_at_index(self, index): - if index >= 0 and index < self.num_children(): - return self.children[index] + def get_child_at_index(self, idx): + if idx >= 0 and idx < self.num_children(): + return self.children[idx] else: return None @@ -132,7 +132,7 @@ class ComPtr_synthetic: # Slang::ComPtr summary -def ComPtr_summary(valobj, dict): +def ComPtr_summary(valobj: lldb.SBValue, dict) -> str: pointer = valobj.GetNonSyntheticValue().GetChildMemberWithName("m_ptr") if is_nullptr(pointer): return "nullptr" @@ -140,8 +140,8 @@ def ComPtr_summary(valobj, dict): # Slang::Array synthetic provider -class Array_synthetic: - def __init__(self, valobj, dict): +class Array_synthetic(lldb.SBSyntheticValueProvider): + def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): @@ -153,11 +153,11 @@ class Array_synthetic: def get_child_index(self, name): return int(name.lstrip("[").rstrip("]")) - def get_child_at_index(self, index): - if index >= 0 and index < self.num_children(): - offset = index * self.data_size + def get_child_at_index(self, idx): + if idx >= 0 and idx < self.num_children(): + offset = idx * self.data_size return self.buffer.CreateChildAtOffset( - "[" + str(index) + "]", offset, self.data_type + "[" + str(idx) + "]", offset, self.data_type ) else: return None @@ -170,8 +170,8 @@ class Array_synthetic: # Slang::List synthetic provider -class List_synthetic: - def __init__(self, valobj, dict): +class List_synthetic(lldb.SBSyntheticValueProvider): + def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): @@ -183,11 +183,11 @@ class List_synthetic: def get_child_index(self, name): return int(name.lstrip("[").rstrip("]")) - def get_child_at_index(self, index): - if index >= 0 and index < self.num_children(): - offset = index * self.data_size + def get_child_at_index(self, idx): + if idx >= 0 and idx < self.num_children(): + offset = idx * self.data_size return self.buffer.CreateChildAtOffset( - "[" + str(index) + "]", offset, self.data_type + "[" + str(idx) + "]", offset, self.data_type ) else: return None @@ -200,8 +200,8 @@ class List_synthetic: # Slang::ShortList synthetic provider -class ShortList_synthetic: - def __init__(self, valobj, dict): +class ShortList_synthetic(lldb.SBSyntheticValueProvider): + def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): @@ -213,16 +213,16 @@ class ShortList_synthetic: def get_child_index(self, name): return int(name.lstrip("[").rstrip("]")) - def get_child_at_index(self, index): - if index >= 0 and index < self.short_count: - offset = index * self.data_size + def get_child_at_index(self, idx): + if idx >= 0 and idx < self.short_count: + offset = idx * self.data_size return self.short_buffer.CreateChildAtOffset( - "[" + str(index) + "]", offset, self.data_type + "[" + str(idx) + "]", offset, self.data_type ) - elif index >= self.short_count and index < self.num_children(): - offset = (index - self.short_count) * self.data_size + elif idx >= self.short_count and idx < self.num_children(): + offset = (idx - self.short_count) * self.data_size return self.buffer.CreateChildAtOffset( - "[" + str(index) + "]", offset, self.data_type + "[" + str(idx) + "]", offset, self.data_type ) else: return None @@ -236,7 +236,7 @@ class ShortList_synthetic: self.data_size = self.data_type.GetByteSize() -def __lldb_init_module(debugger, internal_dict): +def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict): if ENABLE_LOGGING: lldb.formatters.Logger._lldb_formatters_debug_level = 2 diff --git a/typings/README.md b/typings/README.md new file mode 100644 index 000000000..e7c84043c --- /dev/null +++ b/typings/README.md @@ -0,0 +1,5 @@ +# Python type stubs + +This directory holds [Python stub files](https://peps.python.org/pep-0484/#stub-files) to improve the editing experience for Python code in this repo, such as [LLDB data formatters](https://lldb.llvm.org/use/variable.html). + +If you use Pyright (e.g. via [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) in VS Code) then these will be picked up automatically; other tools may require additional configuration to see them. diff --git a/typings/lldb.pyi b/typings/lldb.pyi new file mode 100644 index 000000000..5a4eb1522 --- /dev/null +++ b/typings/lldb.pyi @@ -0,0 +1,408 @@ +# This file holds (incomplete) Python type stubs for LLDB v19.1.7: +# https://lldb.llvm.org/python_api.html + +# The API includes many docstrings which describe the type signatures of +# functions, but these are not in a format that can be read by Python +# type checking tools. This has been requested upstream, but seems to be +# blocked because SWIG (the tool used to generate the LLDB Python +# bindings) doees not support generating Python type hints: +# https://github.com/llvm/llvm-project/issues/79043 + +# For another example of a project that takes the same approach for LLDB +# Python types, see the mongo-c-driver repo: +# https://github.com/mongodb/mongo-c-driver/blob/2.0.2/lldb.pyi + +# The classes in this file, along with the members in each class, are +# listed in the same order as the autogenerated `lldb/__init__.py` file +# distributed with LLVM: +# https://packages.debian.org/sid/amd64/python3-lldb-19/filelist + +# This file should not impose a maintenance burden, because although not +# all classes are present and not all methods are fully typed, each +# present class has all its members listed. As a result, language +# servers like Pylance don't give spurious errors about missing members, +# and can simply report types as "unknown" for methods that have not +# been annotated yet. Thus, when adding a new class to this file, be +# sure to include all its members, but don't feel required to include +# types for everything unless you want to. + +from typing import Sequence + +class SBData: + @property + def thisown(self): ... + def __init__(self, *args): ... + def GetAddressByteSize(self): ... + def SetAddressByteSize(self, addr_byte_size): ... + def Clear(self): ... + def __nonzero__(self): ... + def __bool__(self): ... + def IsValid(self): ... + def GetByteSize(self): ... + def GetByteOrder(self): ... + def SetByteOrder(self, endian): ... + def GetFloat(self, error, offset): ... + def GetDouble(self, error, offset): ... + def GetLongDouble(self, error, offset): ... + def GetAddress(self, error, offset): ... + def GetUnsignedInt8(self, error, offset): ... + def GetUnsignedInt16(self, error, offset): ... + def GetUnsignedInt32(self, error, offset): ... + def GetUnsignedInt64(self, error, offset): ... + def GetSignedInt8(self, error, offset): ... + def GetSignedInt16(self, error, offset): ... + def GetSignedInt32(self, error, offset): ... + def GetSignedInt64(self, error, offset): ... + def GetString(self, error, offset): ... + def ReadRawData(self, error, offset, buf): ... + def GetDescription(self, *args): ... + def SetData(self, error, buf, endian, addr_size): ... + def SetDataWithOwnership(self, error, buf, endian, addr_size): ... + def Append(self, rhs): ... + @staticmethod + def CreateDataFromCString(endian, addr_byte_size, data): ... + @staticmethod + def CreateDataFromUInt64Array(endian, addr_byte_size, array): ... + @staticmethod + def CreateDataFromUInt32Array(endian, addr_byte_size, array): ... + @staticmethod + def CreateDataFromSInt64Array(endian, addr_byte_size, array): ... + @staticmethod + def CreateDataFromSInt32Array(endian, addr_byte_size, array): ... + @staticmethod + def CreateDataFromDoubleArray(endian, addr_byte_size, array): ... + def SetDataFromCString(self, data): ... + def SetDataFromUInt64Array(self, array): ... + def SetDataFromUInt32Array(self, array): ... + def SetDataFromSInt64Array(self, array): ... + def SetDataFromSInt32Array(self, array): ... + def SetDataFromDoubleArray(self, array): ... + def __repr__(self) -> str: ... + def __len__(self): ... + @classmethod + def CreateDataFromInt( + cls, value, size=None, target=None, ptr_size=None, endian=None + ): ... + def _make_helper(self, sbdata, getfunc, itemsize): ... + def _make_helper_uint8(self): ... + def _make_helper_uint16(self): ... + def _make_helper_uint32(self): ... + def _make_helper_uint64(self): ... + def _make_helper_sint8(self): ... + def _make_helper_sint16(self): ... + def _make_helper_sint32(self): ... + def _make_helper_sint64(self): ... + def _make_helper_float(self): ... + def _make_helper_double(self): ... + def _read_all_uint8(self): ... + def _read_all_uint16(self): ... + def _read_all_uint32(self): ... + def _read_all_uint64(self): ... + def _read_all_sint8(self): ... + def _read_all_sint16(self): ... + def _read_all_sint32(self): ... + def _read_all_sint64(self): ... + def _read_all_float(self): ... + def _read_all_double(self): ... + @property + def uint8(self) -> Sequence[int]: ... + @property + def uint16(self): ... + @property + def uint32(self): ... + @property + def uint64(self): ... + @property + def sint8(self): ... + @property + def sint16(self): ... + @property + def sint32(self): ... + @property + def sint64(self): ... + @property + def float(self): ... + @property + def double(self): ... + @property + def uint8s(self): ... + @property + def uint16s(self): ... + @property + def uint32s(self): ... + @property + def uint64s(self): ... + @property + def sint8s(self): ... + @property + def sint16s(self): ... + @property + def sint32s(self): ... + @property + def sint64s(self): ... + @property + def floats(self): ... + @property + def doubles(self): ... + @property + def byte_order(self): ... + @property + def size(self): ... + +class SBDebugger: + def HandleCommand(self, command: str) -> None: ... + +class SBType: + @property + def thisown(self): ... + def __init__(self, *args): ... + def __nonzero__(self): ... + def IsValid(self): ... + def GetByteSize(self) -> int: ... + def GetByteAlign(self): ... + def IsPointerType(self): ... + def IsReferenceType(self): ... + def IsFunctionType(self): ... + def IsPolymorphicClass(self): ... + def IsArrayType(self): ... + def IsVectorType(self): ... + def IsTypedefType(self): ... + def IsAnonymousType(self): ... + def IsScopedEnumerationType(self): ... + def IsAggregateType(self): ... + def GetPointerType(self): ... + def GetPointeeType(self) -> SBType: ... + def GetReferenceType(self): ... + def GetTypedefedType(self): ... + def GetDereferencedType(self): ... + def GetUnqualifiedType(self): ... + def GetArrayElementType(self) -> SBType: ... + def GetArrayType(self, size): ... + def GetVectorElementType(self): ... + def GetCanonicalType(self): ... + def GetEnumerationIntegerType(self): ... + def GetBasicType(self, *args): ... + def GetNumberOfFields(self): ... + def GetNumberOfDirectBaseClasses(self): ... + def GetNumberOfVirtualBaseClasses(self): ... + def GetFieldAtIndex(self, idx): ... + def GetDirectBaseClassAtIndex(self, idx): ... + def GetVirtualBaseClassAtIndex(self, idx): ... + def GetStaticFieldWithName(self, name): ... + def GetEnumMembers(self): ... + def GetNumberOfTemplateArguments(self): ... + def GetTemplateArgumentType(self, idx): ... + def GetTemplateArgumentKind(self, idx): ... + def GetFunctionReturnType(self): ... + def GetFunctionArgumentTypes(self): ... + def GetNumberOfMemberFunctions(self): ... + def GetMemberFunctionAtIndex(self, idx): ... + def GetModule(self): ... + def GetName(self): ... + def GetDisplayTypeName(self): ... + def GetTypeClass(self): ... + def IsTypeComplete(self): ... + def GetTypeFlags(self): ... + def GetDescription(self, description, description_level): ... + def FindDirectNestedType(self, name): ... + def __eq__(self, rhs): ... + def __ne__(self, rhs): ... + def __repr__(self): ... + def template_arg_array(self): ... + def __len__(self): ... + @property + def module(self): ... + @property + def name(self): ... + @property + def size(self): ... + @property + def is_pointer(self): ... + @property + def is_reference(self): ... + @property + def num_fields(self): ... + @property + def num_bases(self): ... + @property + def num_vbases(self): ... + @property + def num_template_args(self): ... + @property + def template_args(self): ... + @property + def type(self): ... + @property + def is_complete(self): ... + def get_bases_array(self): ... + def get_vbases_array(self): ... + def get_fields_array(self): ... + def get_members_array(self): ... + def get_enum_members_array(self): ... + @property + def bases(self): ... + @property + def vbases(self): ... + @property + def fields(self): ... + @property + def members(self): ... + @property + def enum_members(self): ... + +class SBValue: + @property + def thisown(self): ... + def __init__(self, *args): ... + def __nonzero__(self): ... + def IsValid(self): ... + def Clear(self): ... + def GetError(self): ... + def GetID(self): ... + def GetName(self) -> str: ... + def GetTypeName(self): ... + def GetDisplayTypeName(self): ... + def GetByteSize(self): ... + def IsInScope(self): ... + def GetFormat(self): ... + def SetFormat(self, format): ... + def GetValue(self) -> str: ... + def GetValueAsSigned(self, *args): ... + def GetValueAsUnsigned(self, fail_value: int = 0) -> int: ... + def GetValueAsAddress(self): ... + def GetValueType(self): ... + def GetValueDidChange(self): ... + def GetSummary(self, *args): ... + def GetObjectDescription(self): ... + def GetDynamicValue(self, use_dynamic): ... + def GetStaticValue(self): ... + def GetNonSyntheticValue(self) -> SBValue: ... + def GetSyntheticValue(self): ... + def GetPreferDynamicValue(self): ... + def SetPreferDynamicValue(self, use_dynamic): ... + def GetPreferSyntheticValue(self): ... + def SetPreferSyntheticValue(self, use_synthetic): ... + def IsDynamic(self): ... + def IsSynthetic(self): ... + def IsSyntheticChildrenGenerated(self): ... + def SetSyntheticChildrenGenerated(self, arg2): ... + def GetLocation(self): ... + def SetValueFromCString(self, *args): ... + def GetTypeFormat(self): ... + def GetTypeSummary(self): ... + def GetTypeFilter(self): ... + def GetTypeSynthetic(self): ... + def CreateChildAtOffset(self, name: str, offset: int, type: SBType) -> SBValue: ... + def Cast(self, type): ... + def CreateValueFromExpression(self, *args): ... + def CreateValueFromAddress(self, name, address, type): ... + def CreateValueFromData(self, name, data, type): ... + def GetChildAtIndex(self, *args): ... + def GetIndexOfChildWithName(self, name): ... + def GetChildMemberWithName(self, name: str) -> SBValue: ... + def GetValueForExpressionPath(self, expr_path): ... + def AddressOf(self): ... + def GetLoadAddress(self): ... + def GetAddress(self): ... + def GetPointeeData(self, item_idx: int = 0, item_count: int = 1) -> SBData: ... + def GetData(self): ... + def SetData(self, data, error): ... + def Clone(self, new_name): ... + def GetDeclaration(self): ... + def MightHaveChildren(self): ... + def IsRuntimeSupportValue(self): ... + def GetNumChildren(self, max: int | None = None) -> int: ... + def GetOpaqueType(self): ... + def GetTarget(self): ... + def GetProcess(self): ... + def GetThread(self): ... + def GetFrame(self): ... + def Dereference(self) -> SBValue: ... + def TypeIsPointerType(self): ... + def GetType(self) -> SBType: ... + def Persist(self): ... + def GetDescription(self, description): ... + def GetExpressionPath(self, *args): ... + def EvaluateExpression(self, *args): ... + def Watch(self, *args): ... + def WatchPointee(self, resolve_location, read, write, error): ... + def GetVTable(self): ... + def __repr__(self): ... + def __get_dynamic__(self): ... + def get_child_access_object(self): ... + def get_value_child_list(self): ... + def __hex__(self): ... + def __iter__(self): ... + def __len__(self): ... + @property + def children(self) -> list[SBValue]: ... + @property + def child(self): ... + @property + def name(self): ... + @property + def type(self): ... + @property + def size(self): ... + @property + def is_in_scope(self): ... + @property + def format(self): ... + @property + def value(self): ... + @property + def value_type(self): ... + @property + def changed(self): ... + @property + def data(self): ... + @property + def load_addr(self): ... + @property + def addr(self): ... + @property + def deref(self): ... + @property + def address_of(self): ... + @property + def error(self): ... + @property + def summary(self): ... + @property + def description(self): ... + @property + def dynamic(self): ... + @property + def location(self): ... + @property + def target(self): ... + @property + def process(self): ... + @property + def thread(self): ... + @property + def frame(self): ... + @property + def num_children(self): ... + @property + def unsigned(self): ... + @property + def signed(self): ... + def get_expr_path(self): ... + @property + def path(self): ... + def synthetic_child_from_expression(self, name, expr, options=None): ... + def synthetic_child_from_data(self, name, data, type): ... + def synthetic_child_from_address(self, name, addr, type): ... + def __eol_test(val): ... + def linked_list_iter(self, next_item_name, end_of_list_test=__eol_test): ... + +class SBSyntheticValueProvider: + def __init__(self, valobj: SBValue) -> None: ... + def num_children(self) -> int: ... + def get_child_index(self, name: str) -> int: ... + def get_child_at_index(self, idx: int) -> SBValue | None: ... + def update(self) -> bool | None: ... + def has_children(self) -> bool: ... + def __len__(self) -> int: ... + def __iter__(self): ... |
