diff --git a/objdiff-core/src/arch/arm.rs b/objdiff-core/src/arch/arm.rs index 4e0a015..c8d66a7 100644 --- a/objdiff-core/src/arch/arm.rs +++ b/objdiff-core/src/arch/arm.rs @@ -14,7 +14,7 @@ use crate::{ arch::Arch, diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig, display::InstructionPart}, obj::{ - InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation, + InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolFlagSet, SymbolKind, }, }; @@ -183,6 +183,7 @@ impl Arch for ArchArm { address: u64, code: &[u8], section_index: usize, + _relocations: &[Relocation], diff_config: &DiffObjConfig, ) -> Result> { let start_addr = address as u32; diff --git a/objdiff-core/src/arch/arm64.rs b/objdiff-core/src/arch/arm64.rs index 7474e49..a39c727 100644 --- a/objdiff-core/src/arch/arm64.rs +++ b/objdiff-core/src/arch/arm64.rs @@ -17,7 +17,7 @@ use crate::{ arch::Arch, diff::{DiffObjConfig, display::InstructionPart}, obj::{ - InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation, + InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction, }, }; @@ -35,6 +35,7 @@ impl Arch for ArchArm64 { address: u64, code: &[u8], _section_index: usize, + _relocations: &[Relocation], _diff_config: &DiffObjConfig, ) -> Result> { let start_address = address; diff --git a/objdiff-core/src/arch/mips.rs b/objdiff-core/src/arch/mips.rs index 4932c13..6f5147d 100644 --- a/objdiff-core/src/arch/mips.rs +++ b/objdiff-core/src/arch/mips.rs @@ -194,6 +194,7 @@ impl Arch for ArchMips { address: u64, code: &[u8], _section_index: usize, + _relocations: &[Relocation], diff_config: &DiffObjConfig, ) -> Result> { let instruction_flags = self.instruction_flags(diff_config); diff --git a/objdiff-core/src/arch/mod.rs b/objdiff-core/src/arch/mod.rs index f9b0d13..f2cfa90 100644 --- a/objdiff-core/src/arch/mod.rs +++ b/objdiff-core/src/arch/mod.rs @@ -170,6 +170,7 @@ pub trait Arch: Send + Sync + Debug { address: u64, code: &[u8], section_index: usize, + relocations: &[Relocation], diff_config: &DiffObjConfig, ) -> Result>; @@ -301,6 +302,7 @@ impl Arch for ArchDummy { _address: u64, _code: &[u8], _section_index: usize, + _relocations: &[Relocation], _diff_config: &DiffObjConfig, ) -> Result> { Ok(Vec::new()) diff --git a/objdiff-core/src/arch/ppc.rs b/objdiff-core/src/arch/ppc.rs index ee3e153..4e184dd 100644 --- a/objdiff-core/src/arch/ppc.rs +++ b/objdiff-core/src/arch/ppc.rs @@ -87,6 +87,7 @@ impl Arch for ArchPpc { address: u64, code: &[u8], _section_index: usize, + _relocations: &[Relocation], _diff_config: &DiffObjConfig, ) -> Result> { ensure!(code.len() & 3 == 0, "Code length must be a multiple of 4"); diff --git a/objdiff-core/src/arch/x86.rs b/objdiff-core/src/arch/x86.rs index e5f582b..2e8fe38 100644 --- a/objdiff-core/src/arch/x86.rs +++ b/objdiff-core/src/arch/x86.rs @@ -1,6 +1,6 @@ use alloc::{boxed::Box, string::String, vec::Vec}; -use anyhow::{Result, anyhow, bail}; +use anyhow::{Context, Result, anyhow, bail}; use iced_x86::{ Decoder, DecoderOptions, DecoratorKind, FormatterOutput, FormatterTextKind, GasFormatter, Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind, Register, @@ -10,7 +10,9 @@ use object::{Endian as _, Object as _, ObjectSection as _, pe}; use crate::{ arch::Arch, diff::{DiffObjConfig, X86Formatter, display::InstructionPart}, - obj::{InstructionRef, RelocationFlags, ResolvedInstructionRef, ScannedInstruction}, + obj::{ + InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ScannedInstruction, + }, }; #[derive(Debug)] @@ -80,18 +82,48 @@ impl ArchX86 { } } +const DATA_OPCODE: u16 = u16::MAX - 1; + impl Arch for ArchX86 { fn scan_instructions( &self, address: u64, code: &[u8], _section_index: usize, + relocations: &[Relocation], _diff_config: &DiffObjConfig, ) -> Result> { let mut out = Vec::with_capacity(code.len() / 2); let mut decoder = self.decoder(code, address); let mut instruction = Instruction::default(); - while decoder.can_decode() { + let mut reloc_iter = relocations.iter().peekable(); + 'outer: while decoder.can_decode() { + let address = decoder.ip(); + while let Some(reloc) = reloc_iter.peek() { + if reloc.address < address { + reloc_iter.next(); + } else if reloc.address == address { + // If the instruction starts at a relocation, it's inline data + let size = self.reloc_size(reloc.flags).with_context(|| { + format!("Unsupported inline x86 relocation {:?}", reloc.flags) + })?; + if decoder.set_position(decoder.position() + size).is_ok() { + decoder.set_ip(address + size as u64); + out.push(ScannedInstruction { + ins_ref: InstructionRef { + address, + size: size as u8, + opcode: DATA_OPCODE, + }, + branch_dest: None, + }); + reloc_iter.next(); + continue 'outer; + } + } else { + break; + } + } decoder.decode_out(&mut instruction); let branch_dest = match instruction.op0_kind() { OpKind::NearBranch16 => Some(instruction.near_branch16() as u64), @@ -101,7 +133,7 @@ impl Arch for ArchX86 { }; out.push(ScannedInstruction { ins_ref: InstructionRef { - address: instruction.ip(), + address, size: instruction.len() as u8, opcode: instruction.mnemonic() as u16, }, @@ -117,6 +149,21 @@ impl Arch for ArchX86 { diff_config: &DiffObjConfig, cb: &mut dyn FnMut(InstructionPart) -> Result<()>, ) -> Result<()> { + if resolved.ins_ref.opcode == DATA_OPCODE { + let (mnemonic, imm) = match resolved.ins_ref.size { + 2 => (".word", self.endianness.read_u16_bytes(resolved.code.try_into()?) as u64), + 4 => (".dword", self.endianness.read_u32_bytes(resolved.code.try_into()?) as u64), + _ => bail!("Unsupported x86 inline data size {}", resolved.ins_ref.size), + }; + cb(InstructionPart::opcode(mnemonic, DATA_OPCODE))?; + if resolved.relocation.is_some() { + cb(InstructionPart::reloc())?; + } else { + cb(InstructionPart::unsigned(imm))?; + } + return Ok(()); + } + let mut decoder = self.decoder(resolved.code, resolved.ins_ref.address); let mut formatter = self.formatter(diff_config); let mut instruction = Instruction::default(); @@ -406,7 +453,7 @@ mod test { 0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0x85, 0x00, 0x00, 0x00, 0x00, ]; - let scanned = arch.scan_instructions(0, &code, 0, &DiffObjConfig::default()).unwrap(); + let scanned = arch.scan_instructions(0, &code, 0, &[], &DiffObjConfig::default()).unwrap(); assert_eq!(scanned.len(), 2); assert_eq!(scanned[0].ins_ref.address, 0); assert_eq!(scanned[0].ins_ref.size, 10); diff --git a/objdiff-core/src/diff/code.rs b/objdiff-core/src/diff/code.rs index 6625d35..a42a329 100644 --- a/objdiff-core/src/diff/code.rs +++ b/objdiff-core/src/diff/code.rs @@ -32,7 +32,13 @@ pub fn no_diff_code( symbol.address + symbol.size ) })?; - let ops = obj.arch.scan_instructions(symbol.address, data, section_index, diff_config)?; + let ops = obj.arch.scan_instructions( + symbol.address, + data, + section_index, + §ion.relocations, + diff_config, + )?; let mut instruction_rows = Vec::::new(); for i in &ops { instruction_rows @@ -89,12 +95,14 @@ pub fn diff_code( left_symbol.address, left_data, left_section_idx, + &left_section.relocations, diff_config, )?; let right_ops = right_obj.arch.scan_instructions( right_symbol.address, right_data, right_section_idx, + &right_section.relocations, diff_config, )?; let (mut left_rows, mut right_rows) = diff_instructions(&left_ops, &right_ops)?; diff --git a/objdiff-core/tests/arch_x86.rs b/objdiff-core/tests/arch_x86.rs index 5931d95..652e80c 100644 --- a/objdiff-core/tests/arch_x86.rs +++ b/objdiff-core/tests/arch_x86.rs @@ -55,3 +55,16 @@ fn display_section_ordering() { diff::display::display_sections(&obj, &obj_diff, SymbolFilter::None, false, false, false); insta::assert_debug_snapshot!(section_display); } + +#[test] +#[cfg(feature = "x86")] +fn read_x86_jumptable() { + let diff_config = diff::DiffObjConfig::default(); + let obj = obj::read::parse(include_object!("data/x86/jumptable.o"), &diff_config).unwrap(); + insta::assert_debug_snapshot!(obj); + 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(); + insta::assert_debug_snapshot!(diff.instruction_rows); + let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config); + insta::assert_snapshot!(output); +} diff --git a/objdiff-core/tests/data/x86/jumptable.o b/objdiff-core/tests/data/x86/jumptable.o new file mode 100644 index 0000000..6446c6e Binary files /dev/null and b/objdiff-core/tests/data/x86/jumptable.o differ diff --git a/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-2.snap b/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-2.snap new file mode 100644 index 0000000..1ce84c3 --- /dev/null +++ b/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-2.snap @@ -0,0 +1,569 @@ +--- +source: objdiff-core/tests/arch_x86.rs +expression: diff.instruction_rows +--- +[ + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 0, + size: 4, + opcode: 414, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 4, + size: 1, + opcode: 137, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 5, + size: 3, + opcode: 93, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 8, + size: 2, + opcode: 297, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 18, + branch_idx: 0, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 10, + size: 7, + opcode: 308, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 20, + branch_idx: 1, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 17, + size: 5, + opcode: 414, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 20, + ], + branch_idx: 2, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 22, + size: 1, + opcode: 662, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 23, + size: 5, + opcode: 414, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 21, + ], + branch_idx: 3, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 28, + size: 1, + opcode: 662, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 29, + size: 5, + opcode: 414, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 22, + ], + branch_idx: 4, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 34, + size: 1, + opcode: 662, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 35, + size: 5, + opcode: 414, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 23, + ], + branch_idx: 5, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 40, + size: 1, + opcode: 662, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 41, + size: 5, + opcode: 414, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 24, + ], + branch_idx: 6, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 46, + size: 1, + opcode: 662, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 47, + size: 5, + opcode: 414, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 25, + ], + branch_idx: 7, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 52, + size: 1, + opcode: 662, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 53, + size: 5, + opcode: 414, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 26, + ], + branch_idx: 8, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 58, + size: 1, + opcode: 662, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 3, + ], + branch_idx: 0, + }, + ), + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 59, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 60, + size: 4, + opcode: 65534, + }, + ), + kind: None, + branch_from: Some( + InstructionBranchFrom { + ins_idx: [ + 4, + ], + branch_idx: 1, + }, + ), + branch_to: Some( + InstructionBranchTo { + ins_idx: 5, + branch_idx: 2, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 64, + size: 4, + opcode: 65534, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 7, + branch_idx: 3, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 68, + size: 4, + opcode: 65534, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 9, + branch_idx: 4, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 72, + size: 4, + opcode: 65534, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 11, + branch_idx: 5, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 76, + size: 4, + opcode: 65534, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 13, + branch_idx: 6, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 80, + size: 4, + opcode: 65534, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 15, + branch_idx: 7, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 84, + size: 4, + opcode: 65534, + }, + ), + kind: None, + branch_from: None, + branch_to: Some( + InstructionBranchTo { + ins_idx: 17, + branch_idx: 8, + }, + ), + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 88, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 89, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 90, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 91, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 92, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 93, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 94, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, + InstructionDiffRow { + ins_ref: Some( + InstructionRef { + address: 95, + size: 1, + opcode: 465, + }, + ), + kind: None, + branch_from: None, + branch_to: None, + arg_diff: [], + }, +] diff --git a/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-3.snap b/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-3.snap new file mode 100644 index 0000000..efce0ac --- /dev/null +++ b/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-3.snap @@ -0,0 +1,39 @@ +--- +source: objdiff-core/tests/arch_x86.rs +expression: output +--- +[(Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("esp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] +[(Address(4), Normal, 5), (Spacing(4), Normal, 0), (Opcode("dec", 137), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Eol, Normal, 0)] +[(Address(5), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 93), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(6)), Normal, 0), (Eol, Normal, 0)] +[(Address(8), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ja", 297), Normal, 10), (Argument(Opaque("short")), Normal, 0), (Spacing(1), Normal, 0), (BranchDest(58), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)] +[(Address(10), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jmp", 308), Normal, 10), (Argument(Opaque("dword")), Normal, 0), (Spacing(1), Normal, 0), (Argument(Opaque("ptr")), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("eax")), Normal, 0), (Argument(Opaque("*")), Normal, 0), (Argument(Signed(4)), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Symbol(Symbol { name: "$L282", demangled_name: None, address: 60, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic("]"), Normal, 0), (Basic(" ~>"), Rotating(1), 0), (Eol, Normal, 0)] +[(Address(17), Normal, 5), (Basic(" ~> "), Rotating(2), 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(8)), Normal, 0), (Eol, Normal, 0)] +[(Address(22), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)] +[(Address(23), Normal, 5), (Basic(" ~> "), Rotating(3), 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(7)), Normal, 0), (Eol, Normal, 0)] +[(Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)] +[(Address(29), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(6)), Normal, 0), (Eol, Normal, 0)] +[(Address(34), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)] +[(Address(35), Normal, 5), (Basic(" ~> "), Rotating(5), 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(5)), Normal, 0), (Eol, Normal, 0)] +[(Address(40), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)] +[(Address(41), Normal, 5), (Basic(" ~> "), Rotating(6), 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(4)), Normal, 0), (Eol, Normal, 0)] +[(Address(46), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)] +[(Address(47), Normal, 5), (Basic(" ~> "), Rotating(7), 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(3)), Normal, 0), (Eol, Normal, 0)] +[(Address(52), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)] +[(Address(53), Normal, 5), (Basic(" ~> "), Rotating(8), 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(2)), Normal, 0), (Eol, Normal, 0)] +[(Address(58), Normal, 5), (Basic(" ~> "), Rotating(0), 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)] +[(Address(59), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(60), Normal, 5), (Basic(" ~> "), Rotating(1), 0), (Opcode(".word", 65534), Normal, 10), (Symbol(Symbol { name: "$L272", demangled_name: None, address: 17, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(" ~>"), Rotating(2), 0), (Eol, Normal, 0)] +[(Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65534), Normal, 10), (Symbol(Symbol { name: "$L273", demangled_name: None, address: 23, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)] +[(Address(68), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65534), Normal, 10), (Symbol(Symbol { name: "$L274", demangled_name: None, address: 29, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(" ~>"), Rotating(4), 0), (Eol, Normal, 0)] +[(Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65534), Normal, 10), (Symbol(Symbol { name: "$L275", demangled_name: None, address: 35, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(" ~>"), Rotating(5), 0), (Eol, Normal, 0)] +[(Address(76), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65534), Normal, 10), (Symbol(Symbol { name: "$L276", demangled_name: None, address: 41, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(" ~>"), Rotating(6), 0), (Eol, Normal, 0)] +[(Address(80), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65534), Normal, 10), (Symbol(Symbol { name: "$L277", demangled_name: None, address: 47, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(" ~>"), Rotating(7), 0), (Eol, Normal, 0)] +[(Address(84), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65534), Normal, 10), (Symbol(Symbol { name: "$L278", demangled_name: None, address: 53, size: 0, kind: Unknown, section: Some(1), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(" ~>"), Rotating(8), 0), (Eol, Normal, 0)] +[(Address(88), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(89), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(90), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(91), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(92), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(93), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(94), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] +[(Address(95), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 465), Normal, 10), (Eol, Normal, 0)] diff --git a/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable.snap b/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable.snap new file mode 100644 index 0000000..7ca527b --- /dev/null +++ b/objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable.snap @@ -0,0 +1,305 @@ +--- +source: objdiff-core/tests/arch_x86.rs +expression: obj +--- +Object { + arch: ArchX86 { + arch: X86, + endianness: Little, + }, + endianness: Little, + symbols: [ + Symbol { + name: "Z:/tmp/code.c", + demangled_name: None, + address: 0, + size: 0, + kind: Unknown, + section: None, + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "@comp.id", + demangled_name: None, + address: 0, + size: 0, + kind: Object, + section: None, + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.drectve]", + demangled_name: None, + address: 0, + size: 38, + kind: Section, + section: Some( + 0, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.text]", + demangled_name: None, + address: 0, + size: 0, + kind: Section, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "?test@@YAHH@Z", + demangled_name: Some( + "int __cdecl test(int)", + ), + address: 0, + size: 96, + kind: Function, + section: Some( + 1, + ), + flags: FlagSet(Global | SizeInferred), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L278", + demangled_name: None, + address: 53, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L277", + demangled_name: None, + address: 47, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L276", + demangled_name: None, + address: 41, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L275", + demangled_name: None, + address: 35, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L274", + demangled_name: None, + address: 29, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L273", + demangled_name: None, + address: 23, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L272", + demangled_name: None, + address: 17, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "$L282", + demangled_name: None, + address: 60, + size: 0, + kind: Unknown, + section: Some( + 1, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + Symbol { + name: "[.debug$F]", + demangled_name: None, + address: 0, + size: 16, + kind: Section, + section: Some( + 2, + ), + flags: FlagSet(Local), + align: None, + virtual_address: None, + }, + ], + sections: [ + Section { + id: ".drectve-0", + name: ".drectve", + address: 0, + size: 38, + kind: Unknown, + data: SectionData( + 0, + ), + flags: FlagSet(), + relocations: [], + line_info: {}, + virtual_address: None, + }, + Section { + id: ".text-0", + name: ".text", + address: 0, + size: 96, + kind: Code, + data: SectionData( + 96, + ), + flags: FlagSet(), + relocations: [ + Relocation { + flags: Coff( + 6, + ), + address: 13, + target_symbol: 12, + addend: 0, + }, + Relocation { + flags: Coff( + 6, + ), + address: 60, + target_symbol: 11, + addend: 0, + }, + Relocation { + flags: Coff( + 6, + ), + address: 64, + target_symbol: 10, + addend: 0, + }, + Relocation { + flags: Coff( + 6, + ), + address: 68, + target_symbol: 9, + addend: 0, + }, + Relocation { + flags: Coff( + 6, + ), + address: 72, + target_symbol: 8, + addend: 0, + }, + Relocation { + flags: Coff( + 6, + ), + address: 76, + target_symbol: 7, + addend: 0, + }, + Relocation { + flags: Coff( + 6, + ), + address: 80, + target_symbol: 6, + addend: 0, + }, + Relocation { + flags: Coff( + 6, + ), + address: 84, + target_symbol: 5, + addend: 0, + }, + ], + line_info: {}, + virtual_address: None, + }, + Section { + id: ".debug$F-0", + name: ".debug$F", + address: 0, + size: 16, + kind: Unknown, + data: SectionData( + 0, + ), + flags: FlagSet(), + relocations: [], + line_info: {}, + virtual_address: None, + }, + ], + split_meta: None, + path: None, + timestamp: None, +}