From 85431cc459ea70b11456feb5717bde08bfe23b53 Mon Sep 17 00:00:00 2001 From: LagoLunatic Date: Thu, 27 Mar 2025 16:26:21 -0400 Subject: [PATCH 1/3] Reimplement colorized data relocation hover diffs --- objdiff-core/src/diff/display.rs | 43 +++++++++++++++++++--------- objdiff-gui/src/views/data_diff.rs | 16 ++++++++--- objdiff-gui/src/views/diff.rs | 2 ++ objdiff-gui/src/views/symbol_diff.rs | 10 +++++-- 4 files changed, 51 insertions(+), 20 deletions(-) diff --git a/objdiff-core/src/diff/display.rs b/objdiff-core/src/diff/display.rs index 00489151..9a73a361 100644 --- a/objdiff-core/src/diff/display.rs +++ b/objdiff-core/src/diff/display.rs @@ -325,10 +325,13 @@ pub enum SymbolNavigationKind { Extab, } +#[derive(Debug, Clone, Eq, PartialEq)] pub enum HoverItemColor { Normal, // Gray Emphasized, // White Special, // Blue + Delete, // Red + Insert, // Green } pub enum HoverItem { @@ -355,7 +358,12 @@ pub fn symbol_context(obj: &Object, symbol_index: usize) -> Vec { out } -pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec { +pub fn symbol_hover( + obj: &Object, + symbol_index: usize, + addend: i64, + color: HoverItemColor, +) -> Vec { let symbol = &obj.symbols[symbol_index]; let addend_str = match addend.cmp(&0i64) { Ordering::Greater => format!("+{:x}", addend), @@ -366,44 +374,44 @@ pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec Vec { +pub fn relocation_hover( + obj: &Object, + reloc: ResolvedRelocation, + color: HoverItemColor, +) -> Vec { let mut out = Vec::new(); if let Some(name) = obj.arch.reloc_name(reloc.relocation.flags) { out.push(HoverItem::Text { label: "Relocation".into(), value: name.to_string(), - color: HoverItemColor::Normal, + color: color.clone(), }); } else { out.push(HoverItem::Text { label: "Relocation".into(), value: format!("<{:?}>", reloc.relocation.flags), - color: HoverItemColor::Normal, + color: color.clone(), }); } - 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, + color.clone(), + )); out } @@ -545,7 +562,7 @@ pub fn instruction_hover( } if let Some(reloc) = resolved.relocation { out.push(HoverItem::Separator); - out.append(&mut relocation_hover(obj, reloc)); + out.append(&mut relocation_hover(obj, reloc, HoverItemColor::Normal)); if let Some(ty) = obj.arch.guess_data_type(resolved) { let literals = display_ins_data_literals(obj, resolved); if !literals.is_empty() { diff --git a/objdiff-gui/src/views/data_diff.rs b/objdiff-gui/src/views/data_diff.rs index 0c25e200..e2197924 100644 --- a/objdiff-gui/src/views/data_diff.rs +++ b/objdiff-gui/src/views/data_diff.rs @@ -5,7 +5,7 @@ use objdiff_core::{ diff::{ DataDiff, DataDiffKind, DataRelocationDiff, data::resolve_relocation, - display::{ContextItem, HoverItem, relocation_context, relocation_hover}, + display::{ContextItem, HoverItem, HoverItemColor, relocation_context, relocation_hover}, }, obj::Object, }; @@ -29,11 +29,10 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec)]) - } prev_reloc = Some(reloc); - // TODO: Change hover text color depending on Insert/Delete/Replace kind - // let color = get_color_for_diff_kind(reloc_diff.kind, appearance); + let color = get_hover_item_color_for_diff_kind(reloc_diff.kind); let reloc = resolve_relocation(&obj.symbols, reloc); - out.append(&mut relocation_hover(obj, reloc)); + out.append(&mut relocation_hover(obj, reloc, color)); } out } @@ -97,6 +96,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( ui: &mut egui::Ui, obj: Option<&Object>, diff --git a/objdiff-gui/src/views/diff.rs b/objdiff-gui/src/views/diff.rs index 16e1b46e..3390d937 100644 --- a/objdiff-gui/src/views/diff.rs +++ b/objdiff-gui/src/views/diff.rs @@ -795,6 +795,8 @@ pub fn hover_items_ui(ui: &mut Ui, items: Vec, appearance: &Appearanc if !label.is_empty() { let label_color = match color { HoverItemColor::Special => appearance.replace_color, + HoverItemColor::Delete => appearance.delete_color, + HoverItemColor::Insert => appearance.insert_color, _ => appearance.highlight_color, }; write_text(&label, label_color, &mut job, appearance.code_font.clone()); diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index e19cb9f0..bd388893 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -8,8 +8,8 @@ use objdiff_core::{ diff::{ ObjectDiff, SymbolDiff, display::{ - HighlightKind, SectionDisplay, SymbolFilter, SymbolNavigationKind, display_sections, - symbol_context, symbol_hover, + HighlightKind, HoverItemColor, SectionDisplay, SymbolFilter, SymbolNavigationKind, + display_sections, symbol_context, symbol_hover, }, }, jobs::{Job, JobQueue, JobResult, create_scratch::CreateScratchResult, objdiff::ObjDiffResult}, @@ -512,7 +512,11 @@ pub fn symbol_hover_ui( ui.scope(|ui| { ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); 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, HoverItemColor::Normal), + appearance, + ); }); } From 00e46c074e5db8b04bed1e0c77c21527e59e58aa Mon Sep 17 00:00:00 2001 From: LagoLunatic Date: Thu, 27 Mar 2025 16:50:00 -0400 Subject: [PATCH 2/3] 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. --- objdiff-wasm/src/api.rs | 15 +++++++++++---- objdiff-wasm/wit/objdiff.wit | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/objdiff-wasm/src/api.rs b/objdiff-wasm/src/api.rs index 1fea05c6..10f92e8c 100644 --- a/objdiff-wasm/src/api.rs +++ b/objdiff-wasm/src/api.rs @@ -230,10 +230,15 @@ impl GuestDisplay for Component { ) -> Vec { let obj_diff = diff.get::(); let obj = obj_diff.0.as_ref(); - diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0 /* TODO */) - .into_iter() - .map(|item| HoverItem::from(item)) - .collect() + diff::display::symbol_hover( + obj, + symbol_display.symbol as usize, + 0, + diff::display::HoverItemColor::Normal, // TODO: colorize replaced/deleted/inserted relocations + ) + .into_iter() + .map(|item| HoverItem::from(item)) + .collect() } fn instruction_context( @@ -501,6 +506,8 @@ impl From for HoverItemColor { diff::display::HoverItemColor::Normal => HoverItemColor::Normal, diff::display::HoverItemColor::Emphasized => HoverItemColor::Emphasized, diff::display::HoverItemColor::Special => HoverItemColor::Special, + diff::display::HoverItemColor::Delete => HoverItemColor::Delete, + diff::display::HoverItemColor::Insert => HoverItemColor::Insert, } } } diff --git a/objdiff-wasm/wit/objdiff.wit b/objdiff-wasm/wit/objdiff.wit index 8a614e5f..b69a86d4 100644 --- a/objdiff-wasm/wit/objdiff.wit +++ b/objdiff-wasm/wit/objdiff.wit @@ -137,6 +137,8 @@ interface display { normal, emphasized, special, + delete, + insert, } record hover-item-text { From 5def64725c2cb2d7e7e3f330052572ae6c35ce9c Mon Sep 17 00:00:00 2001 From: LagoLunatic Date: Thu, 27 Mar 2025 20:12:26 -0400 Subject: [PATCH 3/3] Reloc hover: Add separators, override special color too --- objdiff-core/src/diff/display.rs | 33 ++++++++++++++-------------- objdiff-gui/src/views/data_diff.rs | 9 +++++++- objdiff-gui/src/views/symbol_diff.rs | 10 +++------ objdiff-wasm/src/api.rs | 15 +++++-------- 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/objdiff-core/src/diff/display.rs b/objdiff-core/src/diff/display.rs index 9a73a361..193ae683 100644 --- a/objdiff-core/src/diff/display.rs +++ b/objdiff-core/src/diff/display.rs @@ -325,9 +325,10 @@ pub enum SymbolNavigationKind { Extab, } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Default, Eq, PartialEq)] pub enum HoverItemColor { - Normal, // Gray + #[default] + Normal, // Gray Emphasized, // White Special, // Blue Delete, // Red @@ -362,7 +363,7 @@ pub fn symbol_hover( obj: &Object, symbol_index: usize, addend: i64, - color: HoverItemColor, + override_color: Option, ) -> Vec { let symbol = &obj.symbols[symbol_index]; let addend_str = match addend.cmp(&0i64) { @@ -374,51 +375,51 @@ pub fn symbol_hover( out.push(HoverItem::Text { label: "Name".into(), value: format!("{}{}", symbol.name, addend_str), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); if let Some(demangled_name) = &symbol.demangled_name { out.push(HoverItem::Text { label: "Demangled".into(), value: demangled_name.into(), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); } if let Some(section) = symbol.section { out.push(HoverItem::Text { label: "Section".into(), value: obj.sections[section].name.clone(), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); out.push(HoverItem::Text { label: "Address".into(), value: format!("{:x}{}", symbol.address, addend_str), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); if symbol.flags.contains(SymbolFlag::SizeInferred) { out.push(HoverItem::Text { label: "Size".into(), value: format!("{:x} (inferred)", symbol.size), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); } else { out.push(HoverItem::Text { label: "Size".into(), value: format!("{:x}", symbol.size), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); } if let Some(align) = symbol.align { out.push(HoverItem::Text { label: "Alignment".into(), value: align.get().to_string(), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); } if let Some(address) = symbol.virtual_address { out.push(HoverItem::Text { label: "Virtual address".into(), value: format!("{:x}", address), - color: HoverItemColor::Special, + color: override_color.clone().unwrap_or(HoverItemColor::Special), }); } } else { @@ -454,27 +455,27 @@ pub fn relocation_context( pub fn relocation_hover( obj: &Object, reloc: ResolvedRelocation, - color: HoverItemColor, + override_color: Option, ) -> Vec { let mut out = Vec::new(); if let Some(name) = obj.arch.reloc_name(reloc.relocation.flags) { out.push(HoverItem::Text { label: "Relocation".into(), value: name.to_string(), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); } else { out.push(HoverItem::Text { label: "Relocation".into(), value: format!("<{:?}>", reloc.relocation.flags), - color: color.clone(), + color: override_color.clone().unwrap_or_default(), }); } out.append(&mut symbol_hover( obj, reloc.relocation.target_symbol, reloc.relocation.addend, - color.clone(), + override_color, )); out } @@ -562,7 +563,7 @@ pub fn instruction_hover( } if let Some(reloc) = resolved.relocation { out.push(HoverItem::Separator); - out.append(&mut relocation_hover(obj, reloc, HoverItemColor::Normal)); + out.append(&mut relocation_hover(obj, reloc, None)); if let Some(ty) = obj.arch.guess_data_type(resolved) { let literals = display_ins_data_literals(obj, resolved); if !literals.is_empty() { diff --git a/objdiff-gui/src/views/data_diff.rs b/objdiff-gui/src/views/data_diff.rs index e2197924..36b71c59 100644 --- a/objdiff-gui/src/views/data_diff.rs +++ b/objdiff-gui/src/views/data_diff.rs @@ -19,6 +19,7 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec)]) - let mut out = Vec::new(); let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs); let mut prev_reloc = None; + let mut first = true; for reloc_diff in reloc_diffs { let reloc = &reloc_diff.reloc; if prev_reloc == Some(reloc) { @@ -29,10 +30,16 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec)]) - } prev_reloc = Some(reloc); + if first { + 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); - out.append(&mut relocation_hover(obj, reloc, color)); + out.append(&mut relocation_hover(obj, reloc, Some(color))); } out } diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index bd388893..cfed70f2 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -8,8 +8,8 @@ use objdiff_core::{ diff::{ ObjectDiff, SymbolDiff, display::{ - HighlightKind, HoverItemColor, SectionDisplay, SymbolFilter, SymbolNavigationKind, - display_sections, symbol_context, symbol_hover, + HighlightKind, SectionDisplay, SymbolFilter, SymbolNavigationKind, display_sections, + symbol_context, symbol_hover, }, }, jobs::{Job, JobQueue, JobResult, create_scratch::CreateScratchResult, objdiff::ObjDiffResult}, @@ -512,11 +512,7 @@ pub fn symbol_hover_ui( ui.scope(|ui| { ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap); - hover_items_ui( - ui, - symbol_hover(ctx.obj, symbol_idx, 0, HoverItemColor::Normal), - appearance, - ); + hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0, None), appearance); }); } diff --git a/objdiff-wasm/src/api.rs b/objdiff-wasm/src/api.rs index 10f92e8c..2943a06b 100644 --- a/objdiff-wasm/src/api.rs +++ b/objdiff-wasm/src/api.rs @@ -230,15 +230,12 @@ impl GuestDisplay for Component { ) -> Vec { let obj_diff = diff.get::(); let obj = obj_diff.0.as_ref(); - diff::display::symbol_hover( - obj, - symbol_display.symbol as usize, - 0, - diff::display::HoverItemColor::Normal, // TODO: colorize replaced/deleted/inserted relocations - ) - .into_iter() - .map(|item| HoverItem::from(item)) - .collect() + // 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() + .map(|item| HoverItem::from(item)) + .collect() } fn instruction_context(