/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 {} |