Last active
December 31, 2015 14:19
-
-
Save klutzy/7999247 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[cfg(unix)] | |
fn trace(n_frames: uint) -> ~[~str] { | |
use std::libc::{c_void, c_int, c_char}; | |
use std::libc; | |
use std::c_str; | |
use std::ptr; | |
use std::vec; | |
extern { | |
fn backtrace(buffer: *mut *mut c_void, size: c_int) -> c_int; | |
fn backtrace_symbols(buffer: **mut c_void, size: c_int) -> *mut *mut c_char; | |
} | |
let mut trace_buf: ~[*mut c_void] = vec::from_elem(n_frames, ptr::mut_null()); | |
let ret = unsafe { backtrace(trace_buf.as_mut_ptr(), n_frames as i32) }; | |
trace_buf.truncate(ret as uint); | |
let symbols = unsafe { backtrace_symbols(trace_buf.as_ptr(), ret) }; | |
let mut strings = ~[]; | |
for i in range(0, ret as int) { | |
unsafe { | |
let c_ptr = *ptr::offset(symbols as **i8, i); | |
let c_str = c_str::CString::new(c_ptr, false); | |
let s = c_str.as_str().unwrap_or("???").to_owned(); | |
strings.push(s); | |
} | |
} | |
unsafe { | |
libc::free(symbols as *c_void); | |
} | |
strings | |
} | |
#[cfg(windows)] | |
fn trace(n_frames: uint) -> ~[~str] { | |
use std::libc::{c_ulong, c_ushort, c_void, wchar_t}; | |
use std::libc::{BOOL, DWORD}; | |
use std::ptr; | |
use std::vec; | |
type HANDLE = *mut c_void; | |
extern "system" { | |
fn RtlCaptureStackBackTrace( | |
FramesToSkip: c_ulong, FramesToCapture: c_ulong, | |
BackTrace: *mut *mut c_void, BackTraceHash: *mut c_ulong | |
) -> c_ushort; | |
fn GetCurrentProcess() -> HANDLE; | |
fn GetLastError() -> DWORD; | |
} | |
struct SYMBOL_INFO { | |
SizeOfStruct: c_ulong, | |
TypeIndex: c_ulong, | |
Reserved: [u64, ..2], | |
Index: c_ulong, | |
Size: c_ulong, | |
ModBase: u64, | |
Flags: c_ulong, | |
Value: u64, | |
Address: u64, | |
Register: c_ulong, | |
Scope: c_ulong, | |
Tag: c_ulong, | |
NameLen: c_ulong, | |
MaxNameLen: c_ulong, | |
Name: [wchar_t, ..256], | |
} | |
#[link(name="dbghelp")] | |
extern "system" { | |
fn SymFromAddrW( | |
hProcess: HANDLE, Address: u64, Displacement: *mut u64, Symbol: *mut SYMBOL_INFO | |
) -> BOOL; | |
fn SymInitializeW(hProcess: HANDLE, UserSearchPath: *wchar_t, fInvadeProcess: BOOL) -> BOOL; | |
} | |
let mut trace_buf: ~[*mut c_void] = vec::from_elem(n_frames, ptr::mut_null()); | |
let ret = trace_buf.as_mut_buf(|buf, size| { | |
unsafe { | |
RtlCaptureStackBackTrace(0, size as c_ulong, buf, ptr::mut_null()) | |
} | |
}); | |
trace_buf.truncate(ret as uint); | |
let handle = unsafe { GetCurrentProcess() }; | |
let init_res = unsafe { | |
SymInitializeW(handle, ptr::null(), 1) | |
}; | |
let mut res = ~[]; | |
for &frame in trace_buf.iter() { | |
let mut symbol_info = SYMBOL_INFO { | |
SizeOfStruct: 88, | |
TypeIndex: 0, | |
Reserved: [0, 0], | |
Index: 0, | |
Size: 0, | |
ModBase: 0, | |
Flags: 0, | |
Value: 0, | |
Address: 0, | |
Register: 0, | |
Scope: 0, | |
Tag: 0, | |
NameLen: 0, | |
MaxNameLen: 255, | |
Name: [0, ..256], | |
}; | |
let addr_res = unsafe { | |
SymFromAddrW(handle, frame as u64, ptr::mut_null(), &mut symbol_info) | |
}; | |
//if addr_res == 0 { | |
// let err = unsafe { GetLastError() }; | |
// println!("err: {:?}", err); | |
//} | |
let name = std::str::from_utf16(symbol_info.Name); | |
res.push(name); | |
} | |
res | |
} | |
fn print_trace(n: uint) { | |
println!("---- trace: ----"); | |
let trac = trace(n); | |
for sym in trac.iter() { | |
println!("* {:s}", sym.as_slice()); | |
} | |
} | |
fn main() { | |
f(); | |
} | |
fn f() { | |
g(); | |
} | |
fn g() { | |
print_trace(20); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
(NOTE: windows part requires mingw-w64 since mingw doesn't export some winapi functions we need..)