From 2fdba8842ea7232cbe38e63cfa7907c2bb66728a Mon Sep 17 00:00:00 2001 From: Bruno Macabeus Date: Fri, 10 Jul 2026 06:28:01 +0100 Subject: [PATCH] Add support for `R_ARM_V4BX` (#377) --- objdiff-core/src/arch/arm.rs | 10 ++++++++++ objdiff-core/tests/arch_arm.rs | 16 ++++++++++++++++ objdiff-core/tests/data/arm/v4bx.o | Bin 0 -> 644 bytes 3 files changed, 26 insertions(+) create mode 100644 objdiff-core/tests/data/arm/v4bx.o diff --git a/objdiff-core/src/arch/arm.rs b/objdiff-core/src/arch/arm.rs index 35416c9..184b26b 100644 --- a/objdiff-core/src/arch/arm.rs +++ b/objdiff-core/src/arch/arm.rs @@ -343,6 +343,15 @@ impl Arch for ArchArm { // Handle ELF implicit relocations object::RelocationFlags::Elf { r_type } => { if relocation.has_implicit_addend() { + // R_ARM_V4BX marks a `bx` instruction so the linker can optionally + // rewrite it for ARMv4 interworking. Drops the addend since it's meaningless. + if r_type == elf::R_ARM_V4BX { + return Ok(Some(RelocationOverride { + target: RelocationOverrideTarget::Skip, + addend: 0, + })); + } + let section_data = section.data()?; let address = address as usize; let addend = match r_type { @@ -419,6 +428,7 @@ impl Arch for ArchArm { elf::R_ARM_CALL => Some("R_ARM_CALL"), elf::R_ARM_THM_PC11 => Some("R_ARM_THM_PC11"), elf::R_ARM_THM_PC9 => Some("R_ARM_THM_PC9"), + elf::R_ARM_V4BX => Some("R_ARM_V4BX"), _ => None, }, _ => None, diff --git a/objdiff-core/tests/arch_arm.rs b/objdiff-core/tests/arch_arm.rs index 9c507e1..37cc838 100644 --- a/objdiff-core/tests/arch_arm.rs +++ b/objdiff-core/tests/arch_arm.rs @@ -82,6 +82,22 @@ fn thumb_short_data_mapping() { ); } +#[test] +#[cfg(feature = "arm")] +fn read_arm_v4bx() { + // R_ARM_V4BX relocations mark `bx` instructions so the linker can optionally + // rewrite them for ARMv4 interworking. + let diff_config = diff::DiffObjConfig::default(); + let obj = + obj::read::parse(include_object!("data/arm/v4bx.o"), &diff_config, diff::DiffSide::Base) + .unwrap(); + let symbol_idx = obj.symbols.iter().position(|s| s.name == "v4bx_func").unwrap(); + let diff = diff::code::no_diff_code(&obj, symbol_idx, &diff_config).unwrap(); + let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config); + // The `bx lr` still disassembles normally; the V4BX hint is simply dropped. + assert!(output.contains("bx"), "expected a `bx` instruction, got:\n{output}"); +} + #[test] #[cfg(feature = "arm")] fn trim_trailing_hword() { diff --git a/objdiff-core/tests/data/arm/v4bx.o b/objdiff-core/tests/data/arm/v4bx.o new file mode 100644 index 0000000000000000000000000000000000000000..11271151f520fc08a9ef2d22990ce6033066da30 GIT binary patch literal 644 zcmb<-^>JflWMqH=Mg|QA1doA12Et)A0V~j8;AG%nko&Ly&{2|sfgv$9F)5RQk)MHq zfz>30fsKiSkrSdGtQs4^jAA+i12Y3NiZW&f7Bm&81~N0SGO!@&5CW-INn|K9NveoX zE6q!W%4vXTz2eH;lEfqiz2cH02%Q0A6{Y6rm84dbFzBTumLxLhB^4Jl=s5=Y>Lr$x z6lErrmZTPgOdtx&GcbT$!N3Mp4GJq{H^SJ`3=9mM3=9koP<2-r7#KJh7{K~Kz67ZQ z@l~Pb!9vCYsvbsx)PmUBQ2m6|88CptnV|rr2ZTZ9Nr4zp3^NZzGeN~bR0snDSQ9(c pjUe|4K>Yx-6Qu440|NsehyleQb3jZ%h`k^t7~etiJ4gVg4glwCCtv^o literal 0 HcmV?d00001