wasmer_engine_jit/
link.rs

1//! Linking for JIT-compiled code.
2
3use std::ptr::write_unaligned;
4use wasmer_compiler::{
5    JumpTable, JumpTableOffsets, Relocation, RelocationKind, RelocationTarget, Relocations,
6    SectionIndex,
7};
8use wasmer_engine::FunctionExtent;
9use wasmer_types::entity::{EntityRef, PrimaryMap};
10use wasmer_types::LocalFunctionIndex;
11use wasmer_vm::ModuleInfo;
12use wasmer_vm::SectionBodyPtr;
13
14fn apply_relocation(
15    body: usize,
16    r: &Relocation,
17    allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
18    jt_offsets: &PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
19    allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
20) {
21    let target_func_address: usize = match r.reloc_target {
22        RelocationTarget::LocalFunc(index) => *allocated_functions[index].ptr as usize,
23        RelocationTarget::LibCall(libcall) => libcall.function_pointer(),
24        RelocationTarget::CustomSection(custom_section) => {
25            *allocated_sections[custom_section] as usize
26        }
27        RelocationTarget::JumpTable(func_index, jt) => {
28            let offset = *jt_offsets
29                .get(func_index)
30                .and_then(|ofs| ofs.get(JumpTable::new(jt.index())))
31                .expect("func jump table");
32            *allocated_functions[func_index].ptr as usize + offset as usize
33        }
34    };
35
36    match r.kind {
37        #[cfg(target_pointer_width = "64")]
38        RelocationKind::Abs8 => unsafe {
39            let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
40            write_unaligned(reloc_address as *mut u64, reloc_delta);
41        },
42        #[cfg(target_pointer_width = "32")]
43        RelocationKind::X86PCRel4 => unsafe {
44            let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
45            write_unaligned(reloc_address as *mut u32, reloc_delta as _);
46        },
47        #[cfg(target_pointer_width = "64")]
48        RelocationKind::X86PCRel8 => unsafe {
49            let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
50            write_unaligned(reloc_address as *mut u64, reloc_delta);
51        },
52        #[cfg(target_pointer_width = "32")]
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::X86PCRelRodata4 => {}
58        kind => panic!(
59            "Relocation kind unsupported in the current architecture {}",
60            kind
61        ),
62    }
63}
64
65/// Links a module, patching the allocated functions with the
66/// required relocations and jump tables.
67pub fn link_module(
68    _module: &ModuleInfo,
69    allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
70    jt_offsets: &PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
71    function_relocations: Relocations,
72    allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
73    section_relocations: &PrimaryMap<SectionIndex, Vec<Relocation>>,
74) {
75    for (i, section_relocs) in section_relocations.iter() {
76        let body = *allocated_sections[i] as usize;
77        for r in section_relocs {
78            apply_relocation(body, r, allocated_functions, jt_offsets, allocated_sections);
79        }
80    }
81    for (i, function_relocs) in function_relocations.iter() {
82        let body = *allocated_functions[i].ptr as usize;
83        for r in function_relocs {
84            apply_relocation(body, r, allocated_functions, jt_offsets, allocated_sections);
85        }
86    }
87}