Skip to content

Commit 2876be3

Browse files
Show relocation diffs in function view when the data's content differs (#153)
* Show reloc diff in func view when data content differs * Add "Relax shifted data diffs" option * Display fake pool relocations at end of line * Diff reloc data by display string instead of raw bytes This is to handle data symbols that contain multiple values in them at once, such as stringBase. If you compare the target symbol's bytes directly, then any part of the symbol having different bytes will cause *all* relocations to that symbol to show as a diff, even if the specific string being accessed is the same. * Fix weak stripped symbols showing as a false diff Fixed this by showing extern symbols correctly instead of skipping them. * Add "Relax shifted data diffs" option to objdiff-cli Includes both a command line argument and a keyboard shortcut (S). * Remove addi string data hack and ... pool name hack * Clippy fix * PPC: Clear relocs from GPRs when overwritten * PPC: Follow branches to improve pool detection accuracy * PPC: Handle following bctr jump table control flow * Clippy fixes * PPC: Fix extern relocations not having their addend copied * Add option to disable func data value diffing * PPC: Handle lmw when clearing GPRs * PPC: Handle moving reloc address with `add` inst * Combine "relax reloc diffs" with other reloc diff options * Add v3 config and migrate from v2 --------- Co-authored-by: Luke Street <luke@street.dev>
1 parent 1117176 commit 2876be3

File tree

8 files changed

+453
-134
lines changed

8 files changed

+453
-134
lines changed

objdiff-cli/src/cmd/report.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,10 @@ fn report_object(
169169
}
170170
_ => {}
171171
}
172-
let diff_config = diff::DiffObjConfig { relax_reloc_diffs: true, ..Default::default() };
172+
let diff_config = diff::DiffObjConfig {
173+
function_reloc_diffs: diff::FunctionRelocDiffs::None,
174+
..Default::default()
175+
};
173176
let mapping_config = diff::MappingConfig::default();
174177
let target = object
175178
.target_path

objdiff-cli/src/views/function_diff.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers, MouseButton,
33
use objdiff_core::{
44
diff::{
55
display::{display_diff, DiffText, HighlightKind},
6-
ObjDiff, ObjInsDiffKind, ObjSymbolDiff,
6+
FunctionRelocDiffs, ObjDiff, ObjInsDiffKind, ObjSymbolDiff,
77
},
88
obj::{ObjInfo, ObjSectionKind, ObjSymbol, SymbolRef},
99
};
@@ -368,10 +368,15 @@ impl UiView for FunctionDiffUi {
368368
self.scroll_x = self.scroll_x.saturating_sub(1);
369369
result.redraw = true;
370370
}
371-
// Toggle relax relocation diffs
371+
// Cycle through function relocation diff mode
372372
KeyCode::Char('x') => {
373-
state.diff_obj_config.relax_reloc_diffs =
374-
!state.diff_obj_config.relax_reloc_diffs;
373+
state.diff_obj_config.function_reloc_diffs =
374+
match state.diff_obj_config.function_reloc_diffs {
375+
FunctionRelocDiffs::None => FunctionRelocDiffs::NameAddress,
376+
FunctionRelocDiffs::NameAddress => FunctionRelocDiffs::DataValue,
377+
FunctionRelocDiffs::DataValue => FunctionRelocDiffs::All,
378+
FunctionRelocDiffs::All => FunctionRelocDiffs::None,
379+
};
375380
result.redraw = true;
376381
return EventControlFlow::Reload;
377382
}

objdiff-core/config-schema.json

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
{
22
"properties": [
33
{
4-
"id": "relaxRelocDiffs",
5-
"type": "boolean",
6-
"default": false,
7-
"name": "Relax relocation diffs",
8-
"description": "Ignores differences in relocation targets. (Address, name, etc)"
4+
"id": "functionRelocDiffs",
5+
"type": "choice",
6+
"default": "name_address",
7+
"name": "Function relocation diffs",
8+
"description": "How relocation targets will be diffed in the function view.",
9+
"items": [
10+
{
11+
"value": "none",
12+
"name": "None"
13+
},
14+
{
15+
"value": "name_address",
16+
"name": "Name or address"
17+
},
18+
{
19+
"value": "data_value",
20+
"name": "Data value"
21+
},
22+
{
23+
"value": "all",
24+
"name": "Name or address, data value"
25+
}
26+
]
927
},
1028
{
1129
"id": "spaceBetweenArgs",
@@ -193,7 +211,7 @@
193211
"id": "general",
194212
"name": "General",
195213
"properties": [
196-
"relaxRelocDiffs",
214+
"functionRelocDiffs",
197215
"spaceBetweenArgs",
198216
"combineDataSections"
199217
]

objdiff-core/src/arch/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,17 @@ pub trait ObjArch: Send + Sync {
156156
Some(format!("Bytes: {:#x?}", bytes))
157157
}
158158

159+
fn display_ins_data(&self, ins: &ObjIns) -> Option<String> {
160+
let reloc = ins.reloc.as_ref()?;
161+
if reloc.addend >= 0 && reloc.target.bytes.len() > reloc.addend as usize {
162+
self.guess_data_type(ins).and_then(|ty| {
163+
self.display_data_type(ty, &reloc.target.bytes[reloc.addend as usize..])
164+
})
165+
} else {
166+
None
167+
}
168+
}
169+
159170
// Downcast methods
160171
#[cfg(feature = "ppc")]
161172
fn ppc(&self) -> Option<&ppc::ObjArchPpc> { None }

0 commit comments

Comments
 (0)