From de74dfdba716abe273c3296b32a92334d6479faa Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sun, 11 Aug 2024 14:27:27 -0600 Subject: [PATCH] Add dummy symbols to empty sections Allows diffing sections without symbols Resolves #87 --- objdiff-core/src/diff/mod.rs | 34 ++++++++++++++++++---------- objdiff-core/src/obj/read.rs | 17 ++++++++++++++ objdiff-gui/src/views/symbol_diff.rs | 30 ++++++++++++------------ 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/objdiff-core/src/diff/mod.rs b/objdiff-core/src/diff/mod.rs index c755a2c..5be8611 100644 --- a/objdiff-core/src/diff/mod.rs +++ b/objdiff-core/src/diff/mod.rs @@ -612,6 +612,20 @@ fn matching_symbols( Ok(matches) } +fn unmatched_symbols<'section, 'used>( + section: &'section ObjSection, + section_idx: usize, + used: Option<&'used HashSet>, +) -> impl Iterator + 'used +where + 'section: 'used, +{ + section.symbols.iter().enumerate().filter(move |&(symbol_idx, _)| { + // Skip symbols that have already been matched + !used.map(|u| u.contains(&SymbolRef { section_idx, symbol_idx })).unwrap_or(false) + }) +} + fn find_symbol( obj: Option<&ObjInfo>, in_symbol: &ObjSymbol, @@ -624,8 +638,8 @@ fn find_symbol( if section.kind != in_section.kind { continue; } - if let Some(symbol_idx) = - section.symbols.iter().position(|symbol| symbol.name == in_symbol.name) + if let Some((symbol_idx, _)) = unmatched_symbols(section, section_idx, used) + .find(|(_, symbol)| symbol.name == in_symbol.name) { return Some(SymbolRef { section_idx, symbol_idx }); } @@ -638,9 +652,11 @@ fn find_symbol( if let Some((section_idx, section)) = obj.sections.iter().enumerate().find(|(_, s)| s.name == in_section.name) { - if let Some(symbol_idx) = section.symbols.iter().position(|symbol| { - symbol.address == in_symbol.address && symbol.name.starts_with('@') - }) { + if let Some((symbol_idx, _)) = + unmatched_symbols(section, section_idx, used).find(|(_, symbol)| { + symbol.address == in_symbol.address && symbol.name.starts_with('@') + }) + { return Some(SymbolRef { section_idx, symbol_idx }); } } @@ -655,13 +671,7 @@ fn find_symbol( continue; } if let Some((symbol_idx, _)) = - section.symbols.iter().enumerate().find(|&(symbol_idx, symbol)| { - if used - .map(|u| u.contains(&SymbolRef { section_idx, symbol_idx })) - .unwrap_or(false) - { - return false; - } + unmatched_symbols(section, section_idx, used).find(|&(_, symbol)| { if let Some((p, s)) = symbol.name.split_once('$') { prefix == p && s.chars().all(char::is_numeric) } else { diff --git a/objdiff-core/src/obj/read.rs b/objdiff-core/src/obj/read.rs index 6f103fe..6ff9f93 100644 --- a/objdiff-core/src/obj/read.rs +++ b/objdiff-core/src/obj/read.rs @@ -160,6 +160,23 @@ fn symbols_by_section( } } } + if result.is_empty() { + // Dummy symbol for empty sections + result.push(ObjSymbol { + name: format!("[{}]", section.name), + demangled_name: None, + has_extab: false, + extab_name: None, + extabindex_name: None, + address: 0, + section_address: 0, + size: section.size, + size_known: true, + flags: Default::default(), + addend: 0, + virtual_address: None, + }); + } Ok(result) } diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index 50ec6b2..ed59bb4 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -233,21 +233,23 @@ fn symbol_ui( { selected = symbol_diff.symbol_ref == sym_ref; } - write_text("[", appearance.text_color, &mut job, appearance.code_font.clone()); - if symbol.flags.0.contains(ObjSymbolFlags::Common) { - write_text("c", appearance.replace_color, &mut job, appearance.code_font.clone()); - } else if symbol.flags.0.contains(ObjSymbolFlags::Global) { - write_text("g", appearance.insert_color, &mut job, appearance.code_font.clone()); - } else if symbol.flags.0.contains(ObjSymbolFlags::Local) { - write_text("l", appearance.text_color, &mut job, appearance.code_font.clone()); + if !symbol.flags.0.is_empty() { + write_text("[", appearance.text_color, &mut job, appearance.code_font.clone()); + if symbol.flags.0.contains(ObjSymbolFlags::Common) { + write_text("c", appearance.replace_color, &mut job, appearance.code_font.clone()); + } else if symbol.flags.0.contains(ObjSymbolFlags::Global) { + write_text("g", appearance.insert_color, &mut job, appearance.code_font.clone()); + } else if symbol.flags.0.contains(ObjSymbolFlags::Local) { + write_text("l", appearance.text_color, &mut job, appearance.code_font.clone()); + } + if symbol.flags.0.contains(ObjSymbolFlags::Weak) { + write_text("w", appearance.text_color, &mut job, appearance.code_font.clone()); + } + if symbol.flags.0.contains(ObjSymbolFlags::Hidden) { + write_text("h", appearance.deemphasized_text_color, &mut job, appearance.code_font.clone()); + } + write_text("] ", appearance.text_color, &mut job, appearance.code_font.clone()); } - if symbol.flags.0.contains(ObjSymbolFlags::Weak) { - write_text("w", appearance.text_color, &mut job, appearance.code_font.clone()); - } - if symbol.flags.0.contains(ObjSymbolFlags::Hidden) { - write_text("h", appearance.deemphasized_text_color, &mut job, appearance.code_font.clone()); - } - write_text("] ", appearance.text_color, &mut job, appearance.code_font.clone()); if let Some(match_percent) = symbol_diff.match_percent { write_text("(", appearance.text_color, &mut job, appearance.code_font.clone()); write_text(