]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/windows/backtrace/printing/msvc.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / libstd / sys / windows / backtrace / printing / msvc.rs
CommitLineData
8bb4bdeb
XL
1use ffi::CStr;
2use io;
8faf50e0 3use libc::{c_char, c_ulong};
8bb4bdeb 4use mem;
8bb4bdeb 5use sys::backtrace::BacktraceContext;
8faf50e0
XL
6use sys::backtrace::StackWalkVariant;
7use sys::c;
8use sys::dynamic_lib::DynamicLibrary;
8bb4bdeb
XL
9use sys_common::backtrace::Frame;
10
8faf50e0
XL
11// Structs holding printing functions and loaders for them
12// Two versions depending on whether dbghelp.dll has StackWalkEx or not
13// (the former being in newer Windows versions, the older being in Win7 and before)
14pub struct PrintingFnsEx {
15 resolve_symname: SymFromInlineContextFn,
16 sym_get_line: SymGetLineFromInlineContextFn,
17}
18pub struct PrintingFns64 {
19 resolve_symname: SymFromAddrFn,
20 sym_get_line: SymGetLineFromAddr64Fn,
21}
22
23pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
24 Ok(PrintingFnsEx {
25 resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?,
26 sym_get_line: sym!(
27 dbghelp,
28 "SymGetLineFromInlineContext",
29 SymGetLineFromInlineContextFn
30 )?,
31 })
32}
33pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result<PrintingFns64> {
34 Ok(PrintingFns64 {
35 resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
36 sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?,
37 })
38}
39
40type SymFromAddrFn =
41 unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
2c00a5a8 42type SymFromInlineContextFn =
8faf50e0
XL
43 unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
44
45type SymGetLineFromAddr64Fn =
46 unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
47type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
48 c::HANDLE,
49 u64,
50 c::ULONG,
51 u64,
52 *mut c::DWORD,
53 *mut c::IMAGEHLP_LINE64,
54) -> c::BOOL;
8bb4bdeb
XL
55
56/// Converts a pointer to symbol to its string value.
8faf50e0
XL
57pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
58where
59 F: FnOnce(Option<&str>) -> io::Result<()>,
8bb4bdeb 60{
8faf50e0
XL
61 match context.StackWalkVariant {
62 StackWalkVariant::StackWalkEx(_, ref fns) => resolve_symname_internal(
63 |process: c::HANDLE,
64 symbol_address: u64,
65 inline_context: c::ULONG,
66 info: *mut c::SYMBOL_INFO| unsafe {
67 let mut displacement = 0u64;
68 (fns.resolve_symname)(
69 process,
70 symbol_address,
71 inline_context,
72 &mut displacement,
73 info,
74 )
75 },
76 frame,
77 callback,
78 context,
79 ),
80 StackWalkVariant::StackWalk64(_, ref fns) => resolve_symname_internal(
81 |process: c::HANDLE,
82 symbol_address: u64,
83 _inline_context: c::ULONG,
84 info: *mut c::SYMBOL_INFO| unsafe {
85 let mut displacement = 0u64;
86 (fns.resolve_symname)(process, symbol_address, &mut displacement, info)
87 },
88 frame,
89 callback,
90 context,
91 ),
92 }
93}
8bb4bdeb 94
8faf50e0
XL
95fn resolve_symname_internal<F, R>(
96 mut symbol_resolver: R,
97 frame: Frame,
98 callback: F,
99 context: &BacktraceContext,
100) -> io::Result<()>
101where
102 F: FnOnce(Option<&str>) -> io::Result<()>,
103 R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL,
104{
8bb4bdeb
XL
105 unsafe {
106 let mut info: c::SYMBOL_INFO = mem::zeroed();
107 info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
108 // the struct size in C. the value is different to
109 // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
110 // due to struct alignment.
111 info.SizeOfStruct = 88;
112
8faf50e0
XL
113 let ret = symbol_resolver(
114 context.handle,
115 frame.symbol_addr as u64,
116 frame.inline_context,
117 &mut info,
118 );
119 let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
2c00a5a8
XL
120 if info.Size != 0 {
121 (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
122 } else {
123 true
124 }
125 } else {
126 false
127 };
128 let symname = if valid_range {
8bb4bdeb
XL
129 let ptr = info.Name.as_ptr() as *const c_char;
130 CStr::from_ptr(ptr).to_str().ok()
131 } else {
132 None
133 };
134 callback(symname)
135 }
136}
137
8faf50e0
XL
138pub fn foreach_symbol_fileline<F>(
139 frame: Frame,
140 callback: F,
141 context: &BacktraceContext,
142) -> io::Result<bool>
143where
144 F: FnMut(&[u8], u32) -> io::Result<()>,
8bb4bdeb 145{
8faf50e0
XL
146 match context.StackWalkVariant {
147 StackWalkVariant::StackWalkEx(_, ref fns) => foreach_symbol_fileline_iternal(
148 |process: c::HANDLE,
149 frame_address: u64,
150 inline_context: c::ULONG,
151 line: *mut c::IMAGEHLP_LINE64| unsafe {
152 let mut displacement = 0u32;
153 (fns.sym_get_line)(
154 process,
155 frame_address,
156 inline_context,
157 0,
158 &mut displacement,
159 line,
160 )
161 },
162 frame,
163 callback,
164 context,
165 ),
166 StackWalkVariant::StackWalk64(_, ref fns) => foreach_symbol_fileline_iternal(
167 |process: c::HANDLE,
168 frame_address: u64,
169 _inline_context: c::ULONG,
170 line: *mut c::IMAGEHLP_LINE64| unsafe {
171 let mut displacement = 0u32;
172 (fns.sym_get_line)(process, frame_address, &mut displacement, line)
173 },
174 frame,
175 callback,
176 context,
177 ),
178 }
179}
8bb4bdeb 180
8faf50e0
XL
181fn foreach_symbol_fileline_iternal<F, G>(
182 mut line_getter: G,
183 frame: Frame,
184 mut callback: F,
185 context: &BacktraceContext,
186) -> io::Result<bool>
187where
188 F: FnMut(&[u8], u32) -> io::Result<()>,
189 G: FnMut(c::HANDLE, u64, c::ULONG, *mut c::IMAGEHLP_LINE64) -> c::BOOL,
190{
8bb4bdeb
XL
191 unsafe {
192 let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
193 line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
194
8faf50e0
XL
195 let ret = line_getter(
196 context.handle,
197 frame.exact_position as u64,
198 frame.inline_context,
199 &mut line,
200 );
8bb4bdeb
XL
201 if ret == c::TRUE {
202 let name = CStr::from_ptr(line.Filename).to_bytes();
8faf50e0 203 callback(name, line.LineNumber as u32)?;
8bb4bdeb
XL
204 }
205 Ok(false)
206 }
207}