Skip to content

Commit a540898

Browse files
committed
Add gdb printer
1 parent ab099d3 commit a540898

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

extra/int128_printer_gdb.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Copyright 2025 Matt Borland
2+
# Distributed under the Boost Software License, Version 1.0.
3+
# https://www.boost.org/LICENSE_1_0.txt
4+
#
5+
# Struct definitions:
6+
# struct uint128_t { std::uint64_t low; std::uint64_t high; };
7+
# struct int128_t { std::uint64_t low; std::int64_t high; };
8+
#
9+
# On big endian machines the word order is reversed
10+
#
11+
# Usage: source int128_printer.py
12+
13+
import gdb
14+
import gdb.printing
15+
import re
16+
17+
class Uint128Printer:
18+
"""Pretty printer for uint128_t type"""
19+
20+
def __init__(self, val):
21+
self.val = val
22+
23+
def to_string(self):
24+
try:
25+
high = int(self.val["high"]) & 0xFFFFFFFFFFFFFFFF # Treat as unsigned
26+
low = int(self.val["low"]) & 0xFFFFFFFFFFFFFFFF
27+
28+
value = (high << 64) | low
29+
return f"{value:,}"
30+
except Exception as e:
31+
return f"<invalid uint128_t: {e}>"
32+
33+
def children(self):
34+
yield "low", self.val["low"]
35+
yield "high", self.val["high"]
36+
37+
def display_hint(self):
38+
return None
39+
40+
41+
class Int128Printer:
42+
"""Pretty printer for int128_t type"""
43+
44+
def __init__(self, val):
45+
self.val = val
46+
47+
def to_string(self):
48+
try:
49+
# high is std::int64_t (signed)
50+
high = int(self.val["high"])
51+
# Ensure high is treated as signed 64-bit
52+
if high >= 0x8000000000000000:
53+
high -= 0x10000000000000000
54+
55+
# low is std::uint64_t (unsigned)
56+
low = int(self.val["low"]) & 0xFFFFFFFFFFFFFFFF
57+
58+
value = (high << 64) + low
59+
return f"{value:,}"
60+
except Exception as e:
61+
return f"<invalid int128_t: {e}>"
62+
63+
def children(self):
64+
yield "low", self.val["low"]
65+
yield "high", self.val["high"]
66+
67+
def display_hint(self):
68+
return None
69+
70+
71+
def lookup_int128_type(val):
72+
"""
73+
Lookup function to detect if a type should use our pretty printers.
74+
Returns the appropriate printer or None.
75+
"""
76+
# Get the basic type name, stripping references and const qualifiers
77+
type_obj = val.type
78+
79+
# Handle references and pointers
80+
if type_obj.code == gdb.TYPE_CODE_REF:
81+
type_obj = type_obj.target()
82+
if type_obj.code == gdb.TYPE_CODE_PTR:
83+
return None # Don't handle pointers directly
84+
85+
# Strip const/volatile qualifiers
86+
type_obj = type_obj.unqualified()
87+
88+
type_name = str(type_obj)
89+
90+
# Patterns to match uint128_t and int128_t types
91+
uint128_pattern = re.compile(
92+
r"^(boost::int128::uint128_t|(\w+::)*uint128_t|uint128_t)$"
93+
)
94+
int128_pattern = re.compile(
95+
r"^(boost::int128::int128_t|(\w+::)*int128_t|int128_t)$"
96+
)
97+
98+
if uint128_pattern.match(type_name):
99+
return Uint128Printer(val)
100+
if int128_pattern.match(type_name):
101+
return Int128Printer(val)
102+
103+
return None
104+
105+
106+
def register_int128_printers(objfile=None):
107+
"""Register the int128 pretty printers."""
108+
if objfile is None:
109+
objfile = gdb
110+
111+
objfile.pretty_printers.append(lookup_int128_type)
112+
113+
114+
# Auto-register when the script is sourced
115+
register_int128_printers()
116+
print("int128_t and uint128_t pretty printers loaded successfully")

0 commit comments

Comments
 (0)