Support declaring anonymous functions and data objects
This commit is contained in:
@@ -180,6 +180,53 @@ impl JITModule {
|
||||
.or_else(|| lookup_with_dlsym(name))
|
||||
}
|
||||
|
||||
fn new_func_plt_entry(&mut self, id: FuncId, val: *const u8) {
|
||||
let got_entry = self
|
||||
.memory
|
||||
.writable
|
||||
.allocate(
|
||||
std::mem::size_of::<*const u8>(),
|
||||
std::mem::align_of::<*const u8>().try_into().unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.cast::<*const u8>();
|
||||
self.function_got_entries[id] = Some(NonNull::new(got_entry).unwrap());
|
||||
unsafe {
|
||||
std::ptr::write(got_entry, val);
|
||||
}
|
||||
let plt_entry = self
|
||||
.memory
|
||||
.code
|
||||
.allocate(std::mem::size_of::<[u8; 16]>(), EXECUTABLE_DATA_ALIGNMENT)
|
||||
.unwrap()
|
||||
.cast::<[u8; 16]>();
|
||||
self.record_function_for_perf(
|
||||
plt_entry as *mut _,
|
||||
std::mem::size_of::<[u8; 16]>(),
|
||||
&format!("{}@plt", self.declarations.get_function_decl(id).name),
|
||||
);
|
||||
self.function_plt_entries[id] = Some(NonNull::new(plt_entry).unwrap());
|
||||
unsafe {
|
||||
Self::write_plt_entry_bytes(plt_entry, got_entry);
|
||||
}
|
||||
}
|
||||
|
||||
fn new_data_got_entry(&mut self, id: DataId, val: *const u8) {
|
||||
let got_entry = self
|
||||
.memory
|
||||
.writable
|
||||
.allocate(
|
||||
std::mem::size_of::<*const u8>(),
|
||||
std::mem::align_of::<*const u8>().try_into().unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.cast::<*const u8>();
|
||||
self.data_object_got_entries[id] = Some(NonNull::new(got_entry).unwrap());
|
||||
unsafe {
|
||||
std::ptr::write(got_entry, val);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn write_plt_entry_bytes(plt_ptr: *mut [u8; 16], got_ptr: *mut *const u8) {
|
||||
assert!(
|
||||
cfg!(target_arch = "x86_64"),
|
||||
@@ -488,40 +535,25 @@ impl Module for JITModule {
|
||||
linkage: Linkage,
|
||||
signature: &ir::Signature,
|
||||
) -> ModuleResult<FuncId> {
|
||||
let (id, _decl) = self
|
||||
let (id, linkage) = self
|
||||
.declarations
|
||||
.declare_function(name, linkage, signature)?;
|
||||
if self.function_got_entries[id].is_none() && self.isa.flags().is_pic() {
|
||||
let got_entry = self
|
||||
.memory
|
||||
.writable
|
||||
.allocate(
|
||||
std::mem::size_of::<*const u8>(),
|
||||
std::mem::align_of::<*const u8>().try_into().unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.cast::<*const u8>();
|
||||
self.function_got_entries[id] = Some(NonNull::new(got_entry).unwrap());
|
||||
// FIXME populate got entries with a null pointer when defined
|
||||
let val = self.lookup_symbol(name).unwrap_or(std::ptr::null());
|
||||
unsafe {
|
||||
std::ptr::write(got_entry, val);
|
||||
}
|
||||
let plt_entry = self
|
||||
.memory
|
||||
.code
|
||||
.allocate(std::mem::size_of::<[u8; 16]>(), EXECUTABLE_DATA_ALIGNMENT)
|
||||
.unwrap()
|
||||
.cast::<[u8; 16]>();
|
||||
self.record_function_for_perf(
|
||||
plt_entry as *mut _,
|
||||
std::mem::size_of::<[u8; 16]>(),
|
||||
&format!("{}@plt", name),
|
||||
);
|
||||
self.function_plt_entries[id] = Some(NonNull::new(plt_entry).unwrap());
|
||||
unsafe {
|
||||
Self::write_plt_entry_bytes(plt_entry, got_entry);
|
||||
}
|
||||
let val = if linkage == Linkage::Import {
|
||||
self.lookup_symbol(name).unwrap_or(std::ptr::null())
|
||||
} else {
|
||||
std::ptr::null()
|
||||
};
|
||||
self.new_func_plt_entry(id, val);
|
||||
}
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
|
||||
let id = self.declarations.declare_anonymous_function(signature)?;
|
||||
if self.isa.flags().is_pic() {
|
||||
self.new_func_plt_entry(id, std::ptr::null());
|
||||
}
|
||||
Ok(id)
|
||||
}
|
||||
@@ -534,25 +566,26 @@ impl Module for JITModule {
|
||||
tls: bool,
|
||||
) -> ModuleResult<DataId> {
|
||||
assert!(!tls, "JIT doesn't yet support TLS");
|
||||
let (id, _decl) = self
|
||||
let (id, linkage) = self
|
||||
.declarations
|
||||
.declare_data(name, linkage, writable, tls)?;
|
||||
if self.data_object_got_entries[id].is_none() && self.isa.flags().is_pic() {
|
||||
let got_entry = self
|
||||
.memory
|
||||
.writable
|
||||
.allocate(
|
||||
std::mem::size_of::<*const u8>(),
|
||||
std::mem::align_of::<*const u8>().try_into().unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
.cast::<*const u8>();
|
||||
self.data_object_got_entries[id] = Some(NonNull::new(got_entry).unwrap());
|
||||
// FIXME populate got entries with a null pointer when defined
|
||||
let val = self.lookup_symbol(name).unwrap_or(std::ptr::null());
|
||||
unsafe {
|
||||
std::ptr::write(got_entry, val);
|
||||
}
|
||||
let val = if linkage == Linkage::Import {
|
||||
self.lookup_symbol(name).unwrap_or(std::ptr::null())
|
||||
} else {
|
||||
std::ptr::null()
|
||||
};
|
||||
self.new_data_got_entry(id, val);
|
||||
}
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
|
||||
assert!(!tls, "JIT doesn't yet support TLS");
|
||||
let id = self.declarations.declare_anonymous_data(writable, tls)?;
|
||||
if self.isa.flags().is_pic() {
|
||||
self.new_data_got_entry(id, std::ptr::null());
|
||||
}
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user