]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
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 | use ffi::CStr; | |
12 | use io; | |
abe05a73 | 13 | use libc::{c_ulong, c_char}; |
8bb4bdeb XL |
14 | use mem; |
15 | use sys::c; | |
16 | use sys::backtrace::BacktraceContext; | |
17 | use sys_common::backtrace::Frame; | |
18 | ||
19 | type SymFromAddrFn = | |
20 | unsafe extern "system" fn(c::HANDLE, u64, *mut u64, | |
21 | *mut c::SYMBOL_INFO) -> c::BOOL; | |
22 | type SymGetLineFromAddr64Fn = | |
23 | unsafe extern "system" fn(c::HANDLE, u64, *mut u32, | |
24 | *mut c::IMAGEHLP_LINE64) -> c::BOOL; | |
25 | ||
26 | /// Converts a pointer to symbol to its string value. | |
27 | pub fn resolve_symname<F>(frame: Frame, | |
28 | callback: F, | |
29 | context: &BacktraceContext) -> io::Result<()> | |
30 | where F: FnOnce(Option<&str>) -> io::Result<()> | |
31 | { | |
32 | let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; | |
33 | ||
34 | unsafe { | |
35 | let mut info: c::SYMBOL_INFO = mem::zeroed(); | |
36 | info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; | |
37 | // the struct size in C. the value is different to | |
38 | // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81) | |
39 | // due to struct alignment. | |
40 | info.SizeOfStruct = 88; | |
41 | ||
42 | let mut displacement = 0u64; | |
43 | let ret = SymFromAddr(context.handle, | |
44 | frame.symbol_addr as u64, | |
45 | &mut displacement, | |
46 | &mut info); | |
47 | ||
48 | let symname = if ret == c::TRUE { | |
49 | let ptr = info.Name.as_ptr() as *const c_char; | |
50 | CStr::from_ptr(ptr).to_str().ok() | |
51 | } else { | |
52 | None | |
53 | }; | |
54 | callback(symname) | |
55 | } | |
56 | } | |
57 | ||
58 | pub fn foreach_symbol_fileline<F>(frame: Frame, | |
59 | mut f: F, | |
60 | context: &BacktraceContext) | |
61 | -> io::Result<bool> | |
abe05a73 | 62 | where F: FnMut(&[u8], u32) -> io::Result<()> |
8bb4bdeb XL |
63 | { |
64 | let SymGetLineFromAddr64 = sym!(&context.dbghelp, | |
65 | "SymGetLineFromAddr64", | |
66 | SymGetLineFromAddr64Fn)?; | |
67 | ||
68 | unsafe { | |
69 | let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); | |
70 | line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32; | |
71 | ||
72 | let mut displacement = 0u32; | |
73 | let ret = SymGetLineFromAddr64(context.handle, | |
74 | frame.exact_position as u64, | |
75 | &mut displacement, | |
76 | &mut line); | |
77 | if ret == c::TRUE { | |
78 | let name = CStr::from_ptr(line.Filename).to_bytes(); | |
abe05a73 | 79 | f(name, line.LineNumber as u32)?; |
8bb4bdeb XL |
80 | } |
81 | Ok(false) | |
82 | } | |
83 | } |