diff --git a/src/app.rs b/src/app.rs index 7824660..9c33651 100644 --- a/src/app.rs +++ b/src/app.rs @@ -110,6 +110,8 @@ pub struct AppConfig { pub code_alg: DiffAlg, #[serde(default)] pub data_alg: DiffAlg, + #[serde(default)] + pub relax_reloc_diffs: bool, #[serde(skip)] pub objects: Vec, @@ -147,6 +149,7 @@ impl Default for AppConfig { recent_projects: vec![], code_alg: Default::default(), data_alg: Default::default(), + relax_reloc_diffs: false, objects: vec![], object_nodes: vec![], watcher_change: false, @@ -492,6 +495,15 @@ impl eframe::App for App { &mut diff_state.symbol_state.show_hidden_symbols, "Show hidden symbols", ); + if ui + .checkbox(&mut config.relax_reloc_diffs, "Relax relocation diffs") + .on_hover_text( + "Ignores differences in relocation targets. (Address, name, etc)", + ) + .changed() + { + config.queue_reload = true; + } }); }); }); diff --git a/src/diff/code.rs b/src/diff/code.rs index 78f32a1..be9530d 100644 --- a/src/diff/code.rs +++ b/src/diff/code.rs @@ -10,7 +10,7 @@ use similar::{capture_diff_slices_deadline, Algorithm}; use crate::{ diff::{ editops::{editops_find, LevEditType}, - DiffAlg, ProcessCodeResult, + DiffAlg, DiffObjConfig, ProcessCodeResult, }, obj::{ mips, ppc, ObjArchitecture, ObjInfo, ObjInsArg, ObjInsArgDiff, ObjInsBranchFrom, @@ -49,7 +49,7 @@ pub fn no_diff_code( #[allow(clippy::too_many_arguments)] pub fn diff_code( - alg: DiffAlg, + config: &DiffObjConfig, arch: ObjArchitecture, left_data: &[u8], right_data: &[u8], @@ -89,7 +89,7 @@ pub fn diff_code( let mut left_diff = Vec::::new(); let mut right_diff = Vec::::new(); - match alg { + match config.code_alg { DiffAlg::Levenshtein => { diff_instructions_lev( &mut left_diff, @@ -134,7 +134,7 @@ pub fn diff_code( let mut diff_state = InsDiffState::default(); for (left, right) in left_diff.iter_mut().zip(right_diff.iter_mut()) { - let result = compare_ins(left, right, &mut diff_state)?; + let result = compare_ins(config, left, right, &mut diff_state)?; left.kind = result.kind; right.kind = result.kind; left.arg_diff = result.left_args_diff; @@ -322,13 +322,20 @@ fn address_eq(left: &ObjSymbol, right: &ObjSymbol) -> bool { left.address as i64 + left.addend == right.address as i64 + right.addend } -fn reloc_eq(left_reloc: Option<&ObjReloc>, right_reloc: Option<&ObjReloc>) -> bool { +fn reloc_eq( + config: &DiffObjConfig, + left_reloc: Option<&ObjReloc>, + right_reloc: Option<&ObjReloc>, +) -> bool { let (Some(left), Some(right)) = (left_reloc, right_reloc) else { return false; }; if left.kind != right.kind { return false; } + if config.relax_reloc_diffs { + return true; + } let name_matches = left.target.name == right.target.name; match (&left.target_section, &right.target_section) { @@ -346,6 +353,7 @@ fn reloc_eq(left_reloc: Option<&ObjReloc>, right_reloc: Option<&ObjReloc>) -> bo } fn arg_eq( + config: &DiffObjConfig, left: &ObjInsArg, right: &ObjInsArg, left_diff: &ObjInsDiff, @@ -359,6 +367,7 @@ fn arg_eq( ObjInsArg::Reloc => { matches!(right, ObjInsArg::Reloc) && reloc_eq( + config, left_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()), right_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()), ) @@ -366,6 +375,7 @@ fn arg_eq( ObjInsArg::RelocWithBase => { matches!(right, ObjInsArg::RelocWithBase) && reloc_eq( + config, left_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()), right_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()), ) @@ -398,6 +408,7 @@ struct InsDiffResult { } fn compare_ins( + config: &DiffObjConfig, left: &ObjInsDiff, right: &ObjInsDiff, state: &mut InsDiffState, @@ -416,7 +427,7 @@ fn compare_ins( state.diff_count += 1; } for (a, b) in left_ins.args.iter().zip(&right_ins.args) { - if arg_eq(a, b, left, right) { + if arg_eq(config, a, b, left, right) { result.left_args_diff.push(None); result.right_args_diff.push(None); } else { diff --git a/src/diff/mod.rs b/src/diff/mod.rs index 6b16ad1..1334f74 100644 --- a/src/diff/mod.rs +++ b/src/diff/mod.rs @@ -25,6 +25,7 @@ pub enum DiffAlg { pub struct DiffObjConfig { pub code_alg: DiffAlg, pub data_alg: DiffAlg, + pub relax_reloc_diffs: bool, } pub struct ProcessCodeResult { @@ -51,7 +52,7 @@ pub fn diff_objs( left_symbol.diff_symbol = Some(right_symbol.name.clone()); right_symbol.diff_symbol = Some(left_symbol.name.clone()); diff_code( - config.code_alg, + config, left.architecture, &left_section.data, &right_section.data, diff --git a/src/jobs/objdiff.rs b/src/jobs/objdiff.rs index ae6366e..c19d48d 100644 --- a/src/jobs/objdiff.rs +++ b/src/jobs/objdiff.rs @@ -42,6 +42,7 @@ pub struct ObjDiffConfig { pub selected_wsl_distro: Option, pub code_alg: DiffAlg, pub data_alg: DiffAlg, + pub relax_reloc_diffs: bool, } impl ObjDiffConfig { @@ -55,6 +56,7 @@ impl ObjDiffConfig { selected_wsl_distro: config.selected_wsl_distro.clone(), code_alg: config.code_alg, data_alg: config.data_alg, + relax_reloc_diffs: config.relax_reloc_diffs, } } } @@ -225,7 +227,11 @@ fn run_build( }; update_status(context, "Performing diff".to_string(), 4, total, &cancel)?; - let diff_config = DiffObjConfig { code_alg: config.code_alg, data_alg: config.data_alg }; + let diff_config = DiffObjConfig { + code_alg: config.code_alg, + data_alg: config.data_alg, + relax_reloc_diffs: config.relax_reloc_diffs, + }; diff_objs(&diff_config, first_obj.as_mut(), second_obj.as_mut())?; update_status(context, "Complete".to_string(), total, total, &cancel)?; diff --git a/src/views/symbol_diff.rs b/src/views/symbol_diff.rs index da7173a..451898e 100644 --- a/src/views/symbol_diff.rs +++ b/src/views/symbol_diff.rs @@ -1,7 +1,7 @@ use std::mem::take; use egui::{ - text::LayoutJob, Align, CollapsingHeader, Color32, Layout, ScrollArea, SelectableLabel, + text::LayoutJob, Align, CollapsingHeader, Color32, Id, Layout, ScrollArea, SelectableLabel, TextEdit, Ui, Vec2, Widget, }; use egui_extras::{Size, StripBuilder}; @@ -234,6 +234,7 @@ fn symbol_list_ui( for section in &obj.sections { CollapsingHeader::new(format!("{} ({:x})", section.name, section.size)) + .id_source(Id::new(section.name.clone()).with(section.index)) .default_open(true) .show(ui, |ui| { if section.kind == ObjSectionKind::Code && state.reverse_fn_order {