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 core
::prelude
::v1
::*;
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
::*;
29 pub fn ip(&self) -> *mut c_void
{
30 self.inner
.AddrPC
.Offset
as *mut _
33 pub fn symbol_address(&self) -> *mut c_void
{
38 #[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in winapi right now
39 struct MyContext(CONTEXT
);
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();
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() }
,
52 let image
= init_frame(&mut frame
.inner
.inner
, &context
.0);
54 // Initialize this process's symbols
55 let _c
= ::dbghelp_init();
57 // And now that we're done with all the setup, do the stack walking!
58 while dbghelp
::StackWalk64(image
as DWORD
,
61 &mut frame
.inner
.inner
,
62 &mut context
.0 as *mut CONTEXT
as *mut _
,
64 Some(dbghelp
::SymFunctionTableAccess64
),
65 Some(dbghelp
::SymGetModuleBase64
),
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 {
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
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