mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-09 19:06:04 +00:00
209 lines
6.6 KiB
Rust
209 lines
6.6 KiB
Rust
|
// https://llvm.org/docs/StackMaps.html#stackmap-section
|
||
|
|
||
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||
|
use std::io::{self, Cursor};
|
||
|
|
||
|
#[derive(Default, Debug, Clone)]
|
||
|
pub struct StackmapRegistry {
|
||
|
pub entries: Vec<StackmapEntry>,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Clone)]
|
||
|
pub struct StackmapEntry {
|
||
|
pub kind: StackmapEntryKind,
|
||
|
pub local_function_id: usize,
|
||
|
pub local_count: usize,
|
||
|
pub stack_count: usize,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Clone, Copy)]
|
||
|
pub enum StackmapEntryKind {
|
||
|
Loop,
|
||
|
Call,
|
||
|
Trappable,
|
||
|
}
|
||
|
|
||
|
#[derive(Clone, Debug, Default)]
|
||
|
pub struct StackMap {
|
||
|
pub version: u8,
|
||
|
pub stk_size_records: Vec<StkSizeRecord>,
|
||
|
pub constants: Vec<Constant>,
|
||
|
pub stk_map_records: Vec<StkMapRecord>,
|
||
|
}
|
||
|
|
||
|
#[derive(Copy, Clone, Debug, Default)]
|
||
|
pub struct StkSizeRecord {
|
||
|
pub function_address: u64,
|
||
|
pub stack_size: u64,
|
||
|
pub record_count: u64,
|
||
|
}
|
||
|
|
||
|
#[derive(Copy, Clone, Debug, Default)]
|
||
|
pub struct Constant {
|
||
|
pub large_constant: u64,
|
||
|
}
|
||
|
|
||
|
#[derive(Clone, Debug, Default)]
|
||
|
pub struct StkMapRecord {
|
||
|
pub patchpoint_id: u64,
|
||
|
pub instruction_offset: u32,
|
||
|
pub locations: Vec<Location>,
|
||
|
pub live_outs: Vec<LiveOut>,
|
||
|
}
|
||
|
|
||
|
#[derive(Copy, Clone, Debug)]
|
||
|
pub struct Location {
|
||
|
pub ty: LocationType,
|
||
|
pub location_size: u16,
|
||
|
pub dwarf_regnum: u16,
|
||
|
pub offset_or_small_constant: i32,
|
||
|
}
|
||
|
|
||
|
#[derive(Copy, Clone, Debug, Default)]
|
||
|
pub struct LiveOut {
|
||
|
pub dwarf_regnum: u16,
|
||
|
pub size_in_bytes: u8,
|
||
|
}
|
||
|
|
||
|
#[derive(Copy, Clone, Debug)]
|
||
|
pub enum LocationType {
|
||
|
Register,
|
||
|
Direct,
|
||
|
Indirect,
|
||
|
Constant,
|
||
|
ConstantIndex,
|
||
|
}
|
||
|
|
||
|
impl StackMap {
|
||
|
pub fn parse(raw: &[u8]) -> io::Result<StackMap> {
|
||
|
let mut reader = Cursor::new(raw);
|
||
|
let mut map = StackMap::default();
|
||
|
|
||
|
let version = reader.read_u8()?;
|
||
|
if version != 3 {
|
||
|
return Err(io::Error::new(io::ErrorKind::Other, "version is not 3"));
|
||
|
}
|
||
|
map.version = version;
|
||
|
if reader.read_u8()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (1)",
|
||
|
));
|
||
|
}
|
||
|
if reader.read_u16::<LittleEndian>()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (2)",
|
||
|
));
|
||
|
}
|
||
|
let num_functions = reader.read_u32::<LittleEndian>()?;
|
||
|
let num_constants = reader.read_u32::<LittleEndian>()?;
|
||
|
let num_records = reader.read_u32::<LittleEndian>()?;
|
||
|
for _ in 0..num_functions {
|
||
|
let mut record = StkSizeRecord::default();
|
||
|
record.function_address = reader.read_u64::<LittleEndian>()?;
|
||
|
record.stack_size = reader.read_u64::<LittleEndian>()?;
|
||
|
record.record_count = reader.read_u64::<LittleEndian>()?;
|
||
|
map.stk_size_records.push(record);
|
||
|
}
|
||
|
for _ in 0..num_constants {
|
||
|
map.constants.push(Constant {
|
||
|
large_constant: reader.read_u64::<LittleEndian>()?,
|
||
|
});
|
||
|
}
|
||
|
for _ in 0..num_records {
|
||
|
let mut record = StkMapRecord::default();
|
||
|
|
||
|
record.patchpoint_id = reader.read_u64::<LittleEndian>()?;
|
||
|
record.instruction_offset = reader.read_u32::<LittleEndian>()?;
|
||
|
if reader.read_u16::<LittleEndian>()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (3)",
|
||
|
));
|
||
|
}
|
||
|
let num_locations = reader.read_u16::<LittleEndian>()?;
|
||
|
for _ in 0..num_locations {
|
||
|
let ty = reader.read_u8()?;
|
||
|
|
||
|
let mut location = Location {
|
||
|
ty: match ty {
|
||
|
1 => LocationType::Register,
|
||
|
2 => LocationType::Direct,
|
||
|
3 => LocationType::Indirect,
|
||
|
4 => LocationType::Constant,
|
||
|
5 => LocationType::ConstantIndex,
|
||
|
_ => {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"unknown location type",
|
||
|
))
|
||
|
}
|
||
|
},
|
||
|
location_size: 0,
|
||
|
dwarf_regnum: 0,
|
||
|
offset_or_small_constant: 0,
|
||
|
};
|
||
|
|
||
|
if reader.read_u8()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (4)",
|
||
|
));
|
||
|
}
|
||
|
location.location_size = reader.read_u16::<LittleEndian>()?;
|
||
|
location.dwarf_regnum = reader.read_u16::<LittleEndian>()?;
|
||
|
if reader.read_u16::<LittleEndian>()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (5)",
|
||
|
));
|
||
|
}
|
||
|
location.offset_or_small_constant = reader.read_i32::<LittleEndian>()?;
|
||
|
|
||
|
record.locations.push(location);
|
||
|
}
|
||
|
if reader.position() % 8 != 0 {
|
||
|
if reader.read_u32::<LittleEndian>()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (6)",
|
||
|
));
|
||
|
}
|
||
|
}
|
||
|
if reader.read_u16::<LittleEndian>()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (7)",
|
||
|
));
|
||
|
}
|
||
|
let num_live_outs = reader.read_u16::<LittleEndian>()?;
|
||
|
for _ in 0..num_live_outs {
|
||
|
let mut liveout = LiveOut::default();
|
||
|
|
||
|
liveout.dwarf_regnum = reader.read_u16::<LittleEndian>()?;
|
||
|
if reader.read_u8()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (8)",
|
||
|
));
|
||
|
}
|
||
|
liveout.size_in_bytes = reader.read_u8()?;
|
||
|
|
||
|
record.live_outs.push(liveout);
|
||
|
}
|
||
|
if reader.position() % 8 != 0 {
|
||
|
if reader.read_u32::<LittleEndian>()? != 0 {
|
||
|
return Err(io::Error::new(
|
||
|
io::ErrorKind::Other,
|
||
|
"reserved field is not zero (9)",
|
||
|
));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
map.stk_map_records.push(record);
|
||
|
}
|
||
|
Ok(map)
|
||
|
}
|
||
|
}
|