Skip to content

Commit c0c9812

Browse files
committed
Add support for x86 indirect tables
Closes #239
1 parent fb1d434 commit c0c9812

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

objdiff-core/src/arch/x86.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,40 @@ impl Arch for ArchX86 {
124124
opcode: DATA_OPCODE,
125125
branch_dest: None,
126126
});
127+
127128
reloc_iter.next();
129+
130+
// support .byte arrays after jump tables (they're typically known as indirect tables)
131+
132+
let indirect_array_address = address.wrapping_add(size as u64);
133+
let indirect_array_pos = decoder.position();
134+
135+
let max_size = code.len().saturating_sub(indirect_array_pos);
136+
137+
let indirect_array_size = reloc_iter
138+
.peek()
139+
.map(|next_reloc| {
140+
next_reloc
141+
.address
142+
.saturating_sub(indirect_array_address) as usize
143+
})
144+
.unwrap_or(max_size)
145+
.min(max_size);
146+
147+
if indirect_array_size > 0 {
148+
for i in 0..indirect_array_size {
149+
out.push(InstructionRef {
150+
address: indirect_array_address + i as u64,
151+
size: 1,
152+
opcode: DATA_OPCODE,
153+
branch_dest: None,
154+
});
155+
}
156+
// move decoder to after the array (there can be multiple jump+indirect tables in one function)
157+
let _ = decoder.set_position(indirect_array_pos + indirect_array_size);
158+
decoder.set_ip(indirect_array_address + indirect_array_size as u64);
159+
}
160+
128161
continue 'outer;
129162
}
130163
}
@@ -156,6 +189,7 @@ impl Arch for ArchX86 {
156189
) -> Result<()> {
157190
if resolved.ins_ref.opcode == DATA_OPCODE {
158191
let (mnemonic, imm) = match resolved.ins_ref.size {
192+
1 => (".byte", resolved.code[0] as u64),
159193
2 => (".word", self.endianness.read_u16_bytes(resolved.code.try_into()?) as u64),
160194
4 => (".dword", self.endianness.read_u32_bytes(resolved.code.try_into()?) as u64),
161195
_ => bail!("Unsupported x86 inline data size {}", resolved.ins_ref.size),
@@ -791,4 +825,28 @@ mod test {
791825
.unwrap();
792826
assert_eq!(parts, &[InstructionPart::opcode("call", opcode), InstructionPart::reloc()]);
793827
}
828+
829+
#[test]
830+
fn test_display_1_byte_inline_data() {
831+
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
832+
let code = [0xAB];
833+
let mut parts = Vec::new();
834+
arch.display_instruction(
835+
ResolvedInstructionRef {
836+
ins_ref: InstructionRef { address: 0x1234, size: 1, opcode: DATA_OPCODE, branch_dest: None },
837+
code: &code,
838+
..Default::default()
839+
},
840+
&DiffObjConfig::default(),
841+
&mut |part| {
842+
parts.push(part.into_static());
843+
Ok(())
844+
},
845+
)
846+
.unwrap();
847+
assert_eq!(parts, &[
848+
InstructionPart::opcode(".byte", DATA_OPCODE),
849+
InstructionPart::unsigned(0xABu64),
850+
]);
851+
}
794852
}

0 commit comments

Comments
 (0)