mirror of
https://github.com/encounter/objdiff.git
synced 2025-06-07 23:23:34 +00:00
Add simple symbol search & handle symbol relocation addends
This commit is contained in:
parent
b7b177af4c
commit
1e44f73b2f
@ -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 {
|
fn reloc_eq(left_reloc: Option<&ObjReloc>, right_reloc: Option<&ObjReloc>) -> bool {
|
||||||
if let (Some(left), Some(right)) = (left_reloc, right_reloc) {
|
if let (Some(left), Some(right)) = (left_reloc, right_reloc) {
|
||||||
if left.kind != right.kind {
|
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) {
|
match (&left.target_section, &right.target_section) {
|
||||||
(Some(sl), Some(sr)) => {
|
(Some(sl), Some(sr)) => {
|
||||||
// Match if section and name or address match
|
// 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,
|
(Some(_), None) => false,
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
|
@ -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")?;
|
let mut name = symbol.name().context("Failed to process symbol name")?;
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
println!("Found empty sym: {:?}", symbol);
|
println!("Found empty sym: {:?}", symbol);
|
||||||
@ -56,6 +56,7 @@ fn to_obj_symbol(obj_file: &File<'_>, symbol: &Symbol<'_, '_>) -> Result<ObjSymb
|
|||||||
size: symbol.size(),
|
size: symbol.size(),
|
||||||
size_known: symbol.size() != 0,
|
size_known: symbol.size() != 0,
|
||||||
flags,
|
flags,
|
||||||
|
addend,
|
||||||
diff_symbol: None,
|
diff_symbol: None,
|
||||||
instructions: vec![],
|
instructions: vec![],
|
||||||
match_percent: 0.0,
|
match_percent: 0.0,
|
||||||
@ -118,7 +119,7 @@ fn symbols_by_section(obj_file: &File<'_>, section: &ObjSection) -> Result<Vec<O
|
|||||||
continue;
|
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();
|
let mut result = Vec::<ObjSymbol>::new();
|
||||||
for symbol in obj_file.symbols() {
|
for symbol in obj_file.symbols() {
|
||||||
if symbol.is_common() {
|
if symbol.is_common() {
|
||||||
result.push(to_obj_symbol(obj_file, &symbol)?);
|
result.push(to_obj_symbol(obj_file, &symbol, 0)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@ -169,7 +170,7 @@ fn find_section_symbol(
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return to_obj_symbol(obj_file, &symbol);
|
return to_obj_symbol(obj_file, &symbol, 0);
|
||||||
}
|
}
|
||||||
let (name, offset) = closest_symbol
|
let (name, offset) = closest_symbol
|
||||||
.and_then(|s| s.name().map(|n| (n, s.address())).ok())
|
.and_then(|s| s.name().map(|n| (n, s.address())).ok())
|
||||||
@ -177,13 +178,14 @@ fn find_section_symbol(
|
|||||||
.unwrap_or(("<unknown>", 0));
|
.unwrap_or(("<unknown>", 0));
|
||||||
let offset_addr = address - offset;
|
let offset_addr = address - offset;
|
||||||
Ok(ObjSymbol {
|
Ok(ObjSymbol {
|
||||||
name: if offset_addr > 0 { format!("{}+{:#X}", name, address) } else { name.to_string() },
|
name: name.to_string(),
|
||||||
demangled_name: None,
|
demangled_name: None,
|
||||||
address,
|
address,
|
||||||
section_address: address - section.address(),
|
section_address: address - section.address(),
|
||||||
size: 0,
|
size: 0,
|
||||||
size_known: false,
|
size_known: false,
|
||||||
flags: Default::default(),
|
flags: Default::default(),
|
||||||
|
addend: offset_addr as i64,
|
||||||
diff_symbol: None,
|
diff_symbol: None,
|
||||||
instructions: vec![],
|
instructions: vec![],
|
||||||
match_percent: 0.0,
|
match_percent: 0.0,
|
||||||
@ -257,7 +259,7 @@ fn relocations_by_section(
|
|||||||
// println!("Reloc: {:?}, symbol: {:?}", reloc, symbol);
|
// println!("Reloc: {:?}, symbol: {:?}", reloc, symbol);
|
||||||
let target = match symbol.kind() {
|
let target = match symbol.kind() {
|
||||||
SymbolKind::Text | SymbolKind::Data | SymbolKind::Unknown => {
|
SymbolKind::Text | SymbolKind::Data | SymbolKind::Unknown => {
|
||||||
to_obj_symbol(obj_file, &symbol)
|
to_obj_symbol(obj_file, &symbol, reloc.addend())
|
||||||
}
|
}
|
||||||
SymbolKind::Section => {
|
SymbolKind::Section => {
|
||||||
let addend = if reloc.has_implicit_addend() {
|
let addend = if reloc.has_implicit_addend() {
|
||||||
|
@ -101,6 +101,7 @@ pub struct ObjSymbol {
|
|||||||
pub size: u64,
|
pub size: u64,
|
||||||
pub size_known: bool,
|
pub size_known: bool,
|
||||||
pub flags: ObjSymbolFlagSet,
|
pub flags: ObjSymbolFlagSet,
|
||||||
|
pub addend: i64,
|
||||||
|
|
||||||
// Diff
|
// Diff
|
||||||
pub diff_symbol: Option<String>,
|
pub diff_symbol: Option<String>,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
|
||||||
use cwdemangle::demangle;
|
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 egui_extras::{Size, StripBuilder, TableBuilder};
|
||||||
use ppc750cl::Argument;
|
use ppc750cl::Argument;
|
||||||
|
|
||||||
@ -11,52 +11,50 @@ use crate::{
|
|||||||
ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc,
|
ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc,
|
||||||
ObjRelocKind, ObjSymbol,
|
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;
|
fn write_reloc_name(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob) {
|
||||||
const FONT_ID: FontId = FontId::new(FONT_SIZE, FontFamily::Monospace);
|
let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name);
|
||||||
|
write_text(name, Color32::LIGHT_GRAY, job);
|
||||||
const COLOR_RED: Color32 = Color32::from_rgb(200, 40, 41);
|
if reloc.target.addend != 0 {
|
||||||
|
write_text(&format!("+{:X}", reloc.target.addend), color, job);
|
||||||
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(reloc: &ObjReloc, job: &mut LayoutJob) {
|
fn write_reloc(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob) {
|
||||||
let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name);
|
|
||||||
match reloc.kind {
|
match reloc.kind {
|
||||||
ObjRelocKind::PpcAddr16Lo => {
|
ObjRelocKind::PpcAddr16Lo => {
|
||||||
write_text(name, Color32::LIGHT_GRAY, job);
|
write_reloc_name(reloc, color, job);
|
||||||
write_text("@l", Color32::GRAY, job);
|
write_text("@l", color, job);
|
||||||
}
|
}
|
||||||
ObjRelocKind::PpcAddr16Hi => {
|
ObjRelocKind::PpcAddr16Hi => {
|
||||||
write_text(name, Color32::LIGHT_GRAY, job);
|
write_reloc_name(reloc, color, job);
|
||||||
write_text("@h", Color32::GRAY, job);
|
write_text("@h", color, job);
|
||||||
}
|
}
|
||||||
ObjRelocKind::PpcAddr16Ha => {
|
ObjRelocKind::PpcAddr16Ha => {
|
||||||
write_text(name, Color32::LIGHT_GRAY, job);
|
write_reloc_name(reloc, color, job);
|
||||||
write_text("@ha", Color32::GRAY, job);
|
write_text("@ha", color, job);
|
||||||
}
|
}
|
||||||
ObjRelocKind::PpcEmbSda21 => {
|
ObjRelocKind::PpcEmbSda21 => {
|
||||||
write_text(name, Color32::LIGHT_GRAY, job);
|
write_reloc_name(reloc, color, job);
|
||||||
write_text("@sda21", Color32::GRAY, job);
|
write_text("@sda21", color, job);
|
||||||
}
|
}
|
||||||
ObjRelocKind::MipsHi16 => {
|
ObjRelocKind::MipsHi16 => {
|
||||||
write_text("%hi(", Color32::GRAY, job);
|
write_text("%hi(", color, job);
|
||||||
write_text(name, Color32::LIGHT_GRAY, job);
|
write_reloc_name(reloc, color, job);
|
||||||
write_text(")", Color32::GRAY, job);
|
write_text(")", color, job);
|
||||||
}
|
}
|
||||||
ObjRelocKind::MipsLo16 => {
|
ObjRelocKind::MipsLo16 => {
|
||||||
write_text("%lo(", Color32::GRAY, job);
|
write_text("%lo(", color, job);
|
||||||
write_text(name, Color32::LIGHT_GRAY, job);
|
write_reloc_name(reloc, color, job);
|
||||||
write_text(")", Color32::GRAY, job);
|
write_text(")", color, job);
|
||||||
}
|
}
|
||||||
ObjRelocKind::Absolute
|
ObjRelocKind::Absolute
|
||||||
| ObjRelocKind::PpcRel24
|
| ObjRelocKind::PpcRel24
|
||||||
| ObjRelocKind::PpcRel14
|
| ObjRelocKind::PpcRel14
|
||||||
| ObjRelocKind::Mips26 => {
|
| ObjRelocKind::Mips26 => {
|
||||||
write_text(name, Color32::LIGHT_GRAY, job);
|
write_reloc_name(reloc, color, job);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -113,10 +111,10 @@ fn write_ins(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ObjInsArg::Reloc => {
|
ObjInsArg::Reloc => {
|
||||||
write_reloc(ins.reloc.as_ref().unwrap(), job);
|
write_reloc(ins.reloc.as_ref().unwrap(), base_color, job);
|
||||||
}
|
}
|
||||||
ObjInsArg::RelocWithBase => {
|
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);
|
write_text("(", base_color, job);
|
||||||
writing_offset = true;
|
writing_offset = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
|
use egui::{text::LayoutJob, Color32, FontFamily, FontId, TextFormat};
|
||||||
|
|
||||||
pub(crate) mod config;
|
pub(crate) mod config;
|
||||||
pub(crate) mod function_diff;
|
pub(crate) mod function_diff;
|
||||||
pub(crate) mod jobs;
|
pub(crate) mod jobs;
|
||||||
pub(crate) mod symbol_diff;
|
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() });
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use egui::{
|
use egui::{
|
||||||
text::LayoutJob, CollapsingHeader, Color32, FontFamily, FontId, Rgba, ScrollArea,
|
text::LayoutJob, CollapsingHeader, Color32, Rgba, ScrollArea,
|
||||||
SelectableLabel, TextFormat, Ui, Widget,
|
SelectableLabel, Ui, Widget,
|
||||||
};
|
};
|
||||||
use egui_extras::{Size, StripBuilder};
|
use egui_extras::{Size, StripBuilder};
|
||||||
|
|
||||||
@ -8,6 +8,7 @@ use crate::{
|
|||||||
app::{View, ViewState},
|
app::{View, ViewState},
|
||||||
jobs::objdiff::BuildStatus,
|
jobs::objdiff::BuildStatus,
|
||||||
obj::{ObjInfo, ObjSymbol, ObjSymbolFlags},
|
obj::{ObjInfo, ObjSymbol, ObjSymbolFlags},
|
||||||
|
views::write_text,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn match_color_for_symbol(symbol: &ObjSymbol) -> Color32 {
|
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) {
|
fn symbol_context_menu_ui(ui: &mut Ui, symbol: &ObjSymbol) {
|
||||||
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);
|
||||||
@ -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(
|
fn symbol_list_ui(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
obj: &ObjInfo,
|
obj: &ObjInfo,
|
||||||
@ -111,7 +115,11 @@ fn symbol_list_ui(
|
|||||||
selected_symbol: &mut Option<String>,
|
selected_symbol: &mut Option<String>,
|
||||||
current_view: &mut View,
|
current_view: &mut View,
|
||||||
reverse_function_order: bool,
|
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| {
|
ScrollArea::both().auto_shrink([false, false]).show(ui, |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);
|
||||||
@ -131,6 +139,9 @@ fn symbol_list_ui(
|
|||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
if section.name == ".text" && reverse_function_order {
|
if section.name == ".text" && reverse_function_order {
|
||||||
for symbol in section.symbols.iter().rev() {
|
for symbol in section.symbols.iter().rev() {
|
||||||
|
if !symbol_matches_search(symbol, &lower_search) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
symbol_ui(
|
symbol_ui(
|
||||||
ui,
|
ui,
|
||||||
symbol,
|
symbol,
|
||||||
@ -141,6 +152,9 @@ fn symbol_list_ui(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for symbol in §ion.symbols {
|
for symbol in §ion.symbols {
|
||||||
|
if !symbol_matches_search(symbol, &lower_search) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
symbol_ui(
|
symbol_ui(
|
||||||
ui,
|
ui,
|
||||||
symbol,
|
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) {
|
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,
|
&view_state.build,
|
||||||
&mut view_state.highlighted_symbol,
|
&mut view_state.highlighted_symbol,
|
||||||
&mut view_state.selected_symbol,
|
&mut view_state.selected_symbol,
|
||||||
&mut view_state.current_view,
|
&mut view_state.current_view,
|
||||||
|
&mut view_state.search,
|
||||||
) {
|
) {
|
||||||
StripBuilder::new(ui).size(Size::exact(40.0)).size(Size::remainder()).vertical(
|
StripBuilder::new(ui).size(Size::exact(40.0)).size(Size::remainder()).vertical(
|
||||||
|mut strip| {
|
|mut strip| {
|
||||||
@ -223,6 +238,7 @@ pub fn symbol_diff_ui(ui: &mut Ui, view_state: &mut ViewState) {
|
|||||||
selected_symbol,
|
selected_symbol,
|
||||||
current_view,
|
current_view,
|
||||||
view_state.reverse_fn_order,
|
view_state.reverse_fn_order,
|
||||||
|
search,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -241,6 +257,7 @@ pub fn symbol_diff_ui(ui: &mut Ui, view_state: &mut ViewState) {
|
|||||||
selected_symbol,
|
selected_symbol,
|
||||||
current_view,
|
current_view,
|
||||||
view_state.reverse_fn_order,
|
view_state.reverse_fn_order,
|
||||||
|
search,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user