about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/etc/gdb_rust_pretty_printing.py364
1 files changed, 188 insertions, 176 deletions
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
index b6770c99975..c5587bb10d1 100755
--- a/src/etc/gdb_rust_pretty_printing.py
+++ b/src/etc/gdb_rust_pretty_printing.py
@@ -14,181 +14,189 @@ import gdb
 # GDB Pretty Printing Module for Rust
 #===============================================================================
 
+
 def register_printers(objfile):
-  "Registers Rust pretty printers for the given objfile"
-  objfile.pretty_printers.append(rust_pretty_printer_lookup_function)
+    "Registers Rust pretty printers for the given objfile"
+    objfile.pretty_printers.append(rust_pretty_printer_lookup_function)
+
 
 def rust_pretty_printer_lookup_function(val):
-  "Returns the correct Rust pretty printer for the given value if there is one"
-  type_code = val.type.code
-
-  if type_code == gdb.TYPE_CODE_STRUCT:
-    struct_kind = classify_struct(val.type)
-
-    if struct_kind == STRUCT_KIND_STR_SLICE:
-      return RustStringSlicePrinter(val)
-
-    if struct_kind == STRUCT_KIND_TUPLE:
-      return RustTuplePrinter(val)
-
-    if struct_kind == STRUCT_KIND_TUPLE_STRUCT:
-      return RustTupleStructPrinter(val, False)
-
-    if struct_kind == STRUCT_KIND_CSTYLE_VARIANT:
-      return RustCStyleEnumPrinter(val[get_field_at_index(val, 0)])
-
-    if struct_kind == STRUCT_KIND_TUPLE_VARIANT:
-      return RustTupleStructPrinter(val, True)
-
-    if struct_kind == STRUCT_KIND_STRUCT_VARIANT:
-      return RustStructPrinter(val, True)
-
-    return RustStructPrinter(val, False)
-
-  # Enum handling
-  if type_code == gdb.TYPE_CODE_UNION:
-    enum_members = list(val.type.fields())
-    enum_member_count = len(enum_members)
-
-    if enum_member_count == 0:
-      return RustStructPrinter(val, False)
-
-    if enum_member_count == 1:
-      first_variant_name = enum_members[0].name
-      if first_variant_name == None:
-        # This is a singleton enum
-        return rust_pretty_printer_lookup_function(val[enum_members[0]])
-      else:
-        assert first_variant_name.startswith("RUST$ENCODED$ENUM$")
-        # This is a space-optimized enum.
-        # This means this enum has only two states, and Rust uses one of the
-        # fields somewhere in the struct to determine which of the two states
-        # it's in. The location of the field is encoded in the name as something
-        # like RUST$ENCODED$ENUM$(num$)*name_of_zero_state
-        last_separator_index = first_variant_name.rfind("$")
-        start_index = len("RUST$ENCODED$ENUM$")
-        disr_field_indices = first_variant_name[start_index :
-                                              last_separator_index].split("$")
-        disr_field_indices = [int(index) for index in disr_field_indices]
-
-        sole_variant_val = val[enum_members[0]]
-        discriminant = sole_variant_val
-        for disr_field_index in disr_field_indices:
-          disr_field = get_field_at_index(discriminant, disr_field_index)
-          discriminant = discriminant[disr_field]
-
-        # If the discriminant field is a fat pointer we have to consider the
-        # first word as the true discriminant
-        if discriminant.type.code == gdb.TYPE_CODE_STRUCT:
-          discriminant = discriminant[get_field_at_index(discriminant, 0)]
-
-        if discriminant == 0:
-          null_variant_name = first_variant_name[last_separator_index + 1:]
-          return IdentityPrinter(null_variant_name)
-
-        return rust_pretty_printer_lookup_function(sole_variant_val)
-
-    # This is a regular enum, extract the discriminant
-    discriminant_name, discriminant_val = extract_discriminant_value(val)
-    return rust_pretty_printer_lookup_function(val[enum_members[discriminant_val]])
-
-  # No pretty printer has been found
-  return None
+    "Returns the correct Rust pretty printer for the given value if there is one"
+    type_code = val.type.code
+
+    if type_code == gdb.TYPE_CODE_STRUCT:
+        struct_kind = classify_struct(val.type)
+
+        if struct_kind == STRUCT_KIND_STR_SLICE:
+            return RustStringSlicePrinter(val)
+
+        if struct_kind == STRUCT_KIND_TUPLE:
+            return RustTuplePrinter(val)
+
+        if struct_kind == STRUCT_KIND_TUPLE_STRUCT:
+            return RustTupleStructPrinter(val, False)
+
+        if struct_kind == STRUCT_KIND_CSTYLE_VARIANT:
+            return RustCStyleEnumPrinter(val[get_field_at_index(val, 0)])
+
+        if struct_kind == STRUCT_KIND_TUPLE_VARIANT:
+            return RustTupleStructPrinter(val, True)
+
+        if struct_kind == STRUCT_KIND_STRUCT_VARIANT:
+            return RustStructPrinter(val, True)
+
+        return RustStructPrinter(val, False)
+
+    # Enum handling
+    if type_code == gdb.TYPE_CODE_UNION:
+        enum_members = list(val.type.fields())
+        enum_member_count = len(enum_members)
+
+        if enum_member_count == 0:
+            return RustStructPrinter(val, False)
+
+        if enum_member_count == 1:
+            first_variant_name = enum_members[0].name
+            if first_variant_name is None:
+                # This is a singleton enum
+                return rust_pretty_printer_lookup_function(val[enum_members[0]])
+            else:
+                assert first_variant_name.startswith("RUST$ENCODED$ENUM$")
+                # This is a space-optimized enum.
+                # This means this enum has only two states, and Rust uses one
+                # of the fields somewhere in the struct to determine which of
+                # the two states it's in. The location of the field is encoded
+                # in the name as something like
+                # RUST$ENCODED$ENUM$(num$)*name_of_zero_state
+                last_separator_index = first_variant_name.rfind("$")
+                start_index = len("RUST$ENCODED$ENUM$")
+                disr_field_indices = first_variant_name[start_index:last_separator_index].split("$")
+                disr_field_indices = [int(index) for index in disr_field_indices]
+
+                sole_variant_val = val[enum_members[0]]
+                discriminant = sole_variant_val
+                for disr_field_index in disr_field_indices:
+                    disr_field = get_field_at_index(discriminant, disr_field_index)
+                    discriminant = discriminant[disr_field]
+
+                # If the discriminant field is a fat pointer we have to consider the
+                # first word as the true discriminant
+                if discriminant.type.code == gdb.TYPE_CODE_STRUCT:
+                    discriminant = discriminant[get_field_at_index(discriminant, 0)]
+
+                if discriminant == 0:
+                    null_variant_name = first_variant_name[last_separator_index + 1:]
+                    return IdentityPrinter(null_variant_name)
+
+                return rust_pretty_printer_lookup_function(sole_variant_val)
+
+        # This is a regular enum, extract the discriminant
+        discriminant_name, discriminant_val = extract_discriminant_value(val)
+        return rust_pretty_printer_lookup_function(val[enum_members[discriminant_val]])
+
+    # No pretty printer has been found
+    return None
 
 #=------------------------------------------------------------------------------
 # Pretty Printer Classes
 #=------------------------------------------------------------------------------
 
