Skip to content

Commit f30520a

Browse files
authored
Merge pull request #1335 from gibbyfree/natvis-doc
Add documentation for debugger_visualizer attribute
2 parents 47b54b5 + 39a0be6 commit f30520a

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
- [Code generation](attributes/codegen.md)
4545
- [Limits](attributes/limits.md)
4646
- [Type System](attributes/type_system.md)
47+
- [Debugger](attributes/debugger.md)
4748

4849
- [Statements and expressions](statements-and-expressions.md)
4950
- [Statements](statements.md)

src/attributes.md

+3
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ The following is an index of all built-in attributes.
271271
- Type System
272272
- [`non_exhaustive`] — Indicate that a type will have more fields/variants
273273
added in future.
274+
- Debugger
275+
- [`debugger_visualizer`] — Embeds a file that specifies debugger output for a type.
274276

275277
[Doc comments]: comments.md#doc-comments
276278
[ECMA-334]: https://www.ecma-international.org/publications/standards/Ecma-334.htm
@@ -291,6 +293,7 @@ The following is an index of all built-in attributes.
291293
[`cold`]: attributes/codegen.md#the-cold-attribute
292294
[`crate_name`]: crates-and-source-files.md#the-crate_name-attribute
293295
[`crate_type`]: linkage.md
296+
[`debugger_visualizer`]: attributes/debugger.md#the-debugger_visualizer-attribute
294297
[`deny`]: attributes/diagnostics.md#lint-check-attributes
295298
[`deprecated`]: attributes/diagnostics.md#the-deprecated-attribute
296299
[`derive`]: attributes/derive.md

src/attributes/debugger.md

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Debugger attributes
2+
3+
The following [attributes] are used for enhancing the debugging experience when using third-party debuggers like GDB or WinDbg.
4+
5+
## The `debugger_visualizer` attribute
6+
7+
The *`debugger_visualizer` attribute* can be used to embed a debugger visualizer file into the debug information.
8+
This enables an improved debugger experience for displaying values in the debugger.
9+
It uses the [_MetaListNameValueStr_] syntax to specify its inputs, and must be specified as a crate attribute.
10+
11+
### Using `debugger_visualizer` with Natvis
12+
13+
Natvis is an XML-based framework for Microsoft debuggers (such as Visual Studio and WinDbg) that uses declarative rules to customize the display of types.
14+
For detailed information on the Natvis format, refer to Microsoft's [Natvis documentation].
15+
16+
This attribute only supports embedding Natvis files on `-windows-msvc` targets.
17+
18+
The path to the Natvis file is specified with the `natvis_file` key, which is a path relative to the crate source file:
19+
20+
<!-- ignore: requires external files, and msvc -->
21+
```rust ignore
22+
#![debugger_visualizer(natvis_file = "Rectangle.natvis")]
23+
24+
struct FancyRect {
25+
x: f32,
26+
y: f32,
27+
dx: f32,
28+
dy: f32,
29+
}
30+
31+
fn main() {
32+
let fancy_rect = FancyRect { x: 10.0, y: 10.0, dx: 5.0, dy: 5.0 };
33+
println!("set breakpoint here");
34+
}
35+
```
36+
37+
and `Rectangle.natvis` contains:
38+
39+
```xml
40+
<?xml version="1.0" encoding="utf-8"?>
41+
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
42+
<Type Name="foo::FancyRect">
43+
<DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
44+
<Expand>
45+
<Synthetic Name="LowerLeft">
46+
<DisplayString>({x}, {y})</DisplayString>
47+
</Synthetic>
48+
<Synthetic Name="UpperLeft">
49+
<DisplayString>({x}, {y + dy})</DisplayString>
50+
</Synthetic>
51+
<Synthetic Name="UpperRight">
52+
<DisplayString>({x + dx}, {y + dy})</DisplayString>
53+
</Synthetic>
54+
<Synthetic Name="LowerRight">
55+
<DisplayString>({x + dx}, {y})</DisplayString>
56+
</Synthetic>
57+
</Expand>
58+
</Type>
59+
</AutoVisualizer>
60+
```
61+
62+
When viewed under WinDbg, the `fancy_rect` variable would be shown as follows:
63+
64+
```text
65+
> Variables:
66+
> fancy_rect: (10.0, 10.0) + (5.0, 5.0)
67+
> LowerLeft: (10.0, 10.0)
68+
> UpperLeft: (10.0, 15.0)
69+
> UpperRight: (15.0, 15.0)
70+
> LowerRight: (15.0, 10.0)
71+
```
72+
73+
### Using `debugger_visualizer` with GDB
74+
75+
GDB supports the use of a structured Python script, called a *pretty printer*, that describes how a type should be visualized in the debugger view.
76+
For detailed information on pretty printers, refer to GDB's [pretty printing documentation].
77+
78+
Embedded pretty printers are not automatically loaded when debugging a binary under GDB.
79+
There are two ways to enable auto-loading embedded pretty printers:
80+
1. Launch GDB with extra arguments to explicitly add a directory or binary to the auto-load safe path: `gdb -iex "add-auto-load-safe-path safe-path path/to/binary" path/to/binary`
81+
For more information, see GDB's [auto-loading documentation].
82+
1. Create a file named `gdbinit` under `$HOME/.config/gdb` (you may need to create the directory if it doesn't already exist). Add the following line to that file: `add-auto-load-safe-path path/to/binary`.
83+
84+
These scripts are embedded using the `gdb_script_file` key, which is a path relative to the crate source file.
85+
86+
<!-- ignore: requires external files -->
87+
```rust ignore
88+
#![debugger_visualizer(gdb_script_file = "printer.py")]
89+
90+
struct Person {
91+
name: String,
92+
age: i32,
93+
}
94+
95+
fn main() {
96+
let bob = Person { name: String::from("Bob"), age: 10 };
97+
println!("set breakpoint here");
98+
}
99+
```
100+
101+
and `printer.py` contains:
102+
103+
```python
104+
import gdb
105+
106+
class PersonPrinter:
107+
"Print a Person"
108+
109+
def __init__(self, val):
110+
self.val = val
111+
self.name = val["name"]
112+
self.age = int(val["age"])
113+
114+
def to_string(self):
115+
return "{} is {} years old.".format(self.name, self.age)
116+
117+
def lookup(val):
118+
lookup_tag = val.type.tag
119+
if lookup_tag is None:
120+
return None
121+
if "foo::Person" == lookup_tag:
122+
return PersonPrinter(val)
123+
124+
return None
125+
126+
gdb.current_objfile().pretty_printers.append(lookup)
127+
```
128+
129+
When the crate's debug executable is passed into GDB[^rust-gdb], `print bob` will display:
130+
131+
```text
132+
"Bob" is 10 years old.
133+
```
134+
135+
[^rust-gdb]: Note: This assumes you are using the `rust-gdb` script which configures pretty-printers for standard library types like `String`.
136+
137+
[auto-loading documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Auto_002dloading-safe-path.html
138+
[attributes]: ../attributes.md
139+
[Natvis documentation]: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects
140+
[pretty printing documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html
141+
[_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax

0 commit comments

Comments
 (0)