Skip to content

Commit 00405f8

Browse files
authored
Merge pull request #1922 from ehuss/debugger_visualizer
Update `debugger_visualizer` to use the attribute template
2 parents c384cd6 + 2551932 commit 00405f8

File tree

1 file changed

+135
-116
lines changed

1 file changed

+135
-116
lines changed

src/attributes/debugger.md

Lines changed: 135 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -3,148 +3,166 @@ r[attributes.debugger]
33

44
The following [attributes] are used for enhancing the debugging experience when using third-party debuggers like GDB or WinDbg.
55

6+
<!-- template:attributes -->
67
r[attributes.debugger.debugger_visualizer]
78
## The `debugger_visualizer` attribute
89

910
r[attributes.debugger.debugger_visualizer.intro]
10-
The *`debugger_visualizer` attribute* can be used to embed a debugger visualizer file into the debug information.
11-
This enables an improved debugger experience for displaying values in the debugger.
11+
The *`debugger_visualizer` [attribute][attributes]* can be used to embed a debugger visualizer file into the debug information. This improves the debugger experience when displaying values.
12+
13+
> [!EXAMPLE]
14+
> <!-- ignore: requires external files-->
15+
> ```rust,ignore
16+
> #![debugger_visualizer(natvis_file = "Example.natvis")]
17+
> #![debugger_visualizer(gdb_script_file = "example.py")]
18+
> ```
1219
1320
r[attributes.debugger.debugger_visualizer.syntax]
14-
It uses the [MetaListNameValueStr] syntax to specify its inputs, and must be specified as a crate attribute.
21+
The `debugger_visualizer` attribute uses the [MetaListNameValueStr] syntax to specify its inputs. One of the following keys must be specified:
22+
23+
- [`natvis_file`][attributes.debugger.debugger_visualizer.natvis]
24+
- [`gdb_script_file`][attributes.debugger.debugger_visualizer.gdb]
25+
26+
r[attributes.debugger.debugger_visualizer.allowed-positions]
27+
The `debugger_visualizer` attribute may only be applied to a [module] or to the crate root.
28+
29+
r[attributes.debugger.debugger_visualizer.duplicates]
30+
The `debugger_visualizer` attribute may be used any number of times on a form. All specified visualizer files will be loaded.
1531
1632
r[attributes.debugger.debugger_visualizer.natvis]
1733
### Using `debugger_visualizer` with Natvis
1834
1935
r[attributes.debugger.debugger_visualizer.natvis.intro]
20-
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.
21-
For detailed information on the Natvis format, refer to Microsoft's [Natvis documentation].
36+
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. For detailed information on the Natvis format, refer to Microsoft's [Natvis documentation].
2237
2338
r[attributes.debugger.debugger_visualizer.natvis.msvc]
2439
This attribute only supports embedding Natvis files on `-windows-msvc` targets.
2540
2641
r[attributes.debugger.debugger_visualizer.natvis.path]
27-
The path to the Natvis file is specified with the `natvis_file` key, which is a path relative to the crate source file:
28-
29-
<!-- ignore: requires external files, and msvc -->
30-
```rust ignore
31-
#![debugger_visualizer(natvis_file = "Rectangle.natvis")]
32-
33-
struct FancyRect {
34-
x: f32,
35-
y: f32,
36-
dx: f32,
37-
dy: f32,
38-
}
39-
40-
fn main() {
41-
let fancy_rect = FancyRect { x: 10.0, y: 10.0, dx: 5.0, dy: 5.0 };
42-
println!("set breakpoint here");
43-
}
44-
```
42+
The path to the Natvis file is specified with the `natvis_file` key, which is a path relative to the source file.
4543
46-
and `Rectangle.natvis` contains:
47-
48-
```xml
49-
<?xml version="1.0" encoding="utf-8"?>
50-
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
51-
<Type Name="foo::FancyRect">
52-
<DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
53-
<Expand>
54-
<Synthetic Name="LowerLeft">
55-
<DisplayString>({x}, {y})</DisplayString>
56-
</Synthetic>
57-
<Synthetic Name="UpperLeft">
58-
<DisplayString>({x}, {y + dy})</DisplayString>
59-
</Synthetic>
60-
<Synthetic Name="UpperRight">
61-
<DisplayString>({x + dx}, {y + dy})</DisplayString>
62-
</Synthetic>
63-
<Synthetic Name="LowerRight">
64-
<DisplayString>({x + dx}, {y})</DisplayString>
65-
</Synthetic>
66-
</Expand>
67-
</Type>
68-
</AutoVisualizer>
69-
```
70-
71-
When viewed under WinDbg, the `fancy_rect` variable would be shown as follows:
72-
73-
```text
74-
> Variables:
75-
> fancy_rect: (10.0, 10.0) + (5.0, 5.0)
76-
> LowerLeft: (10.0, 10.0)
77-
> UpperLeft: (10.0, 15.0)
78-
> UpperRight: (15.0, 15.0)
79-
> LowerRight: (15.0, 10.0)
80-
```
44+
> [!EXAMPLE]
45+
> <!-- ignore: requires external files and msvc -->
46+
> ```rust ignore
47+
> #![debugger_visualizer(natvis_file = "Rectangle.natvis")]
48+
>
49+
> struct FancyRect {
50+
> x: f32,
51+
> y: f32,
52+
> dx: f32,
53+
> dy: f32,
54+
> }
55+
>
56+
> fn main() {
57+
> let fancy_rect = FancyRect { x: 10.0, y: 10.0, dx: 5.0, dy: 5.0 };
58+
> println!("set breakpoint here");
59+
> }
60+
> ```
61+
>
62+
> `Rectangle.natvis` contains:
63+
>
64+
> ```xml
65+
> <?xml version="1.0" encoding="utf-8"?>
66+
> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
67+
> <Type Name="foo::FancyRect">
68+
> <DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
69+
> <Expand>
70+
> <Synthetic Name="LowerLeft">
71+
> <DisplayString>({x}, {y})</DisplayString>
72+
> </Synthetic>
73+
> <Synthetic Name="UpperLeft">
74+
> <DisplayString>({x}, {y + dy})</DisplayString>
75+
> </Synthetic>
76+
> <Synthetic Name="UpperRight">
77+
> <DisplayString>({x + dx}, {y + dy})</DisplayString>
78+
> </Synthetic>
79+
> <Synthetic Name="LowerRight">
80+
> <DisplayString>({x + dx}, {y})</DisplayString>
81+
> </Synthetic>
82+
> </Expand>
83+
> </Type>
84+
> </AutoVisualizer>
85+
> ```
86+
>
87+
> When viewed under WinDbg, the `fancy_rect` variable would be shown as follows:
88+
>
89+
> ```text
90+
> > Variables:
91+
> > fancy_rect: (10.0, 10.0) + (5.0, 5.0)
92+
> > LowerLeft: (10.0, 10.0)
93+
> > UpperLeft: (10.0, 15.0)
94+
> > UpperRight: (15.0, 15.0)
95+
> > LowerRight: (15.0, 10.0)
96+
> ```
8197
8298
r[attributes.debugger.debugger_visualizer.gdb]
8399
### Using `debugger_visualizer` with GDB
84100
85101
r[attributes.debugger.debugger_visualizer.gdb.pretty]
86-
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.
87-
For detailed information on pretty printers, refer to GDB's [pretty printing documentation].
102+
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. For detailed information on pretty printers, refer to GDB's [pretty printing documentation].
88103
89-
Embedded pretty printers are not automatically loaded when debugging a binary under GDB.
90-
There are two ways to enable auto-loading embedded pretty printers:
91-
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`
92-
For more information, see GDB's [auto-loading documentation].
93-
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`.
104+
> [!NOTE]
105+
> Embedded pretty printers are not automatically loaded when debugging a binary under GDB.
106+
>
107+
> There are two ways to enable auto-loading embedded pretty printers:
108+
>
109+
> 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` For more information, see GDB's [auto-loading documentation].
110+
> 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`.
94111
95112
r[attributes.debugger.debugger_visualizer.gdb.path]
96-
These scripts are embedded using the `gdb_script_file` key, which is a path relative to the crate source file.
97-
98-
<!-- ignore: requires external files -->
99-
```rust ignore
100-
#![debugger_visualizer(gdb_script_file = "printer.py")]
101-
102-
struct Person {
103-
name: String,
104-
age: i32,
105-
}
106-
107-
fn main() {
108-
let bob = Person { name: String::from("Bob"), age: 10 };
109-
println!("set breakpoint here");
110-
}
111-
```
113+
These scripts are embedded using the `gdb_script_file` key, which is a path relative to the source file.
112114
113-
and `printer.py` contains:
114-
115-
```python
116-
import gdb
117-
118-
class PersonPrinter:
119-
"Print a Person"
120-
121-
def __init__(self, val):
122-
self.val = val
123-
self.name = val["name"]
124-
self.age = int(val["age"])
125-
126-
def to_string(self):
127-
return "{} is {} years old.".format(self.name, self.age)
128-
129-
def lookup(val):
130-
lookup_tag = val.type.tag
131-
if lookup_tag is None:
132-
return None
133-
if "foo::Person" == lookup_tag:
134-
return PersonPrinter(val)
135-
136-
return None
137-
138-
gdb.current_objfile().pretty_printers.append(lookup)
139-
```
140-
141-
When the crate's debug executable is passed into GDB[^rust-gdb], `print bob` will display:
142-
143-
```text
144-
"Bob" is 10 years old.
145-
```
146-
147-
[^rust-gdb]: Note: This assumes you are using the `rust-gdb` script which configures pretty-printers for standard library types like `String`.
115+
> [!EXAMPLE]
116+
> <!-- ignore: requires external files -->
117+
> ```rust ignore
118+
> #![debugger_visualizer(gdb_script_file = "printer.py")]
119+
>
120+
> struct Person {
121+
> name: String,
122+
> age: i32,
123+
> }
124+
>
125+
> fn main() {
126+
> let bob = Person { name: String::from("Bob"), age: 10 };
127+
> println!("set breakpoint here");
128+
> }
129+
> ```
130+
>
131+
> `printer.py` contains:
132+
>
133+
> ```python
134+
> import gdb
135+
>
136+
> class PersonPrinter:
137+
> "Print a Person"
138+
>
139+
> def __init__(self, val):
140+
> self.val = val
141+
> self.name = val["name"]
142+
> self.age = int(val["age"])
143+
>
144+
> def to_string(self):
145+
> return "{} is {} years old.".format(self.name, self.age)
146+
>
147+
> def lookup(val):
148+
> lookup_tag = val.type.tag
149+
> if lookup_tag is None:
150+
> return None
151+
> if "foo::Person" == lookup_tag:
152+
> return PersonPrinter(val)
153+
>
154+
> return None
155+
>
156+
> gdb.current_objfile().pretty_printers.append(lookup)
157+
> ```
158+
>
159+
> When the crate's debug executable is passed into GDB[^rust-gdb], `print bob` will display:
160+
>
161+
> ```text
162+
> "Bob" is 10 years old.
163+
> ```
164+
>
165+
> [^rust-gdb]: Note: This assumes you are using the `rust-gdb` script which configures pretty-printers for standard library types like `String`.
148166
149167
[auto-loading documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Auto_002dloading-safe-path.html
150168
[attributes]: ../attributes.md
@@ -206,3 +224,4 @@ The `external` behavior is the default for macros that don't have this attribute
206224
[`-C collapse-macro-debuginfo`]: ../../rustc/codegen-options/index.html#collapse-macro-debuginfo
207225
[`macro_rules` definition]: ../macros-by-example.md
208226
[attribute]: ../attributes.md
227+
[module]: ../items/modules.md

0 commit comments

Comments
 (0)