-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
82 lines (68 loc) · 2.52 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#![allow(unused_mut)]
extern crate backtrace;
extern crate libc;
use std::{panic, env, ptr};
use std::process::Command;
use libc::{c_void, c_int, c_char};
use backtrace::Backtrace;
fn test() {
panic!("test panic");
}
extern "C" {
fn dlinfo(handle: *mut c_void, request: c_int, info: *mut c_void) -> c_int;
}
const RTLD_DI_LINKMAP: c_int = 2;
#[allow(dead_code)]
struct LinkMap {
addr: isize,
name: *mut c_char,
l_ld: usize,
l_next: *mut LinkMap,
l_prev: *mut LinkMap,
}
fn main() {
println!("Hello, world!");
panic::set_hook(Box::new(|panic_info| {
let payload = panic_info.payload().downcast_ref::<String>().map(|x| &**x)
.or_else(|| panic_info.payload().downcast_ref::<&'static str>().map(|x| *x));
match payload {
Some(s) => println!("panic occurred: {:?}", s),
None => println!("panic occurred with non-string payload"),
}
let bt = Backtrace::new();
if bt.frames().iter().flat_map(|x| x.symbols()).all(|x| x.name().is_none()) {
// no symbols in this binary
// grab base ptr to calculate offsets
let baseptr = unsafe {
let handle = libc::dlopen(ptr::null(), libc::RTLD_LAZY);
let mut ptr: *mut LinkMap = ptr::null_mut();
let ret = dlinfo(handle, RTLD_DI_LINKMAP, (&mut ptr) as *mut _ as *mut c_void);
assert_eq!(ret, 0);
(*ptr).addr
};
let addrs = bt.frames().iter().map(|x| x.ip().wrapping_offset(-baseptr));
// check for symbol file
let exe = env::current_exe().unwrap();
let dbg = exe.with_extension("dbg");
if dbg.exists() {
// grab stacktrace (only calling addr2line here because this is a mockup)
println!("stack backtrace (symbols from symbol file):");
Command::new("/usr/bin/addr2line")
.arg("-Cipf").arg("-e").arg(exe)
.arg("-a").args(addrs.map(|x| format!("{:p}", x)))
.status().unwrap();
} else {
// have no symbol file here - someone else needs to put run addr2line
println!("stack backtrace (no symbols found):");
for frame in addrs {
print!("{:p} ", frame);
}
println!();
}
} else {
// have real backtrace (symbols in this binary)
println!("{:?}", bt);
}
}));
test();
}