Skip to content

Commit d4fc3ec

Browse files
committed
Add line numbers to windows-gnu backtraces
Fix formatting Remove unused imports Refactor Fix msvc build Fix line lengths Formatting Enable backtrace tests Fix using directive on mac pwd info Work-around buildbot PWD bug, and fix libbacktrace configuration Use alternative to `env -u` which is not supported on bitrig Disable tests on 32-bit windows gnu
1 parent ac12c7f commit d4fc3ec

File tree

15 files changed

+192
-95
lines changed

15 files changed

+192
-95
lines changed

mk/rt.mk

+17-6
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,10 @@ BACKTRACE_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),backtrace)
259259
BACKTRACE_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(BACKTRACE_NAME_$(1))
260260
BACKTRACE_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libbacktrace
261261

262-
# We don't use this on platforms that aren't linux-based, so just make the file
263-
# available, the compilation of libstd won't actually build it.
262+
# We don't use this on platforms that aren't linux-based (with the exception of
263+
# msys2/mingw builds on windows, which use it to read the dwarf debug
264+
# information) so just make the file available, the compilation of libstd won't
265+
# actually build it.
264266
ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin)
265267
# See comment above
266268
$$(BACKTRACE_LIB_$(1)):
@@ -273,7 +275,7 @@ $$(BACKTRACE_LIB_$(1)):
273275
touch $$@
274276
else
275277

276-
ifeq ($$(CFG_WINDOWSY_$(1)),1)
278+
ifeq ($$(findstring msvc,$(1)),msvc)
277279
# See comment above
278280
$$(BACKTRACE_LIB_$(1)):
279281
touch $$@
@@ -296,16 +298,25 @@ endif
296298
# ./configure script. This is done to force libbacktrace to *not* use the
297299
# atomic/sync functionality because it pulls in unnecessary dependencies and we
298300
# never use it anyway.
301+
#
302+
# We also use `env PWD=` to clear the PWD environment variable, and then
303+
# execute the command in a new shell. This is necessary to workaround a
304+
# buildbot/msys2 bug: the shell is launched with PWD set to a windows-style path,
305+
# which results in all further uses of `pwd` also printing a windows-style path,
306+
# which breaks libbacktrace's configure script. Clearing PWD within the same
307+
# shell is not sufficient.
308+
299309
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: $$(BACKTRACE_DEPS) $$(MKFILE_DEPS)
300310
@$$(call E, configure: libbacktrace for $(1))
301311
$$(Q)rm -rf $$(BACKTRACE_BUILD_DIR_$(1))
302312
$$(Q)mkdir -p $$(BACKTRACE_BUILD_DIR_$(1))
303-
$$(Q)(cd $$(BACKTRACE_BUILD_DIR_$(1)) && \
313+
$$(Q)(cd $$(BACKTRACE_BUILD_DIR_$(1)) && env \
314+
PWD= \
304315
CC="$$(CC_$(1))" \
305316
AR="$$(AR_$(1))" \
306317
RANLIB="$$(AR_$(1)) s" \
307318
CFLAGS="$$(CFG_GCCISH_CFLAGS_$(1):-Werror=) -fno-stack-protector" \
308-
$(S)src/libbacktrace/configure --target=$(1) --host=$(CFG_BUILD))
319+
$(S)src/libbacktrace/configure --build=$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$(CFG_GNU_TRIPLE_$(1)))
309320
$$(Q)echo '#undef HAVE_ATOMIC_FUNCTIONS' >> \
310321
$$(BACKTRACE_BUILD_DIR_$(1))/config.h
311322
$$(Q)echo '#undef HAVE_SYNC_FUNCTIONS' >> \
@@ -317,7 +328,7 @@ $$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS)
317328
INCDIR=$(S)src/libbacktrace
318329
$$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@
319330

320-
endif # endif for windowsy
331+
endif # endif for msvc
321332
endif # endif for ios
322333
endif # endif for darwin
323334

