Skip to content

Commit

Permalink
#8519: Add slice pretty-printers
Browse files Browse the repository at this point in the history
  • Loading branch information
artemmukhin committed Aug 9, 2022
1 parent 4787cfb commit 92442e4
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 20 deletions.
Expand Up @@ -202,6 +202,8 @@ class RsDebugProcessConfigurationHelper(
private val RUST_STD_TYPES: List<String> = listOf(
"^(alloc::([a-z_]+::)+)String$",
"^[&*]?(const |mut )?str\\*?$",
"^&(mut )?\\[.*\\]$",
"^(mut )?slice\\$<.+>$",
"^(std::ffi::([a-z_]+::)+)OsString$",
"^((&|&mut )?std::ffi::([a-z_]+::)+)OsStr( \\*)?$",
"^(std::([a-z_]+::)+)PathBuf$",
Expand Down
2 changes: 2 additions & 0 deletions prettyPrinters/gdb_lookup.py
Expand Up @@ -67,6 +67,8 @@ def lookup(valobj):
return StdOsStringProvider(valobj)
if rust_type == RustType.STD_STR:
return StdStrProvider(valobj)
if rust_type == RustType.STD_SLICE:
return StdSliceProvider(valobj)

if rust_type == RustType.STD_VEC:
return StdVecProvider(valobj)
Expand Down
34 changes: 31 additions & 3 deletions prettyPrinters/gdb_providers.py
Expand Up @@ -152,12 +152,20 @@ def display_hint():
return "string"


class StdVecProvider:
class ArrayLikeProviderBase:
def __init__(self, valobj):
# type: (Value) -> None
self.valobj = valobj
self.length = int(valobj["len"])
self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
self.data_ptr = self.get_data_ptr()
self.length = self.get_length()

def get_data_ptr(self):
# type: () -> Value
pass

def get_length(self):
# type: () -> int
pass

def to_string(self):
return "size={}".format(self.length)
Expand All @@ -171,6 +179,26 @@ def display_hint():
return "array"


class StdSliceProvider(ArrayLikeProviderBase):
def get_data_ptr(self):
# type: () -> Value
return self.valobj["data_ptr"]

def get_length(self):
# type: () -> int
return int(self.valobj["length"])


class StdVecProvider(ArrayLikeProviderBase):
def get_data_ptr(self):
# type: () -> Value
return unwrap_unique_or_non_null(self.valobj["buf"]["ptr"])

def get_length(self):
# type: () -> int
return int(self.valobj["len"])


class StdVecDequeProvider:
def __init__(self, valobj):
# type: (Value) -> None
Expand Down
6 changes: 6 additions & 0 deletions prettyPrinters/lldb_lookup.py
Expand Up @@ -41,6 +41,9 @@ def summary_lookup(valobj, dict):
if rust_type == RustType.STD_CSTR:
return StdFFIStrSummaryProvider(valobj, dict, is_null_terminated=True)

if rust_type == RustType.STD_SLICE or rust_type == RustType.STD_MSVC_SLICE:
return SizeSummaryProvider(valobj, dict)

if rust_type == RustType.STD_VEC:
return SizeSummaryProvider(valobj, dict)
if rust_type == RustType.STD_VEC_DEQUE:
Expand Down Expand Up @@ -90,6 +93,9 @@ def synthetic_lookup(valobj, dict):
if rust_type == RustType.SINGLETON_ENUM:
return synthetic_lookup(valobj.GetChildAtIndex(0), dict)

if rust_type == RustType.STD_SLICE or rust_type == RustType.STD_MSVC_SLICE:
return StdSliceSyntheticProvider(valobj, dict)

if rust_type == RustType.STD_VEC:
return StdVecSyntheticProvider(valobj, dict)
if rust_type == RustType.STD_VEC_DEQUE:
Expand Down
60 changes: 43 additions & 17 deletions prettyPrinters/lldb_providers.py
Expand Up @@ -297,21 +297,20 @@ def has_children(self):
return True


class StdVecSyntheticProvider:
"""Pretty-printer for alloc::vec::Vec<T>
struct Vec<T> { buf: RawVec<T>, len: usize }
struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
struct NonNull<T> { pointer: *const T }
"""

class ArrayLikeSyntheticProviderBase:
def __init__(self, valobj, _dict):
# type: (SBValue, dict) -> None
self.valobj = valobj
self.update()

def get_data_ptr(self):
# type: () -> SBValue
pass

def get_length(self):
# type: () -> int
pass

def num_children(self):
# type: () -> int
return self.length
Expand All @@ -326,16 +325,13 @@ def get_child_index(self, name):

def get_child_at_index(self, index):
# type: (int) -> SBValue
start = self.data_ptr.GetValueAsUnsigned()
address = start + index * self.element_type_size
element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
return element
offset = index * self.element_type_size
return self.data_ptr.CreateChildAtOffset("[%s]" % index, offset, self.element_type)

def update(self):
# type: () -> None
self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
self.buf = self.valobj.GetChildMemberWithName("buf")
self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
self.data_ptr = self.get_data_ptr()
self.length = self.get_length()
self.element_type = self.data_ptr.GetType().GetPointeeType()
self.element_type_size = self.element_type.GetByteSize()

Expand All @@ -344,6 +340,36 @@ def has_children(self):
return True


class StdSliceSyntheticProvider(ArrayLikeSyntheticProviderBase):
def get_data_ptr(self):
# type: () -> SBValue
return self.valobj.GetChildMemberWithName("data_ptr")

def get_length(self):
# type: () -> int
return self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned()


class StdVecSyntheticProvider(ArrayLikeSyntheticProviderBase):
"""Pretty-printer for alloc::vec::Vec<T>
struct Vec<T> { buf: RawVec<T>, len: usize }
struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
struct NonNull<T> { pointer: *const T }
"""

def get_data_ptr(self):
# type: () -> SBValue
buf = self.valobj.GetChildMemberWithName("buf")
return unwrap_unique_or_non_null(buf.GetChildMemberWithName("ptr"))

def get_length(self):
# type: () -> int
return self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()


class StdVecDequeSyntheticProvider:
"""Pretty-printer for alloc::collections::vec_deque::VecDeque<T>
Expand Down
7 changes: 7 additions & 0 deletions prettyPrinters/rust_types.py
Expand Up @@ -19,6 +19,8 @@ class RustType(object):
STD_OS_STRING = "StdOsString"
STD_PATH_BUF = "StdPathBuf"
STD_STR = "StdStr"
STD_SLICE = "StdSlice"
STD_MSVC_SLICE = "StdMsvcSlice"
STD_OS_STR = "StdOsStr"
STD_PATH = "StdPath"
STD_CSTRING = "StdCString"
Expand All @@ -42,6 +44,9 @@ class RustType(object):
STD_STRING_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)String$")
# str, mut str, const str*, mut str* (vanilla LLDB); &str, &mut str, *const str, *mut str (Rust-enabled LLDB)
STD_STR_REGEX = re.compile(r"^[&*]?(const |mut )?str\*?$")
STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.*\]$")
STD_MSVC_SLICE_REGEX = re.compile(r"^(mut )?slice\$<.+>$")

STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::([a-z_]+::)+)OsString$")
STD_OS_STR_REGEX = re.compile(r"^((&|&mut )?std::ffi::([a-z_]+::)+)OsStr( \*)?$")
STD_PATH_BUF_REGEX = re.compile(r"^(std::([a-z_]+::)+)PathBuf$")
Expand Down Expand Up @@ -73,6 +78,8 @@ class RustType(object):
RustType.STD_PATH_BUF: STD_PATH_BUF_REGEX,
RustType.STD_PATH: STD_PATH_REGEX,
RustType.STD_STR: STD_STR_REGEX,
RustType.STD_SLICE: STD_SLICE_REGEX,
RustType.STD_MSVC_SLICE: STD_MSVC_SLICE_REGEX,
RustType.STD_OS_STR: STD_OS_STR_REGEX,
RustType.STD_CSTRING: STD_CSTRING_REGEX,
RustType.STD_CSTR: STD_CSTR_REGEX,
Expand Down
26 changes: 26 additions & 0 deletions pretty_printers_tests/tests/slice.rs
@@ -0,0 +1,26 @@
// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print slice
// lldbr-check:[...]slice = size=2 { [0] = 1 [1] = 2 }
// lldbg-check:[...]$0 = size=2 { [0] = 1 [1] = 2 }
// lldb-command:print slice_mut
// lldbr-check:[...]slice_mut = size=2 { [0] = 1 [1] = 2 }
// lldbg-check:[...]$1 = size=2 { [0] = 1 [1] = 2 }

// === GDB TESTS ===================================================================================

// gdb-command:run

// gdb-command:print slice
// gdb-check:[...]$1 = size=2 = {1, 2}
// gdb-command:print slice_mut
// gdb-check:[...]$2 = size=2 = {1, 2}

fn main() {
let slice: &[i32] = &[1, 2];
let slice_mut: &mut [i32] = &mut [1, 2];

print!(""); // #break
}

0 comments on commit 92442e4

Please sign in to comment.