]> git.proxmox.com Git - rustc.git/blob - src/vendor/backtrace/src/backtrace/dbghelp.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / vendor / backtrace / src / backtrace / dbghelp.rs
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(bad_style)]
12
13 use std::mem;
14 use winapi::ctypes::*;
15 use winapi::shared::minwindef::*;
16 use winapi::um::processthreadsapi;
17 use winapi::um::winnt::{self, CONTEXT};
18 use winapi::um::dbghelp;
19 use winapi::um::dbghelp::*;
20
21 pub struct Frame {
22 inner: STACKFRAME64,
23 }
24
25 impl Frame {
26 pub fn ip(&self) -> *mut c_void {
27 self.inner.AddrPC.Offset as *mut _
28 }
29
30 pub fn symbol_address(&self) -> *mut c_void {
31 self.ip()
32 }
33 }
34
35 #[inline(always)]
36 pub fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
37 // According to windows documentation, all dbghelp functions are
38 // single-threaded.
39 let _g = ::lock::lock();
40
41 unsafe {
42 // Allocate necessary structures for doing the stack walk
43 let process = processthreadsapi::GetCurrentProcess();
44 let thread = processthreadsapi::GetCurrentThread();
45
46 // The CONTEXT structure needs to be aligned on a 16-byte boundary for
47 // 64-bit Windows, but currently we don't have a way to express that in
48 // Rust. Allocations are generally aligned to 16-bytes, though, so we
49 // box this up.
50 let mut context = Box::new(mem::zeroed::<CONTEXT>());
51 winnt::RtlCaptureContext(&mut *context);
52 let mut frame = super::Frame {
53 inner: Frame { inner: mem::zeroed() },
54 };
55 let image = init_frame(&mut frame.inner.inner, &context);
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 as *mut _ 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 }
82
83 #[cfg(target_arch = "x86_64")]
84 fn init_frame(frame: &mut STACKFRAME64, ctx: &CONTEXT) -> WORD {
85 frame.AddrPC.Offset = ctx.Rip as u64;
86 frame.AddrPC.Mode = AddrModeFlat;
87 frame.AddrStack.Offset = ctx.Rsp as u64;
88 frame.AddrStack.Mode = AddrModeFlat;
89 frame.AddrFrame.Offset = ctx.Rbp as u64;
90 frame.AddrFrame.Mode = AddrModeFlat;
91 winnt::IMAGE_FILE_MACHINE_AMD64
92 }
93
94 #[cfg(target_arch = "x86")]
95 fn init_frame(frame: &mut STACKFRAME64, ctx: &CONTEXT) -> WORD {
96 frame.AddrPC.Offset = ctx.Eip as u64;
97 frame.AddrPC.Mode = AddrModeFlat;
98 frame.AddrStack.Offset = ctx.Esp as u64;
99 frame.AddrStack.Mode = AddrModeFlat;
100 frame.AddrFrame.Offset = ctx.Ebp as u64;
101 frame.AddrFrame.Mode = AddrModeFlat;
102 winnt::IMAGE_FILE_MACHINE_I386
103 }