wasmer_compiler/artifact_builders/
trampoline.rs1#![cfg_attr(not(feature = "compiler"), allow(dead_code))]
7
8use enum_iterator::IntoEnumIterator;
9use wasmer_types::LibCall;
10use wasmer_types::target::{Architecture, Target};
11
12use crate::types::{
13 relocation::{Relocation, RelocationKind, RelocationTarget},
14 section::{CustomSection, CustomSectionProtection, SectionBody},
15};
16
17const AARCH64_TRAMPOLINE: [u8; 16] = [
23 0x51, 0x00, 0x00, 0x58, 0x20, 0x02, 0x1f, 0xd6, 0, 0, 0, 0, 0, 0, 0, 0,
24];
25
26const X86_64_TRAMPOLINE: [u8; 16] = [
30 0xff, 0x25, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31];
32
33const RISCV64_TRAMPOLINE: [u8; 24] = [
40 0x17, 0x03, 0x00, 0x00, 0x03, 0x33, 0x03, 0x01, 0x67, 0x00, 0x03, 0x00, 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0,
42];
43
44const LOONGARCH64_TRAMPOLINE: [u8; 24] = [
49 0x0c, 0x00, 0x00, 0x18, 0x8c, 0x41, 0xc0, 0x28, 0x80, 0x01, 0x00, 0x4c, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0,
51];
52
53fn make_trampoline(
54 target: &Target,
55 libcall: LibCall,
56 code: &mut Vec<u8>,
57 relocations: &mut Vec<Relocation>,
58) {
59 match target.triple().architecture {
60 Architecture::Aarch64(_) => {
61 code.extend(AARCH64_TRAMPOLINE);
62 relocations.push(Relocation {
63 kind: RelocationKind::Abs8,
64 reloc_target: RelocationTarget::LibCall(libcall),
65 offset: code.len() as u32 - 8,
66 addend: 0,
67 });
68 }
69 Architecture::X86_64 => {
70 code.extend(X86_64_TRAMPOLINE);
71 relocations.push(Relocation {
72 kind: RelocationKind::Abs8,
73 reloc_target: RelocationTarget::LibCall(libcall),
74 offset: code.len() as u32 - 8,
75 addend: 0,
76 });
77 }
78 Architecture::Riscv64(_) => {
79 code.extend(RISCV64_TRAMPOLINE);
80 relocations.push(Relocation {
81 kind: RelocationKind::Abs8,
82 reloc_target: RelocationTarget::LibCall(libcall),
83 offset: code.len() as u32 - 8,
84 addend: 0,
85 });
86 }
87 Architecture::LoongArch64 => {
88 code.extend(LOONGARCH64_TRAMPOLINE);
89 relocations.push(Relocation {
90 kind: RelocationKind::Abs8,
91 reloc_target: RelocationTarget::LibCall(libcall),
92 offset: code.len() as u32 - 8,
93 addend: 0,
94 });
95 }
96 arch => panic!("Unsupported architecture: {arch}"),
97 };
98}
99
100pub fn libcall_trampoline_len(target: &Target) -> usize {
102 match target.triple().architecture {
103 Architecture::Aarch64(_) => AARCH64_TRAMPOLINE.len(),
104 Architecture::X86_64 => X86_64_TRAMPOLINE.len(),
105 Architecture::Riscv64(_) => RISCV64_TRAMPOLINE.len(),
106 Architecture::LoongArch64 => LOONGARCH64_TRAMPOLINE.len(),
107 arch => panic!("Unsupported architecture: {arch}"),
108 }
109}
110
111pub fn make_libcall_trampolines(target: &Target) -> CustomSection {
113 let mut code = vec![];
114 let mut relocations = vec![];
115 for libcall in LibCall::into_enum_iter() {
116 make_trampoline(target, libcall, &mut code, &mut relocations);
117 }
118 CustomSection {
119 protection: CustomSectionProtection::ReadExecute,
120 alignment: None,
121 bytes: SectionBody::new_with_vec(code),
122 relocations,
123 }
124}
125
126pub fn get_libcall_trampoline(
128 libcall: LibCall,
129 libcall_trampolines: usize,
130 libcall_trampoline_len: usize,
131) -> usize {
132 libcall_trampolines + libcall as usize * libcall_trampoline_len
133}