Skip to content

Commit

Permalink
[WIP] Allow selecting symbols to compare
Browse files Browse the repository at this point in the history
  • Loading branch information
encounter committed Oct 8, 2024
1 parent 603dbd6 commit d7055f7
Show file tree
Hide file tree
Showing 14 changed files with 1,205 additions and 647 deletions.
4 changes: 2 additions & 2 deletions objdiff-cli/src/cmd/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ fn find_function(obj: &ObjInfo, name: &str) -> Option<SymbolRef> {
None
}

#[allow(dead_code)]
#[expect(dead_code)]
struct FunctionDiffUi {
relax_reloc_diffs: bool,
left_highlight: HighlightKind,
Expand Down Expand Up @@ -758,7 +758,7 @@ impl FunctionDiffUi {
self.scroll_y += self.per_page / if half { 2 } else { 1 };
}

#[allow(clippy::too_many_arguments)]
#[expect(clippy::too_many_arguments)]
fn print_sym(
&self,
out: &mut Text<'static>,
Expand Down
4 changes: 2 additions & 2 deletions objdiff-core/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ impl ProjectObject {
}

pub fn complete(&self) -> Option<bool> {
#[allow(deprecated)]
#[expect(deprecated)]
self.metadata.as_ref().and_then(|m| m.complete).or(self.complete)
}

pub fn reverse_fn_order(&self) -> Option<bool> {
#[allow(deprecated)]
#[expect(deprecated)]
self.metadata.as_ref().and_then(|m| m.reverse_fn_order).or(self.reverse_fn_order)
}

Expand Down
4 changes: 2 additions & 2 deletions objdiff-core/src/diff/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ fn arg_eq(
left_diff: &ObjInsDiff,
right_diff: &ObjInsDiff,
) -> bool {
return match left {
match left {
ObjInsArg::PlainText(l) => match right {
ObjInsArg::PlainText(r) => l == r,
_ => false,
Expand All @@ -236,7 +236,7 @@ fn arg_eq(
left_diff.branch_to.as_ref().map(|b| b.ins_idx)
== right_diff.branch_to.as_ref().map(|b| b.ins_idx)
}
};
}
}

#[derive(Default)]
Expand Down
75 changes: 71 additions & 4 deletions objdiff-core/src/diff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ pub struct DiffObjConfig {
#[serde(default = "default_true")]
pub space_between_args: bool,
pub combine_data_sections: bool,
pub symbol_overrides: SymbolOverrides,
// x86
pub x86_formatter: X86Formatter,
// MIPS
Expand All @@ -182,6 +183,7 @@ impl Default for DiffObjConfig {
relax_reloc_diffs: false,
space_between_args: true,
combine_data_sections: false,
symbol_overrides: Default::default(),
x86_formatter: Default::default(),
mips_abi: Default::default(),
mips_instr_category: Default::default(),
Expand Down Expand Up @@ -378,7 +380,7 @@ pub fn diff_objs(
right: Option<&ObjInfo>,
prev: Option<&ObjInfo>,
) -> Result<DiffObjsResult> {
let symbol_matches = matching_symbols(left, right, prev)?;
let symbol_matches = matching_symbols(left, right, prev, &config.symbol_overrides)?;
let section_matches = matching_sections(left, right)?;
let mut left = left.map(|p| (p, ObjDiff::new_from_obj(p)));
let mut right = right.map(|p| (p, ObjDiff::new_from_obj(p)));
Expand Down Expand Up @@ -551,11 +553,61 @@ struct SectionMatch {
section_kind: ObjSectionKind,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, serde::Deserialize, serde::Serialize)]
pub struct SymbolOverride {
pub left: Option<String>,
pub right: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, serde::Deserialize, serde::Serialize)]
pub struct SymbolOverrides(pub Vec<SymbolOverride>);

impl SymbolOverrides {
pub fn get(&self, name: &str) -> Option<&SymbolOverride> {
self.0.iter().find(|o| {
o.left.as_ref().is_some_and(|l| l == name)
|| o.right.as_ref().is_some_and(|r| r == name)
})
}

pub fn remove_left(&mut self, left: &str, right: &str) {
self.0.retain(|o| {
o.left.as_ref().map_or(true, |l| l != left)
&& o.right.as_ref().map_or(true, |r| r != right)
});
self.0.push(SymbolOverride { left: None, right: Some(right.to_string()) });
// println!("{:?}", self.0);
}

pub fn remove_right(&mut self, left: &str, right: &str) {
self.0.retain(|o| {
o.left.as_ref().map_or(true, |l| l != left)
&& o.right.as_ref().map_or(true, |r| r != right)
});
self.0.push(SymbolOverride { left: Some(left.to_string()), right: None });
// println!("{:?}", self.0);
}

pub fn set(&mut self, left: String, right: String) {
self.0.retain(|o| {
o.left.as_ref().map_or(true, |l| l != &left && l != &right)
&& o.right.as_ref().map_or(true, |r| r != &left && r != &right)
});
if left != right {
self.0.push(SymbolOverride { left: Some(left), right: Some(right) });
}
// println!("{:?}", self.0);
}

pub fn clear(&mut self) { self.0.clear(); }
}

/// Find matching symbols between each object.
fn matching_symbols(
left: Option<&ObjInfo>,
right: Option<&ObjInfo>,
prev: Option<&ObjInfo>,
overrides: &SymbolOverrides,
) -> Result<Vec<SymbolMatch>> {
let mut matches = Vec::new();
let mut right_used = HashSet::new();
Expand All @@ -564,8 +616,8 @@ fn matching_symbols(
for (symbol_idx, symbol) in section.symbols.iter().enumerate() {
let symbol_match = SymbolMatch {
left: Some(SymbolRef { section_idx, symbol_idx }),
right: find_symbol(right, symbol, section, Some(&right_used)),
prev: find_symbol(prev, symbol, section, None),
right: find_symbol(right, symbol, section, Some(&right_used), overrides),
prev: find_symbol(prev, symbol, section, None, &Default::default()),
section_kind: section.kind,
};
matches.push(symbol_match);
Expand Down Expand Up @@ -597,7 +649,7 @@ fn matching_symbols(
matches.push(SymbolMatch {
left: None,
right: Some(symbol_ref),
prev: find_symbol(prev, symbol, section, None),
prev: find_symbol(prev, symbol, section, None, &Default::default()),
section_kind: section.kind,
});
}
Expand Down Expand Up @@ -637,8 +689,23 @@ fn find_symbol(
in_symbol: &ObjSymbol,
in_section: &ObjSection,
used: Option<&HashSet<SymbolRef>>,
overrides: &SymbolOverrides,
) -> Option<SymbolRef> {
let obj = obj?;
// Check for a symbol override
if let Some(symbol_override) = overrides.get(&in_symbol.name) {
symbol_override.left.as_ref()?;
let right_name = symbol_override.right.as_ref()?;
if let Some((section_idx, section)) =
obj.sections.iter().enumerate().find(|(_, s)| s.name == in_section.name)
{
if let Some((symbol_idx, _)) = unmatched_symbols(section, section_idx, used)
.find(|(_, symbol)| &symbol.name == right_name)
{
return Some(SymbolRef { section_idx, symbol_idx });
}
}
}
// Try to find an exact name match
for (section_idx, section) in obj.sections.iter().enumerate() {
if section.kind != in_section.kind {
Expand Down
10 changes: 10 additions & 0 deletions objdiff-core/src/obj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ pub struct ObjIns {
pub orig: Option<String>,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
pub enum ObjSymbolKind {
#[default]
Unknown,
Function,
Object,
Section,
}

#[derive(Debug, Clone)]
pub struct ObjSymbol {
pub name: String,
Expand All @@ -120,6 +129,7 @@ pub struct ObjSymbol {
pub section_address: u64,
pub size: u64,
pub size_known: bool,
pub kind: ObjSymbolKind,
pub flags: ObjSymbolFlagSet,
pub addend: i64,
/// Original virtual address (from .note.split section)
Expand Down
24 changes: 23 additions & 1 deletion objdiff-core/src/obj/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
obj::{
split_meta::{SplitMeta, SPLITMETA_SECTION},
ObjInfo, ObjReloc, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags,
ObjSymbolKind,
},
util::{read_u16, read_u32},
};
Expand Down Expand Up @@ -94,13 +95,21 @@ fn to_obj_symbol(
})
.unwrap_or(&[]);

let kind = match symbol.kind() {
SymbolKind::Text => ObjSymbolKind::Function,
SymbolKind::Data => ObjSymbolKind::Object,
SymbolKind::Section => ObjSymbolKind::Section,
_ => ObjSymbolKind::Unknown,
};

Ok(ObjSymbol {
name: name.to_string(),
demangled_name,
address,
section_address,
size: symbol.size(),
size_known: symbol.size() != 0,
kind,
flags,
addend,
virtual_address,
Expand Down Expand Up @@ -173,12 +182,19 @@ fn symbols_by_section(
result.sort_by(|a, b| a.address.cmp(&b.address).then(a.size.cmp(&b.size)));
let mut iter = result.iter_mut().peekable();
while let Some(symbol) = iter.next() {
if symbol.size == 0 {
if symbol.kind == ObjSymbolKind::Unknown && symbol.size == 0 {
if let Some(next_symbol) = iter.peek() {
symbol.size = next_symbol.address - symbol.address;
} else {
symbol.size = (section.address + section.size) - symbol.address;
}
// Set symbol kind if we ended up with a non-zero size
if symbol.size > 0 {
symbol.kind = match section.kind {
ObjSectionKind::Code => ObjSymbolKind::Function,
ObjSectionKind::Data | ObjSectionKind::Bss => ObjSymbolKind::Object,
};
}
}
}
if result.is_empty() {
Expand All @@ -196,6 +212,10 @@ fn symbols_by_section(
section_address: 0,
size: section.size,
size_known: true,
kind: match section.kind {
ObjSectionKind::Code => ObjSymbolKind::Function,
ObjSectionKind::Data | ObjSectionKind::Bss => ObjSymbolKind::Object,
},
flags: Default::default(),
addend: 0,
virtual_address: None,
Expand Down Expand Up @@ -281,6 +301,7 @@ fn find_section_symbol(
section_address: 0,
size: 0,
size_known: false,
kind: ObjSymbolKind::Section,
flags: Default::default(),
addend: address as i64 - section.address() as i64,
virtual_address: None,
Expand Down Expand Up @@ -568,6 +589,7 @@ fn update_combined_symbol(symbol: ObjSymbol, address_change: i64) -> Result<ObjS
section_address: (symbol.section_address as i64 + address_change).try_into()?,
size: symbol.size,
size_known: symbol.size_known,
kind: symbol.kind,
flags: symbol.flags,
addend: symbol.addend,
virtual_address: if let Some(virtual_address) = symbol.virtual_address {
Expand Down
1 change: 1 addition & 0 deletions objdiff-gui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ impl App {
if state.config.selected_obj.is_some() {
state.queue_build = true;
}
state.config.diff_obj_config.symbol_overrides.clear();
app.view_state.config_state.queue_check_update = state.config.auto_update_check;
app.state = Arc::new(RwLock::new(state));
}
Expand Down
2 changes: 1 addition & 1 deletion objdiff-gui/src/jobs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl JobQueue {
}

/// Returns whether any job is running.
#[allow(dead_code)]
#[expect(dead_code)]
pub fn any_running(&self) -> bool {
self.jobs.iter().any(|job| {
if let Some(handle) = &job.handle {
Expand Down
82 changes: 82 additions & 0 deletions objdiff-gui/src/views/column_layout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use egui::{Align, Layout, Sense, Vec2};
use egui_extras::{Column, Size, StripBuilder, TableBuilder, TableRow};

pub fn render_header(
ui: &mut egui::Ui,
available_width: f32,
num_columns: usize,
mut add_contents: impl FnMut(&mut egui::Ui, usize),
) {
let column_width = available_width / num_columns as f32;
ui.allocate_ui_with_layout(
Vec2 { x: available_width, y: 100.0 },
Layout::left_to_right(Align::Min),
|ui| {
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Truncate);
for i in 0..num_columns {
ui.allocate_ui_with_layout(
Vec2 { x: column_width, y: 100.0 },
Layout::top_down(Align::Min),
|ui| {
ui.set_width(column_width);
add_contents(ui, i);
},
);
}
},
);
ui.separator();
}

pub fn render_table(
ui: &mut egui::Ui,
available_width: f32,
num_columns: usize,
row_height: f32,
total_rows: usize,
mut add_contents: impl FnMut(&mut TableRow, usize),
) {
ui.style_mut().interaction.selectable_labels = false;
let column_width = available_width / num_columns as f32;
let available_height = ui.available_height();
let table = TableBuilder::new(ui)
.striped(false)
.cell_layout(Layout::left_to_right(Align::Min))
.columns(Column::exact(column_width).clip(true), num_columns)
.resizable(false)
.auto_shrink([false, false])
.min_scrolled_height(available_height)
.sense(Sense::click());
table.body(|body| {
body.rows(row_height, total_rows, |mut row| {
row.set_hovered(false); // Disable hover effect
for i in 0..num_columns {
add_contents(&mut row, i);
}
});
});
}

pub fn render_strips(
ui: &mut egui::Ui,
available_width: f32,
num_columns: usize,
mut add_contents: impl FnMut(&mut egui::Ui, usize),
) {
let column_width = available_width / num_columns as f32;
StripBuilder::new(ui).size(Size::remainder()).clip(true).vertical(|mut strip| {
strip.strip(|builder| {
builder.sizes(Size::exact(column_width), num_columns).clip(true).horizontal(
|mut strip| {
for i in 0..num_columns {
strip.cell(|ui| {
ui.push_id(i, |ui| {
add_contents(ui, i);
});
});
}
},
);
});
});
}
Loading

0 comments on commit d7055f7

Please sign in to comment.