Skip to content

Commit f18e27b

Browse files
authored
Merge pull request #1281 from cppalliance/gdb
Add GDB pretty printer module and docs
2 parents e5fe052 + 898fa9a commit f18e27b

File tree

3 files changed

+209
-15
lines changed

3 files changed

+209
-15
lines changed

doc/modules/ROOT/pages/debugger.adoc

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,37 @@ https://www.boost.org/LICENSE_1_0.txt
88
= Debugger Support
99
:idprefix: debug_
1010

11-
Currently, Boost.Decimal supports pretty printing with LLDB.
11+
Currently, Boost.Decimal supports pretty printing with LLDB and GDB.
12+
13+
== LLDB
14+
1215
To load the pretty printer, add the following line to your `.lldbinit`:
1316

1417
[source]
1518
----
16-
command script import /path/to/decimal/extra/decimal_printer.py
19+
command script import /path/to/decimal/extra/decimal_printer_lldb.py
20+
----
21+
22+
== GDB
23+
24+
To load the pretty printer, add the following line to your `.gdbinit`:
25+
26+
[source]
27+
----
28+
python exec(open("/path/to/decimal/extra/decimal_printer_gdb.py").read())
1729
----
1830

19-
Once you have loaded `decimal_printer.py` you can run the following example to see how different values are represented with the pretty printer.
31+
or you can source it manually in GDB:
32+
33+
[source]
34+
----
35+
(gdb) source /path/to/decimal/extra/decimal_printer_gdb.py
36+
----
37+
38+
== Example
39+
40+
Once you have loaded a pretty printer, you can run the below example to see how different values are represented with the pretty printer.
41+
This expected output of the example below was taken from LLDB, but the results should be quite similar when using GDB.
2042

2143
.The following example can be run with the debugger to show a variety of values
2244
====

