Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/environ/src/compile/trap_encoding.rs
1693 views
1
use crate::TrapInformation;
2
use crate::obj::ELF_WASMTIME_TRAPS;
3
use crate::prelude::*;
4
use object::write::{Object, StandardSegment};
5
use object::{LittleEndian, SectionKind, U32Bytes};
6
use std::ops::Range;
7
8
/// A helper structure to build the custom-encoded section of a wasmtime
9
/// compilation image which encodes trap information.
10
///
11
/// This structure is incrementally fed the results of compiling individual
12
/// functions and handles all the encoding internally, allowing usage of
13
/// `lookup_trap_code` below with the resulting section.
14
#[derive(Default)]
15
pub struct TrapEncodingBuilder {
16
offsets: Vec<U32Bytes<LittleEndian>>,
17
traps: Vec<u8>,
18
last_offset: u32,
19
}
20
21
impl TrapEncodingBuilder {
22
/// Appends trap information about a function into this section.
23
///
24
/// This function is called to describe traps for the `func` range
25
/// specified. The `func` offsets are specified relative to the text section
26
/// itself, and the `traps` offsets are specified relative to the start of
27
/// `func`.
28
///
29
/// This is required to be called in-order for increasing ranges of `func`
30
/// to ensure the final array is properly sorted. Additionally `traps` must
31
/// be sorted.
32
pub fn push(&mut self, func: Range<u64>, traps: &[TrapInformation]) {
33
// NB: for now this only supports <=4GB text sections in object files.
34
// Alternative schemes will need to be created for >32-bit offsets to
35
// avoid making this section overly large.
36
let func_start = u32::try_from(func.start).unwrap();
37
let func_end = u32::try_from(func.end).unwrap();
38
39
// Sanity-check to ensure that functions are pushed in-order, otherwise
40
// the `offsets` array won't be sorted which is our goal.
41
assert!(func_start >= self.last_offset);
42
43
self.offsets.reserve(traps.len());
44
self.traps.reserve(traps.len());
45
for info in traps {
46
let pos = func_start + info.code_offset;
47
assert!(pos >= self.last_offset);
48
self.offsets.push(U32Bytes::new(LittleEndian, pos));
49
self.traps.push(info.trap_code as u8);
50
self.last_offset = pos;
51
}
52
53
self.last_offset = func_end;
54
}
55
56
/// Encodes this section into the object provided.
57
pub fn append_to(self, obj: &mut Object) {
58
let section = obj.add_section(
59
obj.segment_name(StandardSegment::Data).to_vec(),
60
ELF_WASMTIME_TRAPS.as_bytes().to_vec(),
61
SectionKind::ReadOnlyData,
62
);
63
64
// NB: this matches the encoding expected by `lookup` below.
65
let amt = u32::try_from(self.traps.len()).unwrap();
66
obj.append_section_data(section, &amt.to_le_bytes(), 1);
67
obj.append_section_data(section, object::bytes_of_slice(&self.offsets), 1);
68
obj.append_section_data(section, &self.traps, 1);
69
}
70
}
71
72