diff --git a/src/diff.rs b/src/diff.rs index 2eb356d..223b566 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -181,6 +181,10 @@ fn resolve_branches(vec: &mut [ObjInsDiff]) { } } +fn address_eq(left: &ObjSymbol, right: &ObjSymbol) -> bool { + left.address as i64 + left.addend == right.address as i64 + right.addend +} + fn reloc_eq(left_reloc: Option<&ObjReloc>, right_reloc: Option<&ObjReloc>) -> bool { if let (Some(left), Some(right)) = (left_reloc, right_reloc) { if left.kind != right.kind { @@ -190,7 +194,7 @@ fn reloc_eq(left_reloc: Option<&ObjReloc>, right_reloc: Option<&ObjReloc>) -> bo match (&left.target_section, &right.target_section) { (Some(sl), Some(sr)) => { // Match if section and name or address match - sl == sr && (name_matches || left.target.address == right.target.address) + sl == sr && (name_matches || address_eq(&left.target, &right.target)) } (Some(_), None) => false, (None, Some(_)) => { diff --git a/src/obj/elf.rs b/src/obj/elf.rs index 8297b39..dad2f46 100644 --- a/src/obj/elf.rs +++ b/src/obj/elf.rs @@ -22,7 +22,7 @@ fn to_obj_section_kind(kind: SectionKind) -> ObjSectionKind { } } -fn to_obj_symbol(obj_file: &File<'_>, symbol: &Symbol<'_, '_>) -> Result { +fn to_obj_symbol(obj_file: &File<'_>, symbol: &Symbol<'_, '_>, addend: i64) -> Result { let mut name = symbol.name().context("Failed to process symbol name")?; if name.is_empty() { println!("Found empty sym: {:?}", symbol); @@ -56,6 +56,7 @@ fn to_obj_symbol(obj_file: &File<'_>, symbol: &Symbol<'_, '_>) -> Result, section: &ObjSection) -> Result) -> Result> { let mut result = Vec::::new(); for symbol in obj_file.symbols() { if symbol.is_common() { - result.push(to_obj_symbol(obj_file, &symbol)?); + result.push(to_obj_symbol(obj_file, &symbol, 0)?); } } Ok(result) @@ -169,7 +170,7 @@ fn find_section_symbol( } continue; } - return to_obj_symbol(obj_file, &symbol); + return to_obj_symbol(obj_file, &symbol, 0); } let (name, offset) = closest_symbol .and_then(|s| s.name().map(|n| (n, s.address())).ok()) @@ -177,13 +178,14 @@ fn find_section_symbol( .unwrap_or(("", 0)); let offset_addr = address - offset; Ok(ObjSymbol { - name: if offset_addr > 0 { format!("{}+{:#X}", name, address) } else { name.to_string() }, + name: name.to_string(), demangled_name: None, address, section_address: address - section.address(), size: 0, size_known: false, flags: Default::default(), + addend: offset_addr as i64, diff_symbol: None, instructions: vec![], match_percent: 0.0, @@ -257,7 +259,7 @@ fn relocations_by_section( // println!("Reloc: {:?}, symbol: {:?}", reloc, symbol); let target = match symbol.kind() { SymbolKind::Text | SymbolKind::Data | SymbolKind::Unknown => { - to_obj_symbol(obj_file, &symbol) + to_obj_symbol(obj_file, &symbol, reloc.addend()) } SymbolKind::Section => { let addend = if reloc.has_implicit_addend() { diff --git a/src/obj/mod.rs b/src/obj/mod.rs index 864aeb5..89521a2 100644 --- a/src/obj/mod.rs +++ b/src/obj/mod.rs @@ -101,6 +101,7 @@ pub struct ObjSymbol { pub size: u64, pub size_known: bool, pub flags: ObjSymbolFlagSet, + pub addend: i64, // Diff pub diff_symbol: Option, diff --git a/src/views/function_diff.rs b/src/views/function_diff.rs index 90d0d3c..5cb745f 100644 --- a/src/views/function_diff.rs +++ b/src/views/function_diff.rs @@ -1,7 +1,7 @@ use std::default::Default; use cwdemangle::demangle; -use egui::{text::LayoutJob, Color32, FontFamily, FontId, Label, Sense, TextFormat}; +use egui::{text::LayoutJob, Color32, Label, Sense}; use egui_extras::{Size, StripBuilder, TableBuilder}; use ppc750cl::Argument; @@ -11,52 +11,50 @@ use crate::{ ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc, ObjRelocKind, ObjSymbol, }, - views::symbol_diff::match_color_for_symbol, + views::{symbol_diff::match_color_for_symbol, write_text, COLOR_RED, FONT_SIZE}, }; -const FONT_SIZE: f32 = 14.0; -const FONT_ID: FontId = FontId::new(FONT_SIZE, FontFamily::Monospace); - -const COLOR_RED: Color32 = Color32::from_rgb(200, 40, 41); - -fn write_text(str: &str, color: Color32, job: &mut LayoutJob) { - job.append(str, 0.0, TextFormat { font_id: FONT_ID, color, ..Default::default() }); +fn write_reloc_name(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob) { + let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name); + write_text(name, Color32::LIGHT_GRAY, job); + if reloc.target.addend != 0 { + write_text(&format!("+{:X}", reloc.target.addend), color, job); + } } -fn write_reloc(reloc: &ObjReloc, job: &mut LayoutJob) { - let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name); +fn write_reloc(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob) { match reloc.kind { ObjRelocKind::PpcAddr16Lo => { - write_text(name, Color32::LIGHT_GRAY, job); - write_text("@l", Color32::GRAY, job); + write_reloc_name(reloc, color, job); + write_text("@l", color, job); } ObjRelocKind::PpcAddr16Hi => { - write_text(name, Color32::LIGHT_GRAY, job); - write_text("@h", Color32::GRAY, job); + write_reloc_name(reloc, color, job); + write_text("@h", color, job); } ObjRelocKind::PpcAddr16Ha => { - write_text(name, Color32::LIGHT_GRAY, job); - write_text("@ha", Color32::GRAY, job); + write_reloc_name(reloc, color, job); + write_text("@ha", color, job); } ObjRelocKind::PpcEmbSda21 => { - write_text(name, Color32::LIGHT_GRAY, job); - write_text("@sda21", Color32::GRAY, job); + write_reloc_name(reloc, color, job); + write_text("@sda21", color, job); } ObjRelocKind::MipsHi16 => { - write_text("%hi(", Color32::GRAY, job); - write_text(name, Color32::LIGHT_GRAY, job); - write_text(")", Color32::GRAY, job); + write_text("%hi(", color, job); + write_reloc_name(reloc, color, job); + write_text(")", color, job); } ObjRelocKind::MipsLo16 => { - write_text("%lo(", Color32::GRAY, job); - write_text(name, Color32::LIGHT_GRAY, job); - write_text(")", Color32::GRAY, job); + write_text("%lo(", color, job); + write_reloc_name(reloc, color, job); + write_text(")", color, job); } ObjRelocKind::Absolute | ObjRelocKind::PpcRel24 | ObjRelocKind::PpcRel14 | ObjRelocKind::Mips26 => { - write_text(name, Color32::LIGHT_GRAY, job); + write_reloc_name(reloc, color, job); } }; } @@ -113,10 +111,10 @@ fn write_ins( } }, ObjInsArg::Reloc => { - write_reloc(ins.reloc.as_ref().unwrap(), job); + write_reloc(ins.reloc.as_ref().unwrap(), base_color, job); } ObjInsArg::RelocWithBase => { - write_reloc(ins.reloc.as_ref().unwrap(), job); + write_reloc(ins.reloc.as_ref().unwrap(), base_color, job); write_text("(", base_color, job); writing_offset = true; continue; diff --git a/src/views/mod.rs b/src/views/mod.rs index 1e5696e..7a1fdb2 100644 --- a/src/views/mod.rs +++ b/src/views/mod.rs @@ -1,4 +1,15 @@ +use egui::{text::LayoutJob, Color32, FontFamily, FontId, TextFormat}; + pub(crate) mod config; pub(crate) mod function_diff; pub(crate) mod jobs; pub(crate) mod symbol_diff; + +const FONT_SIZE: f32 = 14.0; +const FONT_ID: FontId = FontId::new(FONT_SIZE, FontFamily::Monospace); + +const COLOR_RED: Color32 = Color32::from_rgb(200, 40, 41); + +fn write_text(str: &str, color: Color32, job: &mut LayoutJob) { + job.append(str, 0.0, TextFormat { font_id: FONT_ID, color, ..Default::default() }); +} diff --git a/src/views/symbol_diff.rs b/src/views/symbol_diff.rs index b2c7fbb..dee4c85 100644 --- a/src/views/symbol_diff.rs +++ b/src/views/symbol_diff.rs @@ -1,6 +1,6 @@ use egui::{ - text::LayoutJob, CollapsingHeader, Color32, FontFamily, FontId, Rgba, ScrollArea, - SelectableLabel, TextFormat, Ui, Widget, + text::LayoutJob, CollapsingHeader, Color32, Rgba, ScrollArea, + SelectableLabel, Ui, Widget, }; use egui_extras::{Size, StripBuilder}; @@ -8,6 +8,7 @@ use crate::{ app::{View, ViewState}, jobs::objdiff::BuildStatus, obj::{ObjInfo, ObjSymbol, ObjSymbolFlags}, + views::write_text, }; pub fn match_color_for_symbol(symbol: &ObjSymbol) -> Color32 { @@ -20,13 +21,6 @@ pub fn match_color_for_symbol(symbol: &ObjSymbol) -> Color32 { } } -const FONT_SIZE: f32 = 14.0; -const FONT_ID: FontId = FontId::new(FONT_SIZE, FontFamily::Monospace); - -fn write_text(str: &str, color: Color32, job: &mut LayoutJob) { - job.append(str, 0.0, TextFormat { font_id: FONT_ID, color, ..Default::default() }); -} - fn symbol_context_menu_ui(ui: &mut Ui, symbol: &ObjSymbol) { ui.scope(|ui| { ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); @@ -104,6 +98,16 @@ fn symbol_ui( } } +fn symbol_matches_search(symbol: &ObjSymbol, search_str: &str) -> bool { + search_str.is_empty() + || symbol.name.contains(search_str) + || symbol + .demangled_name + .as_ref() + .map(|s| s.to_ascii_lowercase().contains(search_str)) + .unwrap_or(false) +} + fn symbol_list_ui( ui: &mut Ui, obj: &ObjInfo, @@ -111,7 +115,11 @@ fn symbol_list_ui( selected_symbol: &mut Option, current_view: &mut View, reverse_function_order: bool, + search: &mut String, ) { + ui.text_edit_singleline(search); + let lower_search = search.to_ascii_lowercase(); + ScrollArea::both().auto_shrink([false, false]).show(ui, |ui| { ui.scope(|ui| { ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); @@ -131,6 +139,9 @@ fn symbol_list_ui( .show(ui, |ui| { if section.name == ".text" && reverse_function_order { for symbol in section.symbols.iter().rev() { + if !symbol_matches_search(symbol, &lower_search) { + continue; + } symbol_ui( ui, symbol, @@ -141,6 +152,9 @@ fn symbol_list_ui( } } else { for symbol in §ion.symbols { + if !symbol_matches_search(symbol, &lower_search) { + continue; + } symbol_ui( ui, symbol, @@ -168,11 +182,12 @@ fn build_log_ui(ui: &mut Ui, status: &BuildStatus) { } pub fn symbol_diff_ui(ui: &mut Ui, view_state: &mut ViewState) { - if let (Some(result), highlighted_symbol, selected_symbol, current_view) = ( + if let (Some(result), highlighted_symbol, selected_symbol, current_view, search) = ( &view_state.build, &mut view_state.highlighted_symbol, &mut view_state.selected_symbol, &mut view_state.current_view, + &mut view_state.search, ) { StripBuilder::new(ui).size(Size::exact(40.0)).size(Size::remainder()).vertical( |mut strip| { @@ -223,6 +238,7 @@ pub fn symbol_diff_ui(ui: &mut Ui, view_state: &mut ViewState) { selected_symbol, current_view, view_state.reverse_fn_order, + search, ); }); } @@ -241,6 +257,7 @@ pub fn symbol_diff_ui(ui: &mut Ui, view_state: &mut ViewState) { selected_symbol, current_view, view_state.reverse_fn_order, + search, ); }); }