Skip to content

Reimplement colorized data relocation hover diffs #182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 33 additions & 15 deletions objdiff-core/src/diff/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,14 @@ pub enum SymbolNavigationKind {
Extab,
}

#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub enum HoverItemColor {
Normal, // Gray
#[default]
Normal, // Gray
Emphasized, // White
Special, // Blue
Delete, // Red
Insert, // Green
}

pub enum HoverItem {
Expand All @@ -355,7 +359,12 @@ pub fn symbol_context(obj: &Object, symbol_index: usize) -> Vec<ContextItem> {
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 addend_str = match addend.cmp(&0i64) {
Ordering::Greater => format!("+{:x}", addend),
Expand All @@ -366,51 +375,51 @@ pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec<Hover
out.push(HoverItem::Text {
label: "Name".into(),
value: format!("{}{}", symbol.name, addend_str),
color: HoverItemColor::Normal,
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: HoverItemColor::Normal,
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: HoverItemColor::Normal,
color: override_color.clone().unwrap_or_default(),
});
out.push(HoverItem::Text {
label: "Address".into(),
value: format!("{:x}{}", symbol.address, addend_str),
color: HoverItemColor::Normal,
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: HoverItemColor::Normal,
color: override_color.clone().unwrap_or_default(),
});
} else {
out.push(HoverItem::Text {
label: "Size".into(),
value: format!("{:x}", symbol.size),
color: HoverItemColor::Normal,
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: HoverItemColor::Normal,
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 {
Expand Down Expand Up @@ -443,22 +452,31 @@ pub fn relocation_context(
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();
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: override_color.clone().unwrap_or_default(),
});
} else {
out.push(HoverItem::Text {
label: "Relocation".into(),
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
}

Expand Down Expand Up @@ -545,7 +563,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, None));
if let Some(ty) = obj.arch.guess_data_type(resolved) {
let literals = display_ins_data_literals(obj, resolved);
if !literals.is_empty() {
Expand Down
23 changes: 19 additions & 4 deletions objdiff-gui/src/views/data_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -19,6 +19,7 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
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) {
Expand All @@ -29,11 +30,16 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
}
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);
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));
out.append(&mut relocation_hover(obj, reloc, Some(color)));
}
out
}
Expand Down Expand Up @@ -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(
ui: &mut egui::Ui,
obj: Option<&Object>,
Expand Down
2 changes: 2 additions & 0 deletions objdiff-gui/src/views/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,8 @@ pub fn hover_items_ui(ui: &mut Ui, items: Vec<HoverItem>, 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());
Expand Down
2 changes: 1 addition & 1 deletion objdiff-gui/src/views/symbol_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +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), appearance);
hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0, None), appearance);
});
}

Expand Down
6 changes: 5 additions & 1 deletion objdiff-wasm/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ impl GuestDisplay for Component {
) -> Vec<HoverItem> {
let obj_diff = diff.get::<ResourceObjectDiff>();
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()
.map(|item| HoverItem::from(item))
.collect()
Expand Down Expand Up @@ -501,6 +503,8 @@ impl From<diff::display::HoverItemColor> 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,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions objdiff-wasm/wit/objdiff.wit
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ interface display {
normal,
emphasized,
special,
delete,
insert,
}

record hover-item-text {
Expand Down