1# Pretty printer for smol_str::SmolStr2#3# Usage (any of these):4# (gdb) source /path/to/gdb_smolstr_printer.py5# or add to .gdbinit6# python7# import gdb8# gdb.execute("source /path/to/gdb_smolstr_printer.py")9# end10#11# After loading:12# (gdb) info pretty-printer13# ...14# global pretty-printers:15# smol_str16# SmolStr17#18# Disable/enable:19# (gdb) disable pretty-printer global smol_str SmolStr20# (gdb) enable pretty-printer global smol_str SmolStr2122import gdb23import gdb.printing24import re2526SMOL_INLINE_SIZE_RE = re.compile(r".*::_V(\d+)$")272829def _read_utf8(mem):30 try:31 return mem.tobytes().decode("utf-8", errors="replace")32 except Exception:33 return repr(mem.tobytes())343536def _active_variant(enum_val):37 """Return (variant_name, variant_value) for a Rust enum value using discriminant logic.38 Assume layout: fields[0] is unnamed u8 discriminant; fields[1] is the active variant.39 """40 fields = enum_val.type.fields()41 if len(fields) < 2:42 return None, None43 variant_field = fields[1]44 return variant_field.name, enum_val[variant_field]454647class SmolStrProvider:48 def __init__(self, val):49 self.val = val5051 def to_string(self):52 try:53 repr_enum = self.val["__0"]54 except Exception:55 return "<SmolStr: missing __0>"5657 variant_name, variant_val = _active_variant(repr_enum)58 if not variant_name:59 return "<SmolStr: unknown variant>"6061 if variant_name == "Inline":62 try:63 inline_len_val = variant_val["len"]64 m = SMOL_INLINE_SIZE_RE.match(str(inline_len_val))65 if not m:66 return "<SmolStr Inline: bad len>"67 length = int(m.group(1))68 buf = variant_val["buf"]69 data = bytes(int(buf[i]) for i in range(length))70 return data.decode("utf-8", errors="replace")71 except Exception as e:72 return f"<SmolStr Inline error: {e}>"7374 if variant_name == "Static":75 try:76 # variant_val["__0"] is &'static str77 return variant_val["__0"]78 except Exception as e:79 return f"<SmolStr Static error: {e}>"8081 if variant_name == "Heap":82 try:83 # variant_val["__0"] is an Arc<str>84 inner = variant_val["__0"]["ptr"]["pointer"]85 # inner is a fat pointer to ArcInner<str>86 data_ptr = inner["data_ptr"]87 length = int(inner["length"])88 # ArcInner layout:89 # strong: Atomic<usize>, weak: Atomic<usize> | unsized tail 'data' bytes.90 sizeof_AtomicUsize = gdb.lookup_type(91 "core::sync::atomic::AtomicUsize"92 ).sizeof93 header_size = sizeof_AtomicUsize * 2 # strong + weak counters94 data_arr = int(data_ptr) + header_size95 mem = gdb.selected_inferior().read_memory(data_arr, length)96 return _read_utf8(mem)97 except Exception as e:98 return f"<SmolStr Heap error: {e}>"99100 return f"<SmolStr: unhandled variant {variant_name}>"101102 def display_hint(self):103 return "string"104105106class SmolStrSubPrinter(gdb.printing.SubPrettyPrinter):107 def __init__(self):108 super(SmolStrSubPrinter, self).__init__("SmolStr")109110 def __call__(self, val):111 if not self.enabled:112 return None113 try:114 t = val.type.strip_typedefs()115 if t.code == gdb.TYPE_CODE_STRUCT and t.name == "smol_str::SmolStr":116 return SmolStrProvider(val)117 except Exception:118 pass119 return None120121122class SmolStrPrettyPrinter(gdb.printing.PrettyPrinter):123 def __init__(self):124 super(SmolStrPrettyPrinter, self).__init__("smol_str", [])125 self.subprinters = []126 self._sp = SmolStrSubPrinter()127 self.subprinters.append(self._sp)128129 def __call__(self, val):130 # Iterate subprinters (only one now, scalable for future)131 for sp in self.subprinters:132 pp = sp(val)133 if pp is not None:134 return pp135 return None136137138printer = SmolStrPrettyPrinter()139140141def register_printers(objfile=None):142 gdb.printing.register_pretty_printer(objfile, printer, replace=True)143144145register_printers()
Findings
✓ No findings reported for this file.