Skip to content

Commit a97cd17

Browse files
committed
Auto merge of #47252 - Zoxc:backtrace-win, r=alexcrichton
Print inlined functions on Windows Split from #45637 r? @alexcrichton
2 parents 5669050 + 634f8cc commit a97cd17

File tree

10 files changed

+62
-50
lines changed

10 files changed

+62
-50
lines changed

src/libstd/sys/cloudabi/backtrace.rs

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ extern "C" fn trace_fn(
7777
cx.frames[cx.idx] = Frame {
7878
symbol_addr: symaddr as *mut u8,
7979
exact_position: ip as *mut u8,
80+
inline_context: 0,
8081
};
8182
cx.idx += 1;
8283
}

src/libstd/sys/redox/backtrace/tracing.rs

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
9898
cx.frames[cx.idx] = Frame {
9999
symbol_addr: symaddr as *mut u8,
100100
exact_position: ip as *mut u8,
101+
inline_context: 0,
101102
};
102103
cx.idx += 1;
103104
}

src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub fn unwind_backtrace(frames: &mut [Frame])
3838
*to = Frame {
3939
exact_position: *from as *mut u8,
4040
symbol_addr: *from as *mut u8,
41+
inline_context: 0,
4142
};
4243
}
4344
Ok((nb_frames as usize, BacktraceContext))

src/libstd/sys/unix/backtrace/tracing/gcc_s.rs

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
9898
cx.frames[cx.idx] = Frame {
9999
symbol_addr: symaddr as *mut u8,
100100
exact_position: ip as *mut u8,
101+
inline_context: 0,
101102
};
102103
cx.idx += 1;
103104
}

src/libstd/sys/windows/backtrace/mod.rs

+15-16
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,15 @@ pub fn unwind_backtrace(frames: &mut [Frame])
5656
// Fetch the symbols necessary from dbghelp.dll
5757
let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?;
5858
let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?;
59-
let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn)?;
59+
let StackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn)?;
6060

6161
// Allocate necessary structures for doing the stack walk
6262
let process = unsafe { c::GetCurrentProcess() };
6363
let thread = unsafe { c::GetCurrentThread() };
6464
let mut context: c::CONTEXT = unsafe { mem::zeroed() };
6565
unsafe { c::RtlCaptureContext(&mut context) };
66-
let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() };
66+
let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() };
67+
frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD;
6768
let image = init_frame(&mut frame, &context);
6869

6970
let backtrace_context = BacktraceContext {
@@ -79,24 +80,22 @@ pub fn unwind_backtrace(frames: &mut [Frame])
7980
}
8081

8182
// And now that we're done with all the setup, do the stack walking!
82-
// Start from -1 to avoid printing this stack frame, which will
83-
// always be exactly the same.
8483
let mut i = 0;
8584
unsafe {
8685
while i < frames.len() &&
87-
StackWalk64(image, process, thread, &mut frame, &mut context,
86+
StackWalkEx(image, process, thread, &mut frame, &mut context,
8887
ptr::null_mut(),
8988
ptr::null_mut(),
9089
ptr::null_mut(),
91-
ptr::null_mut()) == c::TRUE
90+
ptr::null_mut(),
91+
0) == c::TRUE
9292
{
93-
let addr = frame.AddrPC.Offset;
94-
if addr == frame.AddrReturn.Offset || addr == 0 ||
95-
frame.AddrReturn.Offset == 0 { break }
93+
let addr = (frame.AddrPC.Offset - 1) as *const u8;
9694

9795
frames[i] = Frame {
98-
symbol_addr: (addr - 1) as *const u8,
99-
exact_position: (addr - 1) as *const u8,
96+
symbol_addr: addr,
97+
exact_position: addr,
98+
inline_context: frame.InlineFrameContext,
10099
};
101100
i += 1;
102101
}
@@ -111,14 +110,14 @@ type SymInitializeFn =
111110
type SymCleanupFn =
112111
unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
113112

114-
type StackWalk64Fn =
113+
type StackWalkExFn =
115114
unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE,
116-
*mut c::STACKFRAME64, *mut c::CONTEXT,
115+
*mut c::STACKFRAME_EX, *mut c::CONTEXT,
117116
*mut c_void, *mut c_void,
118-
*mut c_void, *mut c_void) -> c::BOOL;
117+
*mut c_void, *mut c_void, c::DWORD) -> c::BOOL;
119118

