Skip to content

Commit 9d426ac

Browse files
committed
Make msvc symbol extraction/printing functions generic.
1 parent a0b1501 commit 9d426ac

File tree

1 file changed

+137
-103
lines changed
  • src/libstd/sys/windows/backtrace/printing

1 file changed

+137
-103
lines changed

Diff for: src/libstd/sys/windows/backtrace/printing/msvc.rs

+137-103
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use sys::c;
1818
use sys::dynamic_lib::DynamicLibrary;
1919
use sys_common::backtrace::Frame;
2020

21-
2221
// Structs holding printing functions and loaders for them
2322
// Two versions depending on whether dbghelp.dll has StackWalkEx or not
2423
// (the former being in newer Windows versions, the older being in Win7 and before)
@@ -32,23 +31,29 @@ pub struct PrintingFns64 {
3231
}
3332

3433
pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
35-
Ok(PrintingFnsEx{
36-
resolve_symname: sym!(dbghelp, "SymFromInlineContext",
37-
SymFromInlineContextFn)?,
38-
sym_get_line: sym!(dbghelp, "SymGetLineFromInlineContext",
39-
SymGetLineFromInlineContextFn)?,
34+
Ok(PrintingFnsEx {
35+
resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?,
36+
sym_get_line: sym!(
37+
dbghelp,
38+
"SymGetLineFromInlineContext",
39+
SymGetLineFromInlineContextFn
40+
)?,
4041
})
4142
}
4243
pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result<PrintingFns64> {
43-
Ok(PrintingFns64{
44+
Ok(PrintingFns64 {
4445
resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
45-
sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64",
46-
SymGetLineFromAddr64Fn)?,
46+
sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?,
4747
})
4848
}
4949

50+
type SymFromAddrFn =
51+
unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
5052
type SymFromInlineContextFn =
5153
unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
54+
55+
type SymGetLineFromAddr64Fn =
56+
unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
5257
type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
5358
c::HANDLE,
5459
u64,
@@ -58,73 +63,30 @@ type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
5863
*mut c::IMAGEHLP_LINE64,
5964
) -> c::BOOL;
6065

61-
type SymFromAddrFn =
62-
unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
63-
type SymGetLineFromAddr64Fn =
64-
unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
65-
6666
/// Converts a pointer to symbol to its string value.
6767
pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
6868
where
6969
F: FnOnce(Option<&str>) -> io::Result<()>,
7070
{
7171
match context.StackWalkVariant {
7272
StackWalkVariant::StackWalkEx(_, ref fns) => {
73-
resolve_symname_from_inline_context(fns.resolve_symname, frame, callback, context)
74-
},
73+
resolve_symname_internal(fns.resolve_symname, frame, callback, context)
74+
}
7575
StackWalkVariant::StackWalk64(_, ref fns) => {
76-
resolve_symname_from_addr(fns.resolve_symname, frame, callback, context)
76+
resolve_symname_internal(fns.resolve_symname, frame, callback, context)
7777
}
7878
}
7979
}
8080

