Skip to content

Commit a1ea291

Browse files
authored
Reimplement function data value tooltips, function data value diffing, and data relocation diffing (#166)
* Show data literal values on instruction hover Reimplements #108 * Show reloc diffs in func view when data's content differs Reimplements #153 * Data diff view: Show relocs on hover and in context menu This reimplements #154 Note that colorizing the text depending on the kind of diff has still not been reimplemented yet * Fix up some comments
1 parent 9c31c82 commit a1ea291

File tree

6 files changed

+166
-142
lines changed

6 files changed

+166
-142
lines changed

objdiff-core/src/diff/code.rs

+21-34
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ use alloc::{
88
use anyhow::{anyhow, ensure, Context, Result};
99

1010
use super::{
11-
DiffObjConfig, FunctionRelocDiffs, InstructionArgDiffIndex, InstructionBranchFrom,
12-
InstructionBranchTo, InstructionDiffKind, InstructionDiffRow, SymbolDiff,
11+
display::display_ins_data_literals, DiffObjConfig, FunctionRelocDiffs, InstructionArgDiffIndex,
12+
InstructionBranchFrom, InstructionBranchTo, InstructionDiffKind, InstructionDiffRow,
13+
SymbolDiff,
1314
};
1415
use crate::obj::{
15-
InstructionArg, InstructionArgValue, InstructionRef, Object, ResolvedRelocation,
16-
ScannedInstruction, SymbolFlag, SymbolKind,
16+
InstructionArg, InstructionArgValue, InstructionRef, Object, ResolvedInstructionRef,
17+
ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolKind,
1718
};
1819

1920
pub fn no_diff_code(
@@ -291,12 +292,12 @@ pub(crate) fn section_name_eq(
291292
fn reloc_eq(
292293
left_obj: &Object,
293294
right_obj: &Object,
294-
left_reloc: Option<ResolvedRelocation>,
295-
right_reloc: Option<ResolvedRelocation>,
295+
left_ins: ResolvedInstructionRef,
296+
right_ins: ResolvedInstructionRef,
296297
diff_config: &DiffObjConfig,
297298
) -> bool {
298299
let relax_reloc_diffs = diff_config.function_reloc_diffs == FunctionRelocDiffs::None;
299-
let (left_reloc, right_reloc) = match (left_reloc, right_reloc) {
300+
let (left_reloc, right_reloc) = match (left_ins.relocation, right_ins.relocation) {
300301
(Some(left_reloc), Some(right_reloc)) => (left_reloc, right_reloc),
301302
// If relocations are relaxed, match if left is missing a reloc
302303
(None, Some(_)) => return relax_reloc_diffs,
@@ -319,13 +320,10 @@ fn reloc_eq(
319320
&& (diff_config.function_reloc_diffs == FunctionRelocDiffs::DataValue
320321
|| symbol_name_addend_matches
321322
|| address_eq(left_reloc, right_reloc))
322-
&& (
323-
diff_config.function_reloc_diffs == FunctionRelocDiffs::NameAddress
324-
|| left_reloc.symbol.kind != SymbolKind::Object
325-
// TODO
326-
// || left_obj.arch.display_ins_data_labels(left_ins)
327-
// == left_obj.arch.display_ins_data_labels(right_ins))
328-
)
323+
&& (diff_config.function_reloc_diffs == FunctionRelocDiffs::NameAddress
324+
|| left_reloc.symbol.kind != SymbolKind::Object
325+
|| display_ins_data_literals(left_obj, left_ins)
326+
== display_ins_data_literals(right_obj, right_ins))
329327
}
330328
(Some(_), None) => false,
331329
(None, Some(_)) => {
@@ -343,8 +341,8 @@ fn arg_eq(
343341
right_row: &InstructionDiffRow,
344342
left_arg: &InstructionArg,
345343
right_arg: &InstructionArg,
346-
left_reloc: Option<ResolvedRelocation>,
347-
right_reloc: Option<ResolvedRelocation>,
344+
left_ins: ResolvedInstructionRef,
345+
right_ins: ResolvedInstructionRef,
348346
diff_config: &DiffObjConfig,
349347
) -> bool {
350348
match left_arg {
@@ -357,7 +355,7 @@ fn arg_eq(
357355
},
358356
InstructionArg::Reloc => {
359357
matches!(right_arg, InstructionArg::Reloc)
360-
&& reloc_eq(left_obj, right_obj, left_reloc, right_reloc, diff_config)
358+
&& reloc_eq(left_obj, right_obj, left_ins, right_ins, diff_config)
361359
}
362360
InstructionArg::BranchDest(_) => match right_arg {
363361
// Compare dest instruction idx after diffing
@@ -434,8 +432,10 @@ fn diff_instruction(
434432
.resolve_instruction_ref(right_symbol_idx, r)
435433
.context("Failed to resolve right instruction")?;
436434

437-
if left_resolved.code != right_resolved.code {
438-
// If data doesn't match, process instructions and compare args
435+
if left_resolved.code != right_resolved.code
436+
|| !reloc_eq(left_obj, right_obj, left_resolved, right_resolved, diff_config)
437+
{
438+
// If either the raw code bytes or relocations don't match, process instructions and compare args
439439
let left_ins = left_obj.arch.process_instruction(left_resolved, diff_config)?;
440440
let right_ins = left_obj.arch.process_instruction(right_resolved, diff_config)?;
441441
if left_ins.args.len() != right_ins.args.len() {
@@ -455,8 +455,8 @@ fn diff_instruction(
455455
right_row,
456456
a,
457457
b,
458-
left_resolved.relocation,
459-
right_resolved.relocation,
458+
left_resolved,
459+
right_resolved,
460460
diff_config,
461461
) {
462462
result.left_args_diff.push(InstructionArgDiffIndex::NONE);
@@ -500,19 +500,6 @@ fn diff_instruction(
500500
return Ok(result);
501501
}
502502

503-
// Compare relocations
504-
if !reloc_eq(
505-
left_obj,
506-
right_obj,
507-
left_resolved.relocation,
508-
right_resolved.relocation,
509-
diff_config,
510-
) {
511-
state.diff_score += PENALTY_REG_DIFF;
512-
// TODO add relocation diff to args
513-
return Ok(InstructionDiffResult::new(InstructionDiffKind::ArgMismatch));
514-
}
515-
516503
Ok(InstructionDiffResult::new(InstructionDiffKind::None))
517504
}
518505

objdiff-core/src/diff/data.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ fn reloc_eq(
6363
}
6464

6565
#[inline]
66-
fn resolve_relocation<'obj>(
66+
pub fn resolve_relocation<'obj>(
6767
obj: &'obj Object,
6868
reloc: &'obj Relocation,
6969
) -> ResolvedRelocation<'obj> {
@@ -72,10 +72,6 @@ fn resolve_relocation<'obj>(
7272
}
7373

7474
/// Compares relocations contained with a certain data range.
75-
/// The DataDiffKind for each diff will either be `None`` (if the relocation matches),
76-
/// or `Replace` (if a relocation was changed, added, or removed).
77-
/// `Insert` and `Delete` are not used when a relocation is added or removed to avoid confusing diffs
78-
/// where it looks like the bytes themselves were changed but actually only the relocations changed.
7975
fn diff_data_relocs_for_range<'left, 'right>(
8076
left_obj: &'left Object,
8177
right_obj: &'right Object,
@@ -254,13 +250,21 @@ pub fn diff_data_section(
254250
let len = left_obj.arch.data_reloc_size(left_reloc.relocation.flags);
255251
let range = left_reloc.relocation.address as usize
256252
..left_reloc.relocation.address as usize + len;
257-
left_reloc_diffs.push(DataRelocationDiff { kind: diff_kind, range });
253+
left_reloc_diffs.push(DataRelocationDiff {
254+
reloc: left_reloc.relocation.clone(),
255+
kind: diff_kind,
256+
range,
257+
});
258258
}
259259
if let Some(right_reloc) = right_reloc {
260260
let len = right_obj.arch.data_reloc_size(right_reloc.relocation.flags);
261261
let range = right_reloc.relocation.address as usize
262262
..right_reloc.relocation.address as usize + len;
263-
right_reloc_diffs.push(DataRelocationDiff { kind: diff_kind, range });
263+
right_reloc_diffs.push(DataRelocationDiff {
264+
reloc: right_reloc.relocation.clone(),
265+
kind: diff_kind,
266+
range,
267+
});
264268
}
265269
}
266270

objdiff-core/src/diff/display.rs

+48-20
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
diff::{DiffObjConfig, InstructionDiffKind, InstructionDiffRow, ObjectDiff, SymbolDiff},
1616
obj::{
1717
InstructionArg, InstructionArgValue, Object, ParsedInstruction, ResolvedInstructionRef,
18-
SectionFlag, SectionKind, Symbol, SymbolFlag, SymbolKind,
18+
ResolvedRelocation, SectionFlag, SectionKind, Symbol, SymbolFlag, SymbolKind,
1919
},
2020
};
2121

@@ -424,6 +424,42 @@ pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec<Hover
424424
out
425425
}
426426

427+
pub fn relocation_context(
428+
obj: &Object,
429+
reloc: ResolvedRelocation,
430+
ins: Option<ResolvedInstructionRef>,
431+
) -> Vec<ContextItem> {
432+
let mut out = Vec::new();
433+
if let Some(ins) = ins {
434+
for literal in display_ins_data_literals(obj, ins) {
435+
out.push(ContextItem::Copy { value: literal, label: None });
436+
}
437+
out.push(ContextItem::Separator);
438+
}
439+
out.append(&mut symbol_context(obj, reloc.relocation.target_symbol));
440+
out
441+
}
442+
443+
pub fn relocation_hover(obj: &Object, reloc: ResolvedRelocation) -> Vec<HoverItem> {
444+
let mut out = Vec::new();
445+
if let Some(name) = obj.arch.reloc_name(reloc.relocation.flags) {
446+
out.push(HoverItem::Text {
447+
label: "Relocation type".into(),
448+
value: name.to_string(),
449+
color: HoverItemColor::Normal,
450+
});
451+
} else {
452+
out.push(HoverItem::Text {
453+
label: "Relocation type".into(),
454+
value: format!("<{:?}>", reloc.relocation.flags),
455+
color: HoverItemColor::Normal,
456+
});
457+
}
458+
out.push(HoverItem::Separator);
459+
out.append(&mut symbol_hover(obj, reloc.relocation.target_symbol, reloc.relocation.addend));
460+
out
461+
}
462+
427463
pub fn instruction_context(
428464
obj: &Object,
429465
resolved: ResolvedInstructionRef,
@@ -458,11 +494,7 @@ pub fn instruction_context(
458494
}
459495
}
460496
if let Some(reloc) = resolved.relocation {
461-
for literal in display_ins_data_literals(obj, resolved) {
462-
out.push(ContextItem::Copy { value: literal, label: None });
463-
}
464-
out.push(ContextItem::Separator);
465-
out.append(&mut symbol_context(obj, reloc.relocation.target_symbol));
497+
out.append(&mut relocation_context(obj, reloc, Some(resolved)));
466498
}
467499
out
468500
}
@@ -509,21 +541,17 @@ pub fn instruction_hover(
509541
}
510542
}
511543
if let Some(reloc) = resolved.relocation {
512-
if let Some(name) = obj.arch.reloc_name(reloc.relocation.flags) {
513-
out.push(HoverItem::Text {
514-
label: "Relocation type".into(),
515-
value: name.to_string(),
516-
color: HoverItemColor::Normal,
517-
});
518-
} else {
519-
out.push(HoverItem::Text {
520-
label: "Relocation type".into(),
521-
value: format!("<{:?}>", reloc.relocation.flags),
522-
color: HoverItemColor::Normal,
523-
});
524-
}
544+
out.append(&mut relocation_hover(obj, reloc));
525545
out.push(HoverItem::Separator);
526-
out.append(&mut symbol_hover(obj, reloc.relocation.target_symbol, reloc.relocation.addend));
546+
if let Some(ty) = obj.arch.guess_data_type(resolved) {
547+
for literal in display_ins_data_literals(obj, resolved) {
548+
out.push(HoverItem::Text {
549+
label: format!("{}", ty),
550+
value: literal,
551+
color: HoverItemColor::Normal,
552+
});
553+
}
554+
}
527555
}
528556
out
529557
}

objdiff-core/src/diff/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
diff_generic_section,
1717
},
1818
},
19-
obj::{InstructionRef, Object, SectionKind, Symbol, SymbolFlag},
19+
obj::{InstructionRef, Object, Relocation, SectionKind, Symbol, SymbolFlag},
2020
};
2121

2222
pub mod code;
@@ -93,6 +93,7 @@ pub struct DataDiff {
9393

9494
#[derive(Debug, Clone)]
9595
pub struct DataRelocationDiff {
96+
pub reloc: Relocation,
9697
pub kind: DataDiffKind,
9798
pub range: Range<usize>,
9899
}

0 commit comments

Comments
 (0)