Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 93 additions & 3 deletions objdiff-gui/src/views/diff.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
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,
},
},
obj::{InstructionArgValue, Object, Symbol},
obj::{InstructionArgValue, Object, Symbol, SymbolKind},
util::ReallySigned,
};
use time::format_description;
Expand Down Expand Up @@ -116,6 +119,67 @@ fn get_asm_text(
asm_text
}

fn extract_symbol_name(
obj: &Object,
symbol_idx: usize,
row: &InstructionDiffRow,
) -> Option<String> {
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 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,
left_symbol_diff: &SymbolDiff,
left_symbol_idx: usize,
right_symbol_diff: &SymbolDiff,
right_symbol_idx: usize,
) -> 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) else {
continue;
};

let Some(right_name) = extract_symbol_name(right_obj, right_symbol_idx, right_row) 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,
Expand Down Expand Up @@ -215,6 +279,32 @@ 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,
)));
}

if state.current_view == View::FunctionDiff
&& let Some((_, symbol_diff, symbol_idx)) = left_ctx.symbol
&& let Some((obj, _)) = left_ctx.obj
Expand Down
10 changes: 10 additions & 0 deletions objdiff-gui/src/views/symbol_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
Loading