Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions objdiff-core/src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,16 @@ pub trait Arch: Any + Debug + Send + Sync {
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
) -> Result<()>;

/// Return formatting-token structure that must match for two instructions to be considered equal.
/// Architectures that encode operand structure in their formatted output can override this.
fn instruction_comparison_key(
&self,
_resolved: ResolvedInstructionRef,
_diff_config: &DiffObjConfig,
) -> Result<Option<Vec<String>>> {
Ok(None)
}

/// Generate a list of fake relocations from the given code that represent pooled data accesses.
fn generate_pooled_relocations(
&self,
Expand Down
48 changes: 47 additions & 1 deletion objdiff-core/src/arch/x86.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloc::{boxed::Box, format, vec::Vec};
use alloc::{boxed::Box, format, string::String, vec::Vec};
use core::cmp::Ordering;

use anyhow::{Context, Result, anyhow, bail};
Expand Down Expand Up @@ -102,6 +102,25 @@ impl ArchX86 {
}

impl Arch for ArchX86 {
fn instruction_comparison_key(
&self,
resolved: ResolvedInstructionRef,
diff_config: &DiffObjConfig,
) -> Result<Option<Vec<String>>> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import String for the no-std WASM build

The documented WASM build uses objdiff-wasm, whose Cargo.toml:29-32 disables objdiff-core's default features while enabling x86, so this module is compiled with the core prelude rather than the std prelude. Because x86.rs does not import alloc::string::String, this new Vec<String> signature fails with cannot find type String in this scope and blocks the web artifact; import String from alloc.

AGENTS.md reference: AGENTS.md:L23-L23

Useful? React with 👍 / 👎.

let mut key = Vec::new();
self.display_instruction(resolved, diff_config, &mut |part| {
match part {
InstructionPart::Basic(text) if !text.trim().is_empty() => {
key.push(format!("basic:{text}"));
}
InstructionPart::Arg(_) => key.push("arg".into()),
_ => {}
}
Ok(())
})?;
Ok(Some(key))
}

fn scan_instructions_internal(
&self,
address: u64,
Expand Down Expand Up @@ -891,4 +910,31 @@ mod test {
InstructionPart::unsigned(0xABu64),
]);
}

#[test]
fn test_reported_mov_operand_pair_has_distinct_argument_structure() {
let concrete_arch =
ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
let arch: &dyn Arch = &concrete_arch;
let left_code = [0x8b, 0x03]; // mov eax, [ebx]
let right_code = [0x89, 0x18]; // mov [eax], ebx
let comparison_key = |code: &[u8]| {
arch.instruction_comparison_key(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: 0,
size: 2,
opcode: iced_x86::Mnemonic::Mov as u16,
branch_dest: None,
},
code,
..Default::default()
},
&DiffObjConfig::default(),
)
.unwrap()
.unwrap()
};
assert_ne!(comparison_key(&left_code), comparison_key(&right_code));
}
}
9 changes: 9 additions & 0 deletions objdiff-core/src/diff/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,15 @@ fn diff_instruction(
result.right_args_diff.push(InstructionArgDiffIndex::new(b_diff));
}
}
if let (Some(left_key), Some(right_key)) = (
left_obj.arch.instruction_comparison_key(left_resolved, diff_config)?,
right_obj.arch.instruction_comparison_key(right_resolved, diff_config)?,
) && left_key != right_key
&& result.kind == InstructionDiffKind::None
{
state.diff_score += PENALTY_REG_DIFF;
result.kind = InstructionDiffKind::ArgMismatch;
}
if result.kind == InstructionDiffKind::None
&& left_resolved.code.len() != right_resolved.code.len()
{
Expand Down
Loading