From 23009bf9a31e1b7f94c0ccd027e2d8d217d307f2 Mon Sep 17 00:00:00 2001 From: LagoLunatic Date: Tue, 2 Sep 2025 21:37:17 -0400 Subject: [PATCH] Implement diffing individual data symbols (#244) * Implement diffing individual data symbols * Remove unused code for diffing sections * Data diff view: Make rows show offset within the symbol, not within the section * Remove SelectedSymbol enum as it only has a single variant now * Create fake data section symbols to allow diffing entire sections again * Fix text sections not having their size zeroed out * Update test snapshots * Clean up code for inferring section symbol size * Fix bug where PPC pool references weren't ignoring section symbols * Update comment * Always add unique section symbols for data sections * Update test snapshots * Remove unnecessary clone in format! call * Auto-start mapping for unpaired data symbols --- objdiff-cli/src/cmd/report.rs | 3 +- objdiff-core/src/arch/ppc/mod.rs | 2 + objdiff-core/src/diff/code.rs | 10 +- objdiff-core/src/diff/data.rs | 240 ++++++++++++------ objdiff-core/src/diff/mod.rs | 19 +- objdiff-core/src/obj/read.rs | 57 ++++- .../tests/snapshots/arch_arm__read_arm.snap | 13 + .../arch_mips__filter_non_matching.snap | 13 + .../snapshots/arch_mips__read_mips-3.snap | 4 +- .../tests/snapshots/arch_mips__read_mips.snap | 41 ++- .../tests/snapshots/arch_ppc__diff_ppc-2.snap | 4 + .../tests/snapshots/arch_ppc__diff_ppc.snap | 3 +- .../tests/snapshots/arch_ppc__read_extab.snap | 26 ++ .../tests/snapshots/arch_ppc__read_ppc.snap | 15 +- .../snapshots/arch_ppc__read_vmx128_coff.snap | 39 +++ .../tests/snapshots/arch_x86__read_x86.snap | 13 + .../snapshots/arch_x86__read_x86_64.snap | 195 ++++++++++++++ objdiff-gui/src/views/data_diff.rs | 10 +- objdiff-gui/src/views/diff.rs | 170 +++++-------- objdiff-gui/src/views/symbol_diff.rs | 31 +-- 20 files changed, 687 insertions(+), 221 deletions(-) diff --git a/objdiff-cli/src/cmd/report.rs b/objdiff-cli/src/cmd/report.rs index df7822c..4eee29b 100644 --- a/objdiff-cli/src/cmd/report.rs +++ b/objdiff-cli/src/cmd/report.rs @@ -9,7 +9,7 @@ use objdiff_core::{ }, config::path::platform_path, diff, - obj::{self, SectionKind, SymbolFlag}, + obj::{self, SectionKind, SymbolFlag, SymbolKind}, }; use prost::Message; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; @@ -247,6 +247,7 @@ fn report_object( || symbol.size == 0 || symbol.flags.contains(SymbolFlag::Hidden) || symbol.flags.contains(SymbolFlag::Ignored) + || symbol.kind == SymbolKind::Section { continue; } diff --git a/objdiff-core/src/arch/ppc/mod.rs b/objdiff-core/src/arch/ppc/mod.rs index a40648e..c23ba95 100644 --- a/objdiff-core/src/arch/ppc/mod.rs +++ b/objdiff-core/src/arch/ppc/mod.rs @@ -21,6 +21,7 @@ use crate::{ obj::{ FlowAnalysisResult, InstructionRef, Object, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation, Section, Symbol, SymbolFlag, SymbolFlagSet, + SymbolKind, }, }; @@ -832,6 +833,7 @@ fn make_fake_pool_reloc( && s.size > 0 && !s.flags.contains(SymbolFlag::Hidden) && !s.flags.contains(SymbolFlag::Ignored) + && s.kind != SymbolKind::Section && (s.address..s.address + s.size).contains(&target_address) })?; addend = target_address.checked_sub(symbols[target_symbol].address)? as i64; diff --git a/objdiff-core/src/diff/code.rs b/objdiff-core/src/diff/code.rs index 50efcec..605b0ba 100644 --- a/objdiff-core/src/diff/code.rs +++ b/objdiff-core/src/diff/code.rs @@ -41,7 +41,13 @@ pub fn no_diff_code( instruction_rows.push(InstructionDiffRow { ins_ref: Some(*i), ..Default::default() }); } resolve_branches(&ops, &mut instruction_rows); - Ok(SymbolDiff { target_symbol: None, match_percent: None, diff_score: None, instruction_rows }) + Ok(SymbolDiff { + target_symbol: None, + match_percent: None, + diff_score: None, + instruction_rows, + ..Default::default() + }) } const PENALTY_IMM_DIFF: u64 = 1; @@ -147,12 +153,14 @@ pub fn diff_code( match_percent: Some(match_percent), diff_score: Some((diff_score, max_score)), instruction_rows: left_rows, + ..Default::default() }, SymbolDiff { target_symbol: Some(left_symbol_idx), match_percent: Some(match_percent), diff_score: Some((diff_score, max_score)), instruction_rows: right_rows, + ..Default::default() }, )) } diff --git a/objdiff-core/src/diff/data.rs b/objdiff-core/src/diff/data.rs index 5d08195..3ed4704 100644 --- a/objdiff-core/src/diff/data.rs +++ b/objdiff-core/src/diff/data.rs @@ -24,13 +24,13 @@ pub fn diff_bss_symbol( target_symbol: Some(right_symbol_ref), match_percent: Some(percent), diff_score: None, - instruction_rows: vec![], + ..Default::default() }, SymbolDiff { target_symbol: Some(left_symbol_ref), match_percent: Some(percent), diff_score: None, - instruction_rows: vec![], + ..Default::default() }, )) } @@ -84,7 +84,83 @@ pub fn resolve_relocation<'obj>( ResolvedRelocation { relocation: reloc, symbol } } -/// Compares relocations contained with a certain data range. +/// Compares the bytes within a certain data range. +fn diff_data_range(left_data: &[u8], right_data: &[u8]) -> (f32, Vec, Vec) { + let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data); + let bytes_match_ratio = get_diff_ratio(&ops, left_data.len(), right_data.len()); + + let mut left_data_diff = Vec::::new(); + let mut right_data_diff = Vec::::new(); + for op in ops { + let (tag, left_range, right_range) = op.as_tag_tuple(); + let left_len = left_range.len(); + let right_len = right_range.len(); + let mut len = left_len.max(right_len); + let kind = match tag { + similar::DiffTag::Equal => DataDiffKind::None, + similar::DiffTag::Delete => DataDiffKind::Delete, + similar::DiffTag::Insert => DataDiffKind::Insert, + similar::DiffTag::Replace => { + // Ensure replacements are equal length + len = left_len.min(right_len); + DataDiffKind::Replace + } + }; + let left_data = &left_data[left_range]; + let right_data = &right_data[right_range]; + left_data_diff.push(DataDiff { + data: left_data[..len.min(left_data.len())].to_vec(), + kind, + len, + ..Default::default() + }); + right_data_diff.push(DataDiff { + data: right_data[..len.min(right_data.len())].to_vec(), + kind, + len, + ..Default::default() + }); + if kind == DataDiffKind::Replace { + match left_len.cmp(&right_len) { + Ordering::Less => { + let len = right_len - left_len; + left_data_diff.push(DataDiff { + data: vec![], + kind: DataDiffKind::Insert, + len, + ..Default::default() + }); + right_data_diff.push(DataDiff { + data: right_data[left_len..right_len].to_vec(), + kind: DataDiffKind::Insert, + len, + ..Default::default() + }); + } + Ordering::Greater => { + let len = left_len - right_len; + left_data_diff.push(DataDiff { + data: left_data[right_len..left_len].to_vec(), + kind: DataDiffKind::Delete, + len, + ..Default::default() + }); + right_data_diff.push(DataDiff { + data: vec![], + kind: DataDiffKind::Delete, + len, + ..Default::default() + }); + } + Ordering::Equal => {} + } + } + } + + (bytes_match_ratio, left_data_diff, right_data_diff) +} + +/// Compares relocations contained within a certain data range. fn diff_data_relocs_for_range<'left, 'right>( left_obj: &'left Object, right_obj: &'right Object, @@ -186,76 +262,10 @@ pub fn diff_data_section( .min(right_section.size); let left_data = &left_section.data[..left_max as usize]; let right_data = &right_section.data[..right_max as usize]; - let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data); - let match_percent = get_diff_ratio(&ops, left_data.len(), right_data.len()) * 100.0; - let mut left_data_diff = Vec::::new(); - let mut right_data_diff = Vec::::new(); - for op in ops { - let (tag, left_range, right_range) = op.as_tag_tuple(); - let left_len = left_range.len(); - let right_len = right_range.len(); - let mut len = left_len.max(right_len); - let kind = match tag { - similar::DiffTag::Equal => DataDiffKind::None, - similar::DiffTag::Delete => DataDiffKind::Delete, - similar::DiffTag::Insert => DataDiffKind::Insert, - similar::DiffTag::Replace => { - // Ensure replacements are equal length - len = left_len.min(right_len); - DataDiffKind::Replace - } - }; - let left_data = &left_section.data[left_range]; - let right_data = &right_section.data[right_range]; - left_data_diff.push(DataDiff { - data: left_data[..len.min(left_data.len())].to_vec(), - kind, - len, - ..Default::default() - }); - right_data_diff.push(DataDiff { - data: right_data[..len.min(right_data.len())].to_vec(), - kind, - len, - ..Default::default() - }); - if kind == DataDiffKind::Replace { - match left_len.cmp(&right_len) { - Ordering::Less => { - let len = right_len - left_len; - left_data_diff.push(DataDiff { - data: vec![], - kind: DataDiffKind::Insert, - len, - ..Default::default() - }); - right_data_diff.push(DataDiff { - data: right_data[left_len..right_len].to_vec(), - kind: DataDiffKind::Insert, - len, - ..Default::default() - }); - } - Ordering::Greater => { - let len = left_len - right_len; - left_data_diff.push(DataDiff { - data: left_data[right_len..left_len].to_vec(), - kind: DataDiffKind::Delete, - len, - ..Default::default() - }); - right_data_diff.push(DataDiff { - data: vec![], - kind: DataDiffKind::Delete, - len, - ..Default::default() - }); - } - Ordering::Equal => {} - } - } - } + let (bytes_match_ratio, left_data_diff, right_data_diff) = + diff_data_range(left_data, right_data); + let match_percent = bytes_match_ratio * 100.0; let mut left_reloc_diffs = Vec::new(); let mut right_reloc_diffs = Vec::new(); @@ -314,6 +324,55 @@ pub fn diff_data_section( Ok((left_section_diff, right_section_diff)) } +pub fn no_diff_data_symbol(obj: &Object, symbol_index: usize) -> Result { + let symbol = &obj.symbols[symbol_index]; + let section_idx = symbol.section.ok_or_else(|| anyhow!("Data symbol section not found"))?; + let section = &obj.sections[section_idx]; + + let start = symbol + .address + .checked_sub(section.address) + .ok_or_else(|| anyhow!("Symbol address out of section bounds"))?; + let end = start + symbol.size; + if end > section.size { + return Err(anyhow!( + "Symbol {} size out of section bounds ({} > {})", + symbol.name, + end, + section.size + )); + } + let range = start as usize..end as usize; + let data = §ion.data[range.clone()]; + + let len = symbol.size as usize; + let data_diff = + vec![DataDiff { data: data.to_vec(), kind: DataDiffKind::None, len, ..Default::default() }]; + + let mut reloc_diffs = Vec::new(); + for reloc in section.relocations.iter() { + if !range.contains(&(reloc.address as usize)) { + continue; + } + let reloc_len = obj.arch.data_reloc_size(reloc.flags); + let range = reloc.address as usize..reloc.address as usize + reloc_len; + reloc_diffs.push(DataRelocationDiff { + reloc: reloc.clone(), + kind: DataDiffKind::None, + range, + }); + } + + Ok(SymbolDiff { + target_symbol: None, + match_percent: None, + diff_score: None, + data_diff, + data_reloc_diff: reloc_diffs, + ..Default::default() + }) +} + pub fn diff_data_symbol( left_obj: &Object, right_obj: &Object, @@ -362,6 +421,9 @@ pub fn diff_data_symbol( let left_data = &left_section.data[left_range.clone()]; let right_data = &right_section.data[right_range.clone()]; + let (bytes_match_ratio, left_data_diff, right_data_diff) = + diff_data_range(left_data, right_data); + let reloc_diffs = diff_data_relocs_for_range( left_obj, right_obj, @@ -371,10 +433,9 @@ pub fn diff_data_symbol( right_range, ); - let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data); - let bytes_match_ratio = get_diff_ratio(&ops, left_data.len(), right_data.len()); - let mut match_ratio = bytes_match_ratio; + let mut left_reloc_diffs = Vec::new(); + let mut right_reloc_diffs = Vec::new(); if !reloc_diffs.is_empty() { let mut total_reloc_bytes = 0; let mut matching_reloc_bytes = 0; @@ -390,6 +451,27 @@ pub fn diff_data_symbol( if diff_kind == DataDiffKind::None { matching_reloc_bytes += reloc_diff_len; } + + if let Some(left_reloc) = left_reloc { + let len = left_obj.arch.data_reloc_size(left_reloc.relocation.flags); + let range = left_reloc.relocation.address as usize + ..left_reloc.relocation.address as usize + len; + left_reloc_diffs.push(DataRelocationDiff { + reloc: left_reloc.relocation.clone(), + kind: diff_kind, + range, + }); + } + if let Some(right_reloc) = right_reloc { + let len = right_obj.arch.data_reloc_size(right_reloc.relocation.flags); + let range = right_reloc.relocation.address as usize + ..right_reloc.relocation.address as usize + len; + right_reloc_diffs.push(DataRelocationDiff { + reloc: right_reloc.relocation.clone(), + kind: diff_kind, + range, + }); + } } if total_reloc_bytes > 0 { let relocs_match_ratio = matching_reloc_bytes as f32 / total_reloc_bytes as f32; @@ -411,13 +493,17 @@ pub fn diff_data_symbol( target_symbol: Some(right_symbol_idx), match_percent: Some(match_percent), diff_score: None, - instruction_rows: vec![], + data_diff: left_data_diff, + data_reloc_diff: left_reloc_diffs, + ..Default::default() }, SymbolDiff { target_symbol: Some(left_symbol_idx), match_percent: Some(match_percent), diff_score: None, - instruction_rows: vec![], + data_diff: right_data_diff, + data_reloc_diff: right_reloc_diffs, + ..Default::default() }, )) } diff --git a/objdiff-core/src/diff/mod.rs b/objdiff-core/src/diff/mod.rs index 7f954f2..919ba85 100644 --- a/objdiff-core/src/diff/mod.rs +++ b/objdiff-core/src/diff/mod.rs @@ -13,7 +13,8 @@ use crate::{ code::{diff_code, no_diff_code}, data::{ diff_bss_section, diff_bss_symbol, diff_data_section, diff_data_symbol, - diff_generic_section, no_diff_bss_section, no_diff_data_section, symbol_name_matches, + diff_generic_section, no_diff_bss_section, no_diff_data_section, no_diff_data_symbol, + symbol_name_matches, }, }, obj::{InstructionRef, Object, Relocation, SectionKind, Symbol, SymbolFlag}, @@ -44,6 +45,8 @@ pub struct SymbolDiff { pub match_percent: Option, pub diff_score: Option<(u64, u64)>, pub instruction_rows: Vec, + pub data_diff: Vec, + pub data_reloc_diff: Vec, } #[derive(Debug, Clone, Default)] @@ -163,7 +166,7 @@ impl ObjectDiff { target_symbol: None, match_percent: None, diff_score: None, - instruction_rows: vec![], + ..Default::default() }); } for _ in obj.sections.iter() { @@ -262,7 +265,11 @@ pub fn diff_objs( left_out.symbols[left_symbol_ref] = no_diff_code(left_obj, left_symbol_ref, diff_config)?; } - SectionKind::Data | SectionKind::Bss | SectionKind::Common => { + SectionKind::Data => { + left_out.symbols[left_symbol_ref] = + no_diff_data_symbol(left_obj, left_symbol_ref)?; + } + SectionKind::Bss | SectionKind::Common => { // Nothing needs to be done } SectionKind::Unknown => unreachable!(), @@ -275,7 +282,11 @@ pub fn diff_objs( right_out.symbols[right_symbol_ref] = no_diff_code(right_obj, right_symbol_ref, diff_config)?; } - SectionKind::Data | SectionKind::Bss | SectionKind::Common => { + SectionKind::Data => { + right_out.symbols[right_symbol_ref] = + no_diff_data_symbol(right_obj, right_symbol_ref)?; + } + SectionKind::Bss | SectionKind::Common => { // Nothing needs to be done } SectionKind::Unknown => unreachable!(), diff --git a/objdiff-core/src/obj/read.rs b/objdiff-core/src/obj/read.rs index 798cf9f..2bb6ad1 100644 --- a/objdiff-core/src/obj/read.rs +++ b/objdiff-core/src/obj/read.rs @@ -15,7 +15,7 @@ use crate::{ diff::{DiffObjConfig, DiffSide}, obj::{ FlowAnalysisResult, Object, Relocation, RelocationFlags, Section, SectionData, SectionFlag, - SectionKind, Symbol, SymbolFlag, SymbolKind, + SectionKind, Symbol, SymbolFlag, SymbolFlagSet, SymbolKind, split_meta::{SPLITMETA_SECTION, SplitMeta}, }, util::{align_data_slice_to, align_u64_to, read_u16, read_u32}, @@ -118,7 +118,7 @@ fn map_symbols( split_meta: Option<&SplitMeta>, ) -> Result<(Vec, Vec)> { let symbol_count = obj_file.symbols().count(); - let mut symbols = Vec::::with_capacity(symbol_count); + let mut symbols = Vec::::with_capacity(symbol_count + obj_file.sections().count()); let mut symbol_indices = Vec::::with_capacity(symbol_count + 1); for obj_symbol in obj_file.symbols() { if symbol_indices.len() <= obj_symbol.index().0 { @@ -135,6 +135,52 @@ fn map_symbols( Ok((symbols, symbol_indices)) } +/// Add an extra fake symbol to the start of each data section in order to allow the user to diff +/// all of the data in the section at once by clicking on this fake symbol at the top of the list. +fn add_section_symbols(sections: &[Section], symbols: &mut Vec) { + for (section_idx, section) in sections.iter().enumerate() { + if section.kind != SectionKind::Data { + continue; + } + + // Instead of naming the fake section symbol after `section.name` (e.g. ".data") we use + // `section.id` (e.g. ".data-0") so that it is unique when multiple sections with the same + // name exist and it also doesn't conflict with any real section symbols from the object. + let name = if section.flags.contains(SectionFlag::Combined) { + // For combined sections, `section.id` (e.g. ".data-combined") is inconsistent with + // uncombined section IDs, so we add the "-0" suffix to the name to enable proper + // pairing when one side had multiple sections combined and the other only had one + // section to begin with. + format!("[{}-0]", section.name) + } else { + format!("[{}]", section.id) + }; + + // `section.size` can include extra padding, so instead prefer using the address that the + // last symbol ends at when there are any symbols in the section. + let size = symbols + .iter() + .filter(|s| { + s.section == Some(section_idx) && s.kind == SymbolKind::Object && s.size > 0 + }) + .map(|s| s.address + s.size) + .max() + .unwrap_or(section.size); + + symbols.push(Symbol { + name, + demangled_name: None, + address: 0, + size, + kind: SymbolKind::Section, + section: Some(section_idx), + flags: SymbolFlagSet::default() | SymbolFlag::Local, + align: None, + virtual_address: None, + }); + } +} + /// When inferring a symbol's size, we ignore symbols that start with specific prefixes. They are /// usually emitted as branch targets and do not represent the start of a function or object. fn is_local_label(symbol: &Symbol) -> bool { @@ -216,7 +262,11 @@ fn infer_symbol_sizes(arch: &dyn Arch, symbols: &mut [Symbol], sections: &[Secti let section = §ions[section_idx]; let next_address = next_symbol.map(|s| s.address).unwrap_or_else(|| section.address + section.size); - let new_size = if section.kind == SectionKind::Code { + let new_size = if symbol.kind == SymbolKind::Section && section.kind == SectionKind::Data { + // Data sections already have always-visible section symbols created by objdiff to allow + // diffing them, so no need to unhide these. + 0 + } else if section.kind == SectionKind::Code { arch.infer_function_size(symbol, section, next_address)? } else { next_address.saturating_sub(symbol.address) @@ -954,6 +1004,7 @@ pub fn parse(data: &[u8], config: &DiffObjConfig, diff_side: DiffSide) -> Result if config.combine_data_sections || config.combine_text_sections { combine_sections(&mut sections, &mut symbols, config)?; } + add_section_symbols(§ions, &mut symbols); arch.post_init(§ions, &symbols); let mut obj = Object { arch, diff --git a/objdiff-core/tests/snapshots/arch_arm__read_arm.snap b/objdiff-core/tests/snapshots/arch_arm__read_arm.snap index f3df1fe..674a3b0 100644 --- a/objdiff-core/tests/snapshots/arch_arm__read_arm.snap +++ b/objdiff-core/tests/snapshots/arch_arm__read_arm.snap @@ -1507,6 +1507,19 @@ Object { align: None, virtual_address: None, }, + Symbol { + name: "[.data-0]", + demangled_name: None, + address: 0, + size: 76, + kind: Section, + section: Some( + 2, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ], sections: [ Section { diff --git a/objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap b/objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap index 99db1a2..eca6306 100644 --- a/objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap +++ b/objdiff-core/tests/snapshots/arch_mips__filter_non_matching.snap @@ -449,4 +449,17 @@ expression: obj.symbols align: None, virtual_address: None, }, + Symbol { + name: "[.data-0]", + demangled_name: None, + address: 0, + size: 0, + kind: Section, + section: Some( + 2, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ] diff --git a/objdiff-core/tests/snapshots/arch_mips__read_mips-3.snap b/objdiff-core/tests/snapshots/arch_mips__read_mips-3.snap index 7e9faad..6a5288f 100644 --- a/objdiff-core/tests/snapshots/arch_mips__read_mips-3.snap +++ b/objdiff-core/tests/snapshots/arch_mips__read_mips-3.snap @@ -10,10 +10,10 @@ expression: output [(Address(20), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jal", 2), Normal, 10), (Symbol(Symbol { name: "xglSleep", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)] [(Address(24), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 113), Normal, 10), (Eol, Normal, 0)] [(Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lw", 26), Normal, 10), (Argument(Opaque("$a1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%gp_rel("), Normal, 0), (Symbol(Symbol { name: "WorkEnd", demangled_name: None, address: 64, size: 4, kind: Object, section: Some(8), flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("$gp")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)] -[(Address(32), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lui", 20), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%hi("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 64, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)] +[(Address(32), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lui", 20), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%hi("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 0, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)] [(Address(36), Normal, 5), (Spacing(4), Normal, 0), (Opcode("daddu", 97), Normal, 10), (Argument(Opaque("$a2")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$zero")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$zero")), Normal, 0), (Eol, Normal, 0)] [(Address(40), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jal", 2), Normal, 10), (Symbol(Symbol { name: "xglSoundLoadEffect", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)] -[(Address(44), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addiu", 12), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%lo("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 64, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)] +[(Address(44), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addiu", 12), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%lo("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 0, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)] [(Address(48), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lui", 20), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%hi("), Normal, 0), (Symbol(Symbol { name: "PacketBottomNewVu1DropMicroCode", demangled_name: None, address: 0, size: 12, kind: Object, section: Some(7), flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)] [(Address(52), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lw", 26), Normal, 10), (Argument(Opaque("$a1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%gp_rel("), Normal, 0), (Symbol(Symbol { name: "WorkEnd", demangled_name: None, address: 64, size: 4, kind: Object, section: Some(8), flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("$gp")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)] [(Address(56), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jal", 2), Normal, 10), (Symbol(Symbol { name: "xglSoundLoadSwd", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)] diff --git a/objdiff-core/tests/snapshots/arch_mips__read_mips.snap b/objdiff-core/tests/snapshots/arch_mips__read_mips.snap index 4eeebfa..dd4de0d 100644 --- a/objdiff-core/tests/snapshots/arch_mips__read_mips.snap +++ b/objdiff-core/tests/snapshots/arch_mips__read_mips.snap @@ -112,7 +112,7 @@ Object { name: "[.sdata]", demangled_name: None, address: 0, - size: 64, + size: 0, kind: Section, section: Some( 8, @@ -673,6 +673,45 @@ Object { align: None, virtual_address: None, }, + Symbol { + name: "[.data-0]", + demangled_name: None, + address: 0, + size: 0, + kind: Section, + section: Some( + 2, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.rodata-0]", + demangled_name: None, + address: 0, + size: 12, + kind: Section, + section: Some( + 7, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.sdata-0]", + demangled_name: None, + address: 0, + size: 76, + kind: Section, + section: Some( + 8, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ], sections: [ Section { diff --git a/objdiff-core/tests/snapshots/arch_ppc__diff_ppc-2.snap b/objdiff-core/tests/snapshots/arch_ppc__diff_ppc-2.snap index 4a464d4..a86efe3 100644 --- a/objdiff-core/tests/snapshots/arch_ppc__diff_ppc-2.snap +++ b/objdiff-core/tests/snapshots/arch_ppc__diff_ppc-2.snap @@ -2645,6 +2645,8 @@ expression: "(target_symbol_diff, base_symbol_diff)" arg_diff: [], }, ], + data_diff: [], + data_reloc_diff: [], }, SymbolDiff { target_symbol: Some( @@ -5288,5 +5290,7 @@ expression: "(target_symbol_diff, base_symbol_diff)" arg_diff: [], }, ], + data_diff: [], + data_reloc_diff: [], }, ) diff --git a/objdiff-core/tests/snapshots/arch_ppc__diff_ppc.snap b/objdiff-core/tests/snapshots/arch_ppc__diff_ppc.snap index 707c931..1fb15ee 100644 --- a/objdiff-core/tests/snapshots/arch_ppc__diff_ppc.snap +++ b/objdiff-core/tests/snapshots/arch_ppc__diff_ppc.snap @@ -1,6 +1,5 @@ --- source: objdiff-core/tests/arch_ppc.rs -assertion_line: 70 expression: sections_display --- [ @@ -37,7 +36,7 @@ expression: sections_display ), symbols: [ SectionDisplaySymbol { - symbol: 2, + symbol: 16, is_mapping_symbol: false, }, ], diff --git a/objdiff-core/tests/snapshots/arch_ppc__read_extab.snap b/objdiff-core/tests/snapshots/arch_ppc__read_extab.snap index cc1ac64..e9b4ce9 100644 --- a/objdiff-core/tests/snapshots/arch_ppc__read_extab.snap +++ b/objdiff-core/tests/snapshots/arch_ppc__read_extab.snap @@ -308,6 +308,32 @@ Object { align: None, virtual_address: None, }, + Symbol { + name: "[extab-0]", + demangled_name: None, + address: 0, + size: 40, + kind: Section, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[extabindex-0]", + demangled_name: None, + address: 0, + size: 36, + kind: Section, + section: Some( + 2, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ], sections: [ Section { diff --git a/objdiff-core/tests/snapshots/arch_ppc__read_ppc.snap b/objdiff-core/tests/snapshots/arch_ppc__read_ppc.snap index 2152e56..ebbfcaf 100644 --- a/objdiff-core/tests/snapshots/arch_ppc__read_ppc.snap +++ b/objdiff-core/tests/snapshots/arch_ppc__read_ppc.snap @@ -43,7 +43,7 @@ Object { name: "[.ctors]", demangled_name: None, address: 0, - size: 4, + size: 0, kind: Section, section: Some( 1, @@ -157,6 +157,19 @@ Object { 0, ), }, + Symbol { + name: "[.ctors-0]", + demangled_name: None, + address: 0, + size: 4, + kind: Section, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ], sections: [ Section { diff --git a/objdiff-core/tests/snapshots/arch_ppc__read_vmx128_coff.snap b/objdiff-core/tests/snapshots/arch_ppc__read_vmx128_coff.snap index 0f88302..b8c6106 100644 --- a/objdiff-core/tests/snapshots/arch_ppc__read_vmx128_coff.snap +++ b/objdiff-core/tests/snapshots/arch_ppc__read_vmx128_coff.snap @@ -1101,6 +1101,45 @@ Object { align: None, virtual_address: None, }, + Symbol { + name: "[.XBLD$W-0]", + demangled_name: None, + address: 0, + size: 16, + kind: Section, + section: Some( + 2, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.rdata-0]", + demangled_name: None, + address: 0, + size: 416, + kind: Section, + section: Some( + 4, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.pdata-0]", + demangled_name: None, + address: 0, + size: 40, + kind: Section, + section: Some( + 6, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ], sections: [ Section { diff --git a/objdiff-core/tests/snapshots/arch_x86__read_x86.snap b/objdiff-core/tests/snapshots/arch_x86__read_x86.snap index 92dc5cc..1b3484d 100644 --- a/objdiff-core/tests/snapshots/arch_x86__read_x86.snap +++ b/objdiff-core/tests/snapshots/arch_x86__read_x86.snap @@ -124,6 +124,19 @@ Object { align: None, virtual_address: None, }, + Symbol { + name: "[.data-0]", + demangled_name: None, + address: 0, + size: 10, + kind: Section, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ], sections: [ Section { diff --git a/objdiff-core/tests/snapshots/arch_x86__read_x86_64.snap b/objdiff-core/tests/snapshots/arch_x86__read_x86_64.snap index cc95831..3eeca80 100644 --- a/objdiff-core/tests/snapshots/arch_x86__read_x86_64.snap +++ b/objdiff-core/tests/snapshots/arch_x86__read_x86_64.snap @@ -854,6 +854,201 @@ Object { align: None, virtual_address: None, }, + Symbol { + name: "[.xdata-0]", + demangled_name: None, + address: 0, + size: 8, + kind: Section, + section: Some( + 7, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.pdata-0]", + demangled_name: None, + address: 0, + size: 12, + kind: Section, + section: Some( + 8, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.xdata-1]", + demangled_name: None, + address: 0, + size: 8, + kind: Section, + section: Some( + 9, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.pdata-1]", + demangled_name: None, + address: 0, + size: 12, + kind: Section, + section: Some( + 10, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.xdata-2]", + demangled_name: None, + address: 0, + size: 8, + kind: Section, + section: Some( + 11, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.pdata-2]", + demangled_name: None, + address: 0, + size: 12, + kind: Section, + section: Some( + 12, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.xdata-3]", + demangled_name: None, + address: 0, + size: 8, + kind: Section, + section: Some( + 13, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.pdata-3]", + demangled_name: None, + address: 0, + size: 12, + kind: Section, + section: Some( + 14, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.rdata-0]", + demangled_name: None, + address: 0, + size: 256, + kind: Section, + section: Some( + 15, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.xdata-4]", + demangled_name: None, + address: 0, + size: 20, + kind: Section, + section: Some( + 16, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.pdata-4]", + demangled_name: None, + address: 0, + size: 12, + kind: Section, + section: Some( + 17, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.rtc$IMZ-0]", + demangled_name: None, + address: 0, + size: 8, + kind: Section, + section: Some( + 19, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.rtc$TMZ-0]", + demangled_name: None, + address: 0, + size: 8, + kind: Section, + section: Some( + 20, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.rdata-1]", + demangled_name: None, + address: 0, + size: 4, + kind: Section, + section: Some( + 21, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.rdata-2]", + demangled_name: None, + address: 0, + size: 4, + kind: Section, + section: Some( + 22, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, ], sections: [ Section { diff --git a/objdiff-gui/src/views/data_diff.rs b/objdiff-gui/src/views/data_diff.rs index 9b9cc22..6a68636 100644 --- a/objdiff-gui/src/views/data_diff.rs +++ b/objdiff-gui/src/views/data_diff.rs @@ -115,7 +115,8 @@ fn get_hover_item_color_for_diff_kind(diff_kind: DataDiffKind) -> HoverItemColor pub(crate) fn data_row_ui( ui: &mut egui::Ui, obj: Option<&Object>, - address: usize, + base_address: usize, + row_address: usize, diffs: &[(DataDiff, Vec)], appearance: &Appearance, column: usize, @@ -127,7 +128,7 @@ pub(crate) fn data_row_ui( } let mut job = LayoutJob::default(); write_text( - format!("{address:08x}: ").as_str(), + format!("{row_address:08x}: ").as_str(), appearance.text_color, &mut job, appearance.code_font.clone(), @@ -135,7 +136,7 @@ pub(crate) fn data_row_ui( // The offset shown on the side of the GUI, shifted by insertions/deletions. let mut cur_addr = 0usize; // The offset into the actual bytes of the section on this side, ignoring differences. - let mut cur_addr_actual = address; + let mut cur_addr_actual = base_address + row_address; for (diff, reloc_diffs) in diffs { let base_color = get_color_for_diff_kind(diff.kind, appearance); if diff.data.is_empty() { @@ -211,13 +212,14 @@ pub(crate) fn data_row_ui( pub(crate) fn split_diffs( diffs: &[DataDiff], reloc_diffs: &[DataRelocationDiff], + symbol_offset_in_section: usize, ) -> Vec)>> { let mut split_diffs = Vec::)>>::new(); let mut row_diffs = Vec::<(DataDiff, Vec)>::new(); // The offset shown on the side of the GUI, shifted by insertions/deletions. let mut cur_addr = 0usize; // The offset into the actual bytes of the section on this side, ignoring differences. - let mut cur_addr_actual = 0usize; + let mut cur_addr_actual = symbol_offset_in_section; for diff in diffs { let mut cur_len = 0usize; while cur_len < diff.len { diff --git a/objdiff-gui/src/views/diff.rs b/objdiff-gui/src/views/diff.rs index 6577eae..695c95b 100644 --- a/objdiff-gui/src/views/diff.rs +++ b/objdiff-gui/src/views/diff.rs @@ -2,10 +2,10 @@ use egui::{Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget, text::LayoutJ use objdiff_core::{ build::BuildStatus, diff::{ - DiffObjConfig, ObjectDiff, SectionDiff, SymbolDiff, + DiffObjConfig, ObjectDiff, SymbolDiff, display::{ContextItem, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind}, }, - obj::{Object, Section, Symbol}, + obj::{Object, Symbol}, }; use time::format_description; @@ -25,17 +25,10 @@ use crate::{ }, }; -#[derive(Clone, Copy)] -enum SelectedSymbol { - Symbol(usize), - Section(usize), -} - #[derive(Clone, Copy)] struct DiffColumnContext<'a> { status: &'a BuildStatus, obj: Option<&'a (Object, ObjectDiff)>, - section: Option<(&'a Section, &'a SectionDiff, usize)>, symbol: Option<(&'a Symbol, &'a SymbolDiff, usize)>, } @@ -46,49 +39,28 @@ impl<'a> DiffColumnContext<'a> { obj: Option<&'a (Object, ObjectDiff)>, selected_symbol: Option<&SymbolRefByName>, ) -> Self { - let selected_symbol = match view { + let selected_symbol_idx = match view { View::SymbolDiff => None, - View::FunctionDiff | View::ExtabDiff => match (obj, selected_symbol) { - (Some(obj), Some(s)) => { - obj.0.symbol_by_name(&s.symbol_name).map(SelectedSymbol::Symbol) - } - _ => None, - }, - View::DataDiff => match (obj, selected_symbol) { - (Some(obj), Some(SymbolRefByName { section_name: Some(section_name), .. })) => { - find_section(&obj.0, section_name).map(SelectedSymbol::Section) - } + View::FunctionDiff | View::DataDiff | View::ExtabDiff => match (obj, selected_symbol) { + (Some(obj), Some(s)) => obj.0.symbol_by_name(&s.symbol_name), _ => None, }, }; - let (section, symbol) = match (obj, selected_symbol) { - (Some((obj, obj_diff)), Some(SelectedSymbol::Symbol(symbol_ref))) => { + let symbol = match (obj, selected_symbol_idx) { + (Some((obj, obj_diff)), Some(symbol_ref)) => { let symbol = &obj.symbols[symbol_ref]; - ( - symbol.section.map(|section_idx| { - (&obj.sections[section_idx], &obj_diff.sections[section_idx], section_idx) - }), - Some((symbol, &obj_diff.symbols[symbol_ref], symbol_ref)), - ) + Some((symbol, &obj_diff.symbols[symbol_ref], symbol_ref)) } - (Some((obj, obj_diff)), Some(SelectedSymbol::Section(section_idx))) => ( - Some((&obj.sections[section_idx], &obj_diff.sections[section_idx], section_idx)), - None, - ), - _ => (None, None), + _ => None, }; - Self { status, obj, section, symbol } + Self { status, obj, symbol } } #[inline] - pub fn has_symbol(&self) -> bool { self.section.is_some() || self.symbol.is_some() } + pub fn has_symbol(&self) -> bool { self.symbol.is_some() } #[inline] - pub fn id(&self) -> Option<&str> { - self.symbol - .map(|(symbol, _, _)| symbol.name.as_str()) - .or_else(|| self.section.map(|(section, _, _)| section.name.as_str())) - } + pub fn id(&self) -> Option<&str> { self.symbol.map(|(symbol, _, _)| symbol.name.as_str()) } } #[must_use] @@ -133,10 +105,7 @@ pub fn diff_view_ui( { navigation.right_symbol = Some(target_symbol_ref); } - } else if navigation.left_symbol.is_some() - && left_ctx.obj.is_some() - && left_ctx.section.is_none() - { + } else if navigation.left_symbol.is_some() && left_ctx.obj.is_some() { // Clear selection if symbol goes missing navigation.left_symbol = None; } @@ -147,10 +116,7 @@ pub fn diff_view_ui( { navigation.left_symbol = Some(target_symbol_ref); } - } else if navigation.right_symbol.is_some() - && right_ctx.obj.is_some() - && right_ctx.section.is_none() - { + } else if navigation.right_symbol.is_some() && right_ctx.obj.is_some() { // Clear selection if symbol goes missing navigation.right_symbol = None; } @@ -225,12 +191,6 @@ pub fn diff_view_ui( { ret = Some(action); } - } else if let Some((section, _, _)) = left_ctx.section { - ui.label( - RichText::new(section.name.clone()) - .font(appearance.code_font.clone()) - .color(appearance.highlight_color), - ); } else if right_ctx.has_symbol() { ui.label( RichText::new("Choose target symbol") @@ -363,12 +323,6 @@ pub fn diff_view_ui( { ret = Some(action); } - } else if let Some((section, _, _)) = right_ctx.section { - ui.label( - RichText::new(section.name.clone()) - .font(appearance.code_font.clone()) - .color(appearance.highlight_color), - ); } else if left_ctx.has_symbol() { ui.label( RichText::new("Choose base symbol") @@ -509,17 +463,17 @@ pub fn diff_view_ui( View::DataDiff, Some((left_obj, _left_diff)), Some((right_obj, _right_diff)), - Some((_left_section, left_section_diff, _left_symbol_idx)), - Some((_right_section, right_section_diff, _right_symbol_idx)), + Some((left_symbol, left_symbol_diff, _left_symbol_idx)), + Some((right_symbol, right_symbol_diff, _right_symbol_idx)), ) = - (state.current_view, left_ctx.obj, right_ctx.obj, left_ctx.section, right_ctx.section) + (state.current_view, left_ctx.obj, right_ctx.obj, left_ctx.symbol, right_ctx.symbol) { // Joint diff view hotkeys::check_scroll_hotkeys(ui, true); let left_total_bytes = - left_section_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len); + left_symbol_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len); let right_total_bytes = - right_section_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len); + right_symbol_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len); if left_total_bytes != right_total_bytes { ui.label("Data size mismatch"); return; @@ -528,10 +482,16 @@ pub fn diff_view_ui( return; } let total_rows = (left_total_bytes - 1) / BYTES_PER_ROW + 1; - let left_diffs = - split_diffs(&left_section_diff.data_diff, &left_section_diff.reloc_diff); - let right_diffs = - split_diffs(&right_section_diff.data_diff, &right_section_diff.reloc_diff); + let left_diffs = split_diffs( + &left_symbol_diff.data_diff, + &left_symbol_diff.data_reloc_diff, + left_symbol.address as usize, + ); + let right_diffs = split_diffs( + &right_symbol_diff.data_diff, + &right_symbol_diff.data_reloc_diff, + right_symbol.address as usize, + ); render_table( ui, available_width, @@ -540,13 +500,14 @@ pub fn diff_view_ui( total_rows, |row, column| { let i = row.index(); - let address = i * BYTES_PER_ROW; + let row_offset = i * BYTES_PER_ROW; row.col(|ui| { if column == 0 { data_row_ui( ui, Some(left_obj), - address, + left_symbol.address as usize, + row_offset, &left_diffs[i], appearance, column, @@ -555,7 +516,8 @@ pub fn diff_view_ui( data_row_ui( ui, Some(right_obj), - address, + right_symbol.address as usize, + row_offset, &right_diffs[i], appearance, column, @@ -649,11 +611,46 @@ fn diff_col_ui( if !ctx.status.success { build_log_ui(ui, ctx.status, appearance); } else if let Some((obj, diff)) = ctx.obj { - if let Some((_symbol, symbol_diff, symbol_idx)) = ctx.symbol { + if let Some((symbol, symbol_diff, symbol_idx)) = ctx.symbol { hotkeys::check_scroll_hotkeys(ui, false); let ctx = FunctionDiffContext { obj, diff, symbol_ref: Some(symbol_idx) }; if state.current_view == View::ExtabDiff { extab_ui(ui, ctx, appearance, column); + } else if state.current_view == View::DataDiff { + hotkeys::check_scroll_hotkeys(ui, false); + let total_bytes = + symbol_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len); + if total_bytes == 0 { + return ret; + } + let total_rows = (total_bytes - 1) / BYTES_PER_ROW + 1; + let diffs = split_diffs( + &symbol_diff.data_diff, + &symbol_diff.data_reloc_diff, + symbol.address as usize, + ); + render_table( + ui, + available_width / 2.0, + 1, + appearance.code_font.size, + total_rows, + |row, _column| { + let i = row.index(); + let row_offset = i * BYTES_PER_ROW; + row.col(|ui| { + data_row_ui( + ui, + Some(obj), + symbol.address as usize, + row_offset, + &diffs[i], + appearance, + column, + ); + }); + }, + ); } else { render_table( ui, @@ -678,29 +675,6 @@ fn diff_col_ui( }, ); } - } else if let Some((_section, section_diff, _section_idx)) = ctx.section { - hotkeys::check_scroll_hotkeys(ui, false); - let total_bytes = - section_diff.data_diff.iter().fold(0usize, |accum, item| accum + item.len); - if total_bytes == 0 { - return ret; - } - let total_rows = (total_bytes - 1) / BYTES_PER_ROW + 1; - let diffs = split_diffs(§ion_diff.data_diff, §ion_diff.reloc_diff); - render_table( - ui, - available_width / 2.0, - 1, - appearance.code_font.size, - total_rows, - |row, _column| { - let i = row.index(); - let address = i * BYTES_PER_ROW; - row.col(|ui| { - data_row_ui(ui, Some(obj), address, &diffs[i], appearance, column); - }); - }, - ); } else if let Some((_other_symbol, _other_symbol_diff, other_symbol_idx)) = other_ctx.symbol { if let Some(action) = symbol_list_ui( @@ -796,10 +770,6 @@ fn missing_obj_ui(ui: &mut Ui, appearance: &Appearance) { }); } -fn find_section(obj: &Object, section_name: &str) -> Option { - obj.sections.iter().position(|section| section.name == section_name) -} - pub fn hover_items_ui(ui: &mut Ui, items: Vec, appearance: &Appearance) { for item in items { match item { diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index d701f15..6b088e1 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -233,7 +233,6 @@ impl DiffViewState { let resolved_nav = resolve_navigation(nav.kind, resolved_left, resolved_right); if (resolved_nav.left_symbol.is_some() && resolved_nav.right_symbol.is_some()) || (resolved_nav.left_symbol.is_none() && resolved_nav.right_symbol.is_none()) - || resolved_nav.view != View::FunctionDiff { // Regular navigation if state.is_selecting_symbol() { @@ -416,14 +415,8 @@ fn resolve_navigation( }, (SectionKind::Data, SectionKind::Data) => ResolvedNavigation { view: View::DataDiff, - left_symbol: Some(SymbolRefByName { - symbol_name: "".to_string(), - section_name: Some(left.section.name.clone()), - }), - right_symbol: Some(SymbolRefByName { - symbol_name: "".to_string(), - section_name: Some(right.section.name.clone()), - }), + left_symbol: Some(left.symbol_ref), + right_symbol: Some(right.symbol_ref), }, _ => ResolvedNavigation::default(), }, @@ -438,14 +431,8 @@ fn resolve_navigation( }, SectionKind::Data => ResolvedNavigation { view: View::DataDiff, - left_symbol: Some(SymbolRefByName { - symbol_name: "".to_string(), - section_name: Some(left.section.name.clone()), - }), - right_symbol: Some(SymbolRefByName { - symbol_name: "".to_string(), - section_name: Some(left.section.name.clone()), - }), + left_symbol: Some(left.symbol_ref), + right_symbol: None, }, _ => ResolvedNavigation::default(), }, @@ -460,14 +447,8 @@ fn resolve_navigation( }, SectionKind::Data => ResolvedNavigation { view: View::DataDiff, - left_symbol: Some(SymbolRefByName { - symbol_name: "".to_string(), - section_name: Some(right.section.name.clone()), - }), - right_symbol: Some(SymbolRefByName { - symbol_name: "".to_string(), - section_name: Some(right.section.name.clone()), - }), + left_symbol: None, + right_symbol: Some(right.symbol_ref), }, _ => ResolvedNavigation::default(), },