Support bss and text section diffing

Display section diff % in symbols view
This commit is contained in:
Luke Street 2024-05-21 12:02:00 -06:00
parent 320efcb8cb
commit e254af5acf
3 changed files with 94 additions and 8 deletions

View File

@ -11,6 +11,27 @@ use crate::{
obj::{ObjInfo, ObjSection, SymbolRef}, obj::{ObjInfo, ObjSection, SymbolRef},
}; };
/// Compare the addresses and sizes of each symbol in the BSS sections.
pub fn diff_bss_section(
left: &ObjSection,
right: &ObjSection,
) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
let deadline = Instant::now() + Duration::from_secs(5);
let left_sizes = left.symbols.iter().map(|s| (s.section_address, s.size)).collect::<Vec<_>>();
let right_sizes = right.symbols.iter().map(|s| (s.section_address, s.size)).collect::<Vec<_>>();
let ops = capture_diff_slices_deadline(
Algorithm::Patience,
&left_sizes,
&right_sizes,
Some(deadline),
);
let match_percent = get_diff_ratio(&ops, left_sizes.len(), right_sizes.len()) * 100.0;
Ok((
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
))
}
pub fn diff_bss_symbol( pub fn diff_bss_symbol(
left_obj: &ObjInfo, left_obj: &ObjInfo,
right_obj: &ObjInfo, right_obj: &ObjInfo,
@ -40,14 +61,19 @@ pub fn no_diff_symbol(_obj: &ObjInfo, symbol_ref: SymbolRef) -> ObjSymbolDiff {
ObjSymbolDiff { symbol_ref, diff_symbol: None, instructions: vec![], match_percent: None } ObjSymbolDiff { symbol_ref, diff_symbol: None, instructions: vec![], match_percent: None }
} }
pub fn diff_data( /// Compare the data sections of two object files.
pub fn diff_data_section(
left: &ObjSection, left: &ObjSection,
right: &ObjSection, right: &ObjSection,
) -> Result<(ObjSectionDiff, ObjSectionDiff)> { ) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
let deadline = Instant::now() + Duration::from_secs(5); let deadline = Instant::now() + Duration::from_secs(5);
let left_max = left.symbols.iter().map(|s| s.section_address + s.size).max().unwrap_or(0);
let right_max = right.symbols.iter().map(|s| s.section_address + s.size).max().unwrap_or(0);
let left_data = &left.data[..left_max as usize];
let right_data = &right.data[..right_max as usize];
let ops = let ops =
capture_diff_slices_deadline(Algorithm::Patience, &left.data, &right.data, Some(deadline)); capture_diff_slices_deadline(Algorithm::Patience, left_data, right_data, Some(deadline));
let match_percent = get_diff_ratio(&ops, left.data.len(), right.data.len()) * 100.0; let match_percent = get_diff_ratio(&ops, left_data.len(), right_data.len()) * 100.0;
let mut left_diff = Vec::<ObjDataDiff>::new(); let mut left_diff = Vec::<ObjDataDiff>::new();
let mut right_diff = Vec::<ObjDataDiff>::new(); let mut right_diff = Vec::<ObjDataDiff>::new();
@ -168,3 +194,24 @@ pub fn diff_data_symbol(
}, },
)) ))
} }
/// Compare the text sections of two object files.
/// This essentially adds up the match percentage of each symbol in the text section.
pub fn diff_text_section(
left: &ObjSection,
_right: &ObjSection,
left_diff: &ObjSectionDiff,
_right_diff: &ObjSectionDiff,
) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
let match_percent = left
.symbols
.iter()
.zip(left_diff.symbols.iter())
.map(|(s, d)| d.match_percent.unwrap_or(0.0) * s.size as f32)
.sum::<f32>()
/ left.size as f32;
Ok((
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
ObjSectionDiff { symbols: vec![], data_diff: vec![], match_percent: Some(match_percent) },
))
}

View File

@ -5,7 +5,10 @@ use anyhow::Result;
use crate::{ use crate::{
diff::{ diff::{
code::{diff_code, no_diff_code}, code::{diff_code, no_diff_code},
data::{diff_bss_symbol, diff_data, diff_data_symbol, no_diff_symbol}, data::{
diff_bss_section, diff_bss_symbol, diff_data_section, diff_data_symbol,
diff_text_section, no_diff_symbol,
},
}, },
obj::{ObjInfo, ObjIns, ObjSection, ObjSectionKind, ObjSymbol, SymbolRef}, obj::{ObjInfo, ObjIns, ObjSection, ObjSectionKind, ObjSymbol, SymbolRef},
}; };
@ -324,15 +327,26 @@ pub fn diff_objs(
let right_section = &right_obj.sections[right_section_idx]; let right_section = &right_obj.sections[right_section_idx];
match section_kind { match section_kind {
ObjSectionKind::Code => { ObjSectionKind::Code => {
// TODO? let left_section_diff = left_out.section_diff(left_section_idx);
let right_section_diff = right_out.section_diff(right_section_idx);
let (left_diff, right_diff) = diff_text_section(
left_section,
right_section,
left_section_diff,
right_section_diff,
)?;
left_out.section_diff_mut(left_section_idx).merge(left_diff);
right_out.section_diff_mut(right_section_idx).merge(right_diff);
} }
ObjSectionKind::Data => { ObjSectionKind::Data => {
let (left_diff, right_diff) = diff_data(left_section, right_section)?; let (left_diff, right_diff) = diff_data_section(left_section, right_section)?;
left_out.section_diff_mut(left_section_idx).merge(left_diff); left_out.section_diff_mut(left_section_idx).merge(left_diff);
right_out.section_diff_mut(right_section_idx).merge(right_diff); right_out.section_diff_mut(right_section_idx).merge(right_diff);
} }
ObjSectionKind::Bss => { ObjSectionKind::Bss => {
// TODO let (left_diff, right_diff) = diff_bss_section(left_section, right_section)?;
left_out.section_diff_mut(left_section_idx).merge(left_diff);
right_out.section_diff_mut(right_section_idx).merge(right_diff);
} }
} }
} }

View File

@ -303,7 +303,32 @@ fn symbol_list_ui(
} }
for (section, section_diff) in obj.0.sections.iter().zip(&obj.1.sections) { for (section, section_diff) in obj.0.sections.iter().zip(&obj.1.sections) {
CollapsingHeader::new(format!("{} ({:x})", section.name, section.size)) let mut header = LayoutJob::simple_singleline(
format!("{} ({:x})", section.name, section.size),
appearance.code_font.clone(),
Color32::PLACEHOLDER,
);
if let Some(match_percent) = section_diff.match_percent {
write_text(
" (",
Color32::PLACEHOLDER,
&mut header,
appearance.code_font.clone(),
);
write_text(
&format!("{match_percent:.0}%"),
match_color_for_symbol(match_percent, appearance),
&mut header,
appearance.code_font.clone(),
);
write_text(
")",
Color32::PLACEHOLDER,
&mut header,
appearance.code_font.clone(),
);
}
CollapsingHeader::new(header)
.id_source(Id::new(section.name.clone()).with(section.orig_index)) .id_source(Id::new(section.name.clone()).with(section.orig_index))
.default_open(true) .default_open(true)
.show(ui, |ui| { .show(ui, |ui| {