+
 class RustStructPrinter:
-  def __init__(self, val, hide_first_field):
-    self.val = val
-    self.hide_first_field = hide_first_field
-
-  def to_string(self):
-    return self.val.type.tag
-
-  def children(self):
-    cs = []
-    for field in self.val.type.fields():
-      field_name = field.name
-      # Normally the field name is used as a key to access the field value,
-      # because that's also supported in older versions of GDB...
-      field_key = field_name
-      if field_name == None:
-        field_name = ""
-        # ... but for fields without a name (as in tuples), we have to fall back
-        # to the newer method of using the field object directly as key. In
-        # older versions of GDB, this will just fail.
-        field_key = field
-      name_value_tuple = ( field_name, self.val[field_key] )
-      cs.append( name_value_tuple )
-
-    if self.hide_first_field:
-      cs = cs[1:]
-
-    return cs
+    def __init__(self, val, hide_first_field):
+        self.val = val
+        self.hide_first_field = hide_first_field
+
+    def to_string(self):
+        return self.val.type.tag
+
+    def children(self):
+        cs = []
+        for field in self.val.type.fields():
+            field_name = field.name
+            # Normally the field name is used as a key to access the field
+            # value, because that's also supported in older versions of GDB...
+            field_key = field_name
+            if field_name is None:
+                field_name = ""
+                # ... but for fields without a name (as in tuples), we have to
+                # fall back to the newer method of using the field object
+                # directly as key. In older versions of GDB, this will just
+                # fail.
+                field_key = field
+            name_value_tuple = (field_name, self.val[field_key])
+            cs.append(name_value_tuple)
+
+        if self.hide_first_field:
+            cs = cs[1:]
+
+        return cs
+
 
 class RustTuplePrinter:
-  def __init__(self, val):
-    self.val = val
+    def __init__(self, val):
+        self.val = val
 
-  def to_string(self):
-    return None
+    def to_string(self):
+        return None
+
+    def children(self):
+        cs = []
+        for field in self.val.type.fields():
+            cs.append(("", self.val[field]))
 
-  def children(self):
-    cs = []
-    for field in self.val.type.fields():
-      cs.append( ("", self.val[field]) )
+        return cs
 
-    return cs
+    def display_hint(self):
+        return "array"
 
-  def display_hint(self):
-    return "array"
 
 class RustTupleStructPrinter:
