Add simple symbol search & handle symbol relocation addends

This commit is contained in:
Luke Street 2022-09-20 18:19:44 -04:00
parent b7b177af4c
commit 1e44f73b2f
6 changed files with 78 additions and 45 deletions

View File

@ -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(_)) => {

View File

@ -22,7 +22,7 @@ fn to_obj_section_kind(kind: SectionKind) -> ObjSectionKind {
}
}
fn to_obj_symbol(obj_file: &File<'_>, symbol: &Symbol<'_, '_>) -> Result<ObjSymbol> {
fn to_obj_symbol(obj_file: &File<'_>, symbol: &Symbol<'_, '_>, addend: i64) -> Result<ObjSymbol> {
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<ObjSymb
size: symbol.size(),
size_known: symbol.size() != 0,
flags,
addend,
diff_symbol: None,
instructions: vec![],
match_percent: 0.0,
@ -118,7 +119,7 @@ fn symbols_by_section(obj_file: &File<'_>, section: &ObjSection) -> Result<Vec<O
continue;
}
}
result.push(to_obj_symbol(obj_file, &symbol)?);
result.push(to_obj_symbol(obj_file, &symbol, 0)?);
}
}
}
@ -140,7 +141,7 @@ fn common_symbols(obj_file: &File<'_>) -> Result<Vec<ObjSymbol>> {
let mut result = Vec::<ObjSymbol>::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(("<unknown>", 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() {

View File

@ -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<String>,

View File

@ -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;

View File

@ -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() });
}

View File

@ -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<String>,
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 &section.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,
);
});
}