use crate::InstructionAddressMap;
use crate::obj::ELF_WASMTIME_ADDRMAP;
use crate::prelude::*;
use object::write::{Object, StandardSegment};
use object::{LittleEndian, SectionKind, U32Bytes};
use std::ops::Range;
#[derive(Default)]
pub struct AddressMapSection {
offsets: Vec<U32Bytes<LittleEndian>>,
positions: Vec<U32Bytes<LittleEndian>>,
last_offset: u32,
}
impl AddressMapSection {
pub fn push(&mut self, func: Range<u64>, instrs: &[InstructionAddressMap]) {
let func_start = u32::try_from(func.start).unwrap();
let func_end = u32::try_from(func.end).unwrap();
self.offsets.reserve(instrs.len());
self.positions.reserve(instrs.len());
let mut last_srcloc = None;
for map in instrs {
let pos = func_start + map.code_offset;
assert!(pos >= self.last_offset);
self.last_offset = pos;
let srcloc = map.srcloc.file_offset().unwrap_or(u32::MAX);
if Some(srcloc) == last_srcloc {
continue;
}
last_srcloc = Some(srcloc);
self.offsets.push(U32Bytes::new(LittleEndian, pos));
self.positions.push(U32Bytes::new(LittleEndian, srcloc));
}
self.last_offset = func_end;
}
pub fn append_to(self, obj: &mut Object) {
let section = obj.add_section(
obj.segment_name(StandardSegment::Data).to_vec(),
ELF_WASMTIME_ADDRMAP.as_bytes().to_vec(),
SectionKind::ReadOnlyData,
);
let amt = u32::try_from(self.offsets.len()).unwrap();
obj.append_section_data(section, &amt.to_le_bytes(), 1);
obj.append_section_data(section, object::bytes_of_slice(&self.offsets), 1);
obj.append_section_data(section, object::bytes_of_slice(&self.positions), 1);
}
}