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