Reimplement colorized data relocation hover diffs (#182)

* Reimplement colorized data relocation hover diffs

* Fix objdiff-wasm build

Data diffing doesn't seem to be fully implemented in objdiff-wasm yet, so just putting placeholders in so it compiles.

* Reloc hover: Add separators, override special color too
This commit is contained in:
LagoLunatic 2025-03-28 23:48:14 -04:00 committed by GitHub
parent 7b00a9e9f2
commit 196c003a92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 21 deletions

View File

@ -325,10 +325,14 @@ pub enum SymbolNavigationKind {
Extab, Extab,
} }
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub enum HoverItemColor { pub enum HoverItemColor {
Normal, // Gray #[default]
Normal, // Gray
Emphasized, // White Emphasized, // White
Special, // Blue Special, // Blue
Delete, // Red
Insert, // Green
} }
pub enum HoverItem { pub enum HoverItem {
@ -355,7 +359,12 @@ pub fn symbol_context(obj: &Object, symbol_index: usize) -> Vec<ContextItem> {
out out
} }
pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec<HoverItem> { pub fn symbol_hover(
obj: &Object,
symbol_index: usize,
addend: i64,
override_color: Option<HoverItemColor>,
) -> Vec<HoverItem> {
let symbol = &obj.symbols[symbol_index]; let symbol = &obj.symbols[symbol_index];
let addend_str = match addend.cmp(&0i64) { let addend_str = match addend.cmp(&0i64) {
Ordering::Greater => format!("+{:x}", addend), Ordering::Greater => format!("+{:x}", addend),
@ -366,51 +375,51 @@ pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec<Hover
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Name".into(), label: "Name".into(),
value: format!("{}{}", symbol.name, addend_str), value: format!("{}{}", symbol.name, addend_str),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
if let Some(demangled_name) = &symbol.demangled_name { if let Some(demangled_name) = &symbol.demangled_name {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Demangled".into(), label: "Demangled".into(),
value: demangled_name.into(), value: demangled_name.into(),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
} }
if let Some(section) = symbol.section { if let Some(section) = symbol.section {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Section".into(), label: "Section".into(),
value: obj.sections[section].name.clone(), value: obj.sections[section].name.clone(),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Address".into(), label: "Address".into(),
value: format!("{:x}{}", symbol.address, addend_str), value: format!("{:x}{}", symbol.address, addend_str),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
if symbol.flags.contains(SymbolFlag::SizeInferred) { if symbol.flags.contains(SymbolFlag::SizeInferred) {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Size".into(), label: "Size".into(),
value: format!("{:x} (inferred)", symbol.size), value: format!("{:x} (inferred)", symbol.size),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
} else { } else {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Size".into(), label: "Size".into(),
value: format!("{:x}", symbol.size), value: format!("{:x}", symbol.size),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
} }
if let Some(align) = symbol.align { if let Some(align) = symbol.align {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Alignment".into(), label: "Alignment".into(),
value: align.get().to_string(), value: align.get().to_string(),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
} }
if let Some(address) = symbol.virtual_address { if let Some(address) = symbol.virtual_address {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Virtual address".into(), label: "Virtual address".into(),
value: format!("{:x}", address), value: format!("{:x}", address),
color: HoverItemColor::Special, color: override_color.clone().unwrap_or(HoverItemColor::Special),
}); });
} }
} else { } else {
@ -443,22 +452,31 @@ pub fn relocation_context(
out out
} }
pub fn relocation_hover(obj: &Object, reloc: ResolvedRelocation) -> Vec<HoverItem> { pub fn relocation_hover(
obj: &Object,
reloc: ResolvedRelocation,
override_color: Option<HoverItemColor>,
) -> Vec<HoverItem> {
let mut out = Vec::new(); let mut out = Vec::new();
if let Some(name) = obj.arch.reloc_name(reloc.relocation.flags) { if let Some(name) = obj.arch.reloc_name(reloc.relocation.flags) {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Relocation".into(), label: "Relocation".into(),
value: name.to_string(), value: name.to_string(),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
} else { } else {
out.push(HoverItem::Text { out.push(HoverItem::Text {
label: "Relocation".into(), label: "Relocation".into(),
value: format!("<{:?}>", reloc.relocation.flags), value: format!("<{:?}>", reloc.relocation.flags),
color: HoverItemColor::Normal, color: override_color.clone().unwrap_or_default(),
}); });
} }
out.append(&mut symbol_hover(obj, reloc.relocation.target_symbol, reloc.relocation.addend)); out.append(&mut symbol_hover(
obj,
reloc.relocation.target_symbol,
reloc.relocation.addend,
override_color,
));
out out
} }
@ -545,7 +563,7 @@ pub fn instruction_hover(
} }
if let Some(reloc) = resolved.relocation { if let Some(reloc) = resolved.relocation {
out.push(HoverItem::Separator); out.push(HoverItem::Separator);
out.append(&mut relocation_hover(obj, reloc)); out.append(&mut relocation_hover(obj, reloc, None));
if let Some(ty) = obj.arch.guess_data_type(resolved) { if let Some(ty) = obj.arch.guess_data_type(resolved) {
let literals = display_ins_data_literals(obj, resolved); let literals = display_ins_data_literals(obj, resolved);
if !literals.is_empty() { if !literals.is_empty() {

View File

@ -5,7 +5,7 @@ use objdiff_core::{
diff::{ diff::{
DataDiff, DataDiffKind, DataRelocationDiff, DataDiff, DataDiffKind, DataRelocationDiff,
data::resolve_relocation, data::resolve_relocation,
display::{ContextItem, HoverItem, relocation_context, relocation_hover}, display::{ContextItem, HoverItem, HoverItemColor, relocation_context, relocation_hover},
}, },
obj::Object, obj::Object,
}; };
@ -19,6 +19,7 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
let mut out = Vec::new(); let mut out = Vec::new();
let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs); let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs);
let mut prev_reloc = None; let mut prev_reloc = None;
let mut first = true;
for reloc_diff in reloc_diffs { for reloc_diff in reloc_diffs {
let reloc = &reloc_diff.reloc; let reloc = &reloc_diff.reloc;
if prev_reloc == Some(reloc) { if prev_reloc == Some(reloc) {
@ -29,11 +30,16 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
} }
prev_reloc = Some(reloc); prev_reloc = Some(reloc);
// TODO: Change hover text color depending on Insert/Delete/Replace kind if first {
// let color = get_color_for_diff_kind(reloc_diff.kind, appearance); first = false;
} else {
out.push(HoverItem::Separator);
}
let color = get_hover_item_color_for_diff_kind(reloc_diff.kind);
let reloc = resolve_relocation(&obj.symbols, reloc); let reloc = resolve_relocation(&obj.symbols, reloc);
out.append(&mut relocation_hover(obj, reloc)); out.append(&mut relocation_hover(obj, reloc, Some(color)));
} }
out out
} }
@ -97,6 +103,15 @@ fn get_color_for_diff_kind(diff_kind: DataDiffKind, appearance: &Appearance) ->
} }
} }
fn get_hover_item_color_for_diff_kind(diff_kind: DataDiffKind) -> HoverItemColor {
match diff_kind {
DataDiffKind::None => HoverItemColor::Normal,
DataDiffKind::Replace => HoverItemColor::Special,
DataDiffKind::Delete => HoverItemColor::Delete,
DataDiffKind::Insert => HoverItemColor::Insert,
}
}
pub(crate) fn data_row_ui( pub(crate) fn data_row_ui(
ui: &mut egui::Ui, ui: &mut egui::Ui,
obj: Option<&Object>, obj: Option<&Object>,

View File

@ -795,6 +795,8 @@ pub fn hover_items_ui(ui: &mut Ui, items: Vec<HoverItem>, appearance: &Appearanc
if !label.is_empty() { if !label.is_empty() {
let label_color = match color { let label_color = match color {
HoverItemColor::Special => appearance.replace_color, HoverItemColor::Special => appearance.replace_color,
HoverItemColor::Delete => appearance.delete_color,
HoverItemColor::Insert => appearance.insert_color,
_ => appearance.highlight_color, _ => appearance.highlight_color,
}; };
write_text(&label, label_color, &mut job, appearance.code_font.clone()); write_text(&label, label_color, &mut job, appearance.code_font.clone());

View File

@ -512,7 +512,7 @@ pub fn symbol_hover_ui(
ui.scope(|ui| { ui.scope(|ui| {
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap); ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap);
hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0), appearance); hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0, None), appearance);
}); });
} }

