Skip to content

Commit b3af627

Browse files
committed
Data diff view: Show relocs on hover and in context menu
This reimplements encounter#154 Note that colorizing the text depending on the kind of diff has still not been reimplemented yet
1 parent 12c7ea4 commit b3af627

File tree

5 files changed

+137
-107
lines changed

5 files changed

+137
-107
lines changed

objdiff-core/src/diff/data.rs

Lines changed: 11 additions & 5 deletions
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> {
@@ -74,8 +74,6 @@ fn resolve_relocation<'obj>(
7474
/// Compares relocations contained with a certain data range.
7575
/// The DataDiffKind for each diff will either be `None`` (if the relocation matches),
7676
/// 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.
7977
fn diff_data_relocs_for_range<'left, 'right>(
8078
left_obj: &'left Object,
8179
right_obj: &'right Object,
@@ -254,13 +252,21 @@ pub fn diff_data_section(
254252
let len = left_obj.arch.data_reloc_size(left_reloc.relocation.flags);
255253
let range = left_reloc.relocation.address as usize
256254
..left_reloc.relocation.address as usize + len;
257-
left_reloc_diffs.push(DataRelocationDiff { kind: diff_kind, range });
255+
left_reloc_diffs.push(DataRelocationDiff {
256+
reloc: left_reloc.relocation.clone(),
257+
kind: diff_kind,
258+
range,
259+
});
258260
}
259261
if let Some(right_reloc) = right_reloc {
260262
let len = right_obj.arch.data_reloc_size(right_reloc.relocation.flags);
261263
let range = right_reloc.relocation.address as usize
262264
..right_reloc.relocation.address as usize + len;
263-
right_reloc_diffs.push(DataRelocationDiff { kind: diff_kind, range });
265+
right_reloc_diffs.push(DataRelocationDiff {
266+
reloc: right_reloc.relocation.clone(),
267+
kind: diff_kind,
268+
range,
269+
});
264270
}
265271
}
266272

objdiff-core/src/diff/display.rs

Lines changed: 39 additions & 21 deletions
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,7 @@ 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-
}
525-
out.push(HoverItem::Separator);
526-
out.append(&mut symbol_hover(obj, reloc.relocation.target_symbol, reloc.relocation.addend));
544+
out.append(&mut relocation_hover(obj, reloc));
527545
out.push(HoverItem::Separator);
528546
if let Some(ty) = obj.arch.guess_data_type(resolved) {
529547
for literal in display_ins_data_literals(obj, resolved) {

objdiff-core/src/diff/mod.rs

Lines changed: 2 additions & 1 deletion
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
}

objdiff-gui/src/views/data_diff.rs

Lines changed: 68 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,99 +2,90 @@ use std::{cmp::min, default::Default, mem::take};
22

33
use egui::{text::LayoutJob, Label, Sense, Widget};
44
use objdiff_core::{
5-
diff::{DataDiff, DataDiffKind, DataRelocationDiff},
5+
diff::{
6+
data::resolve_relocation,
7+
display::{relocation_context, relocation_hover, ContextItem, HoverItem},
8+
DataDiff, DataDiffKind, DataRelocationDiff,
9+
},
610
obj::Object,
711
};
812

13+
use super::diff::{context_menu_items_ui, hover_items_ui};
914
use crate::views::{appearance::Appearance, write_text};
1015

1116
pub(crate) const BYTES_PER_ROW: usize = 16;
1217

18+
fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -> Vec<HoverItem> {
19+
let mut out = Vec::new();
20+
let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs);
21+
let mut prev_reloc = None;
22+
for reloc_diff in reloc_diffs {
23+
let reloc = &reloc_diff.reloc;
24+
if prev_reloc == Some(reloc) {
25+
// Avoid showing consecutive duplicate relocations.
26+
// We do this because a single relocation can span across multiple diffs if the
27+
// bytes in the relocation changed (e.g. first byte is added, second is unchanged).
28+
continue;
29+
}
30+
prev_reloc = Some(reloc);
31+
32+
// TODO: Change hover text color depending on Insert/Delete/Replace kind
33+
// let color = get_color_for_diff_kind(reloc_diff.kind, appearance);
34+
35+
let reloc = resolve_relocation(obj, reloc);
36+
out.append(&mut relocation_hover(obj, reloc));
37+
}
38+
39+
out
40+
}
41+
42+
fn data_row_context(
43+
obj: &Object,
44+
diffs: &[(DataDiff, Vec<DataRelocationDiff>)],
45+
) -> Vec<ContextItem> {
46+
let mut out = Vec::new();
47+
let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs);
48+
let mut prev_reloc = None;
49+
for reloc_diff in reloc_diffs {
50+
let reloc = &reloc_diff.reloc;
51+
if prev_reloc == Some(reloc) {
52+
// Avoid showing consecutive duplicate relocations.
53+
// We do this because a single relocation can span across multiple diffs if the
54+
// bytes in the relocation changed (e.g. first byte is added, second is unchanged).
55+
continue;
56+
}
57+
prev_reloc = Some(reloc);
58+
59+
let reloc = resolve_relocation(obj, reloc);
60+
out.append(&mut relocation_context(obj, reloc, None));
61+
}
62+
out
63+
}
64+
1365
fn data_row_hover_ui(
1466
ui: &mut egui::Ui,
15-
_obj: &Object,
16-
_diffs: &[(DataDiff, Vec<DataRelocationDiff>)],
17-
_appearance: &Appearance,
67+
obj: &Object,
68+
diffs: &[(DataDiff, Vec<DataRelocationDiff>)],
69+
appearance: &Appearance,
1870
) {
1971
ui.scope(|ui| {
2072
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
2173
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
22-
23-
// TODO
24-
// let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs);
25-
// let mut prev_reloc = None;
26-
// for reloc_diff in reloc_diffs {
27-
// let reloc = &reloc_diff.reloc;
28-
// if prev_reloc == Some(reloc) {
29-
// // Avoid showing consecutive duplicate relocations.
30-
// // We do this because a single relocation can span across multiple diffs if the
31-
// // bytes in the relocation changed (e.g. first byte is added, second is unchanged).
32-
// continue;
33-
// }
34-
// prev_reloc = Some(reloc);
35-
//
36-
// let color = get_color_for_diff_kind(reloc_diff.kind, appearance);
37-
//
38-
// // TODO: Most of this code is copy-pasted from ins_hover_ui.
39-
// // Try to separate this out into a shared function.
40-
// ui.label(format!("Relocation type: {}", obj.arch.display_reloc(reloc.flags)));
41-
// ui.label(format!("Relocation address: {:x}", reloc.address));
42-
// let addend_str = match reloc.addend.cmp(&0i64) {
43-
// Ordering::Greater => format!("+{:x}", reloc.addend),
44-
// Ordering::Less => format!("-{:x}", -reloc.addend),
45-
// _ => "".to_string(),
46-
// };
47-
// ui.colored_label(color, format!("Name: {}{}", reloc.target.name, addend_str));
48-
// if let Some(orig_section_index) = reloc.target.orig_section_index {
49-
// if let Some(section) =
50-
// obj.sections.iter().find(|s| s.orig_index == orig_section_index)
51-
// {
52-
// ui.colored_label(color, format!("Section: {}", section.name));
53-
// }
54-
// ui.colored_label(
55-
// color,
56-
// format!("Address: {:x}{}", reloc.target.address, addend_str),
57-
// );
58-
// ui.colored_label(color, format!("Size: {:x}", reloc.target.size));
59-
// if reloc.addend >= 0 && reloc.target.bytes.len() > reloc.addend as usize {}
60-
// } else {
61-
// ui.colored_label(color, "Extern".to_string());
62-
// }
63-
// }
74+
hover_items_ui(ui, data_row_hover(obj, diffs), appearance);
6475
});
6576
}
6677

