il2cpp_bridge_rs/memory/info/
symbol.rs1use dashmap::DashMap;
4use once_cell::sync::Lazy;
5use thiserror::Error;
6
7#[derive(Error, Debug)]
8pub enum SymbolError {
10 #[error("Symbol not found: {0}")]
12 NotFound(String),
13 #[error("CString error")]
15 StringError,
16}
17
18static CACHE: Lazy<DashMap<String, usize>> = Lazy::new(DashMap::new);
19
20pub fn resolve_symbol(symbol: &str) -> Result<usize, SymbolError> {
28 if let Some(entry) = CACHE.get(symbol) {
29 return Ok(*entry);
30 }
31
32 let addr = platform::raw_resolve(symbol)?;
33 CACHE.insert(symbol.into(), addr);
34 Ok(addr)
35}
36
37pub fn cache_symbol(s: &str, a: usize) {
45 CACHE.insert(s.into(), a);
46}
47
48pub fn clear_cache() {
50 CACHE.clear();
51}
52
53pub fn promote_library_to_global(library_name: &str) {
64 platform::ensure_global_visibility(library_name);
65}
66
67#[cfg(any(target_os = "macos", target_os = "ios"))]
69mod platform {
70 use super::SymbolError;
71 use std::ffi::CString;
72
73 pub fn raw_resolve(symbol: &str) -> Result<usize, SymbolError> {
74 let c_str = CString::new(symbol).map_err(|_| SymbolError::StringError)?;
75 unsafe {
76 let addr_ptr = libc::dlsym(libc::RTLD_DEFAULT, c_str.as_ptr());
77 if addr_ptr.is_null() {
78 Err(SymbolError::NotFound(symbol.into()))
79 } else {
80 Ok(addr_ptr as usize)
81 }
82 }
83 }
84
85 pub fn ensure_global_visibility(_library_name: &str) {}
86}
87
88#[cfg(any(target_os = "linux", target_os = "android"))]
90mod platform {
91 use super::SymbolError;
92 use std::ffi::{CStr, CString};
93 use std::sync::Once;
94
95 static PROMOTE_ONCE: Once = Once::new();
96
97 pub fn ensure_global_visibility(library_name: &str) {
104 PROMOTE_ONCE.call_once(|| {
105 let path = match crate::memory::image::get_image_path(library_name) {
106 Some(p) => p,
107 None => {
108 crate::logger::warning(&format!(
109 "Could not find loaded library matching '{}'; symbol promotion skipped",
110 library_name
111 ));
112 return;
113 }
114 };
115
116 let c_path = match CString::new(path.as_str()) {
117 Ok(c) => c,
118 Err(_) => return,
119 };
120
121 unsafe {
122 let handle = libc::dlopen(
123 c_path.as_ptr(),
124 libc::RTLD_NOW | libc::RTLD_GLOBAL | libc::RTLD_NOLOAD,
125 );
126 if handle.is_null() {
127 let err = libc::dlerror();
128 let msg = if err.is_null() {
129 "unknown error".to_string()
130 } else {
131 CStr::from_ptr(err).to_string_lossy().into_owned()
132 };
133 crate::logger::warning(&format!(
134 "dlopen promotion failed for '{}': {}",
135 path, msg
136 ));
137 } else {
138 crate::logger::info(&format!(
139 "Promoted '{}' symbols to global visibility",
140 path
141 ));
142 }
143 }
144 });
145 }
146
147 pub fn raw_resolve(symbol: &str) -> Result<usize, SymbolError> {
148 let c_str = CString::new(symbol).map_err(|_| SymbolError::StringError)?;
149 unsafe {
150 let addr_ptr = libc::dlsym(libc::RTLD_DEFAULT, c_str.as_ptr());
151 if addr_ptr.is_null() {
152 Err(SymbolError::NotFound(symbol.into()))
153 } else {
154 Ok(addr_ptr as usize)
155 }
156 }
157 }
158}
159
160#[cfg(target_os = "windows")]
162mod platform {
163 use super::SymbolError;
164 use std::ffi::CString;
165 use windows_sys::Win32::System::LibraryLoader::{GetModuleHandleA, GetProcAddress};
166
167 pub fn raw_resolve(symbol: &str) -> Result<usize, SymbolError> {
168 let c_str = CString::new(symbol).map_err(|_| SymbolError::StringError)?;
169 unsafe {
170 let handle = GetModuleHandleA(std::ptr::null());
172 if handle == 0 {
173 return Err(SymbolError::NotFound(symbol.into()));
174 }
175 let addr = GetProcAddress(handle, c_str.as_ptr() as *const u8);
176 match addr {
177 Some(f) => Ok(f as usize),
178 None => Err(SymbolError::NotFound(symbol.into())),
179 }
180 }
181 }
182
183 pub fn ensure_global_visibility(_library_name: &str) {}
184}
185
186#[cfg(not(any(
188 target_os = "macos",
189 target_os = "ios",
190 target_os = "linux",
191 target_os = "android",
192 target_os = "windows",
193)))]
194mod platform {
195 use super::SymbolError;
196
197 pub fn raw_resolve(symbol: &str) -> Result<usize, SymbolError> {
198 Err(SymbolError::NotFound(format!(
199 "{} (unsupported platform)",
200 symbol
201 )))
202 }
203
204 pub fn ensure_global_visibility(_library_name: &str) {}
205}