mirror of
https://github.com/encounter/objdiff.git
synced 2026-03-30 11:32:16 -07:00
Add support for x86 indirect tables (#251)
* Add support for x86 indirect tables Closes #239 * Fix formatting issues in x86.rs * Add x86 indirect table test
This commit is contained in:
@@ -124,7 +124,40 @@ impl Arch for ArchX86 {
|
||||
opcode: DATA_OPCODE,
|
||||
branch_dest: None,
|
||||
});
|
||||
|
||||
reloc_iter.next();
|
||||
|
||||
// support .byte arrays after jump tables (they're typically known as indirect tables)
|
||||
|
||||
let indirect_array_address = address.wrapping_add(size as u64);
|
||||
let indirect_array_pos = decoder.position();
|
||||
|
||||
let max_size = code.len().saturating_sub(indirect_array_pos);
|
||||
|
||||
let indirect_array_size = reloc_iter
|
||||
.peek()
|
||||
.map(|next_reloc| {
|
||||
next_reloc.address.saturating_sub(indirect_array_address)
|
||||
as usize
|
||||
})
|
||||
.unwrap_or(max_size)
|
||||
.min(max_size);
|
||||
|
||||
if indirect_array_size > 0 {
|
||||
for i in 0..indirect_array_size {
|
||||
out.push(InstructionRef {
|
||||
address: indirect_array_address + i as u64,
|
||||
size: 1,
|
||||
opcode: DATA_OPCODE,
|
||||
branch_dest: None,
|
||||
});
|
||||
}
|
||||
// move decoder to after the array (there can be multiple jump+indirect tables in one function)
|
||||
let _ =
|
||||
decoder.set_position(indirect_array_pos + indirect_array_size);
|
||||
decoder.set_ip(indirect_array_address + indirect_array_size as u64);
|
||||
}
|
||||
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
@@ -156,6 +189,7 @@ impl Arch for ArchX86 {
|
||||
) -> Result<()> {
|
||||
if resolved.ins_ref.opcode == DATA_OPCODE {
|
||||
let (mnemonic, imm) = match resolved.ins_ref.size {
|
||||
1 => (".byte", resolved.code[0] as u64),
|
||||
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),
|
||||
@@ -791,4 +825,33 @@ mod test {
|
||||
.unwrap();
|
||||
assert_eq!(parts, &[InstructionPart::opcode("call", opcode), InstructionPart::reloc()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display_1_byte_inline_data() {
|
||||
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
|
||||
let code = [0xAB];
|
||||
let mut parts = Vec::new();
|
||||
arch.display_instruction(
|
||||
ResolvedInstructionRef {
|
||||
ins_ref: InstructionRef {
|
||||
address: 0x1234,
|
||||
size: 1,
|
||||
opcode: DATA_OPCODE,
|
||||
branch_dest: None,
|
||||
},
|
||||
code: &code,
|
||||
..Default::default()
|
||||
},
|
||||
&DiffObjConfig::default(),
|
||||
&mut |part| {
|
||||
parts.push(part.into_static());
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(parts, &[
|
||||
InstructionPart::opcode(".byte", DATA_OPCODE),
|
||||
InstructionPart::unsigned(0xABu64),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,3 +104,21 @@ fn read_x86_local_labels() {
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(obj);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "x86")]
|
||||
fn read_x86_indirect_table() {
|
||||
let diff_config = diff::DiffObjConfig::default();
|
||||
let obj = obj::read::parse(
|
||||
include_object!("data/x86/indirect_table.obj"),
|
||||
&diff_config,
|
||||
diff::DiffSide::Base,
|
||||
)
|
||||
.unwrap();
|
||||
insta::assert_debug_snapshot!(obj);
|
||||
let symbol_idx = obj.symbols.iter().position(|s| s.name == "?process@@YAHHHH@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);
|
||||
}
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user