Skip to content

Commit 06f00c4

Browse files
committed
Include Rust 1.18 compatible implementations.
Issue #135
1 parent 1ff8f06 commit 06f00c4

File tree

5 files changed

+104
-39
lines changed

5 files changed

+104
-39
lines changed

src/backtrace/dbghelp.rs

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,47 +35,98 @@ impl Frame {
3535
}
3636
}
3737

38-
#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in winapi right now
39-
struct MyContext(CONTEXT);
40-
41-
#[inline(always)]
42-
pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
43-
// Allocate necessary structures for doing the stack walk
44-
let process = processthreadsapi::GetCurrentProcess();
45-
let thread = processthreadsapi::GetCurrentThread();
46-
47-
let mut context = mem::zeroed::<MyContext>();
48-
winnt::RtlCaptureContext(&mut context.0);
49-
let mut frame = super::Frame {
50-
inner: Frame { inner: mem::zeroed() },
51-
};
52-
let image = init_frame(&mut frame.inner.inner, &context.0);
53-
54-
// Initialize this process's symbols
55-
let _c = ::dbghelp_init();
56-
57-
// And now that we're done with all the setup, do the stack walking!
58-
while dbghelp::StackWalk64(image as DWORD,
59-
process,
60-
thread,
61-
&mut frame.inner.inner,
62-
&mut context.0 as *mut CONTEXT as *mut _,
63-
None,
64-
Some(dbghelp::SymFunctionTableAccess64),
65-
Some(dbghelp::SymGetModuleBase64),
66-
None) == TRUE {
67-
if frame.inner.inner.AddrPC.Offset == frame.inner.inner.AddrReturn.Offset ||
68-
frame.inner.inner.AddrPC.Offset == 0 ||
69-
frame.inner.inner.AddrReturn.Offset == 0 {
38+
// This beast is to maintain Rust 1.18 Compatibility
39+
cfg_if! {
40+
if #[cfg(feature = "repr_align")] {
41+
#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in winapi right now
42+
struct MyContext(CONTEXT);
43+
44+
#[inline(always)]
45+
pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
46+
// Allocate necessary structures for doing the stack walk
47+
let process = processthreadsapi::GetCurrentProcess();
48+
let thread = processthreadsapi::GetCurrentThread();
49+
50+
let mut context = mem::zeroed::<MyContext>();
51+
winnt::RtlCaptureContext(&mut context.0);
52+
let mut frame = super::Frame {
53+
inner: Frame { inner: mem::zeroed() },
54+
};
55+
let image = init_frame(&mut frame.inner.inner, &context.0);
56+
57+
// Initialize this process's symbols
58+
let _c = ::dbghelp_init();
59+
60+
// And now that we're done with all the setup, do the stack walking!
61+
while dbghelp::StackWalk64(image as DWORD,
62+
process,
63+
thread,
64+
&mut frame.inner.inner,
65+
&mut context.0 as *mut CONTEXT as *mut _,
66+
None,
67+
Some(dbghelp::SymFunctionTableAccess64),
68+
Some(dbghelp::SymGetModuleBase64),
69+
None) == TRUE {
70+
if frame.inner.inner.AddrPC.Offset == frame.inner.inner.AddrReturn.Offset ||
71+
frame.inner.inner.AddrPC.Offset == 0 ||
72+
frame.inner.inner.AddrReturn.Offset == 0 {
73+
break
74+
}
75+
76+
if !cb(&frame) {
77+
break
78+
}
79+
}
80+
}
81+
} else if #[cfg(feature = "std")] {
82+
#[inline(always)]
83+
pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
84+
// Allocate necessary structures for doing the stack walk
85+
let process = processthreadsapi::GetCurrentProcess();
86+
let thread = processthreadsapi::GetCurrentThread();
87+
88+
// The CONTEXT structure needs to be aligned on a 16-byte boundary for
89+
// 64-bit Windows, but we don't have a way to express that in Rust prior
90+
// to 1.24. Allocations are generally aligned to 16-bytes, though, so we
91+
// box this up.
92+
use std::boxed::Box;
93+
let mut context = Box::new(mem::zeroed::<CONTEXT>());
94+
winnt::RtlCaptureContext(&mut *context);
95+
let mut frame = super::Frame {
96+
inner: Frame { inner: mem::zeroed() },
97+
};
98+
let image = init_frame(&mut frame.inner.inner, &context);
99+
100+
// Initialize this process's symbols
101+
let _c = ::dbghelp_init();
102+
103+
// And now that we're done with all the setup, do the stack walking!
104+
while dbghelp::StackWalk64(image as DWORD,
105+
process,
106+
thread,
107+
&mut frame.inner.inner,
108+
&mut *context as *mut _ as *mut _,
109+
None,
110+
Some(dbghelp::SymFunctionTableAccess64),
111+
Some(dbghelp::SymGetModuleBase64),
112+
None) == TRUE {
113+
if frame.inner.inner.AddrPC.Offset == frame.inner.inner.AddrReturn.Offset ||
114+
frame.inner.inner.AddrPC.Offset == 0 ||
115+
frame.inner.inner.AddrReturn.Offset == 0 {
70116
break
71117
}
72118

73-
if !cb(&frame) {
74-
break
119+
if !cb(&frame) {
120+
break
121+
}
122+
}
75123
}
124+
} else {
125+
compile_error!("`no_std` is not supported for versions of Rust prior to 1.24.");
76126
}
77127
}
78128

