Skip to content

Commit 6f815ca

Browse files
committed
Auto merge of #43221 - MaulingMonkey:natvis-improvements, r=michaelwoerister
Embed MSVC .natvis files into .pdbs and mangle debuginfo for &str, *T, and [T]. No idea if these changes are reasonable - please feel free to suggest changes/rewrites. And these are some of my first real commits to any rust codebase - *don't* be gentle, and nitpick away, I need to learn! ;) ### Overview Embedding `.natvis` files into `.pdb`s allows MSVC (and potentially other debuggers) to automatically pick up the visualizers without having to do any additional configuration (other than to perhaps add the relevant .pdb paths to symbol search paths.) The native debug engine for MSVC parses the type names, making various C++ish assumptions about what they mean and adding various limitations to valid type names. `&str` cannot be matched against a visualizer, but if we emit `str&` instead, it'll be recognized as a reference to a `str`, solving the problem. `[T]` is similarly problematic, but emitting `slice<T>` instead works fine as it looks like a template. I've been unable to get e.g. `slice<u32>&` to match visualizers in VS2015u3, so I've gone with `str*` and `slice<u32>*` instead. ### Possible Issues * I'm not sure if `slice<T>` is a great mangling for `[T]` or if I should worry about name collisions. * I'm not sure if `linker.rs` is the right place to be enumerating natvis files. * I'm not sure if these type name mangling changes should actually be MSVC specific. I recall seeing gdb visualizer tests that might be broken if made more general? I'm hesitant to mess with them without a gdb install. But perhaps I'm just wracking up technical debt. Should I try `pacman -S mingw-w64-x86_64-gdb` and to make things consistent? * I haven't touched `const` / `mut` yet, and I'm worried MSVC might trip up on `mut` or their placement. * I may like terse oneliners too much. * I don't know if there's broader implications for messing with debug type names here. * I may have been mistaken about bellow test failures being ignorable / unrelated to this changelist. ### Test Failures on `x86_64-pc-windows-gnu` ``` ---- [debuginfo-gdb] debuginfo-gdb\associated-types.rs stdout ---- thread '[debuginfo-gdb] debuginfo-gdb\associated-types.rs' panicked at 'gdb not available but debuginfo gdb debuginfo test requested', src\tools\compiletest\src\runtest.rs:48:16 note: Run with `RUST_BACKTRACE=1` for a backtrace. [...identical panic causes omitted...] ---- [debuginfo-gdb] debuginfo-gdb\vec.rs stdout ---- thread '[debuginfo-gdb] debuginfo-gdb\vec.rs' panicked at 'gdb not available but debuginfo gdb debuginfo test requested', src\tools\compiletest\src\runtest.rs:48:16 ``` ### Relevant Issues * #40460 Metaissue for Visual Studio debugging Rust * #36503 Investigate natvis for improved msvc debugging * PistonDevelopers/VisualRust#160 Debug visualization of Rust data structures ### Pretty Pictures ![Collapsed Watch Window](https://user-images.githubusercontent.com/75894/28180998-e44c7516-67bb-11e7-8b48-d4f9605973ae.png) ![Expanded Watch Window](https://user-images.githubusercontent.com/75894/28181000-e8da252e-67bb-11e7-96b8-d613310c04dc.png)
2 parents 7167843 + 90a7cac commit 6f815ca

File tree

4 files changed

+77
-6
lines changed

4 files changed

+77
-6
lines changed

Diff for: src/etc/natvis/intrinsic.natvis

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
3+
<Type Name="str">
4+
<DisplayString>{data_ptr,[length]s8}</DisplayString>
5+
<StringView>data_ptr,[length]s8</StringView>
6+
<Expand>
7+
<Item Name="[size]" ExcludeView="simple">length</Item>
8+
<ArrayItems>
9+
<Size>length</Size>
10+
<ValuePointer>data_ptr</ValuePointer>
11+
</ArrayItems>
12+
</Expand>
13+
</Type>
14+
<Type Name="slice&lt;*&gt;">
15+
<DisplayString>{{ length={length} }}</DisplayString>
16+
<Expand>
17+
<Item Name="[size]" ExcludeView="simple">length</Item>
18+
<ArrayItems>
19+
<Size>length</Size>
20+
<ValuePointer>data_ptr</ValuePointer>
21+
</ArrayItems>
22+
</Expand>
23+
</Type>
24+
</AutoVisualizer>

