1use crate::ffi::{bool_, dr_emit_flags_t, instr_t, instrlist_t};
8use crate::utils;
9use crate::{MOD_BASE_ADDR, MOD_SIZE, ffi};
10use std::os::raw::c_void;
11
12#[derive(Debug, Clone)]
13pub struct RawCallStack {
14 pub stack: Vec<Option<usize>>,
16}
17
18impl RawCallStack {
19 pub fn new() -> Self {
20 Self {
21 stack: Vec::with_capacity(128),
22 }
23 }
24 pub fn push(&mut self, addr: Option<usize>) {
25 self.stack.push(addr);
26 }
27 pub fn pop(&mut self) {
28 self.stack.pop();
29 }
30}
31
32pub fn stack_frames(drcontext: *mut ::std::os::raw::c_void) -> Option<Vec<Option<usize>>> {
37 use crate::drcore::log;
38 log(&format!("[stack frames inside] in1"));
39 unsafe {
40 let stack_ptr = ffi::drmgr_get_tls_field(drcontext, crate::tls_idx) as *mut RawCallStack;
41 if stack_ptr.is_null() {
42 return None;
43 }
44 Some((*stack_ptr).stack.clone())
45 }
46}
47
48pub fn module_bounds() -> (usize, usize) {
50 let base = *MOD_BASE_ADDR
51 .lock()
52 .expect("Failed to lock MOD_BASE_ADDR")
53 .as_ref()
54 .expect("Module base should always be known");
55 let size = *MOD_SIZE
56 .lock()
57 .expect("Failed to lock MOD_SIZE")
58 .as_ref()
59 .expect("Module size should always be known");
60 (base, size)
61}
62
63fn in_target_module(addr: usize) -> bool {
64 let (base, size) = module_bounds();
65 addr >= base && addr < base + size
66}
67
68#[unsafe(no_mangle)]
69pub unsafe extern "C" fn instruction_event(
70 drcontext: *mut ::std::os::raw::c_void,
71 _tag: *mut ::std::os::raw::c_void,
72 bb: *mut instrlist_t,
73 instr: *mut instr_t,
74 _for_trace: bool_,
75 _translating: bool_,
76 _user_data: *mut ::std::os::raw::c_void,
77) -> dr_emit_flags_t {
78 unsafe {
79 if ffi::instr_is_call_direct(instr) != 0 {
80 let instr_addr = ffi::instr_get_app_pc(instr);
81 let target_addr = ffi::instr_get_branch_target_pc(instr);
82 let target_addr_as_opnd = utils::opnd_create_uintptr(target_addr as usize);
83 let instr_addr_as_opnd = utils::opnd_create_uintptr(instr_addr as usize);
84 ffi::dr_insert_clean_call(
85 drcontext,
86 bb,
87 instr,
88 on_direct_call as *mut c_void,
89 false as bool_,
90 2,
91 instr_addr_as_opnd,
92 target_addr_as_opnd,
93 );
94 } else if ffi::instr_is_call_indirect(instr) != 0 {
95 ffi::dr_insert_mbr_instrumentation(
96 drcontext,
97 bb,
98 instr,
99 on_indirect_call as *mut c_void,
100 ffi::dr_spill_slot_t_SPILL_SLOT_1,
101 );
102 }
103
104 if ffi::instr_is_return(instr) != 0 {
105 ffi::dr_insert_mbr_instrumentation(
107 drcontext,
108 bb,
109 instr,
110 on_return as *mut c_void,
111 ffi::dr_spill_slot_t_SPILL_SLOT_1,
112 );
113 }
114 }
115
116 ffi::dr_emit_flags_t_DR_EMIT_DEFAULT
117}
118
119#[cfg(all(target_pointer_width = "32"))]
121extern "cdecl" fn on_direct_call(instr_addr: *mut c_void, target_addr: *mut c_void) {
122 on_direct_call_logic(instr_addr, target_addr)
123}
124
125#[cfg(not(all(target_pointer_width = "32")))]
127extern "C" fn on_direct_call(instr_addr: *mut c_void, target_addr: *mut c_void) {
128 on_direct_call_logic(instr_addr, target_addr)
129}
130
131fn on_direct_call_logic(instr_addr: *mut c_void, target_addr: *mut c_void) {
132 if instr_addr.is_null() | !in_target_module(instr_addr as usize) {
134 return;
135 }
136
137 let addr = if target_addr.is_null() {
138 None
139 } else {
140 Some(target_addr as usize)
141 };
142
143 unsafe {
144 let drcontext = ffi::dr_get_current_drcontext();
145 let tls = ffi::drmgr_get_tls_field(drcontext, crate::tls_idx) as *mut RawCallStack;
146 if !tls.is_null() {
147 (*tls).push(addr);
149 }
150 }
151}
152
153#[cfg(all(target_pointer_width = "32"))]
155extern "cdecl" fn on_indirect_call(branch_instr_addr: *const u8, target_addr: *const u8) {
156 on_indirect_call_logic(branch_instr_addr, target_addr)
157}
158
159#[cfg(not(all(target_pointer_width = "32")))]
161extern "C" fn on_indirect_call(branch_instr_addr: *const u8, target_addr: *const u8) {
162 on_indirect_call_logic(branch_instr_addr, target_addr)
163}
164
165fn on_indirect_call_logic(branch_instr_addr: *const u8, target_addr: *const u8) {
166 unsafe {
167 if !in_target_module(branch_instr_addr as usize) {
168 return;
169 }
170 let drcontext = ffi::dr_get_current_drcontext();
171 let tls = ffi::drmgr_get_tls_field(drcontext, crate::tls_idx) as *mut RawCallStack;
172 if !tls.is_null() {
173 (*tls).push(Some(target_addr as usize));
174 }
175 }
176}
177
178#[cfg(all(target_pointer_width = "32"))]
180extern "cdecl" fn on_return(branch_instr_addr: *const u8, target_addr: *const u8) {
181 on_return_logic(branch_instr_addr, target_addr)
182}
183
184#[cfg(not(all(target_pointer_width = "32")))]
186extern "C" fn on_return(branch_instr_addr: *const u8, target_addr: *const u8) {
187 on_return_logic(branch_instr_addr, target_addr)
188}
189
190fn on_return_logic(_branch_instr_addr: *const u8, target_addr: *const u8) {
191 if !in_target_module(target_addr as usize) {
192 return;
193 }
194 unsafe {
195 let drcontext = ffi::dr_get_current_drcontext();
196 let tls = ffi::drmgr_get_tls_field(drcontext, crate::tls_idx) as *mut RawCallStack;
197 if !tls.is_null() {
198 (*tls).pop();
199 }
200 }
201}