use std::sync::Mutex;
use std::sync::OnceLock;
struct EnclaveBaseAddress {
baseaddress: u64,
size: u64,
}
#[derive(Default)]
struct EnclaveRegistry {
enclaves: Vec<EnclaveBaseAddress>,
}
fn enclave_registry_mutex() -> &'static Mutex<EnclaveRegistry> {
static BASEADDRESS_MUTEX: OnceLock<Mutex<EnclaveRegistry>> = OnceLock::new();
BASEADDRESS_MUTEX.get_or_init(|| Mutex::new(EnclaveRegistry::default()))
}
pub fn register_new_enclave(baseaddress: u64, size: u64) {
enclave_registry_mutex()
.lock()
.expect("Failed to obtain enclave registry mutex for new enclave")
.enclaves
.push(EnclaveBaseAddress { baseaddress, size });
assert_eq!(
ftxsgx_get_baseaddress_from_pointer(baseaddress),
baseaddress
);
}
pub fn unregister_terminated_enclave(baseaddress: u64) {
enclave_registry_mutex()
.lock()
.expect("Failed to obtain an enclave registry mutex for termination")
.enclaves
.retain(|e| e.baseaddress != baseaddress)
}
#[no_mangle]
#[inline(never)]
pub extern "C" fn ftxsgx_get_baseaddress_from_pointer(gdb_pointer: u64) -> u64 {
let registry = enclave_registry_mutex()
.lock()
.expect("Failed to obtain enclave registry mutex for calculating the baseaddress");
let found = registry
.enclaves
.iter()
.find(|e| e.baseaddress <= gdb_pointer && gdb_pointer < e.baseaddress + e.size);
found.map(|enclave| enclave.baseaddress).unwrap_or(0)
}