Add a way to define a symbol lookup fn for the JIT (#2745)

* Couple of cranelift-jit cleanups

* Add a way to define a symbol lookup fn for the JIT
This commit is contained in:
bjorn3
2022-02-19 17:33:39 +01:00
committed by GitHub
parent 5ff1ddee5b
commit 2ca01ae947

View File

@@ -14,6 +14,7 @@ use cranelift_module::{
ModuleDeclarations, ModuleError, ModuleResult,
};
use log::info;
use std::cell::RefCell;
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::ffi::CString;
@@ -31,6 +32,7 @@ const READONLY_DATA_ALIGNMENT: u64 = 0x1;
pub struct JITBuilder {
isa: Box<dyn TargetIsa>,
symbols: HashMap<String, *const u8>,
lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8>>>,
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
hotswap_enabled: bool,
}
@@ -73,9 +75,11 @@ impl JITBuilder {
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
) -> Self {
let symbols = HashMap::new();
let lookup_symbols = vec![Box::new(lookup_with_dlsym) as Box<_>];
Self {
isa,
symbols,
lookup_symbols,
libcall_names,
hotswap_enabled: false,
}
@@ -95,7 +99,7 @@ impl JITBuilder {
/// back to a platform-specific search (this typically involves searching
/// the current process for public symbols, followed by searching the
/// platform's C runtime).
pub fn symbol<K>(&mut self, name: K, ptr: *const u8) -> &Self
pub fn symbol<K>(&mut self, name: K, ptr: *const u8) -> &mut Self
where
K: Into<String>,
{
@@ -106,7 +110,7 @@ impl JITBuilder {
/// Define multiple symbols in the internal symbol table.
///
/// Using this is equivalent to calling `symbol` on each element.
pub fn symbols<It, K>(&mut self, symbols: It) -> &Self
pub fn symbols<It, K>(&mut self, symbols: It) -> &mut Self
where
It: IntoIterator<Item = (K, *const u8)>,
K: Into<String>,
@@ -117,6 +121,18 @@ impl JITBuilder {
self
}
/// Add a symbol lookup fn.
///
/// Symbol lookup fn's are used to lookup symbols when they couldn't be found in the internal
/// symbol table. Symbol lookup fn's are called in reverse of the order in which they were added.
pub fn symbol_lookup_fn(
&mut self,
symbol_lookup_fn: Box<dyn Fn(&str) -> Option<*const u8>>,
) -> &mut Self {
self.lookup_symbols.push(symbol_lookup_fn);
self
}
/// Enable or disable hotswap support. See [`JITModule::prepare_for_function_redefine`]
/// for more information.
///
@@ -143,7 +159,8 @@ struct GotUpdate {
pub struct JITModule {
isa: Box<dyn TargetIsa>,
hotswap_enabled: bool,
symbols: HashMap<String, *const u8>,
symbols: RefCell<HashMap<String, *const u8>>,
lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8>>>,
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
memory: MemoryHandle,
declarations: ModuleDeclarations,
@@ -184,10 +201,20 @@ impl JITModule {
}
fn lookup_symbol(&self, name: &str) -> Option<*const u8> {
self.symbols
.get(name)
.copied()
.or_else(|| lookup_with_dlsym(name))
match self.symbols.borrow_mut().entry(name.to_owned()) {
std::collections::hash_map::Entry::Occupied(occ) => Some(*occ.get()),
std::collections::hash_map::Entry::Vacant(vac) => {
let ptr = self
.lookup_symbols
.iter()
.rev() // Try last lookup function first
.find_map(|lookup| lookup(name));
if let Some(ptr) = ptr {
vac.insert(ptr);
}
ptr
}
}
}
fn new_got_entry(&mut self, val: *const u8) -> NonNull<AtomicPtr<u8>> {
@@ -277,7 +304,7 @@ impl JITModule {
}
}
};
if let Some(ptr) = self.lookup_symbol(&name) {
if let Some(ptr) = self.lookup_symbol(name) {
ptr
} else if linkage == Linkage::Preemptible {
0 as *const u8
@@ -455,7 +482,8 @@ impl JITModule {
let mut module = Self {
isa: builder.isa,
hotswap_enabled: builder.hotswap_enabled,
symbols: builder.symbols,
symbols: RefCell::new(builder.symbols),
lookup_symbols: builder.lookup_symbols,
libcall_names: builder.libcall_names,
memory: MemoryHandle {
code: Memory::new(),
@@ -483,12 +511,7 @@ impl JITModule {
};
for &libcall in all_libcalls {
let sym = (module.libcall_names)(libcall);
let addr = if let Some(addr) = module
.symbols
.get(&sym)
.copied()
.or_else(|| lookup_with_dlsym(&sym))
{
let addr = if let Some(addr) = module.lookup_symbol(&sym) {
addr
} else {
continue;