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.
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.
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
::*;
26 pub fn ip(&self) -> *mut c_void
{
27 self.inner
.AddrPC
.Offset
as *mut _
30 pub fn symbol_address(&self) -> *mut c_void
{
36 pub fn trace(cb
: &mut FnMut(&super::Frame
) -> bool
) {
37 // According to windows documentation, all dbghelp functions are
39 let _g
= ::lock
::lock();
42 // Allocate necessary structures for doing the stack walk
43 let process
= processthreadsapi
::GetCurrentProcess();
44 let thread
= processthreadsapi
::GetCurrentThread();
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
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() }
,
55 let image
= init_frame(&mut frame
.inner
.inner
, &context
);
57 // Initialize this process's symbols
58 let _c
= ::dbghelp_init();
60 // And now that we're done with all the setup, do the stack walking!
61 while dbghelp
::StackWalk64(image
as DWORD
,
64 &mut frame
.inner
.inner
,
65 &mut *context
as *mut _
as *mut _
,
67 Some(dbghelp
::SymFunctionTableAccess64
),
68 Some(dbghelp
::SymGetModuleBase64
),
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 {
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
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