Skip to content

Commit 5a6670d

Browse files
committed
first pass for debugger_visualizer docs
1 parent a9afb04 commit 5a6670d

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

src/attributes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ The following is an index of all built-in attributes.
224224
- [`allow`], [`warn`], [`deny`], [`forbid`] — Alters the default lint level.
225225
- [`deprecated`] — Generates deprecation notices.
226226
- [`must_use`] — Generates a lint for unused values.
227+
- [`debugger_visualizer`] — Embeds a file that specifies debugger output for a type
227228
- ABI, linking, symbols, and FFI
228229
- [`link`] — Specifies a native library to link with an `extern` block.
229230
- [`link_name`] — Specifies the name of the symbol for functions or statics
@@ -291,6 +292,7 @@ The following is an index of all built-in attributes.
291292
[`cold`]: attributes/codegen.md#the-cold-attribute
292293
[`crate_name`]: crates-and-source-files.md#the-crate_name-attribute
293294
[`crate_type`]: linkage.md
295+
[`debugger_visualizer`]: attributes/diagnostics.md#the-debugger_visualizer-attribute
294296
[`deny`]: attributes/diagnostics.md#lint-check-attributes
295297
[`deprecated`]: attributes/diagnostics.md#the-deprecated-attribute
296298
[`derive`]: attributes/derive.md

src/attributes/diagnostics.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,154 @@ When used on a function in a trait implementation, the attribute does nothing.
301301
> let _ = five();
302302
> ```
303303
304+
## The `debugger_visualizer` attribute
305+
306+
The `debugger_visualizer` attribute can be used to embed a debugger visualizer file into the PDB/ELF generated by `rustc`.
307+
This enables an improved debugger experience for types outside of Rust's standard library.
308+
309+
### Using `debugger_visualizer` with Natvis
310+
311+
Natvis is an XML-based framework, and a `.natvis` file declares how a type's fields should be displayed in the debugger view.
312+
A Natvis file is embedded using the `natvis-file` meta item.
313+
Microsoft's [Natvis documentation] can be referenced to help developers write their own `.natvis` files.
314+
315+
<div class="warning">
316+
Currently, this attribute only supports embedding Natvis files on `-windows-msvc` targets.
317+
`-windows-gnu` targets are not currently supported.
318+
</div>
319+
320+
Consider a crate with this directory structure:
321+
322+
```text
323+
/Cargo.toml
324+
/Foo.natvis (Note: the Natvis file does not have to match the name of the crate.)
325+
+-- src
326+
+-- main.rs
327+
```
328+
329+
Where `main.rs` contains:
330+
331+
```rust
332+
#![debugger_visualizer(natvis_file = "../Foo.natvis")]
333+
struct FancyRect {
334+
pub x: f32,
335+
pub y: f32,
336+
pub dx: f32,
337+
pub dy: f32,
338+
}
339+
340+
fn main() {
341+
let mut fancy_rect = FancyRect::new(10.0, 10.0, 5.0, 5.0);
342+
}
343+
```
344+
345+
and `Foo.natvis` contains:
346+
347+
```xml
348+
<?xml version="1.0" encoding="utf-8"?>
349+
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
350+
<Type Name="foo::FancyRect">
351+
<DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
352+
<Expand>
353+
<Synthetic Name="LowerLeft">
354+
<DisplayString>({x}, {y})</DisplayString>
355+
</Synthetic>
356+
<Synthetic Name="UpperLeft">
357+
<DisplayString>({x}, {y + dy})</DisplayString>
358+
</Synthetic>
359+
<Synthetic Name="UpperRight">
360+
<DisplayString>({x + dx}, {y + dy})</DisplayString>
361+
</Synthetic>
362+
<Synthetic Name="LowerRight">
363+
<DisplayString>({x + dx}, {y})</DisplayString>
364+
</Synthetic>
365+
</Expand>
366+
</Type>
367+
</AutoVisualizer>
368+
```
369+
370+
When viewed under WinDbg, the `fancy_rect` variable would be shown as follows:
371+
372+
```text
373+
> Variables:
374+
> fancy_rect: (10, 10) + (5, 5)
375+
> LowerLeft: (10, 10)
376+
> UpperLeft: (10, 15)
377+
> UpperRight: (15, 15)
378+
> LowerRight: (15, 10)
379+
```
380+
381+
### Using `debugger_visualizer` with GDB
382+
383+
Developers using GDB are able to embed *pretty printers* onto types.
384+
In GDB, a pretty printer is a structured Python script that describes how a type's fields should be displayed in the debugger view.
385+
These scripts are embedded using the `gdb_script_file` meta item.
386+
GDB's [pretty print documentation] can be referenced by developers to help them write their own `.py` scripts.
387+
388+
Consider a crate with this directory structure:
389+
390+
```text
391+
/Cargo.toml
392+
/bar.py (Note: the file does not have to match the name of the crate.)
393+
+-- src
394+
+-- main.rs
395+
```
396+
397+
Where `main.rs` contains:
398+
399+
```rust
400+
#![debugger_visualizer(gdb_script_file = "../bar.py")]
401+
mod person {
402+
pub struct Person {
403+
pub name: String,
404+
pub age: i32,
405+
}
406+
}
407+
408+
use person::Person;
409+
410+
fn main() {
411+
let person = Person::new(String::from("Bob"), 10);
412+
}
413+
```
414+
415+
and `bar.py` contains:
416+
417+
```python
418+
import gdb
419+
420+
class PersonPrinter:
421+
"Print a Person"
422+
423+
def __init__(self, val):
424+
self.val = val
425+
self.name = val["name"]
426+
self.age = int(val["age"])
427+
428+
def to_string(self):
429+
return "{} is {} years old.".format(self.name, self.age)
430+
431+
def lookup(val):
432+
lookup_tag = val.type.tag
433+
if lookup_tag is None:
434+
return None
435+
if "main::Person" == lookup_tag:
436+
return PersonPrinter(val)
437+
438+
return None
439+
440+
gdb.current_objfile().pretty_printers.append(lookup)
441+
```
442+
443+
When the crate's debug executable is passed into GDB, `print person` should display:
444+
445+
```
446+
"Bob" is 10 years old.
447+
```
448+
304449
[Clippy]: https://github.com/rust-lang/rust-clippy
450+
[Natvis documentation]: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects
451+
[pretty print documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html
305452
[_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax
306453
[_MetaListPaths_]: ../attributes.md#meta-item-attribute-syntax
307454
[_MetaNameValueStr_]: ../attributes.md#meta-item-attribute-syntax

0 commit comments

Comments
 (0)