[MIPS] Fix symbols being filtered out from target side of diff if target object contains .NON_MATCHING markers (#250)

* Fix filtering out symbols from the target side that have a symbol with the same name and a `.NON_MATCHING` suffix.

- Target side: Show all the symbols except the `.NON_MATCHING` ones.
- Base side: Ignore all the `.NON_MATCHING` symbols and also ignore the ones with the same name without the suffix

* fmt

* comment

* tests

* fmt tests

* maybe this could fix wasm?

* Fix wasm?

* fmt

* Move `DiffSide` to `diff` mod

* Update the stuff the advisories CI told me to
This commit is contained in:
Anghelo Carvajal 2025-09-02 21:13:29 -04:00 committed by GitHub
parent a138dfa907
commit 6fb4bb8855
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 169 additions and 44 deletions

View File

@ -8,8 +8,8 @@ use objdiff_core::{
Report, ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata, Report, ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata,
}, },
config::path::platform_path, config::path::platform_path,
diff, obj, diff,
obj::{SectionKind, SymbolFlag}, obj::{self, SectionKind, SymbolFlag},
}; };
use prost::Message; use prost::Message;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
@ -177,14 +177,16 @@ fn report_object(
.target_path .target_path
.as_ref() .as_ref()
.map(|p| { .map(|p| {
obj::read::read(p.as_ref(), diff_config).with_context(|| format!("Failed to open {p}")) obj::read::read(p.as_ref(), diff_config, diff::DiffSide::Target)
.with_context(|| format!("Failed to open {p}"))
}) })
.transpose()?; .transpose()?;
let base = object let base = object
.base_path .base_path
.as_ref() .as_ref()
.map(|p| { .map(|p| {
obj::read::read(p.as_ref(), diff_config).with_context(|| format!("Failed to open {p}")) obj::read::read(p.as_ref(), diff_config, diff::DiffSide::Base)
.with_context(|| format!("Failed to open {p}"))
}) })
.transpose()?; .transpose()?;
let result = let result =

View File

@ -12,7 +12,7 @@ use rabbitizer::{
use crate::{ use crate::{
arch::{Arch, RelocationOverride, RelocationOverrideTarget}, arch::{Arch, RelocationOverride, RelocationOverrideTarget},
diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart}, diff::{DiffObjConfig, DiffSide, MipsAbi, MipsInstrCategory, display::InstructionPart},
obj::{ obj::{
InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags, InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags,
ResolvedInstructionRef, ResolvedRelocation, Section, Symbol, SymbolFlag, SymbolFlagSet, ResolvedInstructionRef, ResolvedRelocation, Section, Symbol, SymbolFlag, SymbolFlagSet,
@ -27,6 +27,7 @@ pub struct ArchMips {
pub ri_gp_value: i32, pub ri_gp_value: i32,
pub paired_relocations: Vec<BTreeMap<u64, i64>>, pub paired_relocations: Vec<BTreeMap<u64, i64>>,
pub ignored_symbols: BTreeSet<usize>, pub ignored_symbols: BTreeSet<usize>,
pub diff_side: DiffSide,
} }
const EF_MIPS_ABI: u32 = 0x0000F000; const EF_MIPS_ABI: u32 = 0x0000F000;
@ -38,7 +39,7 @@ const EF_MIPS_MACH_5900: u32 = 0x00920000;
const R_MIPS15_S3: u32 = 119; const R_MIPS15_S3: u32 = 119;
impl ArchMips { impl ArchMips {
pub fn new(object: &object::File) -> Result<Self> { pub fn new(object: &object::File, diff_side: DiffSide) -> Result<Self> {
let mut abi = Abi::O32; let mut abi = Abi::O32;
let mut isa_extension = None; let mut isa_extension = None;
match object.flags() { match object.flags() {
@ -124,7 +125,11 @@ impl ArchMips {
let Ok(name) = obj_symbol.name() else { continue }; let Ok(name) = obj_symbol.name() else { continue };
if let Some(prefix) = name.strip_suffix(".NON_MATCHING") { if let Some(prefix) = name.strip_suffix(".NON_MATCHING") {
ignored_symbols.insert(obj_symbol.index().0); ignored_symbols.insert(obj_symbol.index().0);
if let Some(target_symbol) = object.symbol_by_name(prefix) { // Only remove the prefixless symbols if we are on the Base side of the diff,
// to allow diffing against target objects that contain `.NON_MATCHING` markers.
if diff_side == DiffSide::Base
&& let Some(target_symbol) = object.symbol_by_name(prefix)
{
ignored_symbols.insert(target_symbol.index().0); ignored_symbols.insert(target_symbol.index().0);
} }
} }
@ -137,6 +142,7 @@ impl ArchMips {
ri_gp_value, ri_gp_value,
paired_relocations, paired_relocations,
ignored_symbols, ignored_symbols,
diff_side,
}) })
} }

View File

@ -17,7 +17,7 @@ use object::Endian as _;
use crate::{ use crate::{
diff::{ diff::{
DiffObjConfig, DiffObjConfig, DiffSide,
display::{ContextItem, HoverItem, InstructionPart}, display::{ContextItem, HoverItem, InstructionPart},
}, },
obj::{ obj::{
@ -418,15 +418,18 @@ pub trait Arch: Any + Debug + Send + Sync {
} }
} }
pub fn new_arch(object: &object::File) -> Result<Box<dyn Arch>> { pub fn new_arch(object: &object::File, diff_side: DiffSide) -> Result<Box<dyn Arch>> {
use object::Object as _; use object::Object as _;
// Avoid unused warnings on non-mips builds
let _ = diff_side;
Ok(match object.architecture() { Ok(match object.architecture() {
#[cfg(feature = "ppc")] #[cfg(feature = "ppc")]
object::Architecture::PowerPc | object::Architecture::PowerPc64 => { object::Architecture::PowerPc | object::Architecture::PowerPc64 => {
Box::new(ppc::ArchPpc::new(object)?) Box::new(ppc::ArchPpc::new(object)?)
} }
#[cfg(feature = "mips")] #[cfg(feature = "mips")]
object::Architecture::Mips => Box::new(mips::ArchMips::new(object)?), object::Architecture::Mips => Box::new(mips::ArchMips::new(object, diff_side)?),
#[cfg(feature = "x86")] #[cfg(feature = "x86")]
object::Architecture::I386 | object::Architecture::X86_64 => { object::Architecture::I386 | object::Architecture::X86_64 => {
Box::new(x86::ArchX86::new(object)?) Box::new(x86::ArchX86::new(object)?)

View File

@ -807,3 +807,11 @@ fn find_section(
s.kind == section_kind && s.name == name && !matches.iter().any(|m| m.right == Some(i)) s.kind == section_kind && s.name == name && !matches.iter().any(|m| m.right == Some(i))
}) })
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum DiffSide {
/// The target/expected side of the diff.
Target,
/// The base side of the diff.
Base,
}

View File

@ -6,7 +6,7 @@ use typed_path::Utf8PlatformPathBuf;
use crate::{ use crate::{
build::{BuildConfig, BuildStatus, run_make}, build::{BuildConfig, BuildStatus, run_make},
diff::{DiffObjConfig, MappingConfig, ObjectDiff, diff_objs}, diff::{DiffObjConfig, DiffSide, MappingConfig, ObjectDiff, diff_objs},
jobs::{Job, JobContext, JobResult, JobState, start_job, update_status}, jobs::{Job, JobContext, JobResult, JobState, start_job, update_status},
obj::{Object, read}, obj::{Object, read},
}; };
@ -117,7 +117,7 @@ fn run_build(
&cancel, &cancel,
)?; )?;
step_idx += 1; step_idx += 1;
match read::read(target_path.as_ref(), &config.diff_obj_config) { match read::read(target_path.as_ref(), &config.diff_obj_config, DiffSide::Target) {
Ok(obj) => Some(obj), Ok(obj) => Some(obj),
Err(e) => { Err(e) => {
first_status = BuildStatus { first_status = BuildStatus {
@ -141,7 +141,7 @@ fn run_build(
Some(base_path) if second_status.success => { Some(base_path) if second_status.success => {
update_status(context, format!("Loading base {base_path}"), step_idx, total, &cancel)?; update_status(context, format!("Loading base {base_path}"), step_idx, total, &cancel)?;
step_idx += 1; step_idx += 1;
match read::read(base_path.as_ref(), &config.diff_obj_config) { match read::read(base_path.as_ref(), &config.diff_obj_config, DiffSide::Base) {
Ok(obj) => Some(obj), Ok(obj) => Some(obj),
Err(e) => { Err(e) => {
second_status = BuildStatus { second_status = BuildStatus {

View File

@ -12,7 +12,7 @@ use object::{Object as _, ObjectSection as _, ObjectSymbol as _};
use crate::{ use crate::{
arch::{Arch, RelocationOverride, RelocationOverrideTarget, new_arch}, arch::{Arch, RelocationOverride, RelocationOverrideTarget, new_arch},
diff::DiffObjConfig, diff::{DiffObjConfig, DiffSide},
obj::{ obj::{
FlowAnalysisResult, Object, Relocation, RelocationFlags, Section, SectionData, SectionFlag, FlowAnalysisResult, Object, Relocation, RelocationFlags, Section, SectionData, SectionFlag,
SectionKind, Symbol, SymbolFlag, SymbolKind, SectionKind, Symbol, SymbolFlag, SymbolKind,
@ -925,21 +925,25 @@ fn do_combine_sections(
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn read(obj_path: &std::path::Path, config: &DiffObjConfig) -> Result<Object> { pub fn read(
obj_path: &std::path::Path,
config: &DiffObjConfig,
diff_side: DiffSide,
) -> Result<Object> {
let (data, timestamp) = { let (data, timestamp) = {
let file = std::fs::File::open(obj_path)?; let file = std::fs::File::open(obj_path)?;
let timestamp = filetime::FileTime::from_last_modification_time(&file.metadata()?); let timestamp = filetime::FileTime::from_last_modification_time(&file.metadata()?);
(unsafe { memmap2::Mmap::map(&file) }?, timestamp) (unsafe { memmap2::Mmap::map(&file) }?, timestamp)
}; };
let mut obj = parse(&data, config)?; let mut obj = parse(&data, config, diff_side)?;
obj.path = Some(obj_path.to_path_buf()); obj.path = Some(obj_path.to_path_buf());
obj.timestamp = Some(timestamp); obj.timestamp = Some(timestamp);
Ok(obj) Ok(obj)
} }
pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<Object> { pub fn parse(data: &[u8], config: &DiffObjConfig, diff_side: DiffSide) -> Result<Object> {
let obj_file = object::File::parse(data)?; let obj_file = object::File::parse(data)?;
let mut arch = new_arch(&obj_file)?; let mut arch = new_arch(&obj_file, diff_side)?;
let split_meta = parse_split_meta(&obj_file)?; let split_meta = parse_split_meta(&obj_file)?;
let (mut sections, section_indices) = let (mut sections, section_indices) =
map_sections(arch.as_ref(), &obj_file, split_meta.as_ref())?; map_sections(arch.as_ref(), &obj_file, split_meta.as_ref())?;

View File

@ -6,7 +6,12 @@ mod common;
#[cfg(feature = "arm")] #[cfg(feature = "arm")]
fn read_arm() { fn read_arm() {
let diff_config = diff::DiffObjConfig { ..Default::default() }; let diff_config = diff::DiffObjConfig { ..Default::default() };
let obj = obj::read::parse(include_object!("data/arm/LinkStateItem.o"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/arm/LinkStateItem.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = let symbol_idx =
obj.symbols.iter().position(|s| s.name == "_ZN13LinkStateItem12OnStateLeaveEi").unwrap(); obj.symbols.iter().position(|s| s.name == "_ZN13LinkStateItem12OnStateLeaveEi").unwrap();
@ -20,7 +25,9 @@ fn read_arm() {
#[cfg(feature = "arm")] #[cfg(feature = "arm")]
fn read_thumb() { fn read_thumb() {
let diff_config = diff::DiffObjConfig { ..Default::default() }; let diff_config = diff::DiffObjConfig { ..Default::default() };
let obj = obj::read::parse(include_object!("data/arm/thumb.o"), &diff_config).unwrap(); let obj =
obj::read::parse(include_object!("data/arm/thumb.o"), &diff_config, diff::DiffSide::Base)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = obj let symbol_idx = obj
.symbols .symbols
@ -37,7 +44,12 @@ fn read_thumb() {
#[cfg(feature = "arm")] #[cfg(feature = "arm")]
fn combine_text_sections() { fn combine_text_sections() {
let diff_config = diff::DiffObjConfig { combine_text_sections: true, ..Default::default() }; let diff_config = diff::DiffObjConfig { combine_text_sections: true, ..Default::default() };
let obj = obj::read::parse(include_object!("data/arm/enemy300.o"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/arm/enemy300.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
let symbol_idx = obj.symbols.iter().position(|s| s.name == "Enemy300Draw").unwrap(); let symbol_idx = obj.symbols.iter().position(|s| s.name == "Enemy300Draw").unwrap();
let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap(); let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap();
insta::assert_debug_snapshot!(diff.instruction_rows); insta::assert_debug_snapshot!(diff.instruction_rows);

View File

@ -6,7 +6,9 @@ mod common;
#[cfg(feature = "mips")] #[cfg(feature = "mips")]
fn read_mips() { fn read_mips() {
let diff_config = diff::DiffObjConfig { mips_register_prefix: true, ..Default::default() }; let diff_config = diff::DiffObjConfig { mips_register_prefix: true, ..Default::default() };
let obj = obj::read::parse(include_object!("data/mips/main.c.o"), &diff_config).unwrap(); let obj =
obj::read::parse(include_object!("data/mips/main.c.o"), &diff_config, diff::DiffSide::Base)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = obj.symbols.iter().position(|s| s.name == "ControlEntry").unwrap(); let symbol_idx = obj.symbols.iter().position(|s| s.name == "ControlEntry").unwrap();
let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap(); let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap();
@ -19,9 +21,19 @@ fn read_mips() {
#[cfg(feature = "mips")] #[cfg(feature = "mips")]
fn cross_endian_diff() { fn cross_endian_diff() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj_be = obj::read::parse(include_object!("data/mips/code_be.o"), &diff_config).unwrap(); let obj_be = obj::read::parse(
include_object!("data/mips/code_be.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
assert_eq!(obj_be.endianness, object::Endianness::Big); assert_eq!(obj_be.endianness, object::Endianness::Big);
let obj_le = obj::read::parse(include_object!("data/mips/code_le.o"), &diff_config).unwrap(); let obj_le = obj::read::parse(
include_object!("data/mips/code_le.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
assert_eq!(obj_le.endianness, object::Endianness::Little); assert_eq!(obj_le.endianness, object::Endianness::Little);
let left_symbol_idx = obj_be.symbols.iter().position(|s| s.name == "func_00000000").unwrap(); let left_symbol_idx = obj_be.symbols.iter().position(|s| s.name == "func_00000000").unwrap();
let right_symbol_idx = let right_symbol_idx =
@ -42,6 +54,11 @@ fn cross_endian_diff() {
#[cfg(feature = "mips")] #[cfg(feature = "mips")]
fn filter_non_matching() { fn filter_non_matching() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/mips/vw_main.c.o"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/mips/vw_main.c.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj.symbols); insta::assert_debug_snapshot!(obj.symbols);
} }

View File

@ -10,7 +10,9 @@ mod common;
#[cfg(feature = "ppc")] #[cfg(feature = "ppc")]
fn read_ppc() { fn read_ppc() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/ppc/IObj.o"), &diff_config).unwrap(); let obj =
obj::read::parse(include_object!("data/ppc/IObj.o"), &diff_config, diff::DiffSide::Base)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = let symbol_idx =
obj.symbols.iter().position(|s| s.name == "Type2Text__10SObjectTagFUi").unwrap(); obj.symbols.iter().position(|s| s.name == "Type2Text__10SObjectTagFUi").unwrap();
@ -24,7 +26,12 @@ fn read_ppc() {
#[cfg(feature = "ppc")] #[cfg(feature = "ppc")]
fn read_dwarf1_line_info() { fn read_dwarf1_line_info() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/ppc/m_Do_hostIO.o"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/ppc/m_Do_hostIO.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
let line_infos = obj let line_infos = obj
.sections .sections
.iter() .iter()
@ -38,7 +45,12 @@ fn read_dwarf1_line_info() {
#[cfg(feature = "ppc")] #[cfg(feature = "ppc")]
fn read_extab() { fn read_extab() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/ppc/NMWException.o"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/ppc/NMWException.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
} }
@ -47,12 +59,18 @@ fn read_extab() {
fn diff_ppc() { fn diff_ppc() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let mapping_config = diff::MappingConfig::default(); let mapping_config = diff::MappingConfig::default();
let target_obj = let target_obj = obj::read::parse(
obj::read::parse(include_object!("data/ppc/CDamageVulnerability_target.o"), &diff_config) include_object!("data/ppc/CDamageVulnerability_target.o"),
.unwrap(); &diff_config,
let base_obj = diff::DiffSide::Target,
obj::read::parse(include_object!("data/ppc/CDamageVulnerability_base.o"), &diff_config) )
.unwrap(); .unwrap();
let base_obj = obj::read::parse(
include_object!("data/ppc/CDamageVulnerability_base.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
let diff = let diff =
diff::diff_objs(Some(&target_obj), Some(&base_obj), None, &diff_config, &mapping_config) diff::diff_objs(Some(&target_obj), Some(&base_obj), None, &diff_config, &mapping_config)
.unwrap(); .unwrap();
@ -90,7 +108,12 @@ fn diff_ppc() {
#[cfg(feature = "ppc")] #[cfg(feature = "ppc")]
fn read_vmx128_coff() { fn read_vmx128_coff() {
let diff_config = diff::DiffObjConfig { combine_data_sections: true, ..Default::default() }; let diff_config = diff::DiffObjConfig { combine_data_sections: true, ..Default::default() };
let obj = obj::read::parse(include_object!("data/ppc/vmx128.obj"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/ppc/vmx128.obj"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = let symbol_idx =
obj.symbols.iter().position(|s| s.name == "?FloatingPointExample@@YAXXZ").unwrap(); obj.symbols.iter().position(|s| s.name == "?FloatingPointExample@@YAXXZ").unwrap();

View File

@ -6,7 +6,12 @@ mod common;
#[cfg(feature = "x86")] #[cfg(feature = "x86")]
fn read_x86() { fn read_x86() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/x86/staticdebug.obj"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/x86/staticdebug.obj"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = obj.symbols.iter().position(|s| s.name == "?PrintThing@@YAXXZ").unwrap(); let symbol_idx = obj.symbols.iter().position(|s| s.name == "?PrintThing@@YAXXZ").unwrap();
let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap(); let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap();
@ -23,7 +28,9 @@ fn read_x86_combine_sections() {
combine_text_sections: true, combine_text_sections: true,
..Default::default() ..Default::default()
}; };
let obj = obj::read::parse(include_object!("data/x86/rtest.obj"), &diff_config).unwrap(); let obj =
obj::read::parse(include_object!("data/x86/rtest.obj"), &diff_config, diff::DiffSide::Base)
.unwrap();
insta::assert_debug_snapshot!(obj.sections); insta::assert_debug_snapshot!(obj.sections);
} }
@ -31,7 +38,12 @@ fn read_x86_combine_sections() {
#[cfg(feature = "x86")] #[cfg(feature = "x86")]
fn read_x86_64() { fn read_x86_64() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/x86_64/vs2022.o"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/x86_64/vs2022.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = let symbol_idx =
obj.symbols.iter().position(|s| s.name == "?Dot@Vector@@QEAAMPEAU1@@Z").unwrap(); obj.symbols.iter().position(|s| s.name == "?Dot@Vector@@QEAAMPEAU1@@Z").unwrap();
@ -45,7 +57,12 @@ fn read_x86_64() {
#[cfg(feature = "x86")] #[cfg(feature = "x86")]
fn display_section_ordering() { fn display_section_ordering() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/x86/basenode.obj"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/x86/basenode.obj"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
let obj_diff = let obj_diff =
diff::diff_objs(Some(&obj), None, None, &diff_config, &diff::MappingConfig::default()) diff::diff_objs(Some(&obj), None, None, &diff_config, &diff::MappingConfig::default())
.unwrap() .unwrap()
@ -60,7 +77,12 @@ fn display_section_ordering() {
#[cfg(feature = "x86")] #[cfg(feature = "x86")]
fn read_x86_jumptable() { fn read_x86_jumptable() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/x86/jumptable.o"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/x86/jumptable.o"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = obj.symbols.iter().position(|s| s.name == "?test@@YAHH@Z").unwrap(); let symbol_idx = obj.symbols.iter().position(|s| s.name == "?test@@YAHH@Z").unwrap();
let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap(); let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap();
@ -74,6 +96,11 @@ fn read_x86_jumptable() {
#[cfg(feature = "x86")] #[cfg(feature = "x86")]
fn read_x86_local_labels() { fn read_x86_local_labels() {
let diff_config = diff::DiffObjConfig::default(); let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/x86/local_labels.obj"), &diff_config).unwrap(); let obj = obj::read::parse(
include_object!("data/x86/local_labels.obj"),
&diff_config,
diff::DiffSide::Base,
)
.unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
} }

View File

@ -1,5 +1,6 @@
--- ---
source: objdiff-core/tests/arch_mips.rs source: objdiff-core/tests/arch_mips.rs
assertion_line: 10
expression: obj expression: obj
--- ---
Object { Object {
@ -51,6 +52,7 @@ Object {
{}, {},
], ],
ignored_symbols: {}, ignored_symbols: {},
diff_side: Base,
}, },
endianness: Little, endianness: Little,
symbols: [ symbols: [

View File

@ -24,7 +24,7 @@ wit_bindgen::generate!({
use exports::objdiff::core::{ use exports::objdiff::core::{
diff::{ diff::{
DiffConfigBorrow, DiffResult, Guest as GuestDiff, GuestDiffConfig, GuestObject, DiffConfigBorrow, DiffResult, DiffSide, Guest as GuestDiff, GuestDiffConfig, GuestObject,
GuestObjectDiff, MappingConfig, Object, ObjectBorrow, ObjectDiff, ObjectDiffBorrow, GuestObjectDiff, MappingConfig, Object, ObjectBorrow, ObjectDiff, ObjectDiffBorrow,
SymbolFlags, SymbolInfo, SymbolKind, SymbolRef, SymbolFlags, SymbolInfo, SymbolKind, SymbolRef,
}, },
@ -470,8 +470,21 @@ unsafe impl Sync for ObjectCache {}
static OBJECT_CACHE: ObjectCache = ObjectCache::new(); static OBJECT_CACHE: ObjectCache = ObjectCache::new();
impl From<DiffSide> for objdiff_core::diff::DiffSide {
fn from(value: DiffSide) -> Self {
match value {
DiffSide::Target => Self::Target,
DiffSide::Base => Self::Base,
}
}
}
impl GuestObject for ResourceObject { impl GuestObject for ResourceObject {
fn parse(data: Vec<u8>, diff_config: DiffConfigBorrow) -> Result<Object, String> { fn parse(
data: Vec<u8>,
diff_config: DiffConfigBorrow,
diff_side: DiffSide,
) -> Result<Object, String> {
let hash = xxh3_64(&data); let hash = xxh3_64(&data);
let mut cached = None; let mut cached = None;
OBJECT_CACHE.borrow_mut().retain(|c| { OBJECT_CACHE.borrow_mut().retain(|c| {
@ -487,7 +500,9 @@ impl GuestObject for ResourceObject {
return Ok(Object::new(ResourceObject(obj, hash))); return Ok(Object::new(ResourceObject(obj, hash)));
} }
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let obj = Rc::new(obj::read::parse(&data, &diff_config).map_err(|e| e.to_string())?); let obj = Rc::new(
obj::read::parse(&data, &diff_config, diff_side.into()).map_err(|e| e.to_string())?,
);
OBJECT_CACHE.borrow_mut().push(CachedObject(Rc::downgrade(&obj), hash)); OBJECT_CACHE.borrow_mut().push(CachedObject(Rc::downgrade(&obj), hash));
Ok(Object::new(ResourceObject(obj, hash))) Ok(Object::new(ResourceObject(obj, hash)))
} }

View File

@ -19,6 +19,7 @@ interface diff {
parse: static func( parse: static func(
data: list<u8>, data: list<u8>,
config: borrow<diff-config>, config: borrow<diff-config>,
side: diff-side,
) -> result<object, string>; ) -> result<object, string>;
hash: func() -> u64; hash: func() -> u64;
@ -80,6 +81,11 @@ interface diff {
config: borrow<diff-config>, config: borrow<diff-config>,
mapping: mapping-config, mapping: mapping-config,
) -> result<diff-result, string>; ) -> result<diff-result, string>;
enum diff-side {
target,
base,
}
} }
interface display { interface display {