summaryrefslogtreecommitdiff
path: root/rust/examples/dwarf/dwarf_import/src/lib.rs
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2024-10-10 17:36:52 -0400
committerJosh Ferrell <josh@vector35.com>2024-10-10 17:37:09 -0400
commit039033f13726b6ddcb1dd0312419f7495637283a (patch)
tree42c5ffa9ba8643819ea236dc8aa81f5cc8778247 /rust/examples/dwarf/dwarf_import/src/lib.rs
parent7be992787ec6b299c7aeb42f6293809bd9288c67 (diff)
Lots of improvements to stack variable location calculations in DWARF
Diffstat (limited to 'rust/examples/dwarf/dwarf_import/src/lib.rs')
-rw-r--r--rust/examples/dwarf/dwarf_import/src/lib.rs33
1 files changed, 27 insertions, 6 deletions
diff --git a/rust/examples/dwarf/dwarf_import/src/lib.rs b/rust/examples/dwarf/dwarf_import/src/lib.rs
index 94503856..076586f1 100644
--- a/rust/examples/dwarf/dwarf_import/src/lib.rs
+++ b/rust/examples/dwarf/dwarf_import/src/lib.rs
@@ -37,6 +37,7 @@ use dwarfreader::{
create_section_reader, get_endian, is_dwo_dwarf, is_non_dwo_dwarf, is_raw_dwo_dwarf,
};
+use functions::parse_lexical_block;
use gimli::{constants, CfaRule, DebuggingInformationEntry, Dwarf, DwarfFileType, Reader, Section, SectionId, Unit, UnwindContext, UnwindSection};
use helpers::{get_build_id, load_debug_info_for_build_id};
@@ -222,6 +223,7 @@ fn parse_unit<R: ReaderType>(
let mut current_depth: isize = 0;
let mut functions_by_depth: Vec<(Option<usize>, isize)> = vec![];
+ let mut lexical_blocks_by_depth: Vec<(iset::IntervalSet<u64>, isize)> = vec![];
// Really all we care about as we iterate the entries in a given unit is how they modify state (our perception of the file)
// There's a lot of junk we don't care about in DWARF info, so we choose a couple DIEs and mutate state (add functions (which adds the types it uses) and keep track of what namespace we're in)
@@ -250,6 +252,18 @@ fn parse_unit<R: ReaderType>(
else {
break;
}
+
+ if let Some((_lexical_block, depth)) = lexical_blocks_by_depth.last() {
+ if current_depth <= *depth {
+ lexical_blocks_by_depth.pop();
+ }
+ else {
+ break
+ }
+ }
+ else {
+ break;
+ }
}
match entry.tag() {
@@ -257,9 +271,15 @@ fn parse_unit<R: ReaderType>(
let fn_idx = parse_function_entry(dwarf, unit, entry, debug_info_builder_context, debug_info_builder);
functions_by_depth.push((fn_idx, current_depth));
},
+ constants::DW_TAG_lexical_block => {
+ if let Some(block_ranges) = parse_lexical_block(dwarf, unit, entry) {
+ lexical_blocks_by_depth.push((block_ranges, current_depth));
+ }
+ },
constants::DW_TAG_variable => {
let current_fn_idx = functions_by_depth.last().and_then(|x| x.0);
- parse_variable(dwarf, unit, entry, debug_info_builder_context, debug_info_builder, current_fn_idx)
+ let current_lexical_block = lexical_blocks_by_depth.last().and_then(|x| Some(&x.0));
+ parse_variable(dwarf, unit, entry, debug_info_builder_context, debug_info_builder, current_fn_idx, current_lexical_block)
},
constants::DW_TAG_class_type |
constants::DW_TAG_enumeration_type |
@@ -300,13 +320,13 @@ where <U as UnwindSection<R>>::Offset: std::hash::Hash {
}
let mut cies = HashMap::new();
- let mut cie_data_offsets = iset::IntervalMap::new();
+ let mut cfa_offsets = iset::IntervalMap::new();
let mut entries = unwind_section.entries(&bases);
let mut unwind_context = UnwindContext::new();
loop {
match entries.next()? {
- None => return Ok(cie_data_offsets),
+ None => return Ok(cfa_offsets),
Some(gimli::CieOrFde::Cie(_cie)) => {
// TODO: do we want to do anything with standalone CIEs?
}
@@ -325,7 +345,7 @@ where <U as UnwindSection<R>>::Offset: std::hash::Hash {
if fde.len() == 0 {
// This FDE is a terminator
- return Ok(cie_data_offsets);
+ return Ok(cfa_offsets);
}
if fde.initial_address().overflowing_add(fde.len()).1 {
@@ -333,11 +353,12 @@ where <U as UnwindSection<R>>::Offset: std::hash::Hash {
} else {
// Walk the FDE table rows and store their CFA
let mut fde_table = fde.rows(&unwind_section, &bases, &mut unwind_context)?;
+
while let Some(row) = fde_table.next_row()? {
match row.cfa() {
CfaRule::RegisterAndOffset {register: _, offset} => {
- // TODO: this offset could be wrong because register might be something wacky
- cie_data_offsets.insert(
+ // TODO: we should store offsets by register
+ cfa_offsets.insert(
row.start_address()..row.end_address(),
*offset,
);