Coverage Report

Created: 2025-01-06 07:43

/src/wasmtime/crates/environ/src/obj.rs
Line
Count
Source (jump to first uncovered line)
1
//! Utilities for working with object files that operate as Wasmtime's
2
//! serialization and intermediate format for compiled modules.
3
4
use core::fmt;
5
6
/// Filler for the `os_abi` field of the ELF header.
7
///
8
/// This is just a constant that seems reasonable in the sense it's unlikely to
9
/// clash with others.
10
pub const ELFOSABI_WASMTIME: u8 = 200;
11
12
/// Flag for the `e_flags` field in the ELF header indicating a compiled
13
/// module.
14
pub const EF_WASMTIME_MODULE: u32 = 1 << 0;
15
16
/// Flag for the `e_flags` field in the ELF header indicating a compiled
17
/// component.
18
pub const EF_WASMTIME_COMPONENT: u32 = 1 << 1;
19
20
/// Flag for the `sh_flags` field in the ELF text section that indicates that
21
/// the text section does not itself need to be executable. This is used for the
22
/// Pulley target, for example, to indicate that it does not need to be made
23
/// natively executable as it does not contain actual native code.
24
pub const SH_WASMTIME_NOT_EXECUTED: u64 = 1 << 0;
25
26
/// A custom Wasmtime-specific section of our compilation image which stores
27
/// mapping data from offsets in the image to offset in the original wasm
28
/// binary.
29
///
30
/// This section has a custom binary encoding. Currently its encoding is:
31
///
32
/// * The section starts with a 32-bit little-endian integer. This integer is
33
///   how many entries are in the following two arrays.
34
/// * Next is an array with the previous count number of 32-bit little-endian
35
///   integers. This array is a sorted list of relative offsets within the text
36
///   section. This is intended to be a lookup array to perform a binary search
37
///   on an offset within the text section on this array.
38
/// * Finally there is another array, with the same count as before, also of
39
///   32-bit little-endian integers. These integers map 1:1 with the previous
40
///   array of offsets, and correspond to what the original offset was in the
41
///   wasm file.
42
///
43
/// Decoding this section is intentionally simple, it only requires loading a
44
/// 32-bit little-endian integer plus some bounds checks. Reading this section
45
/// is done with the `lookup_file_pos` function below. Reading involves
46
/// performing a binary search on the first array using the index found for the
47
/// native code offset to index into the second array and find the wasm code
48
/// offset.
49
///
50
/// At this time this section has an alignment of 1, which means all reads of it
51
/// are unaligned. Additionally at this time the 32-bit encodings chosen here
52
/// mean that >=4gb text sections are not supported.
53
pub const ELF_WASMTIME_ADDRMAP: &str = ".wasmtime.addrmap";
54
55
/// A custom binary-encoded section of wasmtime compilation artifacts which
56
/// encodes the ability to map an offset in the text section to the trap code
57
/// that it corresponds to.
58
///
59
/// This section is used at runtime to determine what flavor of trap happened to
60
/// ensure that embedders and debuggers know the reason for the wasm trap. The
61
/// encoding of this section is custom to Wasmtime and managed with helpers in
62
/// the `object` crate:
63
///
64
/// * First the section has a 32-bit little endian integer indicating how many
65
///   trap entries are in the section.
66
/// * Next is an array, of the same length as read before, of 32-bit
67
///   little-endian integers. These integers are offsets into the text section
68
///   of the compilation image.
69
/// * Finally is the same count number of bytes. Each of these bytes corresponds
70
///   to a trap code.
71
///
72
/// This section is decoded by `lookup_trap_code` below which will read the
73
/// section count, slice some bytes to get the various arrays, and then perform
74
/// a binary search on the offsets array to find the index corresponding to
75
/// the pc being looked up. If found the same index in the trap array (the array
76
/// of bytes) is the trap code for that offset.
77
///
78
/// Note that at this time this section has an alignment of 1. Additionally due
79
/// to the 32-bit encodings for offsets this doesn't support images >=4gb.
80
pub const ELF_WASMTIME_TRAPS: &str = ".wasmtime.traps";
81
82
/// A custom section which consists of just 1 byte which is either 0 or 1 as to
83
/// whether BTI is enabled.
84
pub const ELF_WASM_BTI: &str = ".wasmtime.bti";
85
86
/// A bincode-encoded section containing engine-specific metadata used to
87
/// double-check that an artifact can be loaded into the current host.
88
pub const ELF_WASM_ENGINE: &str = ".wasmtime.engine";
89
90
/// This is the name of the section in the final ELF image which contains
91
/// concatenated data segments from the original wasm module.
92
///
93
/// This section is simply a list of bytes and ranges into this section are
94
/// stored within a `Module` for each data segment. Memory initialization and
95
/// passive segment management all index data directly located in this section.
96
///
97
/// Note that this implementation does not afford any method of leveraging the
98
/// `data.drop` instruction to actually release the data back to the OS. The
99
/// data section is simply always present in the ELF image. If we wanted to
100
/// release the data it's probably best to figure out what the best
101
/// implementation is for it at the time given a particular set of constraints.
102
pub const ELF_WASM_DATA: &'static str = ".rodata.wasm";
103
104
/// This is the name of the section in the final ELF image which contains a
105
/// `bincode`-encoded `CompiledModuleInfo`.
106
///
107
/// This section is optionally decoded in `CompiledModule::from_artifacts`
108
/// depending on whether or not a `CompiledModuleInfo` is already available. In
109
/// cases like `Module::new` where compilation directly leads into consumption,
110
/// it's available. In cases like `Module::deserialize` this section must be
111
/// decoded to get all the relevant information.
112
pub const ELF_WASMTIME_INFO: &'static str = ".wasmtime.info";
113
114
/// This is the name of the section in the final ELF image which contains a
115
/// concatenated list of all function names.
116
///
117
/// This section is optionally included in the final artifact depending on
118
/// whether the wasm module has any name data at all (or in the future if we add
119
/// an option to not preserve name data). This section is a concatenated list of
120
/// strings where `CompiledModuleInfo::func_names` stores offsets/lengths into
121
/// this section.
122
///
123
/// Note that the goal of this section is to avoid having to decode names at
124
/// module-load time if we can. Names are typically only used for debugging or
125
/// things like backtraces so there's no need to eagerly load all of them. By
126
/// storing the data in a separate section the hope is that the data, which is
127
/// sometimes quite large (3MB seen for spidermonkey-compiled-to-wasm), can be
128
/// paged in lazily from an mmap and is never paged in if we never reference it.
129
pub const ELF_NAME_DATA: &'static str = ".name.wasm";
130
131
/// This is the name of the section in the final ELF image that contains the
132
/// concatenation of all the native DWARF information found in the original wasm
133
/// files.
134
///
135
/// This concatenation is not intended to be read by external tools at this time
136
/// and is instead indexed directly by relative indices stored in compilation
137
/// metadata.
138
pub const ELF_WASMTIME_DWARF: &str = ".wasmtime.dwarf";
139
140
macro_rules! libcalls {
141
    ($($rust:ident = $sym:tt)*) => (
142
        #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
143
        #[allow(missing_docs, reason = "self-describing variants")]
144
        pub enum LibCall {
145
            $($rust,)*
146
        }
147
148
        impl LibCall {
149
            /// Returns the libcall corresponding to the provided symbol name,
150
            /// if one matches.
151
79.4k
            pub fn from_str(s: &str) -> Option<LibCall> {
152
79.4k
                match s {
153
124
                    $($sym => Some(LibCall::$rust),)*
154
0
                    _ => None,
155
                }
156
79.4k
            }
157
158
            /// Returns the symbol name in object files associated with this
159
            /// libcall.
160
3.15k
            pub fn symbol(&self) -> &'static str {
161
3.15k
                match self {
162
                    $(LibCall::$rust => $sym,)*
163
                }
164
3.15k
            }
165
        }
166
    )
167
}
168
169
libcalls! {
170
    FloorF32 = "libcall_floor32"
171
    FloorF64 = "libcall_floor64"
172
    NearestF32 = "libcall_nearestf32"
173
    NearestF64 = "libcall_nearestf64"
174
    CeilF32 = "libcall_ceilf32"
175
    CeilF64 = "libcall_ceilf64"
176
    TruncF32 = "libcall_truncf32"
177
    TruncF64 = "libcall_truncf64"
178
    FmaF32 = "libcall_fmaf32"
179
    FmaF64 = "libcall_fmaf64"
180
    X86Pshufb = "libcall_x86_pshufb"
181
}
182
183
/// Workaround to implement `core::error::Error` until
184
/// gimli-rs/object#747 is settled.
185
pub struct ObjectCrateErrorWrapper(pub object::Error);
186
187
impl fmt::Debug for ObjectCrateErrorWrapper {
188
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189
0
        self.0.fmt(f)
190
0
    }
191
}
192
193
impl fmt::Display for ObjectCrateErrorWrapper {
194
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195
0
        self.0.fmt(f)
196
0
    }
197
}
198
199
impl core::error::Error for ObjectCrateErrorWrapper {}