1use navigator::cli::LibinjectArgs;
2
3use crate::ffi::{self, _module_handle_t, app_pc, generic_func_t, module_data_t};
4use crate::utils::{Boolean, ReadError, Utf8NameError, WriteError};
5use std::ffi::{CStr, CString};
6use std::os::raw::c_void;
7
8const MAX_LOG_LEN: usize = 2500;
9
10impl Boolean for ffi::bool_ {
11 fn as_bool(self: Self) -> bool {
12 self != 0
13 }
14}
15
16pub fn log(s: &str) {
19 if s.len() <= MAX_LOG_LEN {
20 return log_helper(s, true);
21 }
22 log_helper(&s[..MAX_LOG_LEN], false);
23 log(&s[MAX_LOG_LEN..]);
24}
25
26fn log_helper(s: &str, newline: bool) {
27 let mut to_log = s.to_owned();
28 if newline {
29 to_log.push_str("\n");
30 }
31 unsafe {
32 let stderr = ffi::dr_get_stderr_file();
33 ffi::dr_fprintf(stderr, CString::new(to_log).unwrap().as_ptr());
34 }
35}
36
37pub fn safe_read(ptr: *mut c_void, size: usize) -> Result<Vec<u8>, ReadError> {
39 let mut buf = vec![0u8; size];
40 let mut bytes_read: usize = 0;
41 unsafe {
42 let success =
43 ffi::dr_safe_read(ptr, size, buf.as_mut_ptr() as *mut c_void, &mut bytes_read)
44 .as_bool();
45 if success {
46 Ok(buf)
47 } else {
48 Err(ReadError {
49 n_bytes_tried: size,
50 n_bytes_read: bytes_read,
51 buf,
52 })
53 }
54 }
55}
56
57pub fn safe_write(target_ptr: *mut c_void, mut to_write: Vec<u8>) -> Result<(), WriteError> {
59 let mut bytes_written: usize = 0;
60 unsafe {
61 let success = ffi::dr_safe_write(
62 target_ptr,
63 to_write.len(),
64 to_write.as_mut_ptr() as *mut c_void,
65 &mut bytes_written,
66 )
67 .as_bool();
68 if success {
69 Ok(())
70 } else {
71 Err(WriteError {
72 n_bytes_tried: to_write.len(),
73 data_tried: to_write,
74 n_bytes_written: bytes_written,
75 })
76 }
77 }
78}
79
80pub fn utf8_name_of_module(m: module_data_t) -> Result<String, Utf8NameError> {
82 unsafe {
83 let mod_name_ptr = ffi::dr_module_preferred_name(&m);
84 if mod_name_ptr.is_null() {
85 return Err(Utf8NameError::NullPtr);
86 } else {
87 let cstr_mod_name = CStr::from_ptr(mod_name_ptr);
88 match cstr_mod_name.to_str() {
89 Ok(v) => Ok(v.to_string()),
90 Err(_) => Err(Utf8NameError::Malformed(
91 cstr_mod_name.to_string_lossy().to_string(),
92 )),
93 }
94 }
95 }
96}
97
98pub unsafe fn get_proc_address(base_addr: app_pc, name: &str) -> generic_func_t {
99 unsafe {
100 ffi::dr_get_proc_address(
101 base_addr as *mut _module_handle_t,
102 CString::new(name).unwrap().as_ptr(),
103 )
104 }
105}
106
107pub unsafe fn app_pc_is_in_target_module(app_pc: *const u8, cli_args: LibinjectArgs) -> bool {
108 unsafe {
109 let module_ptr = ffi::dr_lookup_module(app_pc as *mut u8);
110 if module_ptr.is_null() {
111 return false;
112 }
113
114 let mod_name = match utf8_name_of_module(*module_ptr) {
115 Ok(name) => name,
116 Err(utf8_name_error) => {
117 log(&format!(
118 "failed to read the module name: {:?}",
119 utf8_name_error
120 ));
121 return false;
122 }
123 };
124
125 mod_name.to_lowercase() == cli_args.target_module.to_lowercase()
126 }
127}