Diff for: src/etc/natvis/liballoc.natvis

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
</Expand>
4343
</Type>
4444
<Type Name="alloc::string::String">
45-
<DisplayString>{*(char**)this,[vec.len]}</DisplayString>
46-
<StringView>*(char**)this,[vec.len]</StringView>
45+
<DisplayString>{*(char**)this,[vec.len]s8}</DisplayString>
46+
<StringView>*(char**)this,[vec.len]s8</StringView>
4747
<Expand>
4848
<Item Name="[size]" ExcludeView="simple">vec.len</Item>
4949
<Item Name="[capacity]" ExcludeView="simple">vec.buf.cap</Item>

Diff for: src/librustc_trans/back/linker.rs

+21
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,27 @@ impl<'a> Linker for MsvcLinker<'a> {
487487
// This will cause the Microsoft linker to generate a PDB file
488488
// from the CodeView line tables in the object files.
489489
self.cmd.arg("/DEBUG");
490+
491+
// This will cause the Microsoft linker to embed .natvis info into the the PDB file
492+
let sysroot = self.sess.sysroot();
493+
let natvis_dir_path = sysroot.join("lib\\rustlib\\etc");
494+
if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
495+
for entry in natvis_dir {
496+
match entry {
497+
Ok(entry) => {
498+
let path = entry.path();
499+
if path.extension() == Some("natvis".as_ref()) {
500+
let mut arg = OsString::from("/NATVIS:");
501+
arg.push(path);
502+
self.cmd.arg(arg);
503+
}
504+
},
505+
Err(err) => {
506+
self.sess.warn(&format!("error enumerating natvis directory: {}", err));
507+
},
508+
}
509+
}
510+
}
490511
}
491512

492513
// Currently the compiler doesn't use `dllexport` (an LLVM attribute) to

Diff for: src/librustc_trans/debuginfo/type_names.rs

+30-4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
3636
t: Ty<'tcx>,
3737
qualified: bool,
3838
output: &mut String) {
39+
// When targeting MSVC, emit C++ style type names for compatability with
40+
// .natvis visualizers (and perhaps other existing native debuggers?)
41+
let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
42+
3943
match t.sty {
4044
ty::TyBool => output.push_str("bool"),
4145
ty::TyChar => output.push_str("char"),
@@ -61,21 +65,33 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
6165
output.push(')');
6266
},
6367
ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
64-
output.push('*');
68+
if !cpp_like_names {
69+
output.push('*');
70+
}
6571
match mutbl {
6672
hir::MutImmutable => output.push_str("const "),
6773
hir::MutMutable => output.push_str("mut "),
6874
}
6975

7076
push_debuginfo_type_name(cx, inner_type, true, output);
77+
78+
if cpp_like_names {
79+
output.push('*');
80+
}
7181
},
7282
ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
73-
output.push('&');
83+
if !cpp_like_names {
84+
output.push('&');
85+
}
7486
if mutbl == hir::MutMutable {
7587
output.push_str("mut ");
7688
}
7789

7890
push_debuginfo_type_name(cx, inner_type, true, output);
91+
92+
if cpp_like_names {
93+
output.push('*');
94+
}
7995
},
8096
ty::TyArray(inner_type, len) => {
8197
output.push('[');
@@ -84,9 +100,19 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
84100
output.push(']');
85101
},
86102
ty::TySlice(inner_type) => {
87-
output.push('[');
103+
if cpp_like_names {
104+
output.push_str("slice<");
105+
} else {
106+
output.push('[');
107+
}
108+
88109
push_debuginfo_type_name(cx, inner_type, true, output);
89-
output.push(']');
110+
111+
if cpp_like_names {
112+
output.push('>');
113+
} else {
114+
output.push(']');
115+
}
90116
},
91117
ty::TyDynamic(ref trait_data, ..) => {
92118
if let Some(principal) = trait_data.principal() {

0 commit comments

Comments
 (0)