]> git.lizzy.rs Git - rust.git/commitdiff
debuginfo: Add GDB pretty printers for slices, Vec<>, and String.
authorMichael Woerister <michaelwoerister@posteo>
Thu, 12 Mar 2015 16:05:44 +0000 (17:05 +0100)
committerMichael Woerister <michaelwoerister@posteo>
Thu, 12 Mar 2015 16:05:44 +0000 (17:05 +0100)
src/etc/gdb_rust_pretty_printing.py
src/test/debuginfo/gdb-pretty-std.rs [new file with mode: 0644]

index c5587bb10d1dacf3840b35dc5350055e1b61cbec..dbf27e88c143e0293cf02c9b1258befc28e33ef9 100755 (executable)
@@ -27,9 +27,18 @@ def rust_pretty_printer_lookup_function(val):
     if type_code == gdb.TYPE_CODE_STRUCT:
         struct_kind = classify_struct(val.type)
 
+        if struct_kind == STRUCT_KIND_SLICE:
+            return RustSlicePrinter(val)
+
         if struct_kind == STRUCT_KIND_STR_SLICE:
             return RustStringSlicePrinter(val)
 
+        if struct_kind == STRUCT_KIND_STD_VEC:
+            return RustStdVecPrinter(val)
+
+        if struct_kind == STRUCT_KIND_STD_STRING:
+            return RustStdStringPrinter(val)
+
         if struct_kind == STRUCT_KIND_TUPLE:
             return RustTuplePrinter(val)
 
@@ -172,6 +181,28 @@ class RustTupleStructPrinter:
     def display_hint(self):
         return "array"
 
+class RustSlicePrinter:
+    def __init__(self, val):
+        self.val = val
+
+    def display_hint(self):
+        return "array"
+
+    def to_string(self):
+        length = int(self.val["length"])
+        return self.val.type.tag + ("(len: %i)" % length)
+
+    def children(self):
+        cs = []
+        length = int(self.val["length"])
+        data_ptr = self.val["data_ptr"]
+        assert data_ptr.type.code == gdb.TYPE_CODE_PTR
+        pointee_type = data_ptr.type.target()
+
+        for index in range(0, length):
+            cs.append((str(index), (data_ptr + index).dereference()))
+
+        return cs
 
 class RustStringSlicePrinter:
     def __init__(self, val):
@@ -181,6 +212,35 @@ class RustStringSlicePrinter:
         slice_byte_len = self.val["length"]
         return '"%s"' % self.val["data_ptr"].string(encoding="utf-8", length=slice_byte_len)
 
+class RustStdVecPrinter:
+    def __init__(self, val):
+        self.val = val
+
+    def display_hint(self):
+        return "array"
+
+    def to_string(self):
+        length = int(self.val["len"])
+        cap = int(self.val["cap"])
+        return self.val.type.tag + ("(len: %i, cap: %i)" % (length, cap))
+
+    def children(self):
+        cs = []
+        (length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val)
+        pointee_type = data_ptr.type.target()
+
+        for index in range(0, length):
+            cs.append((str(index), (data_ptr + index).dereference()))
+        return cs
+
+class RustStdStringPrinter:
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        (length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val["vec"])
+        return '"%s"' % data_ptr.string(encoding="utf-8", length=length)
+
 
 class RustCStyleEnumPrinter:
     def __init__(self, val):
@@ -204,19 +264,38 @@ STRUCT_KIND_TUPLE           = 2
 STRUCT_KIND_TUPLE_VARIANT   = 3
 STRUCT_KIND_STRUCT_VARIANT  = 4
 STRUCT_KIND_CSTYLE_VARIANT  = 5
-STRUCT_KIND_STR_SLICE       = 6
+STRUCT_KIND_SLICE           = 6
+STRUCT_KIND_STR_SLICE       = 7
+STRUCT_KIND_STD_VEC         = 8
+STRUCT_KIND_STD_STRING      = 9
 
 
 def classify_struct(type):
+    # print("\nclassify_struct: tag=%s\n" % type.tag)
     if type.tag == "&str":
         return STRUCT_KIND_STR_SLICE
 
+    if type.tag.startswith("&[") and type.tag.endswith("]"):
+        return STRUCT_KIND_SLICE
+
     fields = list(type.fields())
     field_count = len(fields)
 
     if field_count == 0:
         return STRUCT_KIND_REGULAR_STRUCT
 
+    if (field_count == 3 and
+        fields[0].name == "ptr" and
+        fields[1].name == "len" and
+        fields[2].name == "cap" and
+        type.tag.startswith("Vec<")):
+        return STRUCT_KIND_STD_VEC
+
+    if (field_count == 1 and
+        fields[0].name == "vec" and
+        type.tag == "String"):
+        return STRUCT_KIND_STD_STRING
+
     if fields[0].name == "RUST$ENUM$DISR":
         if field_count == 1:
             return STRUCT_KIND_CSTYLE_VARIANT
@@ -254,3 +333,11 @@ def get_field_at_index(val, index):
             return field
         i += 1
     return None
+
+def extract_length_and_data_ptr_from_std_vec(vec_val):
+    length = int(vec_val["len"])
+    vec_ptr_val = vec_val["ptr"]
+    unique_ptr_val = vec_ptr_val[first_field(vec_ptr_val)]
+    data_ptr = unique_ptr_val[first_field(unique_ptr_val)]
+    assert data_ptr.type.code == gdb.TYPE_CODE_PTR
+    return (length, data_ptr)
\ No newline at end of file
diff --git a/src/test/debuginfo/gdb-pretty-std.rs b/src/test/debuginfo/gdb-pretty-std.rs
new file mode 100644 (file)
index 0000000..dbf80a9
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-windows failing on win32 bot
+// ignore-freebsd: gdb package too new
+// ignore-tidy-linelength
+// ignore-lldb
+// ignore-android: FIXME(#10381)
+// compile-flags:-g
+// min-gdb-version 7.7
+
+// gdb-command: run
+
+// gdb-command: print slice
+// gdb-check:$1 = &[i32](len: 4) = {0, 1, 2, 3}
+
+// gdb-command: print vec
+// gdb-check:$2 = Vec<u64>(len: 4, cap: [...]) = {4, 5, 6, 7}
+
+// gdb-command: print str_slice
+// gdb-check:$3 = "IAMA string slice!"
+
+// gdb-command: print string
+// gdb-check:$4 = "IAMA string!"
+
+// gdb-command: print some
+// gdb-check:$5 = Some = {8}
+
+// gdb-command: print none
+// gdb-check:$6 = None
+
+fn main() {
+
+    // &[]
+    let slice: &[i32] = &[0, 1, 2, 3];
+
+    // Vec
+    let vec = vec![4u64, 5, 6, 7];
+
+    // &str
+    let str_slice = "IAMA string slice!";
+
+    // String
+    let string = "IAMA string!".to_string();
+
+    // Option
+    let some = Some(8i16);
+    let none: Option<i64> = None;
+
+    zzz(); // #break
+}
+
+fn zzz() { () }