wasmer_engine_universal/
link.rs1use std::ptr::{read_unaligned, write_unaligned};
4use wasmer_compiler::{Relocation, RelocationKind, RelocationTarget, Relocations, SectionIndex};
5use wasmer_engine::FunctionExtent;
6use wasmer_engine_universal_artifact::get_libcall_trampoline;
7use wasmer_types::entity::PrimaryMap;
8use wasmer_types::{LocalFunctionIndex, ModuleInfo};
9use wasmer_vm::libcalls::function_pointer;
10use wasmer_vm::SectionBodyPtr;
11
12fn apply_relocation(
13 body: usize,
14 r: &Relocation,
15 allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
16 allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
17 libcall_trampolines: SectionIndex,
18 libcall_trampoline_len: usize,
19) {
20 let target_func_address: usize = match r.reloc_target {
21 RelocationTarget::LocalFunc(index) => *allocated_functions[index].ptr as usize,
22 RelocationTarget::LibCall(libcall) => {
23 if r.kind == RelocationKind::Abs8 || r.kind == RelocationKind::X86PCRel8 {
26 function_pointer(libcall)
27 } else {
28 get_libcall_trampoline(
29 libcall,
30 allocated_sections[libcall_trampolines].0 as usize,
31 libcall_trampoline_len,
32 )
33 }
34 }
35 RelocationTarget::CustomSection(custom_section) => {
36 *allocated_sections[custom_section] as usize
37 }
38 };
39
40 match r.kind {
41 RelocationKind::Abs8 => unsafe {
42 let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
43 write_unaligned(reloc_address as *mut u64, reloc_delta);
44 },
45 RelocationKind::X86PCRel4 => unsafe {
46 let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
47 write_unaligned(reloc_address as *mut u32, reloc_delta as _);
48 },
49 RelocationKind::X86PCRel8 => unsafe {
50 let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
51 write_unaligned(reloc_address as *mut u64, reloc_delta);
52 },
53 RelocationKind::X86CallPCRel4 => unsafe {
54 let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
55 write_unaligned(reloc_address as *mut u32, reloc_delta as _);
56 },
57 RelocationKind::Arm64Call => unsafe {
58 let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
59 if (reloc_delta as i64).abs() >= 0x1000_0000 {
60 panic!(
61 "Relocation to big for {:?} for {:?} with {:x}, current val {:x}",
62 r.kind,
63 r.reloc_target,
64 reloc_delta,
65 read_unaligned(reloc_address as *mut u32)
66 )
67 }
68 let reloc_delta = (((reloc_delta / 4) as u32) & 0x3ff_ffff)
69 | (read_unaligned(reloc_address as *mut u32) & 0xfc00_0000);
70 write_unaligned(reloc_address as *mut u32, reloc_delta);
71 },
72 kind => panic!(
73 "Relocation kind unsupported in the current architecture {}",
74 kind
75 ),
76 }
77}
78
79pub fn link_module(
82 _module: &ModuleInfo,
83 allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
84 function_relocations: Relocations,
85 allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
86 section_relocations: &PrimaryMap<SectionIndex, Vec<Relocation>>,
87 libcall_trampolines: SectionIndex,
88 trampoline_len: usize,
89) {
90 for (i, section_relocs) in section_relocations.iter() {
91 let body = *allocated_sections[i] as usize;
92 for r in section_relocs {
93 apply_relocation(
94 body,
95 r,
96 allocated_functions,
97 allocated_sections,
98 libcall_trampolines,
99 trampoline_len,
100 );
101 }
102 }
103 for (i, function_relocs) in function_relocations.iter() {
104 let body = *allocated_functions[i].ptr as usize;
105 for r in function_relocs {
106 apply_relocation(
107 body,
108 r,
109 allocated_functions,
110 allocated_sections,
111 libcall_trampolines,
112 trampoline_len,
113 );
114 }
115 }
116}