DWARF addresses are relative to the start of the code section

This partially reverts the previous commit.

Also fix the logic in `DebugLocReader::get_loc`.
This commit is contained in:
Philip Craig 2023-02-15 15:40:27 +10:00
parent c999f995be
commit 5470e80851
2 changed files with 23 additions and 10 deletions

View file

@ -36,7 +36,7 @@ pub fn wasm_to_ir(bytes: &[u8]) -> Result<Module<'_>> {
gimli::LocationLists::new(extra_sections.debug_loc, extra_sections.debug_loclists); gimli::LocationLists::new(extra_sections.debug_loc, extra_sections.debug_loclists);
dwarf.ranges = dwarf.ranges =
gimli::RangeLists::new(extra_sections.debug_ranges, extra_sections.debug_rnglists); gimli::RangeLists::new(extra_sections.debug_ranges, extra_sections.debug_rnglists);
let debug_map = DebugMap::from_dwarf(dwarf, &mut module.debug)?; let debug_map = DebugMap::from_dwarf(dwarf, &mut module.debug, extra_sections.code_offset)?;
module.debug_map = debug_map; module.debug_map = debug_map;
Ok(module) Ok(module)
@ -74,6 +74,7 @@ struct ExtraSections<'a> {
debug_loclists: gimli::DebugLocLists<gimli::EndianSlice<'a, gimli::LittleEndian>>, debug_loclists: gimli::DebugLocLists<gimli::EndianSlice<'a, gimli::LittleEndian>>,
debug_ranges: gimli::DebugRanges<gimli::EndianSlice<'a, gimli::LittleEndian>>, debug_ranges: gimli::DebugRanges<gimli::EndianSlice<'a, gimli::LittleEndian>>,
debug_rnglists: gimli::DebugRngLists<gimli::EndianSlice<'a, gimli::LittleEndian>>, debug_rnglists: gimli::DebugRngLists<gimli::EndianSlice<'a, gimli::LittleEndian>>,
code_offset: u32,
} }
fn handle_payload<'a>( fn handle_payload<'a>(
@ -170,6 +171,9 @@ fn handle_payload<'a>(
)); ));
} }
} }
Payload::CodeSectionStart { range, .. } => {
extra_sections.code_offset = range.start as u32;
}
Payload::CodeSectionEntry(body) => { Payload::CodeSectionEntry(body) => {
let func_idx = Func::new(*next_func); let func_idx = Func::new(*next_func);
*next_func += 1; *next_func += 1;
@ -285,7 +289,6 @@ fn handle_payload<'a>(
gimli::DebugRngLists::new(reader.data(), gimli::LittleEndian); gimli::DebugRngLists::new(reader.data(), gimli::LittleEndian);
} }
Payload::CustomSection(_) => {} Payload::CustomSection(_) => {}
Payload::CodeSectionStart { .. } => {}
Payload::Version { .. } => {} Payload::Version { .. } => {}
Payload::ElementSection(reader) => { Payload::ElementSection(reader) => {
for element in reader { for element in reader {
@ -358,19 +361,22 @@ fn handle_payload<'a>(
} }
struct DebugLocReader<'a> { struct DebugLocReader<'a> {
code_offset: u32,
locs: &'a [(u32, u32, SourceLoc)], locs: &'a [(u32, u32, SourceLoc)],
} }
impl<'a> DebugLocReader<'a> { impl<'a> DebugLocReader<'a> {
fn new(module: &'a Module, func_offset_in_file: u32) -> Self { fn new(module: &'a Module, func_offset_in_file: u32) -> Self {
let code_offset = module.debug_map.code_offset;
let func_address = func_offset_in_file - code_offset;
let start = match module let start = match module
.debug_map .debug_map
.tuples .tuples
.binary_search_by(|&(start, len, _)| { .binary_search_by(|&(start, len, _)| {
use std::cmp::Ordering::*; use std::cmp::Ordering::*;
if start > func_offset_in_file { if start > func_address {
Greater Greater
} else if (start + len) <= func_offset_in_file { } else if (start + len) <= func_address {
Less Less
} else { } else {
Equal Equal
@ -380,21 +386,22 @@ impl<'a> DebugLocReader<'a> {
Err(idx) => idx, Err(idx) => idx,
}; };
DebugLocReader { DebugLocReader {
code_offset,
locs: &module.debug_map.tuples[start..], locs: &module.debug_map.tuples[start..],
} }
} }
fn get_loc(&mut self, offset: usize) -> SourceLoc { fn get_loc(&mut self, offset: usize) -> SourceLoc {
let offset = u32::try_from(offset).unwrap(); let address = u32::try_from(offset).unwrap() - self.code_offset;
while self.locs.len() > 0 { while self.locs.len() > 0 {
let (start, len, loc) = self.locs[0]; let (start, len, loc) = self.locs[0];
if offset < start { if address < start {
break; break;
} }
if offset > (start + len) { if address < start + len {
self.locs = &self.locs[1..]; return loc;
} }
return loc; self.locs = &self.locs[1..];
} }
SourceLoc::invalid() SourceLoc::invalid()
} }

View file

@ -48,6 +48,8 @@ impl Debug {
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct DebugMap { pub struct DebugMap {
/// Offset of code section relative to the Wasm file start.
pub code_offset: u32,
/// Each tuple is `(start, len, loc)`. The `start` offset is /// Each tuple is `(start, len, loc)`. The `start` offset is
/// relative to the code section. /// relative to the code section.
pub tuples: Vec<(u32, u32, SourceLoc)>, pub tuples: Vec<(u32, u32, SourceLoc)>,
@ -57,6 +59,7 @@ impl DebugMap {
pub(crate) fn from_dwarf<R: gimli::Reader>( pub(crate) fn from_dwarf<R: gimli::Reader>(
dwarf: gimli::Dwarf<R>, dwarf: gimli::Dwarf<R>,
debug: &mut Debug, debug: &mut Debug,
code_offset: u32,
) -> anyhow::Result<DebugMap> { ) -> anyhow::Result<DebugMap> {
let ctx = addr2line::Context::from_dwarf(dwarf)?; let ctx = addr2line::Context::from_dwarf(dwarf)?;
let mut tuples = vec![]; let mut tuples = vec![];
@ -79,6 +82,9 @@ impl DebugMap {
retain retain
}); });
Ok(DebugMap { tuples }) Ok(DebugMap {
code_offset,
tuples,
})
} }
} }