]> git.proxmox.com Git - cargo.git/blob - vendor/backtrace/src/backtrace/dbghelp.rs
New upstream version 0.33.0
[cargo.git] / 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 core::mem;
14 use core::prelude::v1::*;
15
16 use winapi::shared::minwindef::*;
17 use winapi::um::processthreadsapi;
18 use winapi::um::winnt::{self, CONTEXT};
19 use winapi::um::dbghelp;
20 use winapi::um::dbghelp::*;
21
22 use types::c_void;
23
24 pub struct Frame {
25 inner: STACKFRAME64,
26 }
27
28 impl Frame {
29 pub fn ip(&self) -> *mut c_void {
30 self.inner.AddrPC.Offset as *mut _
31 }
32
33 pub fn symbol_address(&self) -> *mut c_void {
34 self.ip()
35 }
36 }
37
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 {
70 break
71 }
72
73 if !cb(&frame) {
74 break
75 }
76 }
77 }
78
79 #[cfg(target_arch = "x86_64")]
80 fn init_frame(frame: &mut STACKFRAME64, ctx: &CONTEXT) -> WORD {
81 frame.AddrPC.Offset = ctx.Rip as u64;
82 frame.AddrPC.Mode = AddrModeFlat;
83 frame.AddrStack.Offset = ctx.Rsp as u64;
84 frame.AddrStack.Mode = AddrModeFlat;
85 frame.AddrFrame.Offset = ctx.Rbp as u64;
86 frame.AddrFrame.Mode = AddrModeFlat;
87 winnt::IMAGE_FILE_MACHINE_AMD64
88 }
89
90 #[cfg(target_arch = "x86")]
91 fn init_frame(frame: &mut STACKFRAME64, ctx: &CONTEXT) -> WORD {
92 frame.AddrPC.Offset = ctx.Eip as u64;
93 frame.AddrPC.Mode = AddrModeFlat;
94 frame.AddrStack.Offset = ctx.Esp as u64;
95 frame.AddrStack.Mode = AddrModeFlat;
96 frame.AddrFrame.Offset = ctx.Ebp as u64;
97 frame.AddrFrame.Mode = AddrModeFlat;
98 winnt::IMAGE_FILE_MACHINE_I386
99 }