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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::fmt;
use std::borrow::Cow;
use std::ffi::CStr;
use std::ops::Deref;
use std::os::raw::{c_char, c_int, c_void};
use std::path::Path;
use errors::Result;
use errors::ErrorKind::ResolverError;
use processor::StackFrame;
use utils;
extern "C" {
fn stack_frame_function_name(frame: *const StackFrame) -> *const c_char;
fn stack_frame_source_file_name(frame: *const StackFrame) -> *const c_char;
fn stack_frame_source_line(frame: *const StackFrame) -> c_int;
fn stack_frame_delete(frame: *mut StackFrame);
fn resolver_new(buffer: *const c_char, buffer_size: usize) -> *mut IResolver;
fn resolver_delete(resolver: *mut IResolver);
fn resolver_is_corrupt(resolver: *const IResolver) -> bool;
fn resolver_resolve_frame(
resolver: *const IResolver,
frame: *const StackFrame,
) -> *mut StackFrame;
}
pub struct ResolvedStackFrame {
internal: *mut StackFrame,
}
impl ResolvedStackFrame {
pub(crate) fn from_ptr(internal: *mut StackFrame) -> ResolvedStackFrame {
ResolvedStackFrame { internal }
}
pub fn function_name(&self) -> Cow<str> {
unsafe {
let ptr = stack_frame_function_name(self.internal);
CStr::from_ptr(ptr).to_string_lossy()
}
}
pub fn source_file_name(&self) -> Cow<str> {
unsafe {
let ptr = stack_frame_source_file_name(self.internal);
CStr::from_ptr(ptr).to_string_lossy()
}
}
pub fn source_line(&self) -> c_int {
unsafe { stack_frame_source_line(self.internal) }
}
}
impl Deref for ResolvedStackFrame {
type Target = StackFrame;
fn deref(&self) -> &StackFrame {
unsafe { &*self.internal }
}
}
impl Drop for ResolvedStackFrame {
fn drop(&mut self) {
unsafe { stack_frame_delete(self.internal) };
}
}
impl fmt::Debug for ResolvedStackFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ResolvedStackFrame")
.field("instruction", &self.instruction())
.field("function_name", &self.function_name())
.field("source_file_name", &self.source_file_name())
.field("source_line", &self.source_line())
.field("trust", &self.trust())
.field("module", &self.module())
.finish()
}
}
type IResolver = c_void;
pub struct Resolver {
internal: *mut IResolver,
}
impl Resolver {
pub fn from_file<P: AsRef<Path>>(file_path: P) -> Result<Resolver> {
let buffer = utils::read_buffer(file_path)?;
Self::from_buffer(buffer.as_slice())
}
pub fn from_buffer(buffer: &[u8]) -> Result<Resolver> {
let internal = unsafe { resolver_new(buffer.as_ptr() as *const c_char, buffer.len()) };
if internal.is_null() {
Err(ResolverError("Could not load symbols".into()).into())
} else {
Ok(Resolver { internal })
}
}
pub fn corrupt(&self) -> bool {
unsafe { resolver_is_corrupt(self.internal) }
}
pub fn resolve_frame(&self, frame: &StackFrame) -> ResolvedStackFrame {
let ptr = unsafe { resolver_resolve_frame(self.internal, frame) };
ResolvedStackFrame::from_ptr(ptr)
}
}
impl Drop for Resolver {
fn drop(&mut self) {
unsafe { resolver_delete(self.internal) };
}
}