mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-17 08:57:25 +00:00
Compare commits
16 Commits
v3.0.0-bet
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b557e4c8e | ||
|
|
b9ba5796ed | ||
|
|
e101610416 | ||
|
|
196c003a92 | ||
| 7b00a9e9f2 | |||
| 311de887ec | |||
| 485b259c32 | |||
| d8fdfaa2c0 | |||
| 2612cda1fb | |||
| bc46e17824 | |||
| e735adbd3d | |||
| 6768df9d80 | |||
| eaba2391e0 | |||
| bd8f5ede23 | |||
| acf46c6b54 | |||
| 9358d8ec60 |
2
.editorconfig
Normal file
2
.editorconfig
Normal file
@@ -0,0 +1,2 @@
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
8
.github/workflows/build.yaml
vendored
8
.github/workflows/build.yaml
vendored
@@ -4,8 +4,8 @@ on:
|
||||
pull_request:
|
||||
push:
|
||||
paths-ignore:
|
||||
- '*.md'
|
||||
- 'LICENSE*'
|
||||
- "*.md"
|
||||
- "LICENSE*"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
@@ -32,9 +32,9 @@ jobs:
|
||||
- name: Cache Rust workspace
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- name: Cargo check
|
||||
run: cargo check --features all
|
||||
run: cargo check --all-targets --all-features
|
||||
- name: Cargo clippy
|
||||
run: cargo clippy --features all
|
||||
run: cargo clippy --all-targets --all-features
|
||||
|
||||
fmt:
|
||||
name: Format
|
||||
|
||||
36
.pre-commit-config.yaml
Normal file
36
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
args: [--markdown-linebreak-ext=md]
|
||||
- id: end-of-file-fixer
|
||||
- id: fix-byte-order-marker
|
||||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cargo-fmt
|
||||
name: cargo fmt
|
||||
description: Run cargo fmt on all project files.
|
||||
language: system
|
||||
entry: cargo
|
||||
args: ["+nightly", "fmt", "--all"]
|
||||
pass_filenames: false
|
||||
- id: cargo clippy
|
||||
name: cargo clippy
|
||||
description: Run cargo clippy on all project files.
|
||||
language: system
|
||||
entry: cargo
|
||||
args: ["+nightly", "clippy", "--all-targets", "--all-features"]
|
||||
pass_filenames: false
|
||||
- id: cargo-deny
|
||||
name: cargo deny
|
||||
description: Run cargo deny on all project files.
|
||||
language: system
|
||||
entry: cargo
|
||||
args: ["deny", "check"]
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
15
Cargo.lock
generated
15
Cargo.lock
generated
@@ -3280,7 +3280,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objdiff-cli"
|
||||
version = "3.0.0-beta.3"
|
||||
version = "3.0.0-beta.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argp",
|
||||
@@ -3303,7 +3303,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objdiff-core"
|
||||
version = "3.0.0-beta.3"
|
||||
version = "3.0.0-beta.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arm-attr",
|
||||
@@ -3356,7 +3356,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objdiff-gui"
|
||||
version = "3.0.0-beta.3"
|
||||
version = "3.0.0-beta.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
@@ -3392,7 +3392,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objdiff-wasm"
|
||||
version = "3.0.0-beta.3"
|
||||
version = "3.0.0-beta.5"
|
||||
dependencies = [
|
||||
"log",
|
||||
"objdiff-core",
|
||||
@@ -3400,6 +3400,7 @@ dependencies = [
|
||||
"talc",
|
||||
"wit-bindgen",
|
||||
"wit-deps",
|
||||
"xxhash-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6547,6 +6548,12 @@ version = "0.8.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4"
|
||||
|
||||
[[package]]
|
||||
name = "xxhash-rust"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"
|
||||
|
||||
[[package]]
|
||||
name = "yaxpeax-arch"
|
||||
version = "0.3.2"
|
||||
|
||||
@@ -14,7 +14,7 @@ strip = "debuginfo"
|
||||
codegen-units = 1
|
||||
|
||||
[workspace.package]
|
||||
version = "3.0.0-beta.3"
|
||||
version = "3.0.0-beta.5"
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
15
README.md
15
README.md
@@ -173,6 +173,21 @@ $ cargo install --locked --git https://github.com/encounter/objdiff.git objdiff-
|
||||
|
||||
The binaries will be installed to `~/.cargo/bin` as `objdiff` and `objdiff-cli`.
|
||||
|
||||
## Installing `pre-commit`
|
||||
|
||||
When contributing, it's recommended to install `pre-commit` to automatically run the linter and formatter before a commit.
|
||||
|
||||
[`uv`](https://github.com/astral-sh/uv#installation) is recommended to manage Python version and tools.
|
||||
|
||||
Rust nightly is required for `cargo +nightly fmt` and `cargo +nightly clippy`.
|
||||
|
||||
```shell
|
||||
$ cargo install --locked cargo-deny
|
||||
$ rustup toolchain install nightly
|
||||
$ uv tool install pre-commit
|
||||
$ pre-commit install
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
@@ -202,6 +202,9 @@ fn report_object(
|
||||
for ((section_idx, section), section_diff) in
|
||||
obj.sections.iter().enumerate().zip(&obj_diff.sections)
|
||||
{
|
||||
if section.kind == SectionKind::Unknown {
|
||||
continue;
|
||||
}
|
||||
let section_match_percent = section_diff.match_percent.unwrap_or_else(|| {
|
||||
// Support cases where we don't have a target object,
|
||||
// assume complete means 100% match
|
||||
|
||||
@@ -81,6 +81,8 @@ std = [
|
||||
]
|
||||
mips = [
|
||||
"any-arch",
|
||||
"dep:cpp_demangle",
|
||||
"dep:cwdemangle",
|
||||
"dep:rabbitizer",
|
||||
]
|
||||
ppc = [
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
@@ -84,18 +84,11 @@ impl ArchArm {
|
||||
.filter_map(|s| DisasmMode::from_symbol(&s))
|
||||
.collect();
|
||||
mapping_symbols.sort_unstable_by_key(|x| x.address);
|
||||
(s.index().0, mapping_symbols)
|
||||
(s.index().0 - 1, mapping_symbols)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn endian(&self) -> unarm::Endian {
|
||||
match self.endianness {
|
||||
object::Endianness::Little => unarm::Endian::Little,
|
||||
object::Endianness::Big => unarm::Endian::Big,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_flags(&self, diff_config: &DiffObjConfig) -> unarm::ParseFlags {
|
||||
unarm::ParseFlags {
|
||||
ual: diff_config.arm_unified_syntax,
|
||||
@@ -130,6 +123,31 @@ impl ArchArm {
|
||||
code: &[u8],
|
||||
diff_config: &DiffObjConfig,
|
||||
) -> Result<(unarm::Ins, unarm::ParsedIns)> {
|
||||
if ins_ref.opcode == thumb::Opcode::BlH as u16 && ins_ref.size == 4 {
|
||||
// Special case: combined thumb BL instruction
|
||||
let parse_flags = self.parse_flags(diff_config);
|
||||
let first_ins = thumb::Ins {
|
||||
code: match self.endianness {
|
||||
object::Endianness::Little => u16::from_le_bytes([code[0], code[1]]),
|
||||
object::Endianness::Big => u16::from_be_bytes([code[0], code[1]]),
|
||||
} as u32,
|
||||
op: thumb::Opcode::BlH,
|
||||
};
|
||||
let second_ins = thumb::Ins::new(
|
||||
match self.endianness {
|
||||
object::Endianness::Little => u16::from_le_bytes([code[2], code[3]]),
|
||||
object::Endianness::Big => u16::from_be_bytes([code[2], code[3]]),
|
||||
} as u32,
|
||||
&parse_flags,
|
||||
);
|
||||
let first_parsed = first_ins.parse(&parse_flags);
|
||||
let second_parsed = second_ins.parse(&parse_flags);
|
||||
return Ok((
|
||||
unarm::Ins::Thumb(first_ins),
|
||||
first_parsed.combine_thumb_bl(&second_parsed),
|
||||
));
|
||||
}
|
||||
|
||||
let code = match (self.endianness, ins_ref.size) {
|
||||
(object::Endianness::Little, 2) => u16::from_le_bytes([code[0], code[1]]) as u32,
|
||||
(object::Endianness::Little, 4) => {
|
||||
@@ -153,11 +171,7 @@ impl ArchArm {
|
||||
} else {
|
||||
let ins = thumb::Ins { code, op: thumb::Opcode::from(ins_ref.opcode as u8) };
|
||||
let parsed = ins.parse(&self.parse_flags(diff_config));
|
||||
if ins.is_half_bl() {
|
||||
todo!("Combine thumb BL instructions");
|
||||
} else {
|
||||
(unarm::Ins::Thumb(ins), parsed)
|
||||
}
|
||||
};
|
||||
Ok((ins, parsed_ins))
|
||||
}
|
||||
@@ -169,6 +183,7 @@ impl Arch for ArchArm {
|
||||
address: u64,
|
||||
code: &[u8],
|
||||
section_index: usize,
|
||||
_relocations: &[Relocation],
|
||||
diff_config: &DiffObjConfig,
|
||||
) -> Result<Vec<ScannedInstruction>> {
|
||||
let start_addr = address as u32;
|
||||
@@ -184,61 +199,128 @@ impl Arch for ArchArm {
|
||||
.unwrap_or(&fallback_mappings);
|
||||
let first_mapping_idx = mapping_symbols
|
||||
.binary_search_by_key(&start_addr, |x| x.address)
|
||||
.unwrap_or_else(|idx| idx - 1);
|
||||
let first_mapping = mapping_symbols[first_mapping_idx].mapping;
|
||||
.unwrap_or_else(|idx| idx.saturating_sub(1));
|
||||
let mut mode = mapping_symbols[first_mapping_idx].mapping;
|
||||
|
||||
let mut mappings_iter =
|
||||
mapping_symbols.iter().skip(first_mapping_idx + 1).take_while(|x| x.address < end_addr);
|
||||
let mut mappings_iter = mapping_symbols
|
||||
.iter()
|
||||
.copied()
|
||||
.skip(first_mapping_idx + 1)
|
||||
.take_while(|x| x.address < end_addr);
|
||||
let mut next_mapping = mappings_iter.next();
|
||||
|
||||
let ins_count = code.len() / first_mapping.instruction_size(start_addr);
|
||||
let ins_count = code.len() / mode.instruction_size(start_addr);
|
||||
let mut ops = Vec::<ScannedInstruction>::with_capacity(ins_count);
|
||||
|
||||
let endian = self.endian();
|
||||
let parse_flags = self.parse_flags(diff_config);
|
||||
let mut parser = unarm::Parser::new(first_mapping, start_addr, endian, parse_flags, code);
|
||||
|
||||
while let Some((address, ins, _parsed_ins)) = parser.next() {
|
||||
let size = parser.mode.instruction_size(address);
|
||||
if let Some(next) = next_mapping {
|
||||
let next_address = parser.address;
|
||||
if next_address >= next.address {
|
||||
let mut address = start_addr;
|
||||
while address < end_addr {
|
||||
while let Some(next) = next_mapping.take_if(|x| address >= x.address) {
|
||||
// Change mapping
|
||||
parser.mode = next.mapping;
|
||||
mode = next.mapping;
|
||||
next_mapping = mappings_iter.next();
|
||||
}
|
||||
|
||||
let mut ins_size = mode.instruction_size(address);
|
||||
let data = &code[(address - start_addr) as usize..];
|
||||
if data.len() < ins_size {
|
||||
// Push the remainder as data
|
||||
ops.push(ScannedInstruction {
|
||||
ins_ref: InstructionRef {
|
||||
address: address as u64,
|
||||
size: data.len() as u8,
|
||||
opcode: u16::MAX,
|
||||
},
|
||||
branch_dest: None,
|
||||
});
|
||||
break;
|
||||
}
|
||||
let (opcode, branch_dest) = match ins {
|
||||
unarm::Ins::Arm(x) => {
|
||||
let opcode = x.op as u16 | (1 << 15);
|
||||
let branch_dest = match x.op {
|
||||
let code = match (self.endianness, ins_size) {
|
||||
(object::Endianness::Little, 2) => u16::from_le_bytes([data[0], data[1]]) as u32,
|
||||
(object::Endianness::Little, 4) => {
|
||||
u32::from_le_bytes([data[0], data[1], data[2], data[3]])
|
||||
}
|
||||
(object::Endianness::Big, 2) => u16::from_be_bytes([data[0], data[1]]) as u32,
|
||||
(object::Endianness::Big, 4) => {
|
||||
u32::from_be_bytes([data[0], data[1], data[2], data[3]])
|
||||
}
|
||||
_ => {
|
||||
// Invalid instruction size
|
||||
ops.push(ScannedInstruction {
|
||||
ins_ref: InstructionRef {
|
||||
address: address as u64,
|
||||
size: ins_size as u8,
|
||||
opcode: u16::MAX,
|
||||
},
|
||||
branch_dest: None,
|
||||
});
|
||||
address += ins_size as u32;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let (opcode, branch_dest) = match mode {
|
||||
unarm::ParseMode::Arm => {
|
||||
let ins = arm::Ins::new(code, &parse_flags);
|
||||
let opcode = ins.op as u16 | (1 << 15);
|
||||
let branch_dest = match ins.op {
|
||||
arm::Opcode::B | arm::Opcode::Bl => {
|
||||
address.checked_add_signed(x.field_branch_offset())
|
||||
address.checked_add_signed(ins.field_branch_offset())
|
||||
}
|
||||
arm::Opcode::BlxI => address.checked_add_signed(x.field_blx_offset()),
|
||||
arm::Opcode::BlxI => address.checked_add_signed(ins.field_blx_offset()),
|
||||
_ => None,
|
||||
};
|
||||
(opcode, branch_dest)
|
||||
}
|
||||
unarm::Ins::Thumb(x) => {
|
||||
let opcode = x.op as u16;
|
||||
let branch_dest = match x.op {
|
||||
unarm::ParseMode::Thumb => {
|
||||
let ins = thumb::Ins::new(code, &parse_flags);
|
||||
let opcode = ins.op as u16;
|
||||
let branch_dest = match ins.op {
|
||||
thumb::Opcode::B | thumb::Opcode::Bl => {
|
||||
address.checked_add_signed(x.field_branch_offset_8())
|
||||
address.checked_add_signed(ins.field_branch_offset_8())
|
||||
}
|
||||
thumb::Opcode::BlH if data.len() >= 4 => {
|
||||
// Combine BL instructions
|
||||
let second_ins = thumb::Ins::new(
|
||||
match self.endianness {
|
||||
object::Endianness::Little => {
|
||||
u16::from_le_bytes([data[2], data[3]]) as u32
|
||||
}
|
||||
object::Endianness::Big => {
|
||||
u16::from_be_bytes([data[2], data[3]]) as u32
|
||||
}
|
||||
},
|
||||
&parse_flags,
|
||||
);
|
||||
if let Some(low) = match second_ins.op {
|
||||
thumb::Opcode::Bl => Some(second_ins.field_low_branch_offset_11()),
|
||||
thumb::Opcode::BlxI => Some(second_ins.field_low_blx_offset_11()),
|
||||
_ => None,
|
||||
} {
|
||||
ins_size = 4;
|
||||
address.checked_add_signed(
|
||||
(ins.field_high_branch_offset_11() + (low as i32)) << 9 >> 9,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
thumb::Opcode::BLong => {
|
||||
address.checked_add_signed(x.field_branch_offset_11())
|
||||
address.checked_add_signed(ins.field_branch_offset_11())
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
(opcode, branch_dest)
|
||||
}
|
||||
unarm::Ins::Data => (u16::MAX, None),
|
||||
unarm::ParseMode::Data => (u16::MAX, None),
|
||||
};
|
||||
|
||||
ops.push(ScannedInstruction {
|
||||
ins_ref: InstructionRef { address: address as u64, size: size as u8, opcode },
|
||||
ins_ref: InstructionRef { address: address as u64, size: ins_size as u8, opcode },
|
||||
branch_dest: branch_dest.map(|x| x as u64),
|
||||
});
|
||||
address += ins_size as u32;
|
||||
}
|
||||
|
||||
Ok(ops)
|
||||
@@ -391,7 +473,7 @@ fn push_args(
|
||||
let reloc_arg = find_reloc_arg(parsed_ins, relocation);
|
||||
let mut writeback = false;
|
||||
let mut deref = false;
|
||||
for (i, arg) in parsed_ins.args_iter().enumerate() {
|
||||
for (i, &arg) in parsed_ins.args_iter().enumerate() {
|
||||
// Emit punctuation before separator
|
||||
if deref {
|
||||
match arg {
|
||||
@@ -463,19 +545,19 @@ fn push_args(
|
||||
| args::Argument::CoOpcode(value)
|
||||
| args::Argument::SatImm(value) => {
|
||||
arg_cb(InstructionPart::basic("#"))?;
|
||||
arg_cb(InstructionPart::unsigned(*value))?;
|
||||
arg_cb(InstructionPart::unsigned(value))?;
|
||||
}
|
||||
args::Argument::SImm(value)
|
||||
| args::Argument::OffsetImm(args::OffsetImm { post_indexed: _, value }) => {
|
||||
arg_cb(InstructionPart::basic("#"))?;
|
||||
arg_cb(InstructionPart::signed(*value))?;
|
||||
arg_cb(InstructionPart::signed(value))?;
|
||||
}
|
||||
args::Argument::BranchDest(value) => {
|
||||
arg_cb(InstructionPart::branch_dest(cur_addr.wrapping_add_signed(*value)))?;
|
||||
arg_cb(InstructionPart::branch_dest(cur_addr.wrapping_add_signed(value)))?;
|
||||
}
|
||||
args::Argument::CoOption(value) => {
|
||||
arg_cb(InstructionPart::basic("{"))?;
|
||||
arg_cb(InstructionPart::unsigned(*value))?;
|
||||
arg_cb(InstructionPart::unsigned(value))?;
|
||||
arg_cb(InstructionPart::basic("}"))?;
|
||||
}
|
||||
args::Argument::CoprocNum(value) => {
|
||||
|
||||
@@ -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<Vec<ScannedInstruction>> {
|
||||
let start_address = address;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use alloc::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
string::ToString,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::ops::Range;
|
||||
@@ -194,6 +194,7 @@ impl Arch for ArchMips {
|
||||
address: u64,
|
||||
code: &[u8],
|
||||
_section_index: usize,
|
||||
_relocations: &[Relocation],
|
||||
diff_config: &DiffObjConfig,
|
||||
) -> Result<Vec<ScannedInstruction>> {
|
||||
let instruction_flags = self.instruction_flags(diff_config);
|
||||
@@ -286,6 +287,13 @@ impl Arch for ArchMips {
|
||||
})
|
||||
}
|
||||
|
||||
fn demangle(&self, name: &str) -> Option<String> {
|
||||
cpp_demangle::Symbol::new(name)
|
||||
.ok()
|
||||
.and_then(|s| s.demangle(&cpp_demangle::DemangleOptions::default()).ok())
|
||||
.or_else(|| cwdemangle::demangle(name, &cwdemangle::DemangleOptions::default()))
|
||||
}
|
||||
|
||||
fn reloc_name(&self, flags: RelocationFlags) -> Option<&'static str> {
|
||||
match flags {
|
||||
RelocationFlags::Elf(r_type) => match r_type {
|
||||
|
||||
@@ -170,6 +170,7 @@ pub trait Arch: Send + Sync + Debug {
|
||||
address: u64,
|
||||
code: &[u8],
|
||||
section_index: usize,
|
||||
relocations: &[Relocation],
|
||||
diff_config: &DiffObjConfig,
|
||||
) -> Result<Vec<ScannedInstruction>>;
|
||||
|
||||
@@ -301,6 +302,7 @@ impl Arch for ArchDummy {
|
||||
_address: u64,
|
||||
_code: &[u8],
|
||||
_section_index: usize,
|
||||
_relocations: &[Relocation],
|
||||
_diff_config: &DiffObjConfig,
|
||||
) -> Result<Vec<ScannedInstruction>> {
|
||||
Ok(Vec::new())
|
||||
|
||||
@@ -87,6 +87,7 @@ impl Arch for ArchPpc {
|
||||
address: u64,
|
||||
code: &[u8],
|
||||
_section_index: usize,
|
||||
_relocations: &[Relocation],
|
||||
_diff_config: &DiffObjConfig,
|
||||
) -> Result<Vec<ScannedInstruction>> {
|
||||
ensure!(code.len() & 3 == 0, "Code length must be a multiple of 4");
|
||||
@@ -512,6 +513,7 @@ fn guess_data_type_from_load_store_inst_op(inst_op: ppc750cl::Opcode) -> Option<
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PoolReference {
|
||||
addr_src_gpr: ppc750cl::GPR,
|
||||
addr_offset: i16,
|
||||
@@ -644,7 +646,7 @@ fn make_fake_pool_reloc(
|
||||
// example, dCcD_Cyl in The Wind Waker). So just showing that vtable symbol plus an addend
|
||||
// to represent the offset into it works fine in this case.
|
||||
target_symbol = pool_reloc.relocation.target_symbol;
|
||||
addend = pool_reloc.relocation.addend + offset_from_pool;
|
||||
addend = offset_from_pool;
|
||||
}
|
||||
Some(Relocation {
|
||||
flags: RelocationFlags::Elf(elf::R_PPC_NONE),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||
use alloc::{boxed::Box, format, string::String, vec::Vec};
|
||||
use core::cmp::Ordering;
|
||||
|
||||
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 +11,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 +83,50 @@ 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<Vec<ScannedInstruction>> {
|
||||
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() {
|
||||
match reloc.address.cmp(&address) {
|
||||
Ordering::Less => {
|
||||
reloc_iter.next();
|
||||
}
|
||||
Ordering::Equal => {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
Ordering::Greater => break,
|
||||
}
|
||||
}
|
||||
decoder.decode_out(&mut instruction);
|
||||
let branch_dest = match instruction.op0_kind() {
|
||||
OpKind::NearBranch16 => Some(instruction.near_branch16() as u64),
|
||||
@@ -101,7 +136,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 +152,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();
|
||||
@@ -329,6 +379,7 @@ impl FormatterOutput for InstructionFormatterOutput<'_> {
|
||||
(NumberKind::Int8 | NumberKind::UInt8, 1)
|
||||
| (NumberKind::Int16 | NumberKind::UInt16, 2)
|
||||
| (NumberKind::Int32 | NumberKind::UInt32, 4)
|
||||
| (NumberKind::Int64 | NumberKind::UInt64, 4) // x86_64
|
||||
| (NumberKind::Int64 | NumberKind::UInt64, 8) => true,
|
||||
_ => false,
|
||||
}
|
||||
@@ -406,7 +457,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);
|
||||
@@ -611,4 +662,74 @@ mod test {
|
||||
InstructionPart::basic("]"),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_x86_64_instruction_with_reloc_1() {
|
||||
let arch = ArchX86 { arch: Architecture::X86_64, endianness: object::Endianness::Little };
|
||||
let code = [0x48, 0x8b, 0x05, 0x00, 0x00, 0x00, 0x00];
|
||||
let opcode = iced_x86::Mnemonic::Mov as u16;
|
||||
let mut parts = Vec::new();
|
||||
arch.display_instruction(
|
||||
ResolvedInstructionRef {
|
||||
ins_ref: InstructionRef { address: 0x1234, size: 7, opcode },
|
||||
code: &code,
|
||||
relocation: Some(ResolvedRelocation {
|
||||
relocation: &Relocation {
|
||||
flags: RelocationFlags::Coff(pe::IMAGE_REL_AMD64_REL32),
|
||||
address: 0x1234 + 3,
|
||||
target_symbol: 0,
|
||||
addend: 0,
|
||||
},
|
||||
symbol: &Default::default(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
&DiffObjConfig::default(),
|
||||
&mut |part| {
|
||||
parts.push(part.into_static());
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(parts, &[
|
||||
InstructionPart::opcode("mov", opcode),
|
||||
InstructionPart::opaque("rax"),
|
||||
InstructionPart::basic(","),
|
||||
InstructionPart::basic(" "),
|
||||
InstructionPart::basic("["),
|
||||
InstructionPart::reloc(),
|
||||
InstructionPart::basic("]"),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_x86_64_instruction_with_reloc_2() {
|
||||
let arch = ArchX86 { arch: Architecture::X86_64, endianness: object::Endianness::Little };
|
||||
let code = [0xe8, 0x00, 0x00, 0x00, 0x00];
|
||||
let opcode = iced_x86::Mnemonic::Call as u16;
|
||||
let mut parts = Vec::new();
|
||||
arch.display_instruction(
|
||||
ResolvedInstructionRef {
|
||||
ins_ref: InstructionRef { address: 0x1234, size: 5, opcode },
|
||||
code: &code,
|
||||
relocation: Some(ResolvedRelocation {
|
||||
relocation: &Relocation {
|
||||
flags: RelocationFlags::Coff(pe::IMAGE_REL_AMD64_REL32),
|
||||
address: 0x1234 + 1,
|
||||
target_symbol: 0,
|
||||
addend: 0,
|
||||
},
|
||||
symbol: &Default::default(),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
&DiffObjConfig::default(),
|
||||
&mut |part| {
|
||||
parts.push(part.into_static());
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(parts, &[InstructionPart::opcode("call", opcode), InstructionPart::reloc()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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::<InstructionDiffRow>::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)?;
|
||||
|
||||
@@ -325,10 +325,14 @@ pub enum SymbolNavigationKind {
|
||||
Extab,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
||||
pub enum HoverItemColor {
|
||||
#[default]
|
||||
Normal, // Gray
|
||||
Emphasized, // White
|
||||
Special, // Blue
|
||||
Delete, // Red
|
||||
Insert, // Green
|
||||
}
|
||||
|
||||
pub enum HoverItem {
|
||||
@@ -355,7 +359,12 @@ pub fn symbol_context(obj: &Object, symbol_index: usize) -> Vec<ContextItem> {
|
||||
out
|
||||
}
|
||||
|
||||
pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec<HoverItem> {
|
||||
pub fn symbol_hover(
|
||||
obj: &Object,
|
||||
symbol_index: usize,
|
||||
addend: i64,
|
||||
override_color: Option<HoverItemColor>,
|
||||
) -> Vec<HoverItem> {
|
||||
let symbol = &obj.symbols[symbol_index];
|
||||
let addend_str = match addend.cmp(&0i64) {
|
||||
Ordering::Greater => format!("+{:x}", addend),
|
||||
@@ -366,51 +375,51 @@ pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec<Hover
|
||||
out.push(HoverItem::Text {
|
||||
label: "Name".into(),
|
||||
value: format!("{}{}", symbol.name, addend_str),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
if let Some(demangled_name) = &symbol.demangled_name {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Demangled".into(),
|
||||
value: demangled_name.into(),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
if let Some(section) = symbol.section {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Section".into(),
|
||||
value: obj.sections[section].name.clone(),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
out.push(HoverItem::Text {
|
||||
label: "Address".into(),
|
||||
value: format!("{:x}{}", symbol.address, addend_str),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
if symbol.flags.contains(SymbolFlag::SizeInferred) {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Size".into(),
|
||||
value: format!("{:x} (inferred)", symbol.size),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
} else {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Size".into(),
|
||||
value: format!("{:x}", symbol.size),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
if let Some(align) = symbol.align {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Alignment".into(),
|
||||
value: align.get().to_string(),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
if let Some(address) = symbol.virtual_address {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Virtual address".into(),
|
||||
value: format!("{:x}", address),
|
||||
color: HoverItemColor::Special,
|
||||
color: override_color.clone().unwrap_or(HoverItemColor::Special),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -443,22 +452,31 @@ pub fn relocation_context(
|
||||
out
|
||||
}
|
||||
|
||||
pub fn relocation_hover(obj: &Object, reloc: ResolvedRelocation) -> Vec<HoverItem> {
|
||||
pub fn relocation_hover(
|
||||
obj: &Object,
|
||||
reloc: ResolvedRelocation,
|
||||
override_color: Option<HoverItemColor>,
|
||||
) -> Vec<HoverItem> {
|
||||
let mut out = Vec::new();
|
||||
if let Some(name) = obj.arch.reloc_name(reloc.relocation.flags) {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Relocation".into(),
|
||||
value: name.to_string(),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
} else {
|
||||
out.push(HoverItem::Text {
|
||||
label: "Relocation".into(),
|
||||
value: format!("<{:?}>", reloc.relocation.flags),
|
||||
color: HoverItemColor::Normal,
|
||||
color: override_color.clone().unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
out.append(&mut symbol_hover(obj, reloc.relocation.target_symbol, reloc.relocation.addend));
|
||||
out.append(&mut symbol_hover(
|
||||
obj,
|
||||
reloc.relocation.target_symbol,
|
||||
reloc.relocation.addend,
|
||||
override_color,
|
||||
));
|
||||
out
|
||||
}
|
||||
|
||||
@@ -545,7 +563,7 @@ pub fn instruction_hover(
|
||||
}
|
||||
if let Some(reloc) = resolved.relocation {
|
||||
out.push(HoverItem::Separator);
|
||||
out.append(&mut relocation_hover(obj, reloc));
|
||||
out.append(&mut relocation_hover(obj, reloc, None));
|
||||
if let Some(ty) = obj.arch.guess_data_type(resolved) {
|
||||
let literals = display_ins_data_literals(obj, resolved);
|
||||
if !literals.is_empty() {
|
||||
|
||||
@@ -15,3 +15,20 @@ fn read_arm() {
|
||||
let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config);
|
||||
insta::assert_snapshot!(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "arm")]
|
||||
fn read_thumb() {
|
||||
let diff_config = diff::DiffObjConfig { mips_register_prefix: true, ..Default::default() };
|
||||
let obj = obj::read::parse(include_object!("data/arm/thumb.o"), &diff_config).unwrap();
|
||||
insta::assert_debug_snapshot!(obj);
|
||||
let symbol_idx = obj
|
||||
.symbols
|
||||
.iter()
|
||||
.position(|s| s.name == "THUMB_BRANCH_ServerDisplay_UncategorizedMove")
|
||||
.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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
BIN
objdiff-core/tests/data/arm/thumb.o
Normal file
BIN
objdiff-core/tests/data/arm/thumb.o
Normal file
Binary file not shown.
BIN
objdiff-core/tests/data/x86/jumptable.o
Normal file
BIN
objdiff-core/tests/data/x86/jumptable.o
Normal file
Binary file not shown.
@@ -1660,7 +1660,7 @@ expression: diff.instruction_rows
|
||||
InstructionRef {
|
||||
address: 460,
|
||||
size: 4,
|
||||
opcode: 32771,
|
||||
opcode: 65535,
|
||||
},
|
||||
),
|
||||
kind: None,
|
||||
@@ -1673,7 +1673,7 @@ expression: diff.instruction_rows
|
||||
InstructionRef {
|
||||
address: 464,
|
||||
size: 4,
|
||||
opcode: 32771,
|
||||
opcode: 65535,
|
||||
},
|
||||
),
|
||||
kind: None,
|
||||
@@ -1693,7 +1693,7 @@ expression: diff.instruction_rows
|
||||
InstructionRef {
|
||||
address: 468,
|
||||
size: 4,
|
||||
opcode: 32771,
|
||||
opcode: 65535,
|
||||
},
|
||||
),
|
||||
kind: None,
|
||||
|
||||
@@ -107,6 +107,6 @@ expression: output
|
||||
[(Address(408), Normal, 5), (Basic(" ~> "), Rotating(16), 0), (Opcode("mov", 32818), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Address(412), Normal, 5), (Spacing(4), Normal, 0), (Opcode("strb", 32899), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(38)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Address(416), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldmia", 32793), Normal, 10), (Argument(Opaque("sp")), Normal, 0), (Argument(Opaque("!")), Normal, 0), (Basic(", "), Normal, 0), (Basic("{"), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic("}"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Address(420), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andeq", 32771), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "data_027e103c", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Address(424), Normal, 5), (Basic(" ~> "), Rotating(8), 0), (Opcode("andeq", 32771), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "data_027e1098", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Address(428), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andeq", 32771), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "gPlayerControl", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Address(420), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Symbol(Symbol { name: "data_027e103c", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Address(424), Normal, 5), (Basic(" ~> "), Rotating(8), 0), (Opcode(".word", 65535), Normal, 10), (Symbol(Symbol { name: "data_027e1098", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Address(428), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Symbol(Symbol { name: "gPlayerControl", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)]
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: obj
|
||||
Object {
|
||||
arch: ArchArm {
|
||||
disasm_modes: {
|
||||
1: [
|
||||
0: [
|
||||
DisasmMode {
|
||||
address: 0,
|
||||
mapping: Thumb,
|
||||
|
||||
1480
objdiff-core/tests/snapshots/arch_arm__read_thumb-2.snap
Normal file
1480
objdiff-core/tests/snapshots/arch_arm__read_thumb-2.snap
Normal file
File diff suppressed because it is too large
Load Diff
110
objdiff-core/tests/snapshots/arch_arm__read_thumb-3.snap
Normal file
110
objdiff-core/tests/snapshots/arch_arm__read_thumb-3.snap
Normal file
@@ -0,0 +1,110 @@
|
||||
---
|
||||
source: objdiff-core/tests/arch_arm.rs
|
||||
expression: output
|
||||
---
|
||||
[(Line(37), Dim, 5), (Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("push", 56), Normal, 10), (Basic("{"), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("lr")), Normal, 0), (Basic("}"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(37), Dim, 5), (Address(2), Normal, 5), (Spacing(4), Normal, 0), (Opcode("sub", 74), Normal, 10), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(16)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(37), Dim, 5), (Address(4), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(39), Dim, 5), (Address(6), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(39), Dim, 5), (Address(8), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r1")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(39), Dim, 5), (Address(10), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r2")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(39), Dim, 5), (Address(12), Normal, 5), (Spacing(4), Normal, 0), (Opcode("str", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(39), Dim, 5), (Address(14), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "PokeSet_IsRemovedAll", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(39), Dim, 5), (Address(18), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 25), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(39), Dim, 5), (Address(20), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 15), Normal, 10), (BranchDest(212), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)]
|
||||
[(Line(44), Dim, 5), (Address(22), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldrh", 38), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(44), Dim, 5), (Address(24), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 25), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(164)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(44), Dim, 5), (Address(26), Normal, 5), (Spacing(4), Normal, 0), (Opcode("beq", 15), Normal, 10), (BranchDest(48), Normal, 0), (Basic(" ~>"), Rotating(1), 0), (Eol, Normal, 0)]
|
||||
[(Line(44), Dim, 5), (Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(184)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(44), Dim, 5), (Address(30), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 26), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(44), Dim, 5), (Address(32), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 15), Normal, 10), (BranchDest(94), Normal, 0), (Basic(" ~>"), Rotating(2), 0), (Eol, Normal, 0)]
|
||||
[(Line(47), Dim, 5), (Address(34), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 35), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(47), Dim, 5), (Address(36), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(47), Dim, 5), (Address(38), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(47), Dim, 5), (Address(40), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "ServerDisplay_SkillSwap", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(44), Normal, 5), (Spacing(4), Normal, 0), (Opcode("add", 7), Normal, 10), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(16)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(46), Normal, 5), (Spacing(4), Normal, 0), (Opcode("pop", 55), Normal, 10), (Basic("{"), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic("}"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(50), Dim, 5), (Address(48), Normal, 5), (Basic(" ~> "), Rotating(1), 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(50), Dim, 5), (Address(50), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(50), Dim, 5), (Address(52), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "ServerEvent_CreateSubstitute", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(50), Dim, 5), (Address(56), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 25), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(50), Dim, 5), (Address(58), Normal, 5), (Spacing(4), Normal, 0), (Opcode("beq", 15), Normal, 10), (BranchDest(212), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(60), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(156)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(62), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 33), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldrb", 36), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(5)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(66), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lsl", 42), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(31)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(68), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lsr", 44), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(31)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(70), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 15), Normal, 10), (BranchDest(212), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 46), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(1)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(74), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bic", 17), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r1")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(76), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 46), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(1)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(78), Normal, 5), (Spacing(4), Normal, 0), (Opcode("orr", 54), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r2")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(80), Normal, 5), (Spacing(4), Normal, 0), (Opcode("strb", 67), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(5)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(82), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldrb", 36), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(5)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(84), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 46), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(2)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(86), Normal, 5), (Spacing(4), Normal, 0), (Opcode("add", 7), Normal, 10), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(16)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(88), Normal, 5), (Spacing(4), Normal, 0), (Opcode("orr", 54), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r2")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(52), Dim, 5), (Address(90), Normal, 5), (Spacing(4), Normal, 0), (Opcode("strb", 67), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(5)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(92), Normal, 5), (Spacing(4), Normal, 0), (Opcode("pop", 55), Normal, 10), (Basic("{"), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic("}"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(57), Dim, 5), (Address(94), Normal, 5), (Basic(" ~> "), Rotating(2), 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(128)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(57), Dim, 5), (Address(96), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(128)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(57), Dim, 5), (Address(98), Normal, 5), (Spacing(4), Normal, 0), (Opcode("add", 4), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(57), Dim, 5), (Address(100), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "HEManager_PushState", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(57), Dim, 5), (Address(104), Normal, 5), (Spacing(4), Normal, 0), (Opcode("str", 66), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(8)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(61), Dim, 5), (Address(106), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(61), Dim, 5), (Address(108), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "BattleHandler_Result", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(61), Dim, 5), (Address(112), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(114), Normal, 5), (Spacing(4), Normal, 0), (Opcode("add", 6), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(12)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(116), Normal, 5), (Spacing(4), Normal, 0), (Opcode("str", 66), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(118), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 35), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(120), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(122), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(124), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(126), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "ServerEvent_UncategorizedMove", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(130), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 25), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(63), Dim, 5), (Address(132), Normal, 5), (Spacing(4), Normal, 0), (Opcode("beq", 15), Normal, 10), (BranchDest(168), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
|
||||
[(Line(65), Dim, 5), (Address(134), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(65), Dim, 5), (Address(136), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "BattleHandler_Result", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(65), Dim, 5), (Address(140), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 47), Normal, 10), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(66), Dim, 5), (Address(142), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 25), Normal, 10), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(2)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(66), Dim, 5), (Address(144), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 15), Normal, 10), (BranchDest(168), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(146), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(72)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(148), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 33), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(150), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldrb", 36), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(5)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(152), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lsl", 42), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(31)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(154), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lsr", 44), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(31)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(156), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 15), Normal, 10), (BranchDest(168), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(158), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 46), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(1)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(160), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bic", 17), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r1")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(162), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 46), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(1)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(164), Normal, 5), (Spacing(4), Normal, 0), (Opcode("orr", 54), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r2")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(68), Dim, 5), (Address(166), Normal, 5), (Spacing(4), Normal, 0), (Opcode("strb", 67), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(5)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(72), Dim, 5), (Address(168), Normal, 5), (Basic(" ~> "), Rotating(3), 0), (Opcode("cmp", 25), Normal, 10), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(1)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(72), Dim, 5), (Address(170), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bhi", 15), Normal, 10), (BranchDest(200), Normal, 0), (Basic(" ~>"), Rotating(4), 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(172), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 35), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(12)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(174), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 25), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(176), Normal, 5), (Spacing(4), Normal, 0), (Opcode("beq", 15), Normal, 10), (BranchDest(200), Normal, 0), (Basic(" ~>"), Rotating(4), 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(178), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(52)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(180), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldrb", 37), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(182), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lsl", 42), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(27)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(184), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lsr", 44), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(31)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(75), Dim, 5), (Address(186), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 15), Normal, 10), (BranchDest(200), Normal, 0), (Basic(" ~>"), Rotating(4), 0), (Eol, Normal, 0)]
|
||||
[(Line(77), Dim, 5), (Address(188), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 32), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(12)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(77), Dim, 5), (Address(190), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(44)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(77), Dim, 5), (Address(192), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 46), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(90)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(77), Dim, 5), (Address(194), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 46), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(71)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(77), Dim, 5), (Address(196), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "SCQUE_PUT_MsgImpl", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(81), Dim, 5), (Address(200), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(20)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(81), Dim, 5), (Address(202), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 35), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(8)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(81), Dim, 5), (Address(204), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(32)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(81), Dim, 5), (Address(206), Normal, 5), (Spacing(4), Normal, 0), (Opcode("add", 4), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(81), Dim, 5), (Address(208), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "HEManager_PopState", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(212), Normal, 5), (Basic(" ~> "), Rotating(0), 0), (Opcode("add", 7), Normal, 10), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(16)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(214), Normal, 5), (Spacing(4), Normal, 0), (Opcode("pop", 55), Normal, 10), (Basic("{"), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic("}"), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(216), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Basic("#"), Normal, 0), (Argument(Unsigned(285)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(220), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Basic("#"), Normal, 0), (Argument(Unsigned(1192)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(224), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Basic("#"), Normal, 0), (Argument(Unsigned(7544)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(228), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Basic("#"), Normal, 0), (Argument(Unsigned(9103)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(232), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Basic("#"), Normal, 0), (Argument(Unsigned(1930)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(236), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Basic("#"), Normal, 0), (Argument(Unsigned(4294901760)), Normal, 0), (Eol, Normal, 0)]
|
||||
[(Line(86), Dim, 5), (Address(240), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Basic("#"), Normal, 0), (Argument(Unsigned(9129)), Normal, 0), (Eol, Normal, 0)]
|
||||
3808
objdiff-core/tests/snapshots/arch_arm__read_thumb.snap
Normal file
3808
objdiff-core/tests/snapshots/arch_arm__read_thumb.snap
Normal file
File diff suppressed because it is too large
Load Diff
569
objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-2.snap
Normal file
569
objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable-2.snap
Normal file
@@ -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: [],
|
||||
},
|
||||
]
|
||||
@@ -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(".dword", 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(".dword", 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(".dword", 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(".dword", 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(".dword", 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(".dword", 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(".dword", 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)]
|
||||
305
objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable.snap
Normal file
305
objdiff-core/tests/snapshots/arch_x86__read_x86_jumptable.snap
Normal file
@@ -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,
|
||||
}
|
||||
@@ -775,10 +775,8 @@ impl eframe::App for App {
|
||||
|
||||
if side_panel_available {
|
||||
egui::SidePanel::left("side_panel").show_animated(ctx, *show_side_panel, |ui| {
|
||||
egui::ScrollArea::both().show(ui, |ui| {
|
||||
config_ui(ui, state, show_project_config, config_state, appearance);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let mut action = None;
|
||||
|
||||
@@ -297,6 +297,7 @@ pub fn config_ui(
|
||||
node_open = NodeOpen::Open;
|
||||
}
|
||||
|
||||
egui::ScrollArea::both().auto_shrink(false).show(ui, |ui| {
|
||||
CollapsingHeader::new(RichText::new("🗀 Objects").font(FontId {
|
||||
size: appearance.ui_font.size,
|
||||
family: appearance.code_font.family.clone(),
|
||||
@@ -316,9 +317,17 @@ pub fn config_ui(
|
||||
config_state.show_hidden,
|
||||
)
|
||||
}) {
|
||||
display_node(ui, &mut new_selected_index, objects, &node, appearance, node_open);
|
||||
display_node(
|
||||
ui,
|
||||
&mut new_selected_index,
|
||||
objects,
|
||||
&node,
|
||||
appearance,
|
||||
node_open,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if new_selected_index != selected_index {
|
||||
if let Some(idx) = new_selected_index {
|
||||
@@ -327,11 +336,6 @@ pub fn config_ui(
|
||||
state_guard.set_selected_obj(config);
|
||||
}
|
||||
}
|
||||
if state_guard.config.selected_obj.is_some()
|
||||
&& ui.add_enabled(!config_state.build_running, egui::Button::new("Build")).clicked()
|
||||
{
|
||||
config_state.queue_build = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn display_unit(
|
||||
|
||||
@@ -5,7 +5,7 @@ use objdiff_core::{
|
||||
diff::{
|
||||
DataDiff, DataDiffKind, DataRelocationDiff,
|
||||
data::resolve_relocation,
|
||||
display::{ContextItem, HoverItem, relocation_context, relocation_hover},
|
||||
display::{ContextItem, HoverItem, HoverItemColor, relocation_context, relocation_hover},
|
||||
},
|
||||
obj::Object,
|
||||
};
|
||||
@@ -19,6 +19,7 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
|
||||
let mut out = Vec::new();
|
||||
let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs);
|
||||
let mut prev_reloc = None;
|
||||
let mut first = true;
|
||||
for reloc_diff in reloc_diffs {
|
||||
let reloc = &reloc_diff.reloc;
|
||||
if prev_reloc == Some(reloc) {
|
||||
@@ -29,11 +30,16 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
|
||||
}
|
||||
prev_reloc = Some(reloc);
|
||||
|
||||
// TODO: Change hover text color depending on Insert/Delete/Replace kind
|
||||
// let color = get_color_for_diff_kind(reloc_diff.kind, appearance);
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
out.push(HoverItem::Separator);
|
||||
}
|
||||
|
||||
let color = get_hover_item_color_for_diff_kind(reloc_diff.kind);
|
||||
|
||||
let reloc = resolve_relocation(&obj.symbols, reloc);
|
||||
out.append(&mut relocation_hover(obj, reloc));
|
||||
out.append(&mut relocation_hover(obj, reloc, Some(color)));
|
||||
}
|
||||
out
|
||||
}
|
||||
@@ -97,6 +103,15 @@ fn get_color_for_diff_kind(diff_kind: DataDiffKind, appearance: &Appearance) ->
|
||||
}
|
||||
}
|
||||
|
||||
fn get_hover_item_color_for_diff_kind(diff_kind: DataDiffKind) -> HoverItemColor {
|
||||
match diff_kind {
|
||||
DataDiffKind::None => HoverItemColor::Normal,
|
||||
DataDiffKind::Replace => HoverItemColor::Special,
|
||||
DataDiffKind::Delete => HoverItemColor::Delete,
|
||||
DataDiffKind::Insert => HoverItemColor::Insert,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn data_row_ui(
|
||||
ui: &mut egui::Ui,
|
||||
obj: Option<&Object>,
|
||||
|
||||
@@ -795,6 +795,8 @@ pub fn hover_items_ui(ui: &mut Ui, items: Vec<HoverItem>, appearance: &Appearanc
|
||||
if !label.is_empty() {
|
||||
let label_color = match color {
|
||||
HoverItemColor::Special => appearance.replace_color,
|
||||
HoverItemColor::Delete => appearance.delete_color,
|
||||
HoverItemColor::Insert => appearance.insert_color,
|
||||
_ => appearance.highlight_color,
|
||||
};
|
||||
write_text(&label, label_color, &mut job, appearance.code_font.clone());
|
||||
|
||||
@@ -512,7 +512,7 @@ pub fn symbol_hover_ui(
|
||||
ui.scope(|ui| {
|
||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap);
|
||||
hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0), appearance);
|
||||
hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0, None), appearance);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ std = ["objdiff-core/std"]
|
||||
[dependencies]
|
||||
log = { version = "0.4", default-features = false }
|
||||
regex = { version = "1.11", default-features = false, features = ["unicode-case"] }
|
||||
xxhash-rust = { version = "0.8", default-features = false, features = ["xxh3"] }
|
||||
|
||||
[dependencies.objdiff-core]
|
||||
path = "../objdiff-core"
|
||||
|
||||
4
objdiff-wasm/package-lock.json
generated
4
objdiff-wasm/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "objdiff-wasm",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "objdiff-wasm",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.5",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.9.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "objdiff-wasm",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.5",
|
||||
"description": "A local diffing tool for decompilation projects.",
|
||||
"author": {
|
||||
"name": "Luke Street",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use alloc::{
|
||||
format,
|
||||
rc::Rc,
|
||||
rc::{Rc, Weak},
|
||||
str::FromStr,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
@@ -9,6 +9,7 @@ use core::cell::RefCell;
|
||||
|
||||
use objdiff_core::{diff, obj};
|
||||
use regex::{Regex, RegexBuilder};
|
||||
use xxhash_rust::xxh3::xxh3_64;
|
||||
|
||||
use super::logging;
|
||||
|
||||
@@ -41,8 +42,7 @@ impl Guest for Component {
|
||||
fn version() -> String { env!("CARGO_PKG_VERSION").to_string() }
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct ResourceObject(Rc<obj::Object>);
|
||||
struct ResourceObject(Rc<obj::Object>, u64);
|
||||
|
||||
struct ResourceObjectDiff(Rc<obj::Object>, diff::ObjectDiff);
|
||||
|
||||
@@ -230,7 +230,9 @@ impl GuestDisplay for Component {
|
||||
) -> Vec<HoverItem> {
|
||||
let obj_diff = diff.get::<ResourceObjectDiff>();
|
||||
let obj = obj_diff.0.as_ref();
|
||||
diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0 /* TODO */)
|
||||
// TODO: colorize replaced/deleted/inserted relocations
|
||||
let override_color = None;
|
||||
diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0, override_color)
|
||||
.into_iter()
|
||||
.map(|item| HoverItem::from(item))
|
||||
.collect()
|
||||
@@ -421,13 +423,49 @@ impl GuestDiffConfig for ResourceDiffConfig {
|
||||
}
|
||||
}
|
||||
|
||||
struct CachedObject(Weak<obj::Object>, u64);
|
||||
|
||||
struct ObjectCache(RefCell<Vec<CachedObject>>);
|
||||
|
||||
impl ObjectCache {
|
||||
#[inline]
|
||||
const fn new() -> Self { Self(RefCell::new(Vec::new())) }
|
||||
}
|
||||
|
||||
impl core::ops::Deref for ObjectCache {
|
||||
type Target = RefCell<Vec<CachedObject>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
// Assume single-threaded environment
|
||||
unsafe impl Sync for ObjectCache {}
|
||||
|
||||
static OBJECT_CACHE: ObjectCache = ObjectCache::new();
|
||||
|
||||
impl GuestObject for ResourceObject {
|
||||
fn parse(data: Vec<u8>, diff_config: DiffConfigBorrow) -> Result<Object, String> {
|
||||
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
|
||||
obj::read::parse(&data, &diff_config)
|
||||
.map(|o| Object::new(ResourceObject(Rc::new(o))))
|
||||
.map_err(|e| e.to_string())
|
||||
let hash = xxh3_64(&data);
|
||||
let mut cached = None;
|
||||
OBJECT_CACHE.borrow_mut().retain(|c| {
|
||||
if c.0.strong_count() == 0 {
|
||||
return false;
|
||||
}
|
||||
if c.1 == hash {
|
||||
cached = c.0.upgrade();
|
||||
}
|
||||
true
|
||||
});
|
||||
if let Some(obj) = cached {
|
||||
return Ok(Object::new(ResourceObject(obj, hash)));
|
||||
}
|
||||
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
|
||||
let obj = Rc::new(obj::read::parse(&data, &diff_config).map_err(|e| e.to_string())?);
|
||||
OBJECT_CACHE.borrow_mut().push(CachedObject(Rc::downgrade(&obj), hash));
|
||||
Ok(Object::new(ResourceObject(obj, hash)))
|
||||
}
|
||||
|
||||
fn hash(&self) -> u64 { self.1 }
|
||||
}
|
||||
|
||||
impl GuestObjectDiff for ResourceObjectDiff {
|
||||
@@ -465,6 +503,8 @@ impl From<diff::display::HoverItemColor> for HoverItemColor {
|
||||
diff::display::HoverItemColor::Normal => HoverItemColor::Normal,
|
||||
diff::display::HoverItemColor::Emphasized => HoverItemColor::Emphasized,
|
||||
diff::display::HoverItemColor::Special => HoverItemColor::Special,
|
||||
diff::display::HoverItemColor::Delete => HoverItemColor::Delete,
|
||||
diff::display::HoverItemColor::Insert => HoverItemColor::Insert,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ interface diff {
|
||||
data: list<u8>,
|
||||
config: borrow<diff-config>,
|
||||
) -> result<object, string>;
|
||||
|
||||
hash: func() -> u64;
|
||||
}
|
||||
|
||||
resource object-diff {
|
||||
@@ -135,6 +137,8 @@ interface display {
|
||||
normal,
|
||||
emphasized,
|
||||
special,
|
||||
delete,
|
||||
insert,
|
||||
}
|
||||
|
||||
record hover-item-text {
|
||||
|
||||
Reference in New Issue
Block a user