From 5470e808511a8aa0e8b40e55363a9add4e32fbf1 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Wed, 15 Feb 2023 15:40:27 +1000 Subject: [PATCH] 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`. --- src/frontend.rs | 25 ++++++++++++++++--------- src/ir/debug.rs | 8 +++++++- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/frontend.rs b/src/frontend.rs index 21f61bb..ae98a79 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -36,7 +36,7 @@ pub fn wasm_to_ir(bytes: &[u8]) -> Result> { gimli::LocationLists::new(extra_sections.debug_loc, extra_sections.debug_loclists); dwarf.ranges = 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; Ok(module) @@ -74,6 +74,7 @@ struct ExtraSections<'a> { debug_loclists: gimli::DebugLocLists>, debug_ranges: gimli::DebugRanges>, debug_rnglists: gimli::DebugRngLists>, + code_offset: u32, } 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) => { let func_idx = Func::new(*next_func); *next_func += 1; @@ -285,7 +289,6 @@ fn handle_payload<'a>( gimli::DebugRngLists::new(reader.data(), gimli::LittleEndian); } Payload::CustomSection(_) => {} - Payload::CodeSectionStart { .. } => {} Payload::Version { .. } => {} Payload::ElementSection(reader) => { for element in reader { @@ -358,19 +361,22 @@ fn handle_payload<'a>( } struct DebugLocReader<'a> { + code_offset: u32, locs: &'a [(u32, u32, SourceLoc)], } impl<'a> DebugLocReader<'a> { 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 .debug_map .tuples .binary_search_by(|&(start, len, _)| { use std::cmp::Ordering::*; - if start > func_offset_in_file { + if start > func_address { Greater - } else if (start + len) <= func_offset_in_file { + } else if (start + len) <= func_address { Less } else { Equal @@ -380,21 +386,22 @@ impl<'a> DebugLocReader<'a> { Err(idx) => idx, }; DebugLocReader { + code_offset, locs: &module.debug_map.tuples[start..], } } 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 { let (start, len, loc) = self.locs[0]; - if offset < start { + if address < start { break; } - if offset > (start + len) { - self.locs = &self.locs[1..]; + if address < start + len { + return loc; } - return loc; + self.locs = &self.locs[1..]; } SourceLoc::invalid() } diff --git a/src/ir/debug.rs b/src/ir/debug.rs index 85f189d..b19b484 100644 --- a/src/ir/debug.rs +++ b/src/ir/debug.rs @@ -48,6 +48,8 @@ impl Debug { #[derive(Clone, Debug, Default)] 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 /// relative to the code section. pub tuples: Vec<(u32, u32, SourceLoc)>, @@ -57,6 +59,7 @@ impl DebugMap { pub(crate) fn from_dwarf( dwarf: gimli::Dwarf, debug: &mut Debug, + code_offset: u32, ) -> anyhow::Result { let ctx = addr2line::Context::from_dwarf(dwarf)?; let mut tuples = vec![]; @@ -79,6 +82,9 @@ impl DebugMap { retain }); - Ok(DebugMap { tuples }) + Ok(DebugMap { + code_offset, + tuples, + }) } }