View File

@ -230,7 +230,9 @@ impl GuestDisplay for Component {
) -> Vec<HoverItem> { ) -> Vec<HoverItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0 /* TODO */) // TODO: colorize replaced/deleted/inserted relocations
let override_color = None;
diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0, override_color)
.into_iter() .into_iter()
.map(|item| HoverItem::from(item)) .map(|item| HoverItem::from(item))
.collect() .collect()
@ -501,6 +503,8 @@ impl From<diff::display::HoverItemColor> for HoverItemColor {
diff::display::HoverItemColor::Normal => HoverItemColor::Normal, diff::display::HoverItemColor::Normal => HoverItemColor::Normal,
diff::display::HoverItemColor::Emphasized => HoverItemColor::Emphasized, diff::display::HoverItemColor::Emphasized => HoverItemColor::Emphasized,
diff::display::HoverItemColor::Special => HoverItemColor::Special, diff::display::HoverItemColor::Special => HoverItemColor::Special,
diff::display::HoverItemColor::Delete => HoverItemColor::Delete,
diff::display::HoverItemColor::Insert => HoverItemColor::Insert,
} }
} }
} }

View File

@ -137,6 +137,8 @@ interface display {
normal, normal,
emphasized, emphasized,
special, special,
delete,
insert,
} }
record hover-item-text { record hover-item-text {