Make objdiff-core no_std + huge WASM rework

This commit is contained in:
2025-02-07 00:10:49 -07:00
parent d938988d43
commit e8de35b78e
49 changed files with 1463 additions and 1046 deletions

View File

@@ -1,7 +1,12 @@
use std::{cmp::max, collections::BTreeMap};
use alloc::{
collections::BTreeMap,
string::{String, ToString},
vec,
vec::Vec,
};
use anyhow::{anyhow, Result};
use similar::{capture_diff_slices_deadline, Algorithm};
use similar::{capture_diff_slices, Algorithm};
use super::FunctionRelocDiffs;
use crate::{
@@ -118,8 +123,7 @@ fn diff_instructions(
left_code: &ProcessCodeResult,
right_code: &ProcessCodeResult,
) -> Result<()> {
let ops =
capture_diff_slices_deadline(Algorithm::Patience, &left_code.ops, &right_code.ops, None);
let ops = capture_diff_slices(Algorithm::Patience, &left_code.ops, &right_code.ops);
if ops.is_empty() {
left_diff.extend(
left_code
@@ -138,7 +142,7 @@ fn diff_instructions(
for op in ops {
let (_tag, left_range, right_range) = op.as_tag_tuple();
let len = max(left_range.len(), right_range.len());
let len = left_range.len().max(right_range.len());
left_diff.extend(
left_code.insts[left_range.clone()]
.iter()

View File

@@ -1,10 +1,8 @@
use std::{
cmp::{max, min, Ordering},
ops::Range,
};
use alloc::{vec, vec::Vec};
use core::{cmp::Ordering, ops::Range};
use anyhow::{anyhow, Result};
use similar::{capture_diff_slices_deadline, get_diff_ratio, Algorithm};
use similar::{capture_diff_slices, get_diff_ratio, Algorithm};
use super::code::{address_eq, section_name_eq};
use crate::{
@@ -142,7 +140,7 @@ pub fn diff_data_section(
right.symbols.iter().map(|s| s.section_address + s.size).max().unwrap_or(0).min(right.size);
let left_data = &left.data[..left_max as usize];
let right_data = &right.data[..right_max as usize];
let ops = capture_diff_slices_deadline(Algorithm::Patience, left_data, right_data, None);
let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data);
let match_percent = get_diff_ratio(&ops, left_data.len(), right_data.len()) * 100.0;
let mut left_diff = Vec::<ObjDataDiff>::new();
@@ -151,27 +149,27 @@ pub fn diff_data_section(
let (tag, left_range, right_range) = op.as_tag_tuple();
let left_len = left_range.len();
let right_len = right_range.len();
let mut len = max(left_len, right_len);
let mut len = left_len.max(right_len);
let kind = match tag {
similar::DiffTag::Equal => ObjDataDiffKind::None,
similar::DiffTag::Delete => ObjDataDiffKind::Delete,
similar::DiffTag::Insert => ObjDataDiffKind::Insert,
similar::DiffTag::Replace => {
// Ensure replacements are equal length
len = min(left_len, right_len);
len = left_len.min(right_len);
ObjDataDiffKind::Replace
}
};
let left_data = &left.data[left_range];
let right_data = &right.data[right_range];
left_diff.push(ObjDataDiff {
data: left_data[..min(len, left_data.len())].to_vec(),
data: left_data[..len.min(left_data.len())].to_vec(),
kind,
len,
..Default::default()
});
right_diff.push(ObjDataDiff {
data: right_data[..min(len, right_data.len())].to_vec(),
data: right_data[..len.min(right_data.len())].to_vec(),
kind,
len,
..Default::default()
@@ -283,7 +281,7 @@ pub fn diff_data_symbol(
right_range,
);
let ops = capture_diff_slices_deadline(Algorithm::Patience, left_data, right_data, None);
let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data);
let bytes_match_ratio = get_diff_ratio(&ops, left_data.len(), right_data.len());
let mut match_ratio = bytes_match_ratio;
@@ -375,7 +373,7 @@ pub fn diff_bss_section(
) -> Result<(ObjSectionDiff, ObjSectionDiff)> {
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, None);
let ops = capture_diff_slices(Algorithm::Patience, &left_sizes, &right_sizes);
let mut match_percent = get_diff_ratio(&ops, left_sizes.len(), right_sizes.len()) * 100.0;
// Use the highest match percent between two options:

View File

@@ -1,3 +1,5 @@
use alloc::string::{String, ToString};
use crate::{
diff::{ObjInsArgDiff, ObjInsDiff},
obj::{ObjInsArg, ObjInsArgValue, ObjReloc, ObjSymbol},

View File

@@ -1,9 +1,14 @@
use std::{collections::HashSet, ops::Range};
use alloc::{
collections::{BTreeMap, BTreeSet},
string::String,
vec,
vec::Vec,
};
use core::ops::Range;
use anyhow::Result;
use crate::{
config::SymbolMappings,
diff::{
code::{diff_code, no_diff_code, process_code_symbol},
data::{
@@ -473,12 +478,11 @@ struct SectionMatch {
section_kind: ObjSectionKind,
}
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify), tsify(from_wasm_abi))]
#[serde(default)]
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(default))]
pub struct MappingConfig {
/// Manual symbol mappings
pub mappings: SymbolMappings,
pub mappings: BTreeMap<String, String>,
/// The right object symbol name that we're selecting a left symbol for
pub selecting_left: Option<String>,
/// The left object symbol name that we're selecting a right symbol for
@@ -500,8 +504,8 @@ fn apply_symbol_mappings(
left: &ObjInfo,
right: &ObjInfo,
mapping_config: &MappingConfig,
left_used: &mut HashSet<SymbolRef>,
right_used: &mut HashSet<SymbolRef>,
left_used: &mut BTreeSet<SymbolRef>,
right_used: &mut BTreeSet<SymbolRef>,
matches: &mut Vec<SymbolMatch>,
) -> Result<()> {
// If we're selecting a symbol to use as a comparison, mark it as used
@@ -563,8 +567,8 @@ fn matching_symbols(
mappings: &MappingConfig,
) -> Result<Vec<SymbolMatch>> {
let mut matches = Vec::new();
let mut left_used = HashSet::new();
let mut right_used = HashSet::new();
let mut left_used = BTreeSet::new();
let mut right_used = BTreeSet::new();
if let Some(left) = left {
if let Some(right) = right {
apply_symbol_mappings(
@@ -645,7 +649,7 @@ fn matching_symbols(
fn unmatched_symbols<'section, 'used>(
section: &'section ObjSection,
section_idx: usize,
used: Option<&'used HashSet<SymbolRef>>,
used: Option<&'used BTreeSet<SymbolRef>>,
) -> impl Iterator<Item = (usize, &'section ObjSymbol)> + 'used
where
'section: 'used,
@@ -660,7 +664,7 @@ fn find_symbol(
obj: Option<&ObjInfo>,
in_symbol: &ObjSymbol,
in_section: &ObjSection,
used: Option<&HashSet<SymbolRef>>,
used: Option<&BTreeSet<SymbolRef>>,
) -> Option<SymbolRef> {
let obj = obj?;
// Try to find an exact name match