Unify context menu / hover tooltip code + UI improvements

This commit is contained in:
Luke Street
2025-03-02 15:20:29 -07:00
parent 8461b35cd7
commit a1f2a535e5
26 changed files with 1730 additions and 1095 deletions
+26 -56
View File
@@ -5,7 +5,7 @@ use alloc::{
vec::Vec,
};
use anyhow::{anyhow, ensure, Result};
use anyhow::{anyhow, ensure, Context, Result};
use super::{
DiffObjConfig, FunctionRelocDiffs, InstructionArgDiffIndex, InstructionBranchFrom,
@@ -196,7 +196,7 @@ fn diff_instructions(
Ok((left_diff, right_diff))
}
fn arg_to_string(arg: &InstructionArg, reloc: Option<&ResolvedRelocation>) -> String {
fn arg_to_string(arg: &InstructionArg, reloc: Option<ResolvedRelocation>) -> String {
match arg {
InstructionArg::Value(arg) => arg.to_string(),
InstructionArg::Reloc => {
@@ -226,7 +226,7 @@ fn resolve_branches(
for ((i, ins_diff), ins) in
rows.iter_mut().enumerate().filter(|(_, row)| row.ins_ref.is_some()).zip(ops)
{
let branch_dest = if let Some(resolved) = section.relocation_at(ins.ins_ref, obj) {
let branch_dest = if let Some(resolved) = section.relocation_at(obj, ins.ins_ref) {
if resolved.symbol.section == Some(section_index) {
// If the relocation target is in the same section, use it as the branch destination
resolved.symbol.address.checked_add_signed(resolved.relocation.addend)
@@ -258,7 +258,7 @@ fn resolve_branches(
}
}
pub(crate) fn address_eq(left: &ResolvedRelocation, right: &ResolvedRelocation) -> bool {
pub(crate) fn address_eq(left: ResolvedRelocation, right: ResolvedRelocation) -> bool {
if right.symbol.size == 0 && left.symbol.size != 0 {
// The base relocation is against a pool but the target relocation isn't.
// This can happen in rare cases where the compiler will generate a pool+addend relocation
@@ -318,7 +318,7 @@ fn reloc_eq(
section_name_eq(left_obj, right_obj, *sl, *sr)
&& (diff_config.function_reloc_diffs == FunctionRelocDiffs::DataValue
|| symbol_name_addend_matches
|| address_eq(&left_reloc, &right_reloc))
|| address_eq(left_reloc, right_reloc))
&& (
diff_config.function_reloc_diffs == FunctionRelocDiffs::NameAddress
|| left_reloc.symbol.kind != SymbolKind::Object
@@ -427,54 +427,17 @@ fn diff_instruction(
return Ok(InstructionDiffResult::new(InstructionDiffKind::Replace));
}
let left_symbol = &left_obj.symbols[left_symbol_idx];
let right_symbol = &right_obj.symbols[right_symbol_idx];
let left_section = left_symbol
.section
.and_then(|i| left_obj.sections.get(i))
.ok_or_else(|| anyhow!("Missing section for symbol"))?;
let right_section = right_symbol
.section
.and_then(|i| right_obj.sections.get(i))
.ok_or_else(|| anyhow!("Missing section for symbol"))?;
let left_resolved = left_obj
.resolve_instruction_ref(left_symbol_idx, l)
.context("Failed to resolve left instruction")?;
let right_resolved = right_obj
.resolve_instruction_ref(right_symbol_idx, r)
.context("Failed to resolve right instruction")?;
// Resolve relocations
let left_reloc = left_section.relocation_at(l, left_obj);
let right_reloc = right_section.relocation_at(r, right_obj);
// Compare instruction data
let left_data = left_section.data_range(l.address, l.size as usize).ok_or_else(|| {
anyhow!(
"Instruction data out of bounds: {:#x}..{:#x}",
l.address,
l.address + l.size as u64
)
})?;
let right_data = right_section.data_range(r.address, r.size as usize).ok_or_else(|| {
anyhow!(
"Instruction data out of bounds: {:#x}..{:#x}",
r.address,
r.address + r.size as u64
)
})?;
if left_data != right_data {
if left_resolved.code != right_resolved.code {
// If data doesn't match, process instructions and compare args
let left_ins = left_obj.arch.process_instruction(
l,
left_data,
left_reloc,
left_symbol.address..left_symbol.address + left_symbol.size,
left_symbol.section.unwrap(),
diff_config,
)?;
let right_ins = left_obj.arch.process_instruction(
r,
right_data,
right_reloc,
right_symbol.address..right_symbol.address + right_symbol.size,
right_symbol.section.unwrap(),
diff_config,
)?;
let left_ins = left_obj.arch.process_instruction(left_resolved, diff_config)?;
let right_ins = left_obj.arch.process_instruction(right_resolved, diff_config)?;
if left_ins.args.len() != right_ins.args.len() {
state.diff_score += PENALTY_REPLACE;
return Ok(InstructionDiffResult::new(InstructionDiffKind::Replace));
@@ -492,8 +455,8 @@ fn diff_instruction(
right_row,
a,
b,
left_reloc,
right_reloc,
left_resolved.relocation,
right_resolved.relocation,
diff_config,
) {
result.left_args_diff.push(InstructionArgDiffIndex::NONE);
@@ -510,7 +473,7 @@ fn diff_instruction(
if result.kind == InstructionDiffKind::None {
result.kind = InstructionDiffKind::ArgMismatch;
}
let a_str = arg_to_string(a, left_reloc.as_ref());
let a_str = arg_to_string(a, left_resolved.relocation);
let a_diff = match state.left_args_idx.entry(a_str) {
btree_map::Entry::Vacant(e) => {
let idx = state.left_arg_idx;
@@ -520,7 +483,7 @@ fn diff_instruction(
}
btree_map::Entry::Occupied(e) => *e.get(),
};
let b_str = arg_to_string(b, right_reloc.as_ref());
let b_str = arg_to_string(b, right_resolved.relocation);
let b_diff = match state.right_args_idx.entry(b_str) {
btree_map::Entry::Vacant(e) => {
let idx = state.right_arg_idx;
@@ -538,8 +501,15 @@ fn diff_instruction(
}
// Compare relocations
if !reloc_eq(left_obj, right_obj, left_reloc, right_reloc, diff_config) {
if !reloc_eq(
left_obj,
right_obj,
left_resolved.relocation,
right_resolved.relocation,
diff_config,
) {
state.diff_score += PENALTY_REG_DIFF;
// TODO add relocation diff to args
return Ok(InstructionDiffResult::new(InstructionDiffKind::ArgMismatch));
}
+7 -9
View File
@@ -38,8 +38,8 @@ pub fn diff_bss_symbol(
fn reloc_eq(
left_obj: &Object,
right_obj: &Object,
left: &ResolvedRelocation,
right: &ResolvedRelocation,
left: ResolvedRelocation,
right: ResolvedRelocation,
) -> bool {
if left.relocation.flags != right.relocation.flags {
return false;
@@ -104,7 +104,7 @@ fn diff_data_relocs_for_range<'left, 'right>(
continue;
};
let right_reloc = resolve_relocation(right_obj, right_reloc);
if reloc_eq(left_obj, right_obj, &left_reloc, &right_reloc) {
if reloc_eq(left_obj, right_obj, left_reloc, right_reloc) {
diffs.push((DataDiffKind::None, Some(left_reloc), Some(right_reloc)));
} else {
diffs.push((DataDiffKind::Replace, Some(left_reloc), Some(right_reloc)));
@@ -251,13 +251,13 @@ pub fn diff_data_section(
0..right_max as usize,
) {
if let Some(left_reloc) = left_reloc {
let len = left_obj.arch.get_reloc_byte_size(left_reloc.relocation.flags);
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 { kind: diff_kind, range });
}
if let Some(right_reloc) = right_reloc {
let len = right_obj.arch.get_reloc_byte_size(right_reloc.relocation.flags);
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 { kind: diff_kind, range });
@@ -358,11 +358,9 @@ pub fn diff_data_symbol(
let reloc_diff_len = match (left_reloc, right_reloc) {
(None, None) => unreachable!(),
(None, Some(right_reloc)) => {
right_obj.arch.get_reloc_byte_size(right_reloc.relocation.flags)
}
(Some(left_reloc), _) => {
left_obj.arch.get_reloc_byte_size(left_reloc.relocation.flags)
right_obj.arch.data_reloc_size(right_reloc.relocation.flags)
}
(Some(left_reloc), _) => left_obj.arch.data_reloc_size(left_reloc.relocation.flags),
};
total_reloc_bytes += reloc_diff_len;
if diff_kind == DataDiffKind::None {
File diff suppressed because it is too large Load Diff