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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use ffi;
use libc;
use std::ffi::CString;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;
use libdw;
use libdw::Dwarf;
use super::Result;
const STANDARD_CALLBACKS: &'static ffi::Dwfl_Callbacks = &ffi::Dwfl_Callbacks {
find_elf: Some(ffi::dwfl_build_id_find_elf),
find_debuginfo: Some(ffi::dwfl_standard_find_debuginfo),
section_address: Some(ffi::dwfl_offline_section_address),
debuginfo_path: 0 as *mut _,
};
pub struct Dwfl {
inner: *mut ffi::Dwfl,
}
impl Dwfl {
#[inline]
fn new(dwfl: *mut ffi::Dwfl) -> Self {
Dwfl {
inner: dwfl,
}
}
pub fn open<P: AsRef<Path>>(path: P) -> Result<Dwfl> {
let name = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap();
let dwfl = Dwfl::new(ffi!(dwfl_begin(STANDARD_CALLBACKS))?);
ffi!(dwfl_report_offline(dwfl.as_ptr(), name.as_ptr(), name.as_ptr(), -1))?;
ffi!(dwfl_report_end(dwfl.as_ptr(), None, ptr::null_mut()))?;
Ok(dwfl)
}
#[inline]
pub fn dwarfs(&self) -> Dwarfs {
Dwarfs {
dwfl: self,
offset: 0,
}
}
unsafe fn getdwarf<'dwfl, F>(&'dwfl self, offset: isize, mut f: F) -> Result<isize>
where F: FnMut(Dwarf<'dwfl>) -> libc::c_uint
{
let argp = &mut f as *mut F as *mut libc::c_void;
return ffi!(dwfl_getdwarf(self.as_ptr(), Some(callback::<'dwfl, F>), argp, offset));
unsafe extern "C" fn callback<'dwfl, F>(_module: *mut ffi::Dwfl_Module,
_userdata: *mut *mut libc::c_void,
_name: *const libc::c_char,
_start: u64,
dwarf: *mut ffi::Dwarf,
_bias: u64,
argp: *mut libc::c_void)
-> libc::c_int
where F: FnMut(Dwarf<'dwfl>) -> libc::c_uint
{
let f = &mut *(argp as *mut F);
f(Dwarf::from_raw(dwarf)) as libc::c_int
}
}
#[inline]
pub fn as_ptr(&self) -> *mut ffi::Dwfl {
self.inner
}
}
impl Drop for Dwfl {
#[inline]
fn drop(&mut self) {
raw_ffi!(dwfl_end(self.as_ptr()));
}
}
pub struct Dwarfs<'dwfl> {
dwfl: &'dwfl Dwfl,
offset: isize,
}
impl<'dwfl> Iterator for Dwarfs<'dwfl> {
type Item = Result<Dwarf<'dwfl>>;
fn next(&mut self) -> Option<Self::Item> {
let mut dwarf = None;
let rc = unsafe {
self.dwfl.getdwarf(self.offset, |dw| {
dwarf = Some(dw);
libdw::raw::DWARF_CB_ABORT
})
};
match rc {
Ok(offset) => { self.offset = offset; dwarf.map(Ok) },
Err(e) => Some(Err(e)),
}
}
}