120119
#[cfg(target_arch = "x86")]
121-
fn init_frame(frame: &mut c::STACKFRAME64,
120+
fn init_frame(frame: &mut c::STACKFRAME_EX,
122121
ctx: &c::CONTEXT) -> c::DWORD {
123122
frame.AddrPC.Offset = ctx.Eip as u64;
124123
frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
@@ -130,7 +129,7 @@ fn init_frame(frame: &mut c::STACKFRAME64,
130129
}
131130

132131
#[cfg(target_arch = "x86_64")]
133-
fn init_frame(frame: &mut c::STACKFRAME64,
132+
fn init_frame(frame: &mut c::STACKFRAME_EX,
134133
ctx: &c::CONTEXT) -> c::DWORD {
135134
frame.AddrPC.Offset = ctx.Rip as u64;
136135
frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;

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

+34-20
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,22 @@ use sys::c;
1616
use sys::backtrace::BacktraceContext;
1717
use sys_common::backtrace::Frame;
1818

19-
type SymFromAddrFn =
20-
unsafe extern "system" fn(c::HANDLE, u64, *mut u64,
21-
*mut c::SYMBOL_INFO) -> c::BOOL;
22-
type SymGetLineFromAddr64Fn =
23-
unsafe extern "system" fn(c::HANDLE, u64, *mut u32,
24-
*mut c::IMAGEHLP_LINE64) -> c::BOOL;
19+
type SymFromInlineContextFn =
20+
unsafe extern "system" fn(c::HANDLE, u64, c::ULONG,
21+
*mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
22+
type SymGetLineFromInlineContextFn =
23+
unsafe extern "system" fn(c::HANDLE, u64, c::ULONG,
24+
u64, *mut c::DWORD, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
2525

2626
/// Converts a pointer to symbol to its string value.
2727
pub fn resolve_symname<F>(frame: Frame,
2828
callback: F,
2929
context: &BacktraceContext) -> io::Result<()>
3030
where F: FnOnce(Option<&str>) -> io::Result<()>
3131
{
32-
let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?;
32+
let SymFromInlineContext = sym!(&context.dbghelp,
33+
"SymFromInlineContext",
34+
SymFromInlineContextFn)?;
3335

3436
unsafe {
3537
let mut info: c::SYMBOL_INFO = mem::zeroed();
@@ -40,12 +42,22 @@ pub fn resolve_symname<F>(frame: Frame,
4042
info.SizeOfStruct = 88;
4143

4244
let mut displacement = 0u64;
43-
let ret = SymFromAddr(context.handle,
44-
frame.symbol_addr as u64,
45-
&mut displacement,
46-
&mut info);
47-
48-
let symname = if ret == c::TRUE {
45+
let ret = SymFromInlineContext(context.handle,
46+
frame.symbol_addr as u64,
47+
frame.inline_context,
48+
&mut displacement,
49+
&mut info);
50+
let valid_range = if ret == c::TRUE &&
51+
frame.symbol_addr as usize >= info.Address as usize {
52+
if info.Size != 0 {
53+
(frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
54+
} else {
55+
true
56+
}
57+
} else {
58+
false
59+
};
60+
let symname = if valid_range {
4961
let ptr = info.Name.as_ptr() as *const c_char;
5062
CStr::from_ptr(ptr).to_str().ok()
5163
} else {
@@ -61,19 +73,21 @@ pub fn foreach_symbol_fileline<F>(frame: Frame,
6173
-> io::Result<bool>
6274
where F: FnMut(&[u8], u32) -> io::Result<()>
6375
{
64-
let SymGetLineFromAddr64 = sym!(&context.dbghelp,
65-
"SymGetLineFromAddr64",
66-
SymGetLineFromAddr64Fn)?;
76+
let SymGetLineFromInlineContext = sym!(&context.dbghelp,
77+
"SymGetLineFromInlineContext",
78+
SymGetLineFromInlineContextFn)?;
6779

6880
unsafe {
6981
let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
7082
line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
7183

7284
let mut displacement = 0u32;
73-
let ret = SymGetLineFromAddr64(context.handle,
74-
frame.exact_position as u64,
75-
&mut displacement,
76-
&mut line);
85+
let ret = SymGetLineFromInlineContext(context.handle,
86+
frame.exact_position as u64,
87+
frame.inline_context,
88+
0,
89+
&mut displacement,
90+
&mut line);
7791
if ret == c::TRUE {
7892
let name = CStr::from_ptr(line.Filename).to_bytes();
7993
f(name, line.LineNumber as u32)?;

src/libstd/sys/windows/c.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ pub struct ADDRESS64 {
619619

620620
#[repr(C)]
621621
#[cfg(feature = "backtrace")]
622-
pub struct STACKFRAME64 {
622+
pub struct STACKFRAME_EX {
623623
pub AddrPC: ADDRESS64,
624624
pub AddrReturn: ADDRESS64,
625625
pub AddrFrame: ADDRESS64,
@@ -631,6 +631,8 @@ pub struct STACKFRAME64 {
631631
pub Virtual: BOOL,
632632
pub Reserved: [u64; 3],
633633
pub KdHelp: KDHELP64,
634+
pub StackFrameSize: DWORD,
635+
pub InlineFrameContext: DWORD,
634636
}
635637

636638
#[repr(C)]

src/libstd/sys_common/backtrace.rs

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ pub struct Frame {
4141
pub exact_position: *const u8,
4242
/// Address of the enclosing function.
4343
pub symbol_addr: *const u8,
44+
/// Which inlined function is this frame referring to
45+
pub inline_context: u32,
4446
}
4547

4648
/// Max number of frames to print.
@@ -64,6 +66,7 @@ fn _print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
6466
let mut frames = [Frame {
6567
exact_position: ptr::null(),
6668
symbol_addr: ptr::null(),
69+
inline_context: 0,
6770
}; MAX_NB_FRAMES];
6871
let (nb_frames, context) = unwind_backtrace(&mut frames)?;
6972
let (skipped_before, skipped_after) =

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

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

18-
// LLVM does not yet output the required debug info to support showing inlined
19-
// function calls in backtraces when targeting MSVC, so disable inlining in
20-
// this case.
18+
// We emit the wrong location for the caller here when inlined on MSVC
2119
#[cfg_attr(not(target_env = "msvc"), inline(always))]
2220
#[cfg_attr(target_env = "msvc", inline(never))]
2321
pub fn callback_inlined<F>(f: F) where F: FnOnce((&'static str, u32)) {

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

+2-10
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,7 @@ type Pos = (&'static str, u32);
6262
// this goes to stdout and each line has to be occurred
6363
// in the following backtrace to stderr with a correct order.
6464
fn dump_filelines(filelines: &[Pos]) {
65-
// Skip top frame for MSVC, because it sees the macro rather than
66-
// the containing function.
67-
let skip = if cfg!(target_env = "msvc") {1} else {0};
68-
for &(file, line) in filelines.iter().rev().skip(skip) {
65+
for &(file, line) in filelines.iter().rev() {
6966
// extract a basename
7067
let basename = file.split(&['/', '\\'][..]).last().unwrap();
7168
println!("{}:{}", basename, line);
@@ -84,9 +81,7 @@ fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
8481
});
8582
}
8683

87-
// LLVM does not yet output the required debug info to support showing inlined
88-
// function calls in backtraces when targeting MSVC, so disable inlining in
89-
// this case.
84+
// We emit the wrong location for the caller here when inlined on MSVC
9085
#[cfg_attr(not(target_env = "msvc"), inline(always))]
9186
#[cfg_attr(target_env = "msvc", inline(never))]
9287
fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
@@ -137,9 +132,6 @@ fn run_test(me: &str) {
137132
use std::str;
138133
use std::process::Command;
139134

140-
let mut template = Command::new(me);
141-
template.env("RUST_BACKTRACE", "full");
142-
143135
let mut i = 0;
144136
loop {
145137
let out = Command::new(me)

0 commit comments

Comments
 (0)