129+
79130
#[cfg(target_arch = "x86_64")]
80131
fn init_frame(frame: &mut STACKFRAME64, ctx: &CONTEXT) -> WORD {
81132
frame.AddrPC.Offset = ctx.Rip as u64;

src/symbolize/dbghelp.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010

1111
#![allow(bad_style)]
1212

13+
#[cfg(feature = "std")]
14+
use std::char;
15+
1316
use core::mem;
1417
use core::slice;
18+
#[cfg(not(feature = "std"))]
1519
use core::char;
1620

1721
use winapi::ctypes::*;
@@ -63,13 +67,21 @@ impl Symbol {
6367
}
6468
}
6569

70+
// Maintain Rust 1.18 Compatibility
71+
#[cfg(feature = "repr_align")]
6672
#[repr(C, align(8))]
6773
struct Aligned8<T>(T);
6874

6975
pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
70-
const SIZE: usize = 2 * MAX_SYM_NAME + mem::size_of::<SYMBOL_INFOW>();
71-
let mut data = Aligned8([0u8; SIZE]);
76+
let size: usize = 2 * MAX_SYM_NAME + mem::size_of::<SYMBOL_INFOW>();
77+
#[cfg(feature = "repr_align")]
78+
let mut data = Aligned8([0u8; size]);
79+
#[cfg(not(feature = "repr_align"))]
80+
let mut data = vec![0u8; size];
81+
82+
#[cfg(feature = "repr_align")]
7283
let data = &mut data.0;
84+
7385
let info = &mut *(data.as_mut_ptr() as *mut SYMBOL_INFOW);
7486
info.MaxNameLen = MAX_SYM_NAME as ULONG;
7587
// the struct size in C. the value is different to

src/symbolize/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ impl<'a> SymbolName<'a> {
242242
}
243243
}
244244

245+
// Rust 1.18 does not mutate `bytes` or use `err`
246+
#[cfg_attr(not(feature = "utf8_error_error_len"), allow(unused_mut, unused_variables))]
245247
fn format_symbol_name(fmt: fn(&str, &mut fmt::Formatter) -> fmt::Result,
246248
mut bytes: &[u8],
247249
f: &mut fmt::Formatter)
@@ -256,6 +258,7 @@ fn format_symbol_name(fmt: fn(&str, &mut fmt::Formatter) -> fmt::Result,
256258
Err(err) => {
257259
fmt("\u{FFFD}", f)?;
258260

261+
#[cfg(feature = "utf8_error_error_len")]
259262
match err.error_len() {
260263
Some(len) => bytes = &bytes[err.valid_up_to() + len..],
261264
None => break,

src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ impl<'a> BytesOrWideString<'a> {
3131
use self::BytesOrWideString::*;
3232

3333
match self {
34-
Bytes(slice) => String::from_utf8_lossy(slice),
35-
Wide(wide) => Cow::Owned(String::from_utf16_lossy(wide)),
34+
&Bytes(slice) => String::from_utf8_lossy(slice),
35+
&Wide(wide) => Cow::Owned(String::from_utf16_lossy(wide)),
3636
}
3737
}
3838

tests/long_fn_name.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ mod _234567890_234567890_234567890_234567890_234567890 {
2323
#[test]
2424
#[cfg(all(windows, feature = "dbghelp", target_env = "msvc"))]
2525
fn test_long_fn_name() {
26-
use winapi::um::dbghelp;
2726
use _234567890_234567890_234567890_234567890_234567890::
2827
_234567890_234567890_234567890_234567890_234567890 as S;
2928

0 commit comments

Comments
 (0)