wasmtime_environ/compile/
module_artifacts.rs1use crate::WasmChecksum;
5use crate::error::{Result, bail};
6use crate::prelude::*;
7use crate::{
8 CompiledModuleInfo, DebugInfoData, FunctionName, Metadata, ModuleTranslation, Tunables, obj,
9};
10use object::SectionKind;
11use object::write::{Object, SectionId, StandardSegment, WritableBuffer};
12use std::ops::Range;
13
14pub struct ObjectBuilder<'a> {
20 obj: Object<'a>,
22
23 tunables: &'a Tunables,
25
26 data: SectionId,
29
30 names: Option<SectionId>,
35
36 dwarf: Option<SectionId>,
41}
42
43impl<'a> ObjectBuilder<'a> {
44 pub fn new(mut obj: Object<'a>, tunables: &'a Tunables) -> ObjectBuilder<'a> {
46 let data = obj.add_section(
47 obj.segment_name(StandardSegment::Data).to_vec(),
48 obj::ELF_WASM_DATA.as_bytes().to_vec(),
49 SectionKind::ReadOnlyData,
50 );
51 ObjectBuilder {
52 obj,
53 tunables,
54 data,
55 names: None,
56 dwarf: None,
57 }
58 }
59
60 pub fn push_debuginfo(
65 &mut self,
66 dwarf: &mut Vec<(u8, Range<u64>)>,
67 debuginfo: &DebugInfoData<'_>,
68 ) {
69 self.push_debug(dwarf, &debuginfo.dwarf.debug_abbrev);
70 self.push_debug(dwarf, &debuginfo.dwarf.debug_addr);
71 self.push_debug(dwarf, &debuginfo.dwarf.debug_aranges);
72 self.push_debug(dwarf, &debuginfo.dwarf.debug_info);
73 self.push_debug(dwarf, &debuginfo.dwarf.debug_line);
74 self.push_debug(dwarf, &debuginfo.dwarf.debug_line_str);
75 self.push_debug(dwarf, &debuginfo.dwarf.debug_str);
76 self.push_debug(dwarf, &debuginfo.dwarf.debug_str_offsets);
77 self.push_debug(dwarf, &debuginfo.debug_ranges);
78 self.push_debug(dwarf, &debuginfo.debug_rnglists);
79 self.push_debug(dwarf, &debuginfo.debug_cu_index);
80
81 dwarf.sort_by_key(|(id, _)| *id);
83 }
84
85 pub fn append(&mut self, translation: ModuleTranslation<'_>) -> Result<CompiledModuleInfo> {
116 let ModuleTranslation {
117 mut module,
118 debuginfo,
119 has_unparsed_debuginfo,
120 data_align,
121 runtime_data,
122 wasm,
123 ..
124 } = translation;
125
126 let data_offset = self
130 .obj
131 .append_section_data(self.data, &[], data_align.unwrap_or(1));
132 for (i, (_, data)) in runtime_data.iter().enumerate() {
133 let align = if i == 0 { data_align.unwrap_or(1) } else { 1 };
137 self.obj.append_section_data(self.data, data, align);
138 }
139
140 let mut func_names = Vec::new();
143 if debuginfo.name_section.func_names.len() > 0 {
144 let name_id = *self.names.get_or_insert_with(|| {
145 self.obj.add_section(
146 self.obj.segment_name(StandardSegment::Data).to_vec(),
147 obj::ELF_NAME_DATA.as_bytes().to_vec(),
148 SectionKind::ReadOnlyData,
149 )
150 });
151 let mut sorted_names = debuginfo.name_section.func_names.iter().collect::<Vec<_>>();
152 sorted_names.sort_by_key(|(idx, _name)| *idx);
153 for (idx, name) in sorted_names {
154 let offset = self.obj.append_section_data(name_id, name.as_bytes(), 1);
155 let offset = match u32::try_from(offset) {
156 Ok(offset) => offset,
157 Err(_) => bail!("name section too large (> 4gb)"),
158 };
159 let len = u32::try_from(name.len()).unwrap();
160 func_names.push(FunctionName {
161 idx: *idx,
162 offset,
163 len,
164 });
165 }
166 }
167
168 let data_offset = u32::try_from(data_offset).unwrap();
173 for (_, range) in module.runtime_data.iter_mut() {
174 range.start = range.start.checked_add(data_offset).unwrap();
175 range.end = range.end.checked_add(data_offset).unwrap();
176 }
177
178 let mut dwarf = Vec::new();
183 if self.tunables.parse_wasm_debuginfo {
184 self.push_debuginfo(&mut dwarf, &debuginfo);
185 }
186
187 Ok(CompiledModuleInfo {
188 module,
189 func_names,
190 meta: Metadata {
191 has_unparsed_debuginfo,
192 code_section_offset: debuginfo.wasm_file.code_section_offset,
193 has_wasm_debuginfo: self.tunables.parse_wasm_debuginfo,
194 dwarf,
195 },
196 checksum: WasmChecksum::from_binary(wasm, self.tunables.recording),
197 })
198 }
199
200 fn push_debug<'b, T>(&mut self, dwarf: &mut Vec<(u8, Range<u64>)>, section: &T)
201 where
202 T: gimli::Section<gimli::EndianSlice<'b, gimli::LittleEndian>>,
203 {
204 let data = section.reader().slice();
205 if data.is_empty() {
206 return;
207 }
208 let section_id = *self.dwarf.get_or_insert_with(|| {
209 self.obj.add_section(
210 self.obj.segment_name(StandardSegment::Debug).to_vec(),
211 obj::ELF_WASMTIME_DWARF.as_bytes().to_vec(),
212 SectionKind::Debug,
213 )
214 });
215 let offset = self.obj.append_section_data(section_id, data, 1);
216 dwarf.push((T::id() as u8, offset..offset + data.len() as u64));
217 }
218
219 pub fn append_wasm_bytecode<'b>(&mut self, modules: impl IntoIterator<Item = &'b [u8]>) {
225 let bytecode_id = self.obj.add_section(
226 self.obj.segment_name(StandardSegment::Data).to_vec(),
227 obj::ELF_WASMTIME_WASM_BYTECODE.as_bytes().to_vec(),
228 SectionKind::ReadOnlyData,
229 );
230 let ends_id = self.obj.add_section(
231 self.obj.segment_name(StandardSegment::Data).to_vec(),
232 obj::ELF_WASMTIME_WASM_BYTECODE_ENDS.as_bytes().to_vec(),
233 SectionKind::ReadOnlyData,
234 );
235 let mut end: u32 = 0;
236 for wasm in modules {
237 self.obj.append_section_data(bytecode_id, wasm, 1);
238 end = end
239 .checked_add(u32::try_from(wasm.len()).expect("module bytecode exceeds 4 GiB"))
240 .expect("total bytecode exceeds 4 GiB");
241 self.obj.append_section_data(ends_id, &end.to_le_bytes(), 4);
242 }
243 }
244
245 pub fn serialize_info<T>(&mut self, info: &T)
248 where
249 T: serde::Serialize,
250 {
251 let section = self.obj.add_section(
252 self.obj.segment_name(StandardSegment::Data).to_vec(),
253 obj::ELF_WASMTIME_INFO.as_bytes().to_vec(),
254 SectionKind::ReadOnlyData,
255 );
256 let data = postcard::to_allocvec(info).unwrap();
257 self.obj.set_section_data(section, data, 1);
258 }
259
260 pub fn finish<T: WritableBuffer>(self, t: &mut T) -> Result<()> {
263 self.obj.emit(t).map_err(|e| e.into())
264 }
265}
266
267pub trait FinishedObject: Sized {
269 type State;
271
272 fn finish_object(obj: ObjectBuilder<'_>, state: &Self::State) -> Result<Self>;
274}
275
276impl FinishedObject for Vec<u8> {
277 type State = ();
278 fn finish_object(obj: ObjectBuilder<'_>, _state: &Self::State) -> Result<Self> {
279 let mut result = ObjectVec::default();
280 obj.finish(&mut result)?;
281 return Ok(result.0);
282
283 #[derive(Default)]
284 struct ObjectVec(Vec<u8>);
285
286 impl WritableBuffer for ObjectVec {
287 fn len(&self) -> usize {
288 self.0.len()
289 }
290
291 fn reserve(&mut self, additional: usize) -> Result<(), ()> {
292 assert_eq!(self.0.len(), 0, "cannot reserve twice");
293 self.0 = Vec::with_capacity(additional);
294 Ok(())
295 }
296
297 fn resize(&mut self, new_len: usize) {
298 if new_len <= self.0.len() {
299 self.0.truncate(new_len)
300 } else {
301 self.0.extend(vec![0; new_len - self.0.len()])
302 }
303 }
304
305 fn write_bytes(&mut self, val: &[u8]) {
306 self.0.extend(val);
307 }
308 }
309 }
310}