81-
fn resolve_symname_from_inline_context<F>(
82-
SymFromInlineContext: SymFromInlineContextFn,
83-
frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
84-
where
85-
F: FnOnce(Option<&str>) -> io::Result<()>,
86-
{
87-
unsafe {
88-
let mut info: c::SYMBOL_INFO = mem::zeroed();
89-
info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
90-
// the struct size in C. the value is different to
91-
// `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
92-
// due to struct alignment.
93-
info.SizeOfStruct = 88;
94-
95-
let mut displacement = 0u64;
96-
let ret = SymFromInlineContext(
97-
context.handle,
98-
frame.symbol_addr as u64,
99-
frame.inline_context,
100-
&mut displacement,
101-
&mut info,
102-
);
103-
let valid_range =
104-
if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
105-
if info.Size != 0 {
106-
(frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
107-
} else {
108-
true
109-
}
110-
} else {
111-
false
112-
};
113-
let symname = if valid_range {
114-
let ptr = info.Name.as_ptr() as *const c_char;
115-
CStr::from_ptr(ptr).to_str().ok()
116-
} else {
117-
None
118-
};
119-
callback(symname)
120-
}
121-
}
122-
123-
fn resolve_symname_from_addr<F>(
124-
SymFromAddr: SymFromAddrFn,
125-
frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
81+
fn resolve_symname_internal<F, R>(
82+
symbol_resolver: R,
83+
frame: Frame,
84+
callback: F,
85+
context: &BacktraceContext,
86+
) -> io::Result<()>
12687
where
12788
F: FnOnce(Option<&str>) -> io::Result<()>,
89+
R: SymbolResolver,
12890
{
12991
unsafe {
13092
let mut info: c::SYMBOL_INFO = mem::zeroed();
@@ -134,15 +96,22 @@ where
13496
// due to struct alignment.
13597
info.SizeOfStruct = 88;
13698

137-
let mut displacement = 0u64;
138-
let ret = SymFromAddr(
99+
let ret = symbol_resolver.resolve_symbol(
139100
context.handle,
140101
frame.symbol_addr as u64,
141-
&mut displacement,
102+
frame.inline_context,
142103
&mut info,
143104
);
144-
145-
let symname = if ret == c::TRUE {
105+
let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
106+
if info.Size != 0 {
107+
(frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
108+
} else {
109+
true
110+
}
111+
} else {
112+
false
113+
};
114+
let symname = if valid_range {
146115
let ptr = info.Name.as_ptr() as *const c_char;
147116
CStr::from_ptr(ptr).to_str().ok()
148117
} else {
@@ -152,76 +121,141 @@ where
152121
}
153122
}
154123

124+
trait SymbolResolver {
125+
fn resolve_symbol(
126+
&self,
127+
process: c::HANDLE,
128+
symbol_address: u64,
129+
inline_context: c::ULONG,
130+
info: *mut c::SYMBOL_INFO,
131+
) -> c::BOOL;
132+
}
133+
134+
impl SymbolResolver for SymFromAddrFn {
135+
fn resolve_symbol(
136+
&self,
137+
process: c::HANDLE,
138+
symbol_address: u64,
139+
_inline_context: c::ULONG,
140+
info: *mut c::SYMBOL_INFO,
141+
) -> c::BOOL {
142+
unsafe {
143+
let mut displacement = 0u64;
144+
self(process, symbol_address, &mut displacement, info)
145+
}
146+
}
147+
}
148+
149+
impl SymbolResolver for SymFromInlineContextFn {
150+
fn resolve_symbol(
151+
&self,
152+
process: c::HANDLE,
153+
symbol_address: u64,
154+
inline_context: c::ULONG,
155+
info: *mut c::SYMBOL_INFO,
156+
) -> c::BOOL {
157+
unsafe {
158+
let mut displacement = 0u64;
159+
self(
160+
process,
161+
symbol_address,
162+
inline_context,
163+
&mut displacement,
164+
info,
165+
)
166+
}
167+
}
168+
}
169+
155170
pub fn foreach_symbol_fileline<F>(
156171
frame: Frame,
157-
f: F,
172+
callback: F,
158173
context: &BacktraceContext,
159174
) -> io::Result<bool>
160175
where
161176
F: FnMut(&[u8], u32) -> io::Result<()>,
162177
{
163178
match context.StackWalkVariant {
164-
StackWalkVariant::StackWalkEx(_, ref fns) =>
165-
foreach_symbol_fileline_ex(fns.sym_get_line, frame, f, context),
166-
StackWalkVariant::StackWalk64(_, ref fns) =>
167-
foreach_symbol_fileline_64(fns.sym_get_line, frame, f, context),
179+
StackWalkVariant::StackWalkEx(_, ref fns) => {
180+
foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context)
181+
}
182+
StackWalkVariant::StackWalk64(_, ref fns) => {
183+
foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context)
184+
}
168185
}
169186
}
170187

171-
fn foreach_symbol_fileline_ex<F>(
172-
SymGetLineFromInlineContext: SymGetLineFromInlineContextFn,
188+
fn foreach_symbol_fileline_iternal<F, G>(
189+
line_getter: G,
173190
frame: Frame,
174-
mut f: F,
191+
mut callback: F,
175192
context: &BacktraceContext,
176193
) -> io::Result<bool>
177194
where
178195
F: FnMut(&[u8], u32) -> io::Result<()>,
196+
G: LineGetter,
179197
{
180198
unsafe {
181199
let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
182200
line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
183201

184-
let mut displacement = 0u32;
185-
let ret = SymGetLineFromInlineContext(
202+
let ret = line_getter.get_line(
186203
context.handle,
187204
frame.exact_position as u64,
188205
frame.inline_context,
189-
0,
190-
&mut displacement,
191206
&mut line,
192207
);
193208
if ret == c::TRUE {
194209
let name = CStr::from_ptr(line.Filename).to_bytes();
195-
f(name, line.LineNumber as u32)?;
210+
callback(name, line.LineNumber as u32)?;
196211
}
197212
Ok(false)
198213
}
199214
}
200215

201-
fn foreach_symbol_fileline_64<F>(
202-
SymGetLineFromAddr64: SymGetLineFromAddr64Fn,
203-
frame: Frame,
204-
mut f: F,
205-
context: &BacktraceContext,
206-
) -> io::Result<bool>
207-
where
208-
F: FnMut(&[u8], u32) -> io::Result<()>,
209-
{
210-
unsafe {
211-
let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
212-
line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
216+
trait LineGetter {
217+
fn get_line(
218+
&self,
219+
process: c::HANDLE,
220+
frame_address: u64,
221+
inline_context: c::ULONG,
222+
line: *mut c::IMAGEHLP_LINE64,
223+
) -> c::BOOL;
224+
}
213225

214-
let mut displacement = 0u32;
215-
let ret = SymGetLineFromAddr64(
216-
context.handle,
217-
frame.exact_position as u64,
218-
&mut displacement,
219-
&mut line,
220-
);
221-
if ret == c::TRUE {
222-
let name = CStr::from_ptr(line.Filename).to_bytes();
223-
f(name, line.LineNumber as u32)?;
226+
impl LineGetter for SymGetLineFromAddr64Fn {
227+
fn get_line(
228+
&self,
229+
process: c::HANDLE,
230+
frame_address: u64,
231+
_inline_context: c::ULONG,
232+
line: *mut c::IMAGEHLP_LINE64,
233+
) -> c::BOOL {
234+
unsafe {
235+
let mut displacement = 0u32;
236+
self(process, frame_address, &mut displacement, line)
237+
}
238+
}
239+
}
240+
241+
impl LineGetter for SymGetLineFromInlineContextFn {
242+
fn get_line(
243+
&self,
244+
process: c::HANDLE,
245+
frame_address: u64,
246+
inline_context: c::ULONG,
247+
line: *mut c::IMAGEHLP_LINE64,
248+
) -> c::BOOL {
249+
unsafe {
250+
let mut displacement = 0u32;
251+
self(
252+
process,
253+
frame_address,
254+
inline_context,
255+
0,
256+
&mut displacement,
257+
line,
258+
)
224259
}
225-
Ok(false)
226260
}
227261
}

0 commit comments

Comments
 (0)