Auto merge of #28242 - Diggsey:msvc-backtrace, r=alexcrichton
Currently LLVM does not generate the debug info required to get complete backtraces even when functions are inlined, so that part of the `run-pass/backtrace-debuginfo.rs` test is disabled when targetting MSVC. At worst this results in missing stack frames where functions have been inlined.
This commit is contained in:
commit
6b36e921f4
4 changed files with 50 additions and 10 deletions
|
@ -60,6 +60,9 @@ extern "system" {
|
|||
type SymFromAddrFn =
|
||||
extern "system" fn(libc::HANDLE, u64, *mut u64,
|
||||
*mut SYMBOL_INFO) -> libc::BOOL;
|
||||
type SymGetLineFromAddr64Fn =
|
||||
extern "system" fn(libc::HANDLE, u64, *mut u32,
|
||||
*mut IMAGEHLP_LINE64) -> libc::BOOL;
|
||||
type SymInitializeFn =
|
||||
extern "system" fn(libc::HANDLE, *mut libc::c_void,
|
||||
libc::BOOL) -> libc::BOOL;
|
||||
|
@ -99,6 +102,14 @@ struct SYMBOL_INFO {
|
|||
Name: [libc::c_char; MAX_SYM_NAME],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct IMAGEHLP_LINE64 {
|
||||
SizeOfStruct: u32,
|
||||
Key: *const libc::c_void,
|
||||
LineNumber: u32,
|
||||
Filename: *const libc::c_char,
|
||||
Address: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
enum ADDRESS_MODE {
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use sys_common::backtrace::output;
|
||||
use sys_common::backtrace::{output, output_fileline};
|
||||
use ffi::CStr;
|
||||
use dynamic_lib::DynamicLibrary;
|
||||
use super::{SymFromAddrFn, SYMBOL_INFO, MAX_SYM_NAME};
|
||||
use super::{SymFromAddrFn, SymGetLineFromAddr64Fn, SYMBOL_INFO, MAX_SYM_NAME, IMAGEHLP_LINE64};
|
||||
use io;
|
||||
use io::prelude::*;
|
||||
use intrinsics;
|
||||
|
@ -20,6 +20,7 @@ use libc;
|
|||
pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary, process: libc::HANDLE)
|
||||
-> io::Result<()> {
|
||||
let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn);
|
||||
let SymGetLineFromAddr64 = sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn);
|
||||
|
||||
let mut info: SYMBOL_INFO = unsafe { intrinsics::init() };
|
||||
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
|
|||
info.SizeOfStruct = 88;
|
||||
|
||||
let mut displacement = 0u64;
|
||||
let ret = SymFromAddr(process, addr as u64, &mut displacement, &mut info);
|
||||
let ret = SymFromAddr(process, addr, &mut displacement, &mut info);
|
||||
|
||||
let name = if ret == libc::TRUE {
|
||||
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
|
|||
None
|
||||
};
|
||||
|
||||
output(w, i, addr as usize as *mut libc::c_void, name)
|
||||
try!(output(w, i, addr as usize as *mut libc::c_void, name));
|
||||
|
||||
// Now find out the filename and line number
|
||||
let mut line: IMAGEHLP_LINE64 = unsafe { intrinsics::init() };
|
||||
line.SizeOfStruct = ::mem::size_of::<IMAGEHLP_LINE64>() as u32;
|
||||
|
||||
let mut displacement = 0u32;
|
||||
let ret = SymGetLineFromAddr64(process, addr, &mut displacement, &mut line);
|
||||
if ret == libc::TRUE {
|
||||
output_fileline(w,
|
||||
unsafe { CStr::from_ptr(line.Filename).to_bytes() },
|
||||
line.LineNumber as libc::c_int,
|
||||
false)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,11 @@ pub fn callback<F>(f: F) where F: FnOnce((&'static str, u32)) {
|
|||
f((file!(), line!()))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
// LLVM does not yet output the required debug info to support showing inlined
|
||||
// function calls in backtraces when targetting MSVC, so disable inlining in
|
||||
// this case.
|
||||
#[cfg_attr(not(target_env = "msvc"), inline(always))]
|
||||
#[cfg_attr(target_env = "msvc", inline(never))]
|
||||
pub fn callback_inlined<F>(f: F) where F: FnOnce((&'static str, u32)) {
|
||||
f((file!(), line!()))
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ macro_rules! pos {
|
|||
not(target_os = "ios"),
|
||||
not(target_os = "android"),
|
||||
not(all(target_os = "linux", target_arch = "arm"))),
|
||||
all(windows, target_env = "gnu", not(target_arch = "x86"))))]
|
||||
all(windows, not(target_arch = "x86"))))]
|
||||
macro_rules! dump_and_die {
|
||||
($($pos:expr),*) => ({
|
||||
// FIXME(#18285): we cannot include the current position because
|
||||
|
@ -48,7 +48,7 @@ macro_rules! dump_and_die {
|
|||
not(target_os = "ios"),
|
||||
not(target_os = "android"),
|
||||
not(all(target_os = "linux", target_arch = "arm"))),
|
||||
all(windows, target_env = "gnu", not(target_arch = "x86")))))]
|
||||
all(windows, not(target_arch = "x86")))))]
|
||||
macro_rules! dump_and_die {
|
||||
($($pos:expr),*) => ({ let _ = [$($pos),*]; })
|
||||
}
|
||||
|
@ -69,7 +69,10 @@ type Pos = (&'static str, u32);
|
|||
// this goes to stdout and each line has to be occurred
|
||||
// in the following backtrace to stderr with a correct order.
|
||||
fn dump_filelines(filelines: &[Pos]) {
|
||||
for &(file, line) in filelines.iter().rev() {
|
||||
// Skip top frame for MSVC, because it sees the macro rather than
|
||||
// the containing function.
|
||||
let skip = if cfg!(target_env = "msvc") {1} else {0};
|
||||
for &(file, line) in filelines.iter().rev().skip(skip) {
|
||||
// extract a basename
|
||||
let basename = file.split(&['/', '\\'][..]).last().unwrap();
|
||||
println!("{}:{}", basename, line);
|
||||
|
@ -88,12 +91,18 @@ fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
|||
});
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
// LLVM does not yet output the required debug info to support showing inlined
|
||||
// function calls in backtraces when targetting MSVC, so disable inlining in
|
||||
// this case.
|
||||
#[cfg_attr(not(target_env = "msvc"), inline(always))]
|
||||
#[cfg_attr(target_env = "msvc", inline(never))]
|
||||
fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
||||
check!(counter; main_pos, outer_pos);
|
||||
check!(counter; main_pos, outer_pos);
|
||||
|
||||
#[inline(always)]
|
||||
// Again, disable inlining for MSVC.
|
||||
#[cfg_attr(not(target_env = "msvc"), inline(always))]
|
||||
#[cfg_attr(target_env = "msvc", inline(never))]
|
||||
fn inner_further_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
|
||||
check!(counter; main_pos, outer_pos, inner_pos);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue