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