67-
fn data_row_context_menu(ui: &mut egui::Ui, _diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) {
78+
fn data_row_context_menu(
79+
ui: &mut egui::Ui,
80+
obj: &Object,
81+
diffs: &[(DataDiff, Vec<DataRelocationDiff>)],
82+
column: usize,
83+
appearance: &Appearance,
84+
) {
6885
ui.scope(|ui| {
6986
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
7087
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
71-
72-
// TODO
73-
// let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs);
74-
// let mut prev_reloc = None;
75-
// for reloc_diff in reloc_diffs {
76-
// let reloc = &reloc_diff.reloc;
77-
// if prev_reloc == Some(reloc) {
78-
// // Avoid showing consecutive duplicate relocations.
79-
// // We do this because a single relocation can span across multiple diffs if the
80-
// // bytes in the relocation changed (e.g. first byte is added, second is unchanged).
81-
// continue;
82-
// }
83-
// prev_reloc = Some(reloc);
84-
//
85-
// // TODO: This code is copy-pasted from ins_context_menu.
86-
// // Try to separate this out into a shared function.
87-
// if let Some(name) = &reloc.target.demangled_name {
88-
// if ui.button(format!("Copy \"{name}\"")).clicked() {
89-
// ui.output_mut(|output| output.copied_text.clone_from(name));
90-
// ui.close_menu();
91-
// }
92-
// }
93-
// if ui.button(format!("Copy \"{}\"", reloc.target.name)).clicked() {
94-
// ui.output_mut(|output| output.copied_text.clone_from(&reloc.target.name));
95-
// ui.close_menu();
96-
// }
97-
// }
88+
context_menu_items_ui(ui, data_row_context(obj, diffs), column, appearance);
9889
});
9990
}
10091

@@ -113,6 +104,7 @@ pub(crate) fn data_row_ui(
113104
address: usize,
114105
diffs: &[(DataDiff, Vec<DataRelocationDiff>)],
115106
appearance: &Appearance,
107+
column: usize,
116108
) {
117109
if diffs.iter().any(|(dd, rds)| {
118110
dd.kind != DataDiffKind::None || rds.iter().any(|rd| rd.kind != DataDiffKind::None)
@@ -191,9 +183,8 @@ pub(crate) fn data_row_ui(
191183

192184
let response = Label::new(job).sense(Sense::click()).ui(ui);
193185
if let Some(obj) = obj {
194-
response
195-
.on_hover_ui_at_pointer(|ui| data_row_hover_ui(ui, obj, diffs, appearance))
196-
.context_menu(|ui| data_row_context_menu(ui, diffs));
186+
response.context_menu(|ui| data_row_context_menu(ui, obj, diffs, column, appearance));
187+
response.on_hover_ui_at_pointer(|ui| data_row_hover_ui(ui, obj, diffs, appearance));
197188
}
198189
}
199190

objdiff-gui/src/views/diff.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -525,9 +525,23 @@ pub fn diff_view_ui(
525525
let address = i * BYTES_PER_ROW;
526526
row.col(|ui| {
527527
if column == 0 {
528-
data_row_ui(ui, Some(left_obj), address, &left_diffs[i], appearance);
528+
data_row_ui(
529+
ui,
530+
Some(left_obj),
531+
address,
532+
&left_diffs[i],
533+
appearance,
534+
column,
535+
);
529536
} else if column == 1 {
530-
data_row_ui(ui, Some(right_obj), address, &right_diffs[i], appearance);
537+
data_row_ui(
538+
ui,
539+
Some(right_obj),
540+
address,
541+
&right_diffs[i],
542+
appearance,
543+
column,
544+
);
531545
}
532546
});
533547
},
@@ -667,7 +681,7 @@ fn diff_col_ui(
667681
let i = row.index();
668682
let address = i * BYTES_PER_ROW;
669683
row.col(|ui| {
670-
data_row_ui(ui, Some(obj), address, &diffs[i], appearance);
684+
data_row_ui(ui, Some(obj), address, &diffs[i], appearance, column);
671685
});
672686
},
673687
);

0 commit comments

Comments
 (0)