From 1059248692e88467aeee4a10bc867b937211f37a Mon Sep 17 00:00:00 2001 From: dbalatoni13 <40299962+dbalatoni13@users.noreply.github.com> Date: Wed, 31 Dec 2025 04:30:28 +0100 Subject: [PATCH 1/3] Add button to automatically pair up relocs --- objdiff-gui/src/views/diff.rs | 116 +++++++++++++++++++++++++-- objdiff-gui/src/views/symbol_diff.rs | 12 ++- 2 files changed, 122 insertions(+), 6 deletions(-) diff --git a/objdiff-gui/src/views/diff.rs b/objdiff-gui/src/views/diff.rs index f7c4a67..e801341 100644 --- a/objdiff-gui/src/views/diff.rs +++ b/objdiff-gui/src/views/diff.rs @@ -1,17 +1,17 @@ -use std::cmp::Ordering; +use std::{cmp::Ordering, collections::{HashMap, HashSet}}; use egui::{Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget, text::LayoutJob}; use objdiff_core::{ build::BuildStatus, diff::{ - DiffObjConfig, ObjectDiff, SymbolDiff, + DiffObjConfig, FunctionRelocDiffs, InstructionDiffRow, ObjectDiff, SymbolDiff, data::BYTES_PER_ROW, display::{ - ContextItem, DiffText, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind, - display_row, + ContextItem, DiffText, DiffTextSegment, HoverItem, HoverItemColor, SymbolFilter, + SymbolNavigationKind, display_row, }, }, - obj::{InstructionArgValue, Object, Symbol}, + obj::{InstructionArgValue, Object, Symbol, SymbolKind}, util::ReallySigned, }; use time::format_description; @@ -116,6 +116,85 @@ fn get_asm_text( asm_text } +fn extract_symbol_name( + obj: &Object, + symbol_idx: usize, + row: &InstructionDiffRow, + diff_config: &DiffObjConfig, +) -> Option { + let mut result = None; + + let _ = display_row(obj, symbol_idx, row, diff_config, |segment| { + if let DiffTextSegment { text: DiffText::Symbol(sym), .. } = segment + && (sym.kind == SymbolKind::Function || sym.kind == SymbolKind::Object) + { + result = Some(sym.name.clone()); + } + Ok(()) + }); + + result +} + +// Obtains all relocation pairs that match by color. Used to automatically pair them up using a symbol mapping. +fn get_reloc_mappings( + left_obj: &Object, + right_obj: &Object, + left_symbol_diff: &SymbolDiff, + left_symbol_idx: usize, + right_symbol_diff: &SymbolDiff, + right_symbol_idx: usize, + diff_config: &DiffObjConfig, +) -> Vec<(String, String)> { + let mut mappings = Vec::new(); + + for (left_row, right_row) in + left_symbol_diff.instruction_rows.iter().zip(&right_symbol_diff.instruction_rows) + { + let Some(left_name) = extract_symbol_name(left_obj, left_symbol_idx, left_row, diff_config) + else { + continue; + }; + + let Some(right_name) = + extract_symbol_name(right_obj, right_symbol_idx, right_row, diff_config) + else { + continue; + }; + + mappings.push((left_name, right_name)); + } + + // Remove "ambigous" matches (where the left or right side is used in multiple mappings) + let mut left_to_right: HashMap<&String, HashSet<&String>> = HashMap::new(); + let mut right_to_left: HashMap<&String, HashSet<&String>> = HashMap::new(); + + for (left, right) in &mappings { + left_to_right.entry(left).or_default().insert(right); + right_to_left.entry(right).or_default().insert(left); + } + + let ambiguous_left: HashSet<&String> = left_to_right + .iter() + .filter(|(_, rights)| rights.len() > 1) + .map(|(l, _)| *l) + .collect(); + + let ambiguous_right: HashSet<&String> = right_to_left + .iter() + .filter(|(_, lefts)| lefts.len() > 1) + .map(|(r, _)| *r) + .collect(); + + let unambiguous: Vec<(String, String)> = mappings + .iter() + .filter(|(l, r)| !ambiguous_left.contains(l) && !ambiguous_right.contains(r)) + .map(|(l, r)| (l.clone(), r.clone())) + .collect(); + + unambiguous +} + #[must_use] pub fn diff_view_ui( ui: &mut Ui, @@ -215,6 +294,33 @@ pub fn diff_view_ui( } } + if state.current_view == View::FunctionDiff + && let Some((_, left_symbol_diff, left_symbol_idx)) = left_ctx.symbol + && let Some((left_obj, _)) = left_ctx.obj + && let Some((_, right_symbol_diff, right_symbol_idx)) = right_ctx.symbol + && let Some((right_obj, _)) = right_ctx.obj + && ui + .add_enabled( + diff_config.function_reloc_diffs != FunctionRelocDiffs::None + && diff_config.function_reloc_diffs + != FunctionRelocDiffs::DataValue, + egui::Button::new("Pair up relocs"), + ) + .on_hover_text_at_pointer("Automatically pair up symbol names") + .on_disabled_hover_text("Name relocation diffs have to be enabled") + .clicked() + { + ret = Some(DiffViewAction::SetRelocMappings(get_reloc_mappings( + left_obj, + right_obj, + left_symbol_diff, + left_symbol_idx, + right_symbol_diff, + right_symbol_idx, + diff_config, + ))); + } + if state.current_view == View::FunctionDiff && let Some((_, symbol_diff, symbol_idx)) = left_ctx.symbol && let Some((obj, _)) = left_ctx.obj diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index bb40f21..a45e132 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -1,4 +1,4 @@ -use std::mem::take; +use std::{mem::take}; use egui::{ CollapsingHeader, Color32, Id, OpenUrl, ScrollArea, Ui, Widget, style::ScrollAnimation, @@ -77,6 +77,8 @@ pub enum DiffViewAction { SelectingRight(SymbolRefByName), /// Set a symbol mapping. SetMapping(usize, usize), + /// Set a batch of relocation mappings. + SetRelocMappings(Vec<(String, String)>), /// Set the show_mapped_symbols flag SetShowMappedSymbols(bool), /// Set the show_data_flow flag @@ -356,6 +358,14 @@ impl DiffViewState { }; self.post_build_nav = Some(resolved_nav); } + DiffViewAction::SetRelocMappings(mappings) => { + let Ok(mut state) = state.write() else { + return; + }; + for (left_name, right_name) in mappings { + state.set_symbol_mapping(left_name, right_name); + } + } DiffViewAction::SetShowMappedSymbols(value) => { self.symbol_state.show_mapped_symbols = value; } From 989b4006b54555bee32bbac5dc6cb91b35a3320e Mon Sep 17 00:00:00 2001 From: dbalatoni13 <40299962+dbalatoni13@users.noreply.github.com> Date: Wed, 31 Dec 2025 04:32:40 +0100 Subject: [PATCH 2/3] Fix formatting --- objdiff-gui/src/views/diff.rs | 19 ++++++++----------- objdiff-gui/src/views/symbol_diff.rs | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/objdiff-gui/src/views/diff.rs b/objdiff-gui/src/views/diff.rs index e801341..e78f65a 100644 --- a/objdiff-gui/src/views/diff.rs +++ b/objdiff-gui/src/views/diff.rs @@ -1,4 +1,7 @@ -use std::{cmp::Ordering, collections::{HashMap, HashSet}}; +use std::{ + cmp::Ordering, + collections::{HashMap, HashSet}, +}; use egui::{Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget, text::LayoutJob}; use objdiff_core::{ @@ -174,17 +177,11 @@ fn get_reloc_mappings( right_to_left.entry(right).or_default().insert(left); } - let ambiguous_left: HashSet<&String> = left_to_right - .iter() - .filter(|(_, rights)| rights.len() > 1) - .map(|(l, _)| *l) - .collect(); + let ambiguous_left: HashSet<&String> = + left_to_right.iter().filter(|(_, rights)| rights.len() > 1).map(|(l, _)| *l).collect(); - let ambiguous_right: HashSet<&String> = right_to_left - .iter() - .filter(|(_, lefts)| lefts.len() > 1) - .map(|(r, _)| *r) - .collect(); + let ambiguous_right: HashSet<&String> = + right_to_left.iter().filter(|(_, lefts)| lefts.len() > 1).map(|(r, _)| *r).collect(); let unambiguous: Vec<(String, String)> = mappings .iter() diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index a45e132..df3b39f 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -1,4 +1,4 @@ -use std::{mem::take}; +use std::mem::take; use egui::{ CollapsingHeader, Color32, Id, OpenUrl, ScrollArea, Ui, Widget, style::ScrollAnimation, From ac280ade5c9ab90b9b931c835d014d0670d15c09 Mon Sep 17 00:00:00 2001 From: dbalatoni13 <40299962+dbalatoni13@users.noreply.github.com> Date: Wed, 31 Dec 2025 05:07:32 +0100 Subject: [PATCH 3/3] Simplify symbol name extraction and fix comment --- objdiff-gui/src/views/diff.rs | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/objdiff-gui/src/views/diff.rs b/objdiff-gui/src/views/diff.rs index e78f65a..be5f55a 100644 --- a/objdiff-gui/src/views/diff.rs +++ b/objdiff-gui/src/views/diff.rs @@ -10,8 +10,8 @@ use objdiff_core::{ DiffObjConfig, FunctionRelocDiffs, InstructionDiffRow, ObjectDiff, SymbolDiff, data::BYTES_PER_ROW, display::{ - ContextItem, DiffText, DiffTextSegment, HoverItem, HoverItemColor, SymbolFilter, - SymbolNavigationKind, display_row, + ContextItem, DiffText, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind, + display_row, }, }, obj::{InstructionArgValue, Object, Symbol, SymbolKind}, @@ -123,23 +123,15 @@ fn extract_symbol_name( obj: &Object, symbol_idx: usize, row: &InstructionDiffRow, - diff_config: &DiffObjConfig, ) -> Option { - let mut result = None; - - let _ = display_row(obj, symbol_idx, row, diff_config, |segment| { - if let DiffTextSegment { text: DiffText::Symbol(sym), .. } = segment - && (sym.kind == SymbolKind::Function || sym.kind == SymbolKind::Object) - { - result = Some(sym.name.clone()); - } - Ok(()) - }); - - result + let symbol = obj.resolve_instruction_ref(symbol_idx, row.ins_ref?)?.relocation?.symbol; + match symbol.kind { + SymbolKind::Function | SymbolKind::Object => Some(symbol.name.clone()), + _ => None, + } } -// Obtains all relocation pairs that match by color. Used to automatically pair them up using a symbol mapping. +// Obtains all unambigious relocation pairs inside a function. Used to automatically pair them up using a symbol mapping. fn get_reloc_mappings( left_obj: &Object, right_obj: &Object, @@ -147,21 +139,17 @@ fn get_reloc_mappings( left_symbol_idx: usize, right_symbol_diff: &SymbolDiff, right_symbol_idx: usize, - diff_config: &DiffObjConfig, ) -> Vec<(String, String)> { let mut mappings = Vec::new(); for (left_row, right_row) in left_symbol_diff.instruction_rows.iter().zip(&right_symbol_diff.instruction_rows) { - let Some(left_name) = extract_symbol_name(left_obj, left_symbol_idx, left_row, diff_config) - else { + let Some(left_name) = extract_symbol_name(left_obj, left_symbol_idx, left_row) else { continue; }; - let Some(right_name) = - extract_symbol_name(right_obj, right_symbol_idx, right_row, diff_config) - else { + let Some(right_name) = extract_symbol_name(right_obj, right_symbol_idx, right_row) else { continue; }; @@ -314,7 +302,6 @@ pub fn diff_view_ui( left_symbol_idx, right_symbol_diff, right_symbol_idx, - diff_config, ))); }