waffle/src/ir/debug.rs

91 lines
2.7 KiB
Rust
Raw Normal View History

2023-02-10 23:04:01 -06:00
//! Debug info (currently, source-location maps).
use crate::declare_entity;
use crate::entity::EntityVec;
use addr2line::gimli;
use std::collections::hash_map::Entry as HashEntry;
use std::collections::HashMap;
declare_entity!(SourceFile, "file");
declare_entity!(SourceLoc, "loc");
#[derive(Clone, Debug, Default)]
pub struct Debug {
2023-02-13 18:17:17 -06:00
pub source_files: EntityVec<SourceFile, String>,
2023-02-10 23:04:01 -06:00
source_file_dedup: HashMap<String, SourceFile>,
2023-02-13 18:17:17 -06:00
pub source_locs: EntityVec<SourceLoc, SourceLocData>,
2023-02-10 23:04:01 -06:00
source_loc_dedup: HashMap<SourceLocData, SourceLoc>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceLocData {
2023-02-13 18:17:17 -06:00
pub file: SourceFile,
pub line: u32,
pub col: u32,
2023-02-10 23:04:01 -06:00
}
impl Debug {
pub fn intern_file(&mut self, path: &str) -> SourceFile {
if let Some(id) = self.source_file_dedup.get(path) {
return *id;
}
let id = self.source_files.push(path.to_owned());
self.source_file_dedup.insert(path.to_owned(), id);
id
}
pub fn intern_loc(&mut self, file: SourceFile, line: u32, col: u32) -> SourceLoc {
let data = SourceLocData { file, line, col };
match self.source_loc_dedup.entry(data) {
HashEntry::Vacant(v) => {
let id = self.source_locs.push(data);
*v.insert(id)
}
HashEntry::Occupied(o) => *o.get(),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct DebugMap {
/// Offset of code section relative to the Wasm file start.
pub code_offset: u32,
2023-02-13 19:02:25 -06:00
/// Each tuple is `(start, len, loc)`. The `start` offset is
2023-02-13 19:42:43 -06:00
/// relative to the code section.
2023-02-13 19:02:25 -06:00
pub tuples: Vec<(u32, u32, SourceLoc)>,
2023-02-10 23:04:01 -06:00
}
impl DebugMap {
pub(crate) fn from_dwarf<R: gimli::Reader>(
dwarf: gimli::Dwarf<R>,
debug: &mut Debug,
code_offset: u32,
) -> anyhow::Result<DebugMap> {
let ctx = addr2line::Context::from_dwarf(dwarf)?;
2023-02-10 23:04:01 -06:00
let mut tuples = vec![];
let mut locs = ctx.find_location_range(0, u64::MAX).unwrap();
2023-02-13 18:17:17 -06:00
while let Some((start, len, loc)) = locs.next() {
2023-02-10 23:04:01 -06:00
let file = debug.intern_file(loc.file.unwrap_or(""));
let loc = debug.intern_loc(file, loc.line.unwrap_or(0), loc.column.unwrap_or(0));
2023-02-13 19:42:43 -06:00
log::trace!("tuple: loc {} start {:x} len {:x}", loc, start, len);
2023-02-13 18:17:17 -06:00
tuples.push((start as u32, len as u32, loc));
2023-02-10 23:04:01 -06:00
}
tuples.sort();
2023-02-10 23:04:01 -06:00
let mut last = 0;
2023-02-13 18:17:17 -06:00
tuples.retain(|&(start, len, _)| {
let retain = start >= last;
if retain {
last = start + len;
}
2023-02-13 18:17:17 -06:00
retain
});
2023-02-10 23:04:01 -06:00
Ok(DebugMap {
code_offset,
tuples,
})
2023-02-10 23:04:01 -06:00
}
}