src/libbacktrace/configure

+1-1
Original file line numberDiff line numberDiff line change
@@ -3974,7 +3974,7 @@ am_lf='
39743974
'
39753975
case `pwd` in
39763976
*[\\\"\#\$\&\'\`$am_lf]*)
3977-
as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
3977+
as_fn_error "unsafe absolute working directory name: \``pwd`'" "$LINENO" 5;;
39783978
esac
39793979
case $srcdir in
39803980
*[\\\"\#\$\&\'\`$am_lf\ \ ]*)

src/libstd/sys/common/backtrace.rs

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

11-
use io::prelude::*;
12-
1311
use io;
12+
use io::prelude::*;
13+
use str;
14+
use libc;
1415

1516
#[cfg(target_pointer_width = "64")]
1617
pub const HEX_WIDTH: usize = 18;
1718

1819
#[cfg(target_pointer_width = "32")]
1920
pub const HEX_WIDTH: usize = 10;
2021

22+
23+
// These output functions should now be used everywhere to ensure consistency.
24+
pub fn output(w: &mut Write, idx: isize, addr: *mut libc::c_void,
25+
s: Option<&[u8]>) -> io::Result<()> {
26+
try!(write!(w, " {:2}: {:2$?} - ", idx, addr, HEX_WIDTH));
27+
match s.and_then(|s| str::from_utf8(s).ok()) {
28+
Some(string) => try!(demangle(w, string)),
29+
None => try!(write!(w, "<unknown>")),
30+
}
31+
w.write_all(&['\n' as u8])
32+
}
33+
34+
#[allow(dead_code)]
35+
pub fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int,
36+
more: bool) -> io::Result<()> {
37+
let file = str::from_utf8(file).unwrap_or("<unknown>");
38+
// prior line: " ##: {:2$} - func"
39+
try!(write!(w, " {:3$}at {}:{}", "", file, line, HEX_WIDTH));
40+
if more {
41+
try!(write!(w, " <... and possibly more>"));
42+
}
43+
w.write_all(&['\n' as u8])
44+
}
45+
46+
2147
// All rust symbols are in theory lists of "::"-separated identifiers. Some
2248
// assemblers, however, can't handle these characters in symbol names. To get
2349
// around this, we use C++-style mangling. The mangling method is:

src/libstd/sys/unix/backtrace/printing/libbacktrace.rs src/libstd/sys/common/gnu/libbacktrace.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
use io;
1212
use io::prelude::*;
1313
use libc;
14+
use sys_common::backtrace::{output, output_fileline};
1415

15-
use sys::backtrace::{output, output_fileline};
1616
pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void,
1717
symaddr: *mut libc::c_void) -> io::Result<()> {
1818
use env;
1919
use ffi::CStr;
20-
use os::unix::prelude::*;
2120
use ptr;
2221

2322
////////////////////////////////////////////////////////////////////////
@@ -129,14 +128,15 @@ pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void,
129128
let selfname = if cfg!(target_os = "freebsd") ||
130129
cfg!(target_os = "dragonfly") ||
131130
cfg!(target_os = "bitrig") ||
132-
cfg!(target_os = "openbsd") {
131+
cfg!(target_os = "openbsd") ||
132+
cfg!(target_os = "windows") {
133133
env::current_exe().ok()
134134
} else {
135135
None
136136
};
137-
let filename = match selfname {
137+
let filename = match selfname.as_ref().and_then(|s| s.as_os_str().to_bytes()) {
138138
Some(path) => {
139-
let bytes = path.as_os_str().as_bytes();
139+
let bytes = path;
140140
if bytes.len() < LAST_FILENAME.len() {
141141
let i = bytes.iter();
142142
for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {

src/libstd/sys/common/gnu/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(missing_docs)]
12+
#![allow(non_camel_case_types)]
13+
#![allow(non_snake_case)]
14+
15+
pub mod libbacktrace;

src/libstd/sys/common/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ pub mod thread_info;
2323
pub mod thread_local;
2424
pub mod wtf8;
2525

26+
#[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios"))),
27+
all(windows, target_env = "gnu")))]
28+
pub mod gnu;
29+
2630
// common error constructors
2731

2832
/// A trait for viewing representations from std types

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

-29
Original file line numberDiff line numberDiff line change
@@ -85,36 +85,7 @@
8585
8686
pub use self::tracing::write;
8787

88-
use io;
89-
use io::prelude::*;
90-
use libc;
91-
use str;
92-
93-
use sys_common::backtrace::{demangle, HEX_WIDTH};
94-
9588
// tracing impls:
9689
mod tracing;
9790
// symbol resolvers:
9891
mod printing;
99-
100-
pub fn output(w: &mut Write, idx: isize, addr: *mut libc::c_void,
101-
s: Option<&[u8]>) -> io::Result<()> {
102-
try!(write!(w, " {:2}: {:2$?} - ", idx, addr, HEX_WIDTH));
103-
match s.and_then(|s| str::from_utf8(s).ok()) {
104-
Some(string) => try!(demangle(w, string)),
105-
None => try!(write!(w, "<unknown>")),
106-
}
107-
w.write_all(&['\n' as u8])
108-
}
109-
110-
#[allow(dead_code)]
111-
pub fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int,
112-
more: bool) -> io::Result<()> {
113-
let file = str::from_utf8(file).unwrap_or("<unknown>");
114-
// prior line: " ##: {:2$} - func"
115-
try!(write!(w, " {:3$}at {}:{}", "", file, line, HEX_WIDTH));
116-
if more {
117-
try!(write!(w, " <... and possibly more>"));
118-
}
119-
w.write_all(&['\n' as u8])
120-
}

src/libstd/sys/unix/backtrace/printing/dladdr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use libc;
1414

1515
pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void,
1616
_symaddr: *mut libc::c_void) -> io::Result<()> {
17-
use sys::backtrace::{output};
17+
use sys_common::backtrace::{output};
1818
use intrinsics;
1919
use ffi::CStr;
2020

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub use sys_common::gnu::libbacktrace::print;

src/libstd/sys/unix/backtrace/printing/mod.rs

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

11-
pub use self::imp::*;
11+
pub use self::imp::print;
1212

1313
#[cfg(any(target_os = "macos", target_os = "ios"))]
1414
#[path = "dladdr.rs"]
1515
mod imp;
1616

1717
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
18-
#[path = "libbacktrace.rs"]
18+
#[path = "gnu.rs"]
1919
mod imp;

src/libstd/sys/windows/backtrace.rs

+25-38
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,28 @@
2727
use io::prelude::*;
2828

2929
use dynamic_lib::DynamicLibrary;
30-
use ffi::CStr;
3130
use intrinsics;
3231
use io;
3332
use libc;
34-
use mem;
3533
use path::Path;
3634
use ptr;
37-
use str;
3835
use sync::StaticMutex;
3936

40-
use sys_common::backtrace::*;
37+
macro_rules! sym{ ($lib:expr, $e:expr, $t:ident) => (unsafe {
38+
let lib = $lib;
39+
match lib.symbol($e) {
40+
Ok(f) => $crate::mem::transmute::<*mut u8, $t>(f),
41+
Err(..) => return Ok(())
42+
}
43+
}) }
44+
45+
#[cfg(target_env = "msvc")]
46+
#[path = "printing/msvc.rs"]
47+
mod printing;
48+
49+
#[cfg(target_env = "gnu")]
50+
#[path = "printing/gnu.rs"]
51+
mod printing;
4152

4253
#[allow(non_snake_case)]
4354
extern "system" {
@@ -302,23 +313,15 @@ pub fn write(w: &mut Write) -> io::Result<()> {
302313
// Open up dbghelp.dll, we don't link to it explicitly because it can't
303314
// always be found. Additionally, it's nice having fewer dependencies.
304315
let path = Path::new("dbghelp.dll");
305-
let lib = match DynamicLibrary::open(Some(&path)) {
316+
let dbghelp = match DynamicLibrary::open(Some(&path)) {
306317
Ok(lib) => lib,
307318
Err(..) => return Ok(()),
308319
};
309320

310-
macro_rules! sym{ ($e:expr, $t:ident) => (unsafe {
311-
match lib.symbol($e) {
312-
Ok(f) => mem::transmute::<*mut u8, $t>(f),
313-
Err(..) => return Ok(())
314-
}
315-
}) }
316-
317321
// Fetch the symbols necessary from dbghelp.dll
318-
let SymFromAddr = sym!("SymFromAddr", SymFromAddrFn);
319-
let SymInitialize = sym!("SymInitialize", SymInitializeFn);
320-
let SymCleanup = sym!("SymCleanup", SymCleanupFn);
321-
let StackWalk64 = sym!("StackWalk64", StackWalk64Fn);
322+
let SymInitialize = sym!(&dbghelp, "SymInitialize", SymInitializeFn);
323+
let SymCleanup = sym!(&dbghelp, "SymCleanup", SymCleanupFn);
324+
let StackWalk64 = sym!(&dbghelp, "StackWalk64", StackWalk64Fn);
322325

323326
// Allocate necessary structures for doing the stack walk
324327
let process = unsafe { GetCurrentProcess() };
@@ -334,7 +337,9 @@ pub fn write(w: &mut Write) -> io::Result<()> {
334337
let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
335338

336339
// And now that we're done with all the setup, do the stack walking!
337-
let mut i = 0;
340+
// Start from -1 to avoid printing this stack frame, which will
341+
// always be exactly the same.
342+
let mut i = -1;
338343
try!(write!(w, "stack backtrace:\n"));
339344
while StackWalk64(image, process, thread, &mut frame, &mut context,
340345
ptr::null_mut(),
@@ -346,28 +351,10 @@ pub fn write(w: &mut Write) -> io::Result<()> {
346351
frame.AddrReturn.Offset == 0 { break }
347352

348353
i += 1;
349-
try!(write!(w, " {:2}: {:#2$x}", i, addr, HEX_WIDTH));
350-
let mut info: SYMBOL_INFO = unsafe { intrinsics::init() };
351-
info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong;
352-
// the struct size in C. the value is different to
353-
// `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
354-
// due to struct alignment.
355-
info.SizeOfStruct = 88;
356-
357-
let mut displacement = 0u64;
358-
let ret = SymFromAddr(process, addr as u64, &mut displacement,
359-
&mut info);
360-
361-
if ret == libc::TRUE {
362-
try!(write!(w, " - "));
363-
let ptr = info.Name.as_ptr() as *const libc::c_char;
364-
let bytes = unsafe { CStr::from_ptr(ptr).to_bytes() };
365-
match str::from_utf8(bytes) {
366-
Ok(s) => try!(demangle(w, s)),
367-
Err(..) => try!(w.write_all(&bytes[..bytes.len()-1])),
368-
}
354+
355+
if i >= 0 {
356+
try!(printing::print(w, i, addr-1, &dbghelp, process));
369357
}
370-
try!(w.write_all(&['\n' as u8]));
371358
}
372359

373360
Ok(())
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use dynamic_lib::DynamicLibrary;
12+
use io;
13+
use io::prelude::*;
14+
use libc;
15+
16+
use sys_common::gnu::libbacktrace;
17+
18+
pub fn print(w: &mut Write, i: isize, addr: u64, _: &DynamicLibrary, _: libc::HANDLE)
19+
-> io::Result<()> {
20+
let addr = addr as usize as *mut libc::c_void;
21+
libbacktrace::print(w, i, addr, addr)
22+
}

0 commit comments

Comments
 (0)