extra/decimal_printer_gdb.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
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+
from detail.decode_ieee_type import decode_decimal32
6+
from detail.decode_ieee_type import decode_decimal64
7+
from detail.decode_ieee_type import decode_decimal128
8+
from detail.decode_fast_type import decode_decimal_fast32
9+
from detail.decode_fast_type import decode_decimal_fast64
10+
from detail.decode_fast_type import decode_decimal_fast128
11+
12+
import gdb
13+
import gdb.printing
14+
15+
class Decimal32Printer:
16+
"""Pretty printer for decimal32_t type"""
17+
18+
def __init__(self, val):
19+
self.val = val
20+
21+
def to_string(self):
22+
try:
23+
bits = int(self.val['bits_'])
24+
return decode_decimal32(bits)
25+
except Exception as e:
26+
return f"<invalid decimal32_t: {e}>"
27+
28+
def children(self):
29+
yield ('bits_', self.val['bits_'])
30+
31+
32+
class Decimal64Printer:
33+
"""Pretty printer for decimal64_t type"""
34+
35+
def __init__(self, val):
36+
self.val = val
37+
38+
def to_string(self):
39+
try:
40+
bits = int(self.val['bits_'])
41+
return decode_decimal64(bits)
42+
except Exception as e:
43+
return f"<invalid decimal64_t: {e}>"
44+
45+
def children(self):
46+
yield ('bits_', self.val['bits_'])
47+
48+
49+
class Decimal128Printer:
50+
"""Pretty printer for decimal128_t type"""
51+
52+
def __init__(self, val):
53+
self.val = val
54+
55+
def to_string(self):
56+
try:
57+
bits = self.val['bits_']
58+
bits_high = int(bits['high'])
59+
bits_low = int(bits['low'])
60+
combined_bits = (bits_high << 64) | bits_low
61+
return decode_decimal128(combined_bits)
62+
except Exception as e:
63+
return f"<invalid decimal128_t: {e}>"
64+
65+
def children(self):
66+
yield ('bits_', self.val['bits_'])
67+
68+
69+
class DecimalFast32Printer:
70+
"""Pretty printer for decimal_fast32_t type"""
71+
72+
def __init__(self, val):
73+
self.val = val
74+
75+
def to_string(self):
76+
try:
77+
significand = int(self.val['significand_'])
78+
exp = int(self.val['exponent_'])
79+
sign = int(self.val['sign_'])
80+
return decode_decimal_fast32(significand, exp, sign)
81+
except Exception as e:
82+
return f"<invalid decimal_fast32_t: {e}>"
83+
84+
def children(self):
85+
yield ('significand_', self.val['significand_'])
86+
yield ('exponent_', self.val['exponent_'])
87+
yield ('sign_', self.val['sign_'])
88+
89+
90+
class DecimalFast64Printer:
91+
"""Pretty printer for decimal_fast64_t type"""
92+
93+
def __init__(self, val):
94+
self.val = val
95+
96+
def to_string(self):
97+
try:
98+
significand = int(self.val['significand_'])
99+
exp = int(self.val['exponent_'])
100+
sign = int(self.val['sign_'])
101+
return decode_decimal_fast64(significand, exp, sign)
102+
except Exception as e:
103+
return f"<invalid decimal_fast64_t: {e}>"
104+
105+
def children(self):
106+
yield ('significand_', self.val['significand_'])
107+
yield ('exponent_', self.val['exponent_'])
108+
yield ('sign_', self.val['sign_'])
109+
110+
111+
class DecimalFast128Printer:
112+
"""Pretty printer for decimal_fast128_t type"""
113+
114+
def __init__(self, val):
115+
self.val = val
116+
117+
def to_string(self):
118+
try:
119+
significand = self.val['significand_']
120+
bits_high = int(significand['high'])
121+
bits_low = int(significand['low'])
122+
combined_bits = (bits_high << 64) | bits_low
123+
124+
exp = int(self.val['exponent_'])
125+
sign = int(self.val['sign_'])
126+
127+
return decode_decimal_fast128(combined_bits, exp, sign)
128+
except Exception as e:
129+
return f"<invalid decimal_fast128_t: {e}>"
130+
131+
def children(self):
132+
yield ('significand_', self.val['significand_'])
133+
yield ('exponent_', self.val['exponent_'])
134+
yield ('sign_', self.val['sign_'])
135+
136+
137+
def build_pretty_printer():
138+
"""Build and return the pretty printer collection"""
139+
pp = gdb.printing.RegexpCollectionPrettyPrinter("boost_decimal")
140+
141+
# IEEE types
142+
pp.add_printer('decimal32_t',
143+
r'^(const )?(boost::decimal::)?decimal32_t( &| \*)?$',
144+
Decimal32Printer)
145+
pp.add_printer('decimal64_t',
146+
r'^(const )?(boost::decimal::)?decimal64_t( &| \*)?$',
147+
Decimal64Printer)
148+
pp.add_printer('decimal128_t',
149+
r'^(const )?(boost::decimal::)?decimal128_t( &| \*)?$',
150+
Decimal128Printer)
151+
152+
# Fast types
153+
pp.add_printer('decimal_fast32_t',
154+
r'^(const )?(boost::decimal::)?decimal_fast32_t( &| \*)?$',
155+
DecimalFast32Printer)
156+
pp.add_printer('decimal_fast64_t',
157+
r'^(const )?(boost::decimal::)?decimal_fast64_t( &| \*)?$',
158+
DecimalFast64Printer)
159+
pp.add_printer('decimal_fast128_t',
160+
r'^(const )?(boost::decimal::)?decimal_fast128_t( &| \*)?$',
161+
DecimalFast128Printer)
162+
163+
return pp
164+
165+
166+
def register_printers(objfile=None):
167+
gdb.printing.register_pretty_printer(objfile, build_pretty_printer())
168+
169+
170+
# Auto-register when the module is loaded
171+
register_printers()
172+
print("Boost.Decimal pretty printers loaded successfully")
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,55 +119,55 @@ def __lldb_init_module(debugger, internal_dict):
119119
decimal_fast128_pattern = r"^(const )?(boost::decimal::decimal_fast128_t|(\w+::)*decimal_fast128_t)( &| \*)?$"
120120

121121
debugger.HandleCommand(
122-
f'type summary add -x "{decimal32_pattern}" -e -F decimal_printer.decimal32_summary'
122+
f'type summary add -x "{decimal32_pattern}" -e -F decimal_printer_lldb.decimal32_summary'
123123
)
124124
debugger.HandleCommand(
125-
f'type synthetic add -x "{decimal32_pattern}" -l decimal_printer.DecimalSyntheticProvider'
125+
f'type synthetic add -x "{decimal32_pattern}" -l decimal_printer_lldb.DecimalSyntheticProvider'
126126
)
127127

128128
print("decimal32_t printer loaded successfully")
129129

130130
debugger.HandleCommand(
131-
f'type summary add -x "{decimal64_pattern}" -e -F decimal_printer.decimal64_summary'
131+
f'type summary add -x "{decimal64_pattern}" -e -F decimal_printer_lldb.decimal64_summary'
132132
)
133133
debugger.HandleCommand(
134-
f'type synthetic add -x "{decimal64_pattern}" -l decimal_printer.DecimalSyntheticProvider'
134+
f'type synthetic add -x "{decimal64_pattern}" -l decimal_printer_lldb.DecimalSyntheticProvider'
135135
)
136136

137137
print("decimal64_t printer loaded successfully")
138138

139139
debugger.HandleCommand(
140-
f'type summary add -x "{decimal128_pattern}" -e -F decimal_printer.decimal128_summary'
140+
f'type summary add -x "{decimal128_pattern}" -e -F decimal_printer_lldb.decimal128_summary'
141141
)
142142
debugger.HandleCommand(
143-
f'type synthetic add -x "{decimal128_pattern}" -l decimal_printer.DecimalSyntheticProvider'
143+
f'type synthetic add -x "{decimal128_pattern}" -l decimal_printer_lldb.DecimalSyntheticProvider'
144144
)
145145

146146
print("decimal128_t printer loaded successfully")
147147

148148
debugger.HandleCommand(
149-
f'type summary add -x "{decimal_fast32_pattern}" -e -F decimal_printer.decimal_fast32_summary'
149+
f'type summary add -x "{decimal_fast32_pattern}" -e -F decimal_printer_lldb.decimal_fast32_summary'
150150
)
151151
debugger.HandleCommand(
152-
f'type synthetic add -x "{decimal_fast32_pattern}" -l decimal_printer.DecimalFastSyntheticProvider'
152+
f'type synthetic add -x "{decimal_fast32_pattern}" -l decimal_printer_lldb.DecimalFastSyntheticProvider'
153153
)
154154

155155
print("decimal_fast32_t printer loaded successfully")
156156

157157
debugger.HandleCommand(
158-
f'type summary add -x "{decimal_fast64_pattern}" -e -F decimal_printer.decimal_fast64_summary'
158+
f'type summary add -x "{decimal_fast64_pattern}" -e -F decimal_printer_lldb.decimal_fast64_summary'
159159
)
160160
debugger.HandleCommand(
161-
f'type synthetic add -x "{decimal_fast64_pattern}" -l decimal_printer.DecimalFastSyntheticProvider'
161+
f'type synthetic add -x "{decimal_fast64_pattern}" -l decimal_printer_lldb.DecimalFastSyntheticProvider'
162162
)
163163

164164
print("decimal_fast64_t printer loaded successfully")
165165

166166
debugger.HandleCommand(
167-
f'type summary add -x "{decimal_fast128_pattern}" -e -F decimal_printer.decimal_fast128_summary'
167+
f'type summary add -x "{decimal_fast128_pattern}" -e -F decimal_printer_lldb.decimal_fast128_summary'
168168
)
169169
debugger.HandleCommand(
170-
f'type synthetic add -x "{decimal_fast128_pattern}" -l decimal_printer.DecimalFastSyntheticProvider'
170+
f'type synthetic add -x "{decimal_fast128_pattern}" -l decimal_printer_lldb.DecimalFastSyntheticProvider'
171171
)
172172

173173
print("decimal_fast128_t printer loaded successfully")

0 commit comments

Comments
 (0)