Skip to content

Commit 9a83842

Browse files
committed
Add line numbers to MSVC backtrace
Add comments
1 parent b4de424 commit 9a83842

File tree

4 files changed

+50
-10
lines changed

4 files changed

+50
-10
lines changed

src/libstd/sys/windows/backtrace.rs

+11
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ extern "system" {
6060
type SymFromAddrFn =
6161
extern "system" fn(libc::HANDLE, u64, *mut u64,
6262
*mut SYMBOL_INFO) -> libc::BOOL;
63+
type SymGetLineFromAddr64Fn =
64+
extern "system" fn(libc::HANDLE, u64, *mut u32,
65+
*mut IMAGEHLP_LINE64) -> libc::BOOL;
6366
type SymInitializeFn =
6467
extern "system" fn(libc::HANDLE, *mut libc::c_void,
6568
libc::BOOL) -> libc::BOOL;
@@ -99,6 +102,14 @@ struct SYMBOL_INFO {
99102
Name: [libc::c_char; MAX_SYM_NAME],
100103
}
101104

105+
#[repr(C)]
106+
struct IMAGEHLP_LINE64 {
107+
SizeOfStruct: u32,
108+
Key: *const libc::c_void,
109+
LineNumber: u32,
110+
Filename: *const libc::c_char,
111+
Address: u64,
112+
}
102113

103114
#[repr(C)]
104115
enum ADDRESS_MODE {

src/libstd/sys/windows/printing/msvc.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use sys_common::backtrace::output;
11+
use sys_common::backtrace::{output, output_fileline};
1212
use ffi::CStr;
1313
use dynamic_lib::DynamicLibrary;
14-
use super::{SymFromAddrFn, SYMBOL_INFO, MAX_SYM_NAME};
14+
use super::{SymFromAddrFn, SymGetLineFromAddr64Fn, SYMBOL_INFO, MAX_SYM_NAME, IMAGEHLP_LINE64};
1515
use io;
1616
use io::prelude::*;
1717
use intrinsics;
@@ -20,6 +20,7 @@ use libc;
2020
pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, process: libc::HANDLE)
2121
-> io::Result<()> {
2222
let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn);
23+
let SymGetLineFromAddr64 = sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn);
2324

2425
let mut info: SYMBOL_INFO = unsafe { intrinsics::init() };
2526
info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong;
@@ -29,7 +30,7 @@ pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, proce
2930
info.SizeOfStruct = 88;
3031

3132
let mut displacement = 0u64;
32-
let ret = SymFromAddr(process, addr as u64, &mut displacement, &mut info);
33+
let ret = SymFromAddr(process, addr, &mut displacement, &mut info);
3334

3435
let name = if ret == libc::TRUE {
3536
let ptr = info.Name.as_ptr() as *const libc::c_char;
@@ -38,5 +39,20 @@ pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, proce
3839
None
3940
};
4041

41-
output(w, i, addr as usize as *mut libc::c_void, name)
42+
try!(output(w, i, addr as usize as *mut libc::c_void, name));
43+
44+
// Now find out the filename and line number
45+
let mut line: IMAGEHLP_LINE64 = unsafe { intrinsics::init() };
46+
line.SizeOfStruct = ::mem::size_of::<IMAGEHLP_LINE64>() as u32;
47+
48+
let mut displacement = 0u32;
49+
let ret = SymGetLineFromAddr64(process, addr, &mut displacement, &mut line);
50+
if ret == libc::TRUE {
51+
output_fileline(w,
52+
unsafe { CStr::from_ptr(line.Filename).to_bytes() },
53+
line.LineNumber as libc::c_int,
54+
false)
55+
} else {
56+
Ok(())
57+
}
4258
}

src/test/run-pass/backtrace-debuginfo-aux.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ pub fn callback<F>(f: F) where F: FnOnce((&'static str, u32)) {
1515
f((file!(), line!()))
1616
}
1717

18-
#[inline(always)]
18+
// LLVM does not yet output the required debug info to support showing inlined
19+
// function calls in backtraces when targetting MSVC, so disable inlining in
20+
// this case.
21+
#[cfg_attr(not(target_env = "msvc"), inline(always))]
22+
#[cfg_attr(target_env = "msvc", inline(never))]
1923
pub fn callback_inlined<F>(f: F) where F: FnOnce((&'static str, u32)) {
2024
f((file!(), line!()))
2125
}

src/test/run-pass/backtrace-debuginfo.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ macro_rules! pos {
3232
not(target_os = "ios"),
3333
not(target_os = "android"),
3434
not(all(target_os = "linux", target_arch = "arm"))),
35-
all(windows, target_env = "gnu", not(target_arch = "x86"))))]
35+
all(windows, not(target_arch = "x86"))))]
3636
macro_rules! dump_and_die {
3737
($($pos:expr),*) => ({
3838
// FIXME(#18285): we cannot include the current position because
@@ -48,7 +48,7 @@ macro_rules! dump_and_die {
4848
not(target_os = "ios"),
4949
not(target_os = "android"),
5050
not(all(target_os = "linux", target_arch = "arm"))),
51-
all(windows, target_env = "gnu", not(target_arch = "x86")))))]
51+
all(windows, not(target_arch = "x86")))))]
5252
macro_rules! dump_and_die {
5353
($($pos:expr),*) => ({ let _ = [$($pos),*]; })
5454
}
@@ -69,7 +69,10 @@ type Pos = (&'static str, u32);
6969
// this goes to stdout and each line has to be occurred
7070
// in the following backtrace to stderr with a correct order.
7171
fn dump_filelines(filelines: &[Pos]) {
72-
for &(file, line) in filelines.iter().rev() {
72+
// Skip top frame for MSVC, because it sees the macro rather than
73+
// the containing function.
74+
let skip = if cfg!(target_env = "msvc") {1} else {0};
75+
for &(file, line) in filelines.iter().rev().skip(skip) {
7376
// extract a basename
7477
let basename = file.split(&['/', '\\'][..]).last().unwrap();
7578
println!("{}:{}", basename, line);
@@ -88,12 +91,18 @@ fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
8891
});
8992
}
9093

91-
#[inline(always)]
94+
// LLVM does not yet output the required debug info to support showing inlined
95+
// function calls in backtraces when targetting MSVC, so disable inlining in
96+
// this case.
97+
#[cfg_attr(not(target_env = "msvc"), inline(always))]
98+
#[cfg_attr(target_env = "msvc", inline(never))]
9299
fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
93100
check!(counter; main_pos, outer_pos);
94101
check!(counter; main_pos, outer_pos);
95102

96-
#[inline(always)]
103+
// Again, disable inlining for MSVC.
104+
#[cfg_attr(not(target_env = "msvc"), inline(always))]
105+
#[cfg_attr(target_env = "msvc", inline(never))]
97106
fn inner_further_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
98107
check!(counter; main_pos, outer_pos, inner_pos);
99108
}

0 commit comments

Comments
 (0)