1use crate::{compiled_blob::CompiledBlob, memory::BranchProtection, memory::Memory};
4use cranelift_codegen::binemit::Reloc;
5use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
6use cranelift_codegen::settings::Configurable;
7use cranelift_codegen::{ir, settings};
8use cranelift_control::ControlPlane;
9use cranelift_entity::SecondaryMap;
10use cranelift_module::{
11 DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleDeclarations, ModuleError,
12 ModuleReloc, ModuleRelocTarget, ModuleResult,
13};
14use log::info;
15use std::cell::RefCell;
16use std::collections::HashMap;
17use std::ffi::CString;
18use std::io::Write;
19use std::ptr;
20use std::ptr::NonNull;
21use std::sync::atomic::{AtomicPtr, Ordering};
22use target_lexicon::PointerWidth;
23
24const WRITABLE_DATA_ALIGNMENT: u64 = 0x8;
25const READONLY_DATA_ALIGNMENT: u64 = 0x1;
26
27pub struct JITBuilder {
29 isa: OwnedTargetIsa,
30 symbols: HashMap<String, SendWrapper<*const u8>>,
31 lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8> + Send>>,
32 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
33}
34
35impl JITBuilder {
36 pub fn new(
43 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
44 ) -> ModuleResult<Self> {
45 Self::with_flags(&[], libcall_names)
46 }
47
48 pub fn with_flags(
55 flags: &[(&str, &str)],
56 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
57 ) -> ModuleResult<Self> {
58 let mut flag_builder = settings::builder();
59 for (name, value) in flags {
60 flag_builder.set(name, value)?;
61 }
62
63 flag_builder.set("use_colocated_libcalls", "false").unwrap();
67 flag_builder.set("is_pic", "true").unwrap();
68 let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
69 panic!("host machine is not supported: {msg}");
70 });
71 let isa = isa_builder.finish(settings::Flags::new(flag_builder))?;
72 Ok(Self::with_isa(isa, libcall_names))
73 }
74
75 pub fn with_isa(
86 isa: OwnedTargetIsa,
87 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
88 ) -> Self {
89 let symbols = HashMap::new();
90 let lookup_symbols = vec![Box::new(lookup_with_dlsym) as Box<_>];
91 Self {
92 isa,
93 symbols,
94 lookup_symbols,
95 libcall_names,
96 }
97 }
98
99 pub fn symbol<K>(&mut self, name: K, ptr: *const u8) -> &mut Self
114 where
115 K: Into<String>,
116 {
117 self.symbols.insert(name.into(), SendWrapper(ptr));
118 self
119 }
120
121 pub fn symbols<It, K>(&mut self, symbols: It) -> &mut Self
125 where
126 It: IntoIterator<Item = (K, *const u8)>,
127 K: Into<String>,
128 {
129 for (name, ptr) in symbols {
130 self.symbols.insert(name.into(), SendWrapper(ptr));
131 }
132 self
133 }
134
135 pub fn symbol_lookup_fn(
140 &mut self,
141 symbol_lookup_fn: Box<dyn Fn(&str) -> Option<*const u8> + Send>,
142 ) -> &mut Self {
143 self.lookup_symbols.push(symbol_lookup_fn);
144 self
145 }
146}
147
148struct GotUpdate {
150 entry: NonNull<AtomicPtr<u8>>,
152
153 ptr: *const u8,
155}
156
157unsafe impl Send for GotUpdate {}
158
159#[derive(Copy, Clone)]
163struct SendWrapper<T>(T);
164unsafe impl<T> Send for SendWrapper<T> {}
165
166pub struct JITModule {
171 isa: OwnedTargetIsa,
172 symbols: RefCell<HashMap<String, SendWrapper<*const u8>>>,
173 lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8> + Send>>,
174 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
175 memory: MemoryHandle,
176 declarations: ModuleDeclarations,
177 function_got_entries: SecondaryMap<FuncId, Option<SendWrapper<NonNull<AtomicPtr<u8>>>>>,
178 function_plt_entries: SecondaryMap<FuncId, Option<SendWrapper<NonNull<[u8; 16]>>>>,
179 data_object_got_entries: SecondaryMap<DataId, Option<SendWrapper<NonNull<AtomicPtr<u8>>>>>,
180 libcall_got_entries: HashMap<ir::LibCall, SendWrapper<NonNull<AtomicPtr<u8>>>>,
181 libcall_plt_entries: HashMap<ir::LibCall, SendWrapper<NonNull<[u8; 16]>>>,
182 compiled_functions: SecondaryMap<FuncId, Option<CompiledBlob>>,
183 compiled_data_objects: SecondaryMap<DataId, Option<CompiledBlob>>,
184 functions_to_finalize: Vec<FuncId>,
185 data_objects_to_finalize: Vec<DataId>,
186
187 pending_got_updates: Vec<GotUpdate>,
189}
190
191struct MemoryHandle {
193 code: Memory,
194 readonly: Memory,
195 writable: Memory,
196}
197
198impl JITModule {
199 pub unsafe fn free_memory(mut self) {
208 self.memory.code.free_memory();
209 self.memory.readonly.free_memory();
210 self.memory.writable.free_memory();
211 }
212
213 fn lookup_symbol(&self, name: &str) -> Option<*const u8> {
214 match self.symbols.borrow_mut().entry(name.to_owned()) {
215 std::collections::hash_map::Entry::Occupied(occ) => Some(occ.get().0),
216 std::collections::hash_map::Entry::Vacant(vac) => {
217 let ptr = self
218 .lookup_symbols
219 .iter()
220 .rev() .find_map(|lookup| lookup(name));
222 if let Some(ptr) = ptr {
223 vac.insert(SendWrapper(ptr));
224 }
225 ptr
226 }
227 }
228 }
229
230 fn new_got_entry(&mut self, val: *const u8) -> NonNull<AtomicPtr<u8>> {
231 let got_entry = self
232 .memory
233 .writable
234 .allocate(
235 std::mem::size_of::<AtomicPtr<u8>>(),
236 std::mem::align_of::<AtomicPtr<u8>>().try_into().unwrap(),
237 )
238 .unwrap()
239 .cast::<AtomicPtr<u8>>();
240 unsafe {
241 std::ptr::write(got_entry, AtomicPtr::new(val as *mut _));
242 }
243 NonNull::new(got_entry).unwrap()
244 }
245
246 fn new_plt_entry(&mut self, got_entry: NonNull<AtomicPtr<u8>>) -> NonNull<[u8; 16]> {
247 let plt_entry = self
248 .memory
249 .code
250 .allocate(
251 std::mem::size_of::<[u8; 16]>(),
252 self.isa
253 .symbol_alignment()
254 .max(self.isa.function_alignment().minimum as u64),
255 )
256 .unwrap()
257 .cast::<[u8; 16]>();
258 unsafe {
259 Self::write_plt_entry_bytes(plt_entry, got_entry);
260 }
261 NonNull::new(plt_entry).unwrap()
262 }
263
264 fn new_func_plt_entry(&mut self, id: FuncId, val: *const u8) {
265 let got_entry = self.new_got_entry(val);
266 self.function_got_entries[id] = Some(SendWrapper(got_entry));
267 let plt_entry = self.new_plt_entry(got_entry);
268 self.record_function_for_perf(
269 plt_entry.as_ptr().cast(),
270 std::mem::size_of::<[u8; 16]>(),
271 &format!(
272 "{}@plt",
273 self.declarations.get_function_decl(id).linkage_name(id)
274 ),
275 );
276 self.function_plt_entries[id] = Some(SendWrapper(plt_entry));
277 }
278
279 fn new_data_got_entry(&mut self, id: DataId, val: *const u8) {
280 let got_entry = self.new_got_entry(val);
281 self.data_object_got_entries[id] = Some(SendWrapper(got_entry));
282 }
283
284 unsafe fn write_plt_entry_bytes(plt_ptr: *mut [u8; 16], got_ptr: NonNull<AtomicPtr<u8>>) {
285 assert!(
286 cfg!(target_arch = "x86_64"),
287 "PLT is currently only supported on x86_64"
288 );
289 let mut plt_val = [
291 0xff, 0x25, 0, 0, 0, 0, 0x0f, 0x0b, 0x0f, 0x0b, 0x0f, 0x0b, 0x0f, 0x0b, 0x0f, 0x0b,
292 ];
293 let what = got_ptr.as_ptr() as isize - 4;
294 let at = plt_ptr as isize + 2;
295 plt_val[2..6].copy_from_slice(&i32::to_ne_bytes(i32::try_from(what - at).unwrap()));
296 std::ptr::write(plt_ptr, plt_val);
297 }
298
299 fn get_address(&self, name: &ModuleRelocTarget) -> *const u8 {
300 match *name {
301 ModuleRelocTarget::User { .. } => {
302 let (name, linkage) = if ModuleDeclarations::is_function(name) {
303 let func_id = FuncId::from_name(name);
304 match &self.compiled_functions[func_id] {
305 Some(compiled) => return compiled.ptr,
306 None => {
307 let decl = self.declarations.get_function_decl(func_id);
308 (&decl.name, decl.linkage)
309 }
310 }
311 } else {
312 let data_id = DataId::from_name(name);
313 match &self.compiled_data_objects[data_id] {
314 Some(compiled) => return compiled.ptr,
315 None => {
316 let decl = self.declarations.get_data_decl(data_id);
317 (&decl.name, decl.linkage)
318 }
319 }
320 };
321 let name = name
322 .as_ref()
323 .expect("anonymous symbol must be defined locally");
324 if let Some(ptr) = self.lookup_symbol(name) {
325 ptr
326 } else if linkage == Linkage::Preemptible {
327 0 as *const u8
328 } else {
329 panic!("can't resolve symbol {name}");
330 }
331 }
332 ModuleRelocTarget::LibCall(ref libcall) => {
333 let sym = (self.libcall_names)(*libcall);
334 self.lookup_symbol(&sym)
335 .unwrap_or_else(|| panic!("can't resolve libcall {sym}"))
336 }
337 _ => panic!("invalid name"),
338 }
339 }
340
341 pub fn read_got_entry(&self, func_id: FuncId) -> *const u8 {
345 let got_entry = self.function_got_entries[func_id].unwrap();
346 unsafe { got_entry.0.as_ref() }.load(Ordering::SeqCst)
347 }
348
349 fn get_got_address(&self, name: &ModuleRelocTarget) -> NonNull<AtomicPtr<u8>> {
350 match *name {
351 ModuleRelocTarget::User { .. } => {
352 if ModuleDeclarations::is_function(name) {
353 let func_id = FuncId::from_name(name);
354 self.function_got_entries[func_id].unwrap().0
355 } else {
356 let data_id = DataId::from_name(name);
357 self.data_object_got_entries[data_id].unwrap().0
358 }
359 }
360 ModuleRelocTarget::LibCall(ref libcall) => {
361 self.libcall_got_entries
362 .get(libcall)
363 .unwrap_or_else(|| panic!("can't resolve libcall {libcall}"))
364 .0
365 }
366 _ => panic!("invalid name"),
367 }
368 }
369
370 fn get_plt_address(&self, name: &ModuleRelocTarget) -> *const u8 {
371 match *name {
372 ModuleRelocTarget::User { .. } => {
373 if ModuleDeclarations::is_function(name) {
374 let func_id = FuncId::from_name(name);
375 self.function_plt_entries[func_id]
376 .unwrap()
377 .0
378 .as_ptr()
379 .cast::<u8>()
380 } else {
381 unreachable!("PLT relocations can only have functions as target");
382 }
383 }
384 ModuleRelocTarget::LibCall(ref libcall) => self
385 .libcall_plt_entries
386 .get(libcall)
387 .unwrap_or_else(|| panic!("can't resolve libcall {libcall}"))
388 .0
389 .as_ptr()
390 .cast::<u8>(),
391 _ => panic!("invalid name"),
392 }
393 }
394
395 pub fn get_finalized_function(&self, func_id: FuncId) -> *const u8 {
400 let info = &self.compiled_functions[func_id];
401 assert!(
402 !self.functions_to_finalize.iter().any(|x| *x == func_id),
403 "function not yet finalized"
404 );
405 info.as_ref()
406 .expect("function must be compiled before it can be finalized")
407 .ptr
408 }
409
410 pub fn get_finalized_data(&self, data_id: DataId) -> (*const u8, usize) {
415 let info = &self.compiled_data_objects[data_id];
416 assert!(
417 !self.data_objects_to_finalize.iter().any(|x| *x == data_id),
418 "data object not yet finalized"
419 );
420 let compiled = info
421 .as_ref()
422 .expect("data object must be compiled before it can be finalized");
423
424 (compiled.ptr, compiled.size)
425 }
426
427 fn record_function_for_perf(&self, ptr: *mut u8, size: usize, name: &str) {
428 if cfg!(unix) && ::std::env::var_os("PERF_BUILDID_DIR").is_some() {
434 let mut map_file = ::std::fs::OpenOptions::new()
435 .create(true)
436 .append(true)
437 .open(format!("/tmp/perf-{}.map", ::std::process::id()))
438 .unwrap();
439
440 let _ = writeln!(map_file, "{:x} {:x} {}", ptr as usize, size, name);
441 }
442 }
443
444 pub fn finalize_definitions(&mut self) -> ModuleResult<()> {
453 for func in std::mem::take(&mut self.functions_to_finalize) {
454 let decl = self.declarations.get_function_decl(func);
455 assert!(decl.linkage.is_definable());
456 let func = self.compiled_functions[func]
457 .as_ref()
458 .expect("function must be compiled before it can be finalized");
459 func.perform_relocations(
460 |name| self.get_address(name),
461 |name| self.get_got_address(name).as_ptr().cast(),
462 |name| self.get_plt_address(name),
463 );
464 }
465
466 for data in std::mem::take(&mut self.data_objects_to_finalize) {
467 let decl = self.declarations.get_data_decl(data);
468 assert!(decl.linkage.is_definable());
469 let data = self.compiled_data_objects[data]
470 .as_ref()
471 .expect("data object must be compiled before it can be finalized");
472 data.perform_relocations(
473 |name| self.get_address(name),
474 |name| self.get_got_address(name).as_ptr().cast(),
475 |name| self.get_plt_address(name),
476 );
477 }
478
479 self.memory.readonly.set_readonly()?;
481 self.memory.code.set_readable_and_executable()?;
482
483 for update in self.pending_got_updates.drain(..) {
484 unsafe { update.entry.as_ref() }.store(update.ptr as *mut _, Ordering::SeqCst);
485 }
486 Ok(())
487 }
488
489 pub fn new(builder: JITBuilder) -> Self {
491 let branch_protection =
492 if cfg!(target_arch = "aarch64") && use_bti(&builder.isa.isa_flags()) {
493 BranchProtection::BTI
494 } else {
495 BranchProtection::None
496 };
497 let mut module = Self {
498 isa: builder.isa,
499 symbols: RefCell::new(builder.symbols),
500 lookup_symbols: builder.lookup_symbols,
501 libcall_names: builder.libcall_names,
502 memory: MemoryHandle {
503 code: Memory::new(branch_protection),
504 readonly: Memory::new(BranchProtection::None),
506 writable: Memory::new(BranchProtection::None),
507 },
508 declarations: ModuleDeclarations::default(),
509 function_got_entries: SecondaryMap::new(),
510 function_plt_entries: SecondaryMap::new(),
511 data_object_got_entries: SecondaryMap::new(),
512 libcall_got_entries: HashMap::new(),
513 libcall_plt_entries: HashMap::new(),
514 compiled_functions: SecondaryMap::new(),
515 compiled_data_objects: SecondaryMap::new(),
516 functions_to_finalize: Vec::new(),
517 data_objects_to_finalize: Vec::new(),
518 pending_got_updates: Vec::new(),
519 };
520
521 let all_libcalls = if module.isa.flags().is_pic() {
523 ir::LibCall::all_libcalls()
524 } else {
525 &[] };
527 for &libcall in all_libcalls {
528 let sym = (module.libcall_names)(libcall);
529 let addr = if let Some(addr) = module.lookup_symbol(&sym) {
530 addr
531 } else {
532 continue;
533 };
534 let got_entry = module.new_got_entry(addr);
535 module
536 .libcall_got_entries
537 .insert(libcall, SendWrapper(got_entry));
538 let plt_entry = module.new_plt_entry(got_entry);
539 module
540 .libcall_plt_entries
541 .insert(libcall, SendWrapper(plt_entry));
542 }
543
544 module
545 }
546}
547
548impl Module for JITModule {
549 fn isa(&self) -> &dyn TargetIsa {
550 &*self.isa
551 }
552
553 fn declarations(&self) -> &ModuleDeclarations {
554 &self.declarations
555 }
556
557 fn declare_function(
558 &mut self,
559 name: &str,
560 linkage: Linkage,
561 signature: &ir::Signature,
562 ) -> ModuleResult<FuncId> {
563 let (id, linkage) = self
564 .declarations
565 .declare_function(name, linkage, signature)?;
566 if self.function_got_entries[id].is_none() && self.isa.flags().is_pic() {
567 let val = if linkage == Linkage::Import {
569 self.lookup_symbol(name).unwrap_or(std::ptr::null())
570 } else {
571 std::ptr::null()
572 };
573 self.new_func_plt_entry(id, val);
574 }
575 Ok(id)
576 }
577
578 fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
579 let id = self.declarations.declare_anonymous_function(signature)?;
580 if self.isa.flags().is_pic() {
581 self.new_func_plt_entry(id, std::ptr::null());
582 }
583 Ok(id)
584 }
585
586 fn declare_data(
587 &mut self,
588 name: &str,
589 linkage: Linkage,
590 writable: bool,
591 tls: bool,
592 ) -> ModuleResult<DataId> {
593 assert!(!tls, "JIT doesn't yet support TLS");
594 let (id, linkage) = self
595 .declarations
596 .declare_data(name, linkage, writable, tls)?;
597 if self.data_object_got_entries[id].is_none() && self.isa.flags().is_pic() {
598 let val = if linkage == Linkage::Import {
600 self.lookup_symbol(name).unwrap_or(std::ptr::null())
601 } else {
602 std::ptr::null()
603 };
604 self.new_data_got_entry(id, val);
605 }
606 Ok(id)
607 }
608
609 fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
610 assert!(!tls, "JIT doesn't yet support TLS");
611 let id = self.declarations.declare_anonymous_data(writable, tls)?;
612 if self.isa.flags().is_pic() {
613 self.new_data_got_entry(id, std::ptr::null());
614 }
615 Ok(id)
616 }
617
618 fn define_function_with_control_plane(
619 &mut self,
620 id: FuncId,
621 ctx: &mut cranelift_codegen::Context,
622 ctrl_plane: &mut ControlPlane,
623 ) -> ModuleResult<()> {
624 info!("defining function {}: {}", id, ctx.func.display());
625 let decl = self.declarations.get_function_decl(id);
626 if !decl.linkage.is_definable() {
627 return Err(ModuleError::InvalidImportDefinition(
628 decl.linkage_name(id).into_owned(),
629 ));
630 }
631
632 if !self.compiled_functions[id].is_none() {
633 return Err(ModuleError::DuplicateDefinition(
634 decl.linkage_name(id).into_owned(),
635 ));
636 }
637
638 let res = ctx.compile(self.isa(), ctrl_plane)?;
640 let alignment = res.buffer.alignment as u64;
641 let compiled_code = ctx.compiled_code().unwrap();
642
643 let size = compiled_code.code_info().total_size as usize;
644 let align = alignment.max(self.isa.symbol_alignment());
645 let ptr = self
646 .memory
647 .code
648 .allocate(size, align)
649 .map_err(|e| ModuleError::Allocation {
650 message: "unable to alloc function",
651 err: e,
652 })?;
653
654 {
655 let mem = unsafe { std::slice::from_raw_parts_mut(ptr, size) };
656 mem.copy_from_slice(compiled_code.code_buffer());
657 }
658
659 let relocs = compiled_code
660 .buffer
661 .relocs()
662 .iter()
663 .map(|reloc| ModuleReloc::from_mach_reloc(reloc, &ctx.func, id))
664 .collect();
665
666 self.record_function_for_perf(ptr, size, &decl.linkage_name(id));
667 self.compiled_functions[id] = Some(CompiledBlob { ptr, size, relocs });
668
669 if self.isa.flags().is_pic() {
670 self.pending_got_updates.push(GotUpdate {
671 entry: self.function_got_entries[id].unwrap().0,
672 ptr,
673 })
674 }
675
676 self.functions_to_finalize.push(id);
677
678 Ok(())
679 }
680
681 fn define_function_bytes(
682 &mut self,
683 id: FuncId,
684 alignment: u64,
685 bytes: &[u8],
686 relocs: &[ModuleReloc],
687 ) -> ModuleResult<()> {
688 info!("defining function {} with bytes", id);
689 let decl = self.declarations.get_function_decl(id);
690 if !decl.linkage.is_definable() {
691 return Err(ModuleError::InvalidImportDefinition(
692 decl.linkage_name(id).into_owned(),
693 ));
694 }
695
696 if !self.compiled_functions[id].is_none() {
697 return Err(ModuleError::DuplicateDefinition(
698 decl.linkage_name(id).into_owned(),
699 ));
700 }
701
702 let size = bytes.len();
703 let align = alignment.max(self.isa.symbol_alignment());
704 let ptr = self
705 .memory
706 .code
707 .allocate(size, align)
708 .map_err(|e| ModuleError::Allocation {
709 message: "unable to alloc function bytes",
710 err: e,
711 })?;
712
713 unsafe {
714 ptr::copy_nonoverlapping(bytes.as_ptr(), ptr, size);
715 }
716
717 self.record_function_for_perf(ptr, size, &decl.linkage_name(id));
718 self.compiled_functions[id] = Some(CompiledBlob {
719 ptr,
720 size,
721 relocs: relocs.to_owned(),
722 });
723
724 if self.isa.flags().is_pic() {
725 self.pending_got_updates.push(GotUpdate {
726 entry: self.function_got_entries[id].unwrap().0,
727 ptr,
728 })
729 }
730
731 self.functions_to_finalize.push(id);
732
733 Ok(())
734 }
735
736 fn define_data(&mut self, id: DataId, data: &DataDescription) -> ModuleResult<()> {
737 let decl = self.declarations.get_data_decl(id);
738 if !decl.linkage.is_definable() {
739 return Err(ModuleError::InvalidImportDefinition(
740 decl.linkage_name(id).into_owned(),
741 ));
742 }
743
744 if !self.compiled_data_objects[id].is_none() {
745 return Err(ModuleError::DuplicateDefinition(
746 decl.linkage_name(id).into_owned(),
747 ));
748 }
749
750 assert!(!decl.tls, "JIT doesn't yet support TLS");
751
752 let &DataDescription {
753 ref init,
754 function_decls: _,
755 data_decls: _,
756 function_relocs: _,
757 data_relocs: _,
758 custom_segment_section: _,
759 align,
760 } = data;
761
762 let alloc_size = std::cmp::max(init.size(), 1);
767
768 let ptr = if decl.writable {
769 self.memory
770 .writable
771 .allocate(alloc_size, align.unwrap_or(WRITABLE_DATA_ALIGNMENT))
772 .map_err(|e| ModuleError::Allocation {
773 message: "unable to alloc writable data",
774 err: e,
775 })?
776 } else {
777 self.memory
778 .readonly
779 .allocate(alloc_size, align.unwrap_or(READONLY_DATA_ALIGNMENT))
780 .map_err(|e| ModuleError::Allocation {
781 message: "unable to alloc readonly data",
782 err: e,
783 })?
784 };
785
786 if ptr.is_null() {
787 std::alloc::handle_alloc_error(
789 std::alloc::Layout::from_size_align(
790 alloc_size,
791 align.unwrap_or(READONLY_DATA_ALIGNMENT).try_into().unwrap(),
792 )
793 .unwrap(),
794 );
795 }
796
797 match *init {
798 Init::Uninitialized => {
799 panic!("data is not initialized yet");
800 }
801 Init::Zeros { size } => {
802 unsafe { ptr::write_bytes(ptr, 0, size) };
803 }
804 Init::Bytes { ref contents } => {
805 let src = contents.as_ptr();
806 unsafe { ptr::copy_nonoverlapping(src, ptr, contents.len()) };
807 }
808 }
809
810 let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
811 PointerWidth::U16 => panic!(),
812 PointerWidth::U32 => Reloc::Abs4,
813 PointerWidth::U64 => Reloc::Abs8,
814 };
815 let relocs = data.all_relocs(pointer_reloc).collect::<Vec<_>>();
816
817 self.compiled_data_objects[id] = Some(CompiledBlob {
818 ptr,
819 size: init.size(),
820 relocs,
821 });
822 self.data_objects_to_finalize.push(id);
823 if self.isa.flags().is_pic() {
824 self.pending_got_updates.push(GotUpdate {
825 entry: self.data_object_got_entries[id].unwrap().0,
826 ptr,
827 })
828 }
829
830 Ok(())
831 }
832
833 fn get_name(&self, name: &str) -> Option<cranelift_module::FuncOrDataId> {
834 self.declarations().get_name(name)
835 }
836
837 fn target_config(&self) -> cranelift_codegen::isa::TargetFrontendConfig {
838 self.isa().frontend_config()
839 }
840
841 fn make_context(&self) -> cranelift_codegen::Context {
842 let mut ctx = cranelift_codegen::Context::new();
843 ctx.func.signature.call_conv = self.isa().default_call_conv();
844 ctx
845 }
846
847 fn clear_context(&self, ctx: &mut cranelift_codegen::Context) {
848 ctx.clear();
849 ctx.func.signature.call_conv = self.isa().default_call_conv();
850 }
851
852 fn make_signature(&self) -> ir::Signature {
853 ir::Signature::new(self.isa().default_call_conv())
854 }
855
856 fn clear_signature(&self, sig: &mut ir::Signature) {
857 sig.clear(self.isa().default_call_conv());
858 }
859}
860
861#[cfg(not(windows))]
862fn lookup_with_dlsym(name: &str) -> Option<*const u8> {
863 let c_str = CString::new(name).unwrap();
864 let c_str_ptr = c_str.as_ptr();
865 let sym = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c_str_ptr) };
866 if sym.is_null() {
867 None
868 } else {
869 Some(sym as *const u8)
870 }
871}
872
873#[cfg(windows)]
874fn lookup_with_dlsym(name: &str) -> Option<*const u8> {
875 use std::os::windows::io::RawHandle;
876 use windows_sys::Win32::Foundation::HMODULE;
877 use windows_sys::Win32::System::LibraryLoader;
878
879 const UCRTBASE: &[u8] = b"ucrtbase.dll\0";
880
881 let c_str = CString::new(name).unwrap();
882 let c_str_ptr = c_str.as_ptr();
883
884 unsafe {
885 let handles = [
886 ptr::null_mut(),
888 LibraryLoader::GetModuleHandleA(UCRTBASE.as_ptr()) as RawHandle,
890 ];
891
892 for handle in &handles {
893 let addr = LibraryLoader::GetProcAddress(*handle as HMODULE, c_str_ptr.cast());
894 match addr {
895 None => continue,
896 Some(addr) => return Some(addr as *const u8),
897 }
898 }
899
900 None
901 }
902}
903
904fn use_bti(isa_flags: &Vec<settings::Value>) -> bool {
905 isa_flags
906 .iter()
907 .find(|&f| f.name == "use_bti")
908 .map_or(false, |f| f.as_bool().unwrap_or(false))
909}