-  def __init__(self, val, hide_first_field):
-    self.val = val
-    self.hide_first_field = hide_first_field
+    def __init__(self, val, hide_first_field):
+        self.val = val
+        self.hide_first_field = hide_first_field
 
-  def to_string(self):
-    return self.val.type.tag
+    def to_string(self):
+        return self.val.type.tag
 
-  def children(self):
-    cs = []
-    for field in self.val.type.fields():
-      cs.append( ("", self.val[field]) )
+    def children(self):
+        cs = []
+        for field in self.val.type.fields():
+            cs.append(("", self.val[field]))
 
-    if self.hide_first_field:
-      cs = cs[1:]
+        if self.hide_first_field:
+            cs = cs[1:]
 
-    return cs
+        return cs
+
+    def display_hint(self):
+        return "array"
 
-  def display_hint(self):
-    return "array"
 
 class RustStringSlicePrinter:
-  def __init__(self, val):
-    self.val = val
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        slice_byte_len = self.val["length"]
+        return '"%s"' % self.val["data_ptr"].string(encoding="utf-8", length=slice_byte_len)
 
-  def to_string(self):
-    slice_byte_len = self.val["length"]
-    return '"%s"' % self.val["data_ptr"].string(encoding = "utf-8",
-                                                length = slice_byte_len)
 
 class RustCStyleEnumPrinter:
-  def __init__(self, val):
-    assert val.type.code == gdb.TYPE_CODE_ENUM
-    self.val = val
+    def __init__(self, val):
+        assert val.type.code == gdb.TYPE_CODE_ENUM
+        self.val = val
+
+    def to_string(self):
+        return str(self.val)
 
-  def to_string(self):
-    return str(self.val)
 
 class IdentityPrinter:
-  def __init__(self, string):
-    self.string = string
+    def __init__(self, string):
+        self.string = string
 
-  def to_string(self):
-    return self.string
+    def to_string(self):
+        return self.string
 
 STRUCT_KIND_REGULAR_STRUCT  = 0
 STRUCT_KIND_TUPLE_STRUCT    = 1
@@ -198,47 +206,51 @@ STRUCT_KIND_STRUCT_VARIANT  = 4
 STRUCT_KIND_CSTYLE_VARIANT  = 5
 STRUCT_KIND_STR_SLICE       = 6
 
+
 def classify_struct(type):
-  if type.tag == "&str":
-    return STRUCT_KIND_STR_SLICE
+    if type.tag == "&str":
+        return STRUCT_KIND_STR_SLICE
 
-  fields = list(type.fields())
-  field_count = len(fields)
+    fields = list(type.fields())
+    field_count = len(fields)
 
-  if field_count == 0:
-    return STRUCT_KIND_REGULAR_STRUCT
+    if field_count == 0:
+        return STRUCT_KIND_REGULAR_STRUCT
+
+    if fields[0].name == "RUST$ENUM$DISR":
+        if field_count == 1:
+            return STRUCT_KIND_CSTYLE_VARIANT
+        elif fields[1].name is None:
+            return STRUCT_KIND_TUPLE_VARIANT
+        else:
+            return STRUCT_KIND_STRUCT_VARIANT
 
-  if fields[0].name == "RUST$ENUM$DISR":
-    if field_count == 1:
-      return STRUCT_KIND_CSTYLE_VARIANT
-    elif fields[1].name == None:
-      return STRUCT_KIND_TUPLE_VARIANT
-    else:
-      return STRUCT_KIND_STRUCT_VARIANT
+    if fields[0].name is None:
+        if type.tag.startswith("("):
+            return STRUCT_KIND_TUPLE
+        else:
+            return STRUCT_KIND_TUPLE_STRUCT
 
-  if fields[0].name == None:
-    if type.tag.startswith("("):
-      return STRUCT_KIND_TUPLE
-    else:
-      return STRUCT_KIND_TUPLE_STRUCT
+    return STRUCT_KIND_REGULAR_STRUCT
 
-  return STRUCT_KIND_REGULAR_STRUCT
 
 def extract_discriminant_value(enum_val):
-  assert enum_val.type.code == gdb.TYPE_CODE_UNION
-  for variant_descriptor in enum_val.type.fields():
-    variant_val = enum_val[variant_descriptor]
-    for field in variant_val.type.fields():
-      return (field.name, int(variant_val[field]))
+    assert enum_val.type.code == gdb.TYPE_CODE_UNION
+    for variant_descriptor in enum_val.type.fields():
+        variant_val = enum_val[variant_descriptor]
+        for field in variant_val.type.fields():
+            return (field.name, int(variant_val[field]))
+
 
 def first_field(val):
-  for field in val.type.fields():
-    return field
+    for field in val.type.fields():
+        return field
+
 
 def get_field_at_index(val, index):
-  i = 0
-  for field in val.type.fields():
-    if i == index:
-      return field
-    i += 1
-  return None
+    i = 0
+    for field in val.type.fields():
+        if i == index:
+            return field
+        i += 1
+    return None