Coverage Report

Created: 2024-10-16 07:58

/src/wasmer/lib/compiler/src/artifact_builders/trampoline.rs
Line
Count
Source (jump to first uncovered line)
1
//! Trampolines for libcalls.
2
//!
3
//! This is needed because the target of libcall relocations are not reachable
4
//! through normal branch instructions.
5
6
use enum_iterator::IntoEnumIterator;
7
use wasmer_types::{
8
    Architecture, CustomSection, CustomSectionProtection, LibCall, Relocation, RelocationKind,
9
    RelocationTarget, SectionBody, Target,
10
};
11
12
// SystemV says that both x16 and x17 are available as intra-procedural scratch
13
// registers but Apple's ABI restricts us to use x17.
14
// LDR x17, [PC, #8]  51 00 00 58
15
// BR x17             20 02 1f d6
16
// JMPADDR            00 00 00 00 00 00 00 00
17
const AARCH64_TRAMPOLINE: [u8; 16] = [
18
    0x51, 0x00, 0x00, 0x58, 0x20, 0x02, 0x1f, 0xd6, 0, 0, 0, 0, 0, 0, 0, 0,
19
];
20
21
// 2 padding bytes are used to preserve alignment.
22
// JMP [RIP + 2]   FF 25 02 00 00 00 [00 00]
23
// 64-bit ADDR     00 00 00 00 00 00 00 00
24
const X86_64_TRAMPOLINE: [u8; 16] = [
25
    0xff, 0x25, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26
];
27
28
// can it be shorter than this?
29
// 4 padding bytes are used to preserve alignment.
30
// AUIPC t1,0     17 03 00 00
31
// LD t1, 16(t1)  03 33 03 01
32
// JR t1          67 00 03 00 [00 00 00 00]
33
// JMPADDR        00 00 00 00 00 00 00 00
34
const RISCV64_TRAMPOLINE: [u8; 24] = [
35
    0x17, 0x03, 0x00, 0x00, 0x03, 0x33, 0x03, 0x01, 0x67, 0x00, 0x03, 0x00, 0, 0, 0, 0, 0, 0, 0, 0,
36
    0, 0, 0, 0,
37
];
38
39
1.57M
fn make_trampoline(
40
1.57M
    target: &Target,
41
1.57M
    libcall: LibCall,
42
1.57M
    code: &mut Vec<u8>,
43
1.57M
    relocations: &mut Vec<Relocation>,
44
1.57M
) {
45
1.57M
    match target.triple().architecture {
46
0
        Architecture::Aarch64(_) => {
47
0
            code.extend(AARCH64_TRAMPOLINE);
48
0
            relocations.push(Relocation {
49
0
                kind: RelocationKind::Abs8,
50
0
                reloc_target: RelocationTarget::LibCall(libcall),
51
0
                offset: code.len() as u32 - 8,
52
0
                addend: 0,
53
0
            });
54
0
        }
55
1.57M
        Architecture::X86_64 => {
56
1.57M
            code.extend(X86_64_TRAMPOLINE);
57
1.57M
            relocations.push(Relocation {
58
1.57M
                kind: RelocationKind::Abs8,
59
1.57M
                reloc_target: RelocationTarget::LibCall(libcall),
60
1.57M
                offset: code.len() as u32 - 8,
61
1.57M
                addend: 0,
62
1.57M
            });
63
1.57M
        }
64
0
        Architecture::Riscv64(_) => {
65
0
            code.extend(RISCV64_TRAMPOLINE);
66
0
            relocations.push(Relocation {
67
0
                kind: RelocationKind::Abs8,
68
0
                reloc_target: RelocationTarget::LibCall(libcall),
69
0
                offset: code.len() as u32 - 8,
70
0
                addend: 0,
71
0
            });
72
0
        }
73
0
        arch => panic!("Unsupported architecture: {}", arch),
74
    };
75
1.57M
}
wasmer_compiler::artifact_builders::trampoline::make_trampoline
Line
Count
Source
39
1.11M
fn make_trampoline(
40
1.11M
    target: &Target,
41
1.11M
    libcall: LibCall,
42
1.11M
    code: &mut Vec<u8>,
43
1.11M
    relocations: &mut Vec<Relocation>,
44
1.11M
) {
45
1.11M
    match target.triple().architecture {
46
0
        Architecture::Aarch64(_) => {
47
0
            code.extend(AARCH64_TRAMPOLINE);
48
0
            relocations.push(Relocation {
49
0
                kind: RelocationKind::Abs8,
50
0
                reloc_target: RelocationTarget::LibCall(libcall),
51
0
                offset: code.len() as u32 - 8,
52
0
                addend: 0,
53
0
            });
54
0
        }
55
1.11M
        Architecture::X86_64 => {
56
1.11M
            code.extend(X86_64_TRAMPOLINE);
57
1.11M
            relocations.push(Relocation {
58
1.11M
                kind: RelocationKind::Abs8,
59
1.11M
                reloc_target: RelocationTarget::LibCall(libcall),
60
1.11M
                offset: code.len() as u32 - 8,
61
1.11M
                addend: 0,
62
1.11M
            });
63
1.11M
        }
64
0
        Architecture::Riscv64(_) => {
65
0
            code.extend(RISCV64_TRAMPOLINE);
66
0
            relocations.push(Relocation {
67
0
                kind: RelocationKind::Abs8,
68
0
                reloc_target: RelocationTarget::LibCall(libcall),
69
0
                offset: code.len() as u32 - 8,
70
0
                addend: 0,
71
0
            });
72
0
        }
73
0
        arch => panic!("Unsupported architecture: {}", arch),
74
    };
75
1.11M
}
wasmer_compiler::artifact_builders::trampoline::make_trampoline
Line
Count
Source
39
451k
fn make_trampoline(
40
451k
    target: &Target,
41
451k
    libcall: LibCall,
42
451k
    code: &mut Vec<u8>,
43
451k
    relocations: &mut Vec<Relocation>,
44
451k
) {
45
451k
    match target.triple().architecture {
46
0
        Architecture::Aarch64(_) => {
47
0
            code.extend(AARCH64_TRAMPOLINE);
48
0
            relocations.push(Relocation {
49
0
                kind: RelocationKind::Abs8,
50
0
                reloc_target: RelocationTarget::LibCall(libcall),
51
0
                offset: code.len() as u32 - 8,
52
0
                addend: 0,
53
0
            });
54
0
        }
55
451k
        Architecture::X86_64 => {
56
451k
            code.extend(X86_64_TRAMPOLINE);
57
451k
            relocations.push(Relocation {
58
451k
                kind: RelocationKind::Abs8,
59
451k
                reloc_target: RelocationTarget::LibCall(libcall),
60
451k
                offset: code.len() as u32 - 8,
61
451k
                addend: 0,
62
451k
            });
63
451k
        }
64
0
        Architecture::Riscv64(_) => {
65
0
            code.extend(RISCV64_TRAMPOLINE);
66
0
            relocations.push(Relocation {
67
0
                kind: RelocationKind::Abs8,
68
0
                reloc_target: RelocationTarget::LibCall(libcall),
69
0
                offset: code.len() as u32 - 8,
70
0
                addend: 0,
71
0
            });
72
0
        }
73
0
        arch => panic!("Unsupported architecture: {}", arch),
74
    };
75
451k
}
76
77
/// Returns the length of a libcall trampoline.
78
42.4k
pub fn libcall_trampoline_len(target: &Target) -> usize {
79
42.4k
    match target.triple().architecture {
80
0
        Architecture::Aarch64(_) => AARCH64_TRAMPOLINE.len(),
81
42.4k
        Architecture::X86_64 => X86_64_TRAMPOLINE.len(),
82
0
        Architecture::Riscv64(_) => RISCV64_TRAMPOLINE.len(),
83
0
        arch => panic!("Unsupported architecture: {}", arch),
84
    }
85
42.4k
}
wasmer_compiler::artifact_builders::trampoline::libcall_trampoline_len
Line
Count
Source
78
30.2k
pub fn libcall_trampoline_len(target: &Target) -> usize {
79
30.2k
    match target.triple().architecture {
80
0
        Architecture::Aarch64(_) => AARCH64_TRAMPOLINE.len(),
81
30.2k
        Architecture::X86_64 => X86_64_TRAMPOLINE.len(),
82
0
        Architecture::Riscv64(_) => RISCV64_TRAMPOLINE.len(),
83
0
        arch => panic!("Unsupported architecture: {}", arch),
84
    }
85
30.2k
}
wasmer_compiler::artifact_builders::trampoline::libcall_trampoline_len
Line
Count
Source
78
12.2k
pub fn libcall_trampoline_len(target: &Target) -> usize {
79
12.2k
    match target.triple().architecture {
80
0
        Architecture::Aarch64(_) => AARCH64_TRAMPOLINE.len(),
81
12.2k
        Architecture::X86_64 => X86_64_TRAMPOLINE.len(),
82
0
        Architecture::Riscv64(_) => RISCV64_TRAMPOLINE.len(),
83
0
        arch => panic!("Unsupported architecture: {}", arch),
84
    }
85
12.2k
}
86
87
/// Creates a custom section containing the libcall trampolines.
88
42.4k
pub fn make_libcall_trampolines(target: &Target) -> CustomSection {
89
42.4k
    let mut code = vec![];
90
42.4k
    let mut relocations = vec![];
91
1.61M
    for libcall in LibCall::into_enum_iter() {
92
1.57M
        make_trampoline(target, libcall, &mut code, &mut relocations);
93
1.57M
    }
94
42.4k
    CustomSection {
95
42.4k
        protection: CustomSectionProtection::ReadExecute,
96
42.4k
        bytes: SectionBody::new_with_vec(code),
97
42.4k
        relocations,
98
42.4k
    }
99
42.4k
}
wasmer_compiler::artifact_builders::trampoline::make_libcall_trampolines
Line
Count
Source
88
30.2k
pub fn make_libcall_trampolines(target: &Target) -> CustomSection {
89
30.2k
    let mut code = vec![];
90
30.2k
    let mut relocations = vec![];
91
1.14M
    for libcall in LibCall::into_enum_iter() {
92
1.11M
        make_trampoline(target, libcall, &mut code, &mut relocations);
93
1.11M
    }
94
30.2k
    CustomSection {
95
30.2k
        protection: CustomSectionProtection::ReadExecute,
96
30.2k
        bytes: SectionBody::new_with_vec(code),
97
30.2k
        relocations,
98
30.2k
    }
99
30.2k
}
wasmer_compiler::artifact_builders::trampoline::make_libcall_trampolines
Line
Count
Source
88
12.2k
pub fn make_libcall_trampolines(target: &Target) -> CustomSection {
89
12.2k
    let mut code = vec![];
90
12.2k
    let mut relocations = vec![];
91
464k
    for libcall in LibCall::into_enum_iter() {
92
451k
        make_trampoline(target, libcall, &mut code, &mut relocations);
93
451k
    }
94
12.2k
    CustomSection {
95
12.2k
        protection: CustomSectionProtection::ReadExecute,
96
12.2k
        bytes: SectionBody::new_with_vec(code),
97
12.2k
        relocations,
98
12.2k
    }
99
12.2k
}
100
101
/// Returns the address of a trampoline in the libcall trampolines section.
102
0
pub fn get_libcall_trampoline(
103
0
    libcall: LibCall,
104
0
    libcall_trampolines: usize,
105
0
    libcall_trampoline_len: usize,
106
0
) -> usize {
107
0
    libcall_trampolines + libcall as usize * libcall_trampoline_len
108
0
}
Unexecuted instantiation: wasmer_compiler::artifact_builders::trampoline::get_libcall_trampoline
Unexecuted instantiation: wasmer_compiler::artifact_builders::trampoline::get_libcall_trampoline