mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-16 08:27:04 +00:00
Compare commits
6 Commits
v3.0.0-bet
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
| ffb38d1bb0 | |||
| d56dda72f0 | |||
| c6971f3f2d | |||
| 3965a035fa | |||
| f1fc29f77e | |||
| 7c4f1c5d13 |
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ab_glyph"
|
name = "ab_glyph"
|
||||||
@@ -2652,7 +2652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3268,7 +3268,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-cli"
|
name = "objdiff-cli"
|
||||||
version = "3.0.0-beta.1"
|
version = "3.0.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"argp",
|
"argp",
|
||||||
@@ -3291,7 +3291,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-core"
|
name = "objdiff-core"
|
||||||
version = "3.0.0-beta.1"
|
version = "3.0.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arm-attr",
|
"arm-attr",
|
||||||
@@ -3344,7 +3344,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-gui"
|
name = "objdiff-gui"
|
||||||
version = "3.0.0-beta.1"
|
version = "3.0.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -3380,7 +3380,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-wasm"
|
name = "objdiff-wasm"
|
||||||
version = "3.0.0-beta.1"
|
version = "3.0.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"objdiff-core",
|
"objdiff-core",
|
||||||
@@ -3894,7 +3894,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rabbitizer"
|
name = "rabbitizer"
|
||||||
version = "2.0.0-dev0"
|
version = "2.0.0-dev0"
|
||||||
source = "git+https://github.com/Decompollaborate/rabbitizer.git?branch=🦀#06dc8b6c826c3d60e112d4c2cd70aa54e308be12"
|
source = "git+https://github.com/Decompollaborate/rabbitizer.git?branch=%F0%9F%A6%80#06dc8b6c826c3d60e112d4c2cd70aa54e308be12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
]
|
]
|
||||||
@@ -4205,9 +4205,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.17.11"
|
version = "0.17.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da5349ae27d3887ca812fb375b45a4fbb36d8d12d2df394968cd86e35683fe73"
|
checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ strip = "debuginfo"
|
|||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "3.0.0-beta.1"
|
version = "3.0.0-beta.2"
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ ignore = [
|
|||||||
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
||||||
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
||||||
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
||||||
|
{ id = "RUSTSEC-2024-0436", reason = "Unmaintained paste crate is an indirect dependency" },
|
||||||
]
|
]
|
||||||
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
||||||
# If this is false, then it uses a built-in git library.
|
# If this is false, then it uses a built-in git library.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use crossterm::{
|
|||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
bindings::diff::DiffResult,
|
bindings::diff::DiffResult,
|
||||||
build::{
|
build::{
|
||||||
BuildConfig,
|
BuildConfig, BuildStatus,
|
||||||
watcher::{Watcher, create_watcher},
|
watcher::{Watcher, create_watcher},
|
||||||
},
|
},
|
||||||
config::{
|
config::{
|
||||||
@@ -251,6 +251,8 @@ pub struct AppState {
|
|||||||
pub project_config: Option<ProjectConfig>,
|
pub project_config: Option<ProjectConfig>,
|
||||||
pub target_path: Option<Utf8PlatformPathBuf>,
|
pub target_path: Option<Utf8PlatformPathBuf>,
|
||||||
pub base_path: Option<Utf8PlatformPathBuf>,
|
pub base_path: Option<Utf8PlatformPathBuf>,
|
||||||
|
pub left_status: Option<BuildStatus>,
|
||||||
|
pub right_status: Option<BuildStatus>,
|
||||||
pub left_obj: Option<(Object, ObjectDiff)>,
|
pub left_obj: Option<(Object, ObjectDiff)>,
|
||||||
pub right_obj: Option<(Object, ObjectDiff)>,
|
pub right_obj: Option<(Object, ObjectDiff)>,
|
||||||
pub prev_obj: Option<(Object, ObjectDiff)>,
|
pub prev_obj: Option<(Object, ObjectDiff)>,
|
||||||
@@ -348,6 +350,8 @@ impl AppState {
|
|||||||
JobResult::None => unreachable!("Unexpected JobResult::None"),
|
JobResult::None => unreachable!("Unexpected JobResult::None"),
|
||||||
JobResult::ObjDiff(result) => {
|
JobResult::ObjDiff(result) => {
|
||||||
let result = result.unwrap();
|
let result = result.unwrap();
|
||||||
|
self.left_status = Some(result.first_status);
|
||||||
|
self.right_status = Some(result.second_status);
|
||||||
self.left_obj = result.first_obj;
|
self.left_obj = result.first_obj;
|
||||||
self.right_obj = result.second_obj;
|
self.right_obj = result.second_obj;
|
||||||
self.reload_time = Some(result.time);
|
self.reload_time = Some(result.time);
|
||||||
@@ -388,6 +392,8 @@ fn run_interactive(
|
|||||||
project_config,
|
project_config,
|
||||||
target_path,
|
target_path,
|
||||||
base_path,
|
base_path,
|
||||||
|
left_status: None,
|
||||||
|
right_status: None,
|
||||||
left_obj: None,
|
left_obj: None,
|
||||||
right_obj: None,
|
right_obj: None,
|
||||||
prev_obj: None,
|
prev_obj: None,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
use anyhow::{Result, bail};
|
use anyhow::Result;
|
||||||
use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers, MouseButton, MouseEventKind};
|
use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers, MouseButton, MouseEventKind};
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
|
build::BuildStatus,
|
||||||
diff::{
|
diff::{
|
||||||
DiffObjConfig, FunctionRelocDiffs, InstructionDiffKind, ObjectDiff, SymbolDiff,
|
DiffObjConfig, FunctionRelocDiffs, InstructionDiffKind, ObjectDiff, SymbolDiff,
|
||||||
display::{DiffText, DiffTextColor, HighlightKind, display_row},
|
display::{DiffText, DiffTextColor, HighlightKind, display_row},
|
||||||
@@ -126,6 +127,11 @@ impl UiView for FunctionDiffUi {
|
|||||||
);
|
);
|
||||||
max_width = max_width.max(text.width());
|
max_width = max_width.max(text.width());
|
||||||
left_text = Some(text);
|
left_text = Some(text);
|
||||||
|
} else if let Some(status) = &state.left_status {
|
||||||
|
let mut text = Text::default();
|
||||||
|
self.print_build_status(&mut text, status);
|
||||||
|
max_width = max_width.max(text.width());
|
||||||
|
left_text = Some(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut right_text = None;
|
let mut right_text = None;
|
||||||
@@ -155,6 +161,11 @@ impl UiView for FunctionDiffUi {
|
|||||||
let rect = content_chunks[1].inner(Margin::new(1, 1));
|
let rect = content_chunks[1].inner(Margin::new(1, 1));
|
||||||
self.print_margin(&mut text, symbol_diff, rect);
|
self.print_margin(&mut text, symbol_diff, rect);
|
||||||
margin_text = Some(text);
|
margin_text = Some(text);
|
||||||
|
} else if let Some(status) = &state.right_status {
|
||||||
|
let mut text = Text::default();
|
||||||
|
self.print_build_status(&mut text, status);
|
||||||
|
max_width = max_width.max(text.width());
|
||||||
|
right_text = Some(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut prev_text = None;
|
let mut prev_text = None;
|
||||||
@@ -453,7 +464,7 @@ impl UiView for FunctionDiffUi {
|
|||||||
}
|
}
|
||||||
(Some((_l, _ls, ld)), None) => ld.instruction_rows.len(),
|
(Some((_l, _ls, ld)), None) => ld.instruction_rows.len(),
|
||||||
(None, Some((_r, _rs, rd))) => rd.instruction_rows.len(),
|
(None, Some((_r, _rs, rd))) => rd.instruction_rows.len(),
|
||||||
(None, None) => bail!("Symbol not found: {}", self.symbol_name),
|
(None, None) => 0,
|
||||||
};
|
};
|
||||||
self.left_sym = left_sym;
|
self.left_sym = left_sym;
|
||||||
self.right_sym = right_sym;
|
self.right_sym = right_sym;
|
||||||
@@ -596,6 +607,18 @@ impl FunctionDiffUi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_build_status<'a>(&self, out: &mut Text<'a>, status: &'a BuildStatus) {
|
||||||
|
if !status.cmdline.is_empty() {
|
||||||
|
out.lines.push(Line::styled(status.cmdline.clone(), Style::new().fg(Color::LightBlue)));
|
||||||
|
}
|
||||||
|
for line in status.stdout.lines() {
|
||||||
|
out.lines.push(Line::styled(line, Style::new().fg(Color::White)));
|
||||||
|
}
|
||||||
|
for line in status.stderr.lines() {
|
||||||
|
out.lines.push(Line::styled(line, Style::new().fg(Color::Red)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const COLOR_ROTATION: [Color; 7] = [
|
pub const COLOR_ROTATION: [Color; 7] = [
|
||||||
|
|||||||
@@ -19,7 +19,15 @@ fn compile_protos() {
|
|||||||
.map(|m| m.modified().unwrap())
|
.map(|m| m.modified().unwrap())
|
||||||
.unwrap_or(std::time::SystemTime::UNIX_EPOCH);
|
.unwrap_or(std::time::SystemTime::UNIX_EPOCH);
|
||||||
let mut run_protoc = false;
|
let mut run_protoc = false;
|
||||||
let proto_files = vec![root.join("report.proto")];
|
let proto_files = root
|
||||||
|
.read_dir()
|
||||||
|
.unwrap()
|
||||||
|
.filter_map(|e| {
|
||||||
|
let e = e.unwrap();
|
||||||
|
let path = e.path();
|
||||||
|
(path.extension() == Some(std::ffi::OsStr::new("proto"))).then_some(path)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
for proto_file in &proto_files {
|
for proto_file in &proto_files {
|
||||||
println!("cargo:rerun-if-changed={}", proto_file.display());
|
println!("cargo:rerun-if-changed={}", proto_file.display());
|
||||||
let mtime = match std::fs::metadata(proto_file) {
|
let mtime = match std::fs::metadata(proto_file) {
|
||||||
|
|||||||
59
objdiff-core/protos/changes.proto
Normal file
59
objdiff-core/protos/changes.proto
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "report.proto";
|
||||||
|
|
||||||
|
package objdiff.report;
|
||||||
|
|
||||||
|
// A pair of reports to compare and generate changes
|
||||||
|
message ChangesInput {
|
||||||
|
// The previous report
|
||||||
|
Report from = 1;
|
||||||
|
// The current report
|
||||||
|
Report to = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changes between two reports
|
||||||
|
message Changes {
|
||||||
|
// The progress info for the previous report
|
||||||
|
Measures from = 1;
|
||||||
|
// The progress info for the current report
|
||||||
|
Measures to = 2;
|
||||||
|
// Units that changed
|
||||||
|
repeated ChangeUnit units = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A changed unit
|
||||||
|
message ChangeUnit {
|
||||||
|
// The name of the unit
|
||||||
|
string name = 1;
|
||||||
|
// The previous progress info (omitted if new)
|
||||||
|
optional Measures from = 2;
|
||||||
|
// The current progress info (omitted if removed)
|
||||||
|
optional Measures to = 3;
|
||||||
|
// Sections that changed
|
||||||
|
repeated ChangeItem sections = 4;
|
||||||
|
// Functions that changed
|
||||||
|
repeated ChangeItem functions = 5;
|
||||||
|
// Extra metadata for this unit
|
||||||
|
optional ReportUnitMetadata metadata = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A changed section or function
|
||||||
|
message ChangeItem {
|
||||||
|
// The name of the item
|
||||||
|
string name = 1;
|
||||||
|
// The previous progress info (omitted if new)
|
||||||
|
optional ChangeItemInfo from = 2;
|
||||||
|
// The current progress info (omitted if removed)
|
||||||
|
optional ChangeItemInfo to = 3;
|
||||||
|
// Extra metadata for this item
|
||||||
|
optional ReportItemMetadata metadata = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress info for a section or function
|
||||||
|
message ChangeItemInfo {
|
||||||
|
// The overall match percent for this item
|
||||||
|
float fuzzy_match_percent = 1;
|
||||||
|
// The size of the item in bytes
|
||||||
|
uint64 size = 2;
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -2,6 +2,18 @@ syntax = "proto3";
|
|||||||
|
|
||||||
package objdiff.report;
|
package objdiff.report;
|
||||||
|
|
||||||
|
// Project progress report
|
||||||
|
message Report {
|
||||||
|
// Overall progress info
|
||||||
|
Measures measures = 1;
|
||||||
|
// Units within this report
|
||||||
|
repeated ReportUnit units = 2;
|
||||||
|
// Report version
|
||||||
|
uint32 version = 3;
|
||||||
|
// Progress categories
|
||||||
|
repeated ReportCategory categories = 4;
|
||||||
|
}
|
||||||
|
|
||||||
// Progress info for a report or unit
|
// Progress info for a report or unit
|
||||||
message Measures {
|
message Measures {
|
||||||
// Overall match percent, including partially matched functions and data
|
// Overall match percent, including partially matched functions and data
|
||||||
@@ -38,18 +50,6 @@ message Measures {
|
|||||||
uint32 complete_units = 16;
|
uint32 complete_units = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Project progress report
|
|
||||||
message Report {
|
|
||||||
// Overall progress info
|
|
||||||
Measures measures = 1;
|
|
||||||
// Units within this report
|
|
||||||
repeated ReportUnit units = 2;
|
|
||||||
// Report version
|
|
||||||
uint32 version = 3;
|
|
||||||
// Progress categories
|
|
||||||
repeated ReportCategory categories = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ReportCategory {
|
message ReportCategory {
|
||||||
// The ID of the category
|
// The ID of the category
|
||||||
string id = 1;
|
string id = 1;
|
||||||
@@ -108,57 +108,3 @@ message ReportItemMetadata {
|
|||||||
// The virtual address of the function or section
|
// The virtual address of the function or section
|
||||||
optional uint64 virtual_address = 2;
|
optional uint64 virtual_address = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A pair of reports to compare and generate changes
|
|
||||||
message ChangesInput {
|
|
||||||
// The previous report
|
|
||||||
Report from = 1;
|
|
||||||
// The current report
|
|
||||||
Report to = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Changes between two reports
|
|
||||||
message Changes {
|
|
||||||
// The progress info for the previous report
|
|
||||||
Measures from = 1;
|
|
||||||
// The progress info for the current report
|
|
||||||
Measures to = 2;
|
|
||||||
// Units that changed
|
|
||||||
repeated ChangeUnit units = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A changed unit
|
|
||||||
message ChangeUnit {
|
|
||||||
// The name of the unit
|
|
||||||
string name = 1;
|
|
||||||
// The previous progress info (omitted if new)
|
|
||||||
optional Measures from = 2;
|
|
||||||
// The current progress info (omitted if removed)
|
|
||||||
optional Measures to = 3;
|
|
||||||
// Sections that changed
|
|
||||||
repeated ChangeItem sections = 4;
|
|
||||||
// Functions that changed
|
|
||||||
repeated ChangeItem functions = 5;
|
|
||||||
// Extra metadata for this unit
|
|
||||||
optional ReportUnitMetadata metadata = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A changed section or function
|
|
||||||
message ChangeItem {
|
|
||||||
// The name of the item
|
|
||||||
string name = 1;
|
|
||||||
// The previous progress info (omitted if new)
|
|
||||||
optional ChangeItemInfo from = 2;
|
|
||||||
// The current progress info (omitted if removed)
|
|
||||||
optional ChangeItemInfo to = 3;
|
|
||||||
// Extra metadata for this item
|
|
||||||
optional ReportItemMetadata metadata = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Progress info for a section or function
|
|
||||||
message ChangeItemInfo {
|
|
||||||
// The overall match percent for this item
|
|
||||||
float fuzzy_match_percent = 1;
|
|
||||||
// The size of the item in bytes
|
|
||||||
uint64 size = 2;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,17 +15,36 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ArchX86 {
|
pub struct ArchX86 {
|
||||||
bits: u32,
|
arch: Architecture,
|
||||||
endianness: object::Endianness,
|
endianness: object::Endianness,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Architecture {
|
||||||
|
X86,
|
||||||
|
X86_64,
|
||||||
|
}
|
||||||
|
|
||||||
impl ArchX86 {
|
impl ArchX86 {
|
||||||
pub fn new(object: &object::File) -> Result<Self> {
|
pub fn new(object: &object::File) -> Result<Self> {
|
||||||
Ok(Self { bits: if object.is_64() { 64 } else { 32 }, endianness: object.endianness() })
|
let arch = match object.architecture() {
|
||||||
|
object::Architecture::I386 => Architecture::X86,
|
||||||
|
object::Architecture::X86_64 => Architecture::X86_64,
|
||||||
|
_ => bail!("Unsupported architecture for ArchX86: {:?}", object.architecture()),
|
||||||
|
};
|
||||||
|
Ok(Self { arch, endianness: object.endianness() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decoder<'a>(&self, code: &'a [u8], address: u64) -> Decoder<'a> {
|
fn decoder<'a>(&self, code: &'a [u8], address: u64) -> Decoder<'a> {
|
||||||
Decoder::with_ip(self.bits, code, address, DecoderOptions::NONE)
|
Decoder::with_ip(
|
||||||
|
match self.arch {
|
||||||
|
Architecture::X86 => 32,
|
||||||
|
Architecture::X86_64 => 64,
|
||||||
|
},
|
||||||
|
code,
|
||||||
|
address,
|
||||||
|
DecoderOptions::NONE,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn formatter(&self, diff_config: &DiffObjConfig) -> Box<dyn iced_x86::Formatter> {
|
fn formatter(&self, diff_config: &DiffObjConfig) -> Box<dyn iced_x86::Formatter> {
|
||||||
@@ -38,6 +57,27 @@ impl ArchX86 {
|
|||||||
formatter.options_mut().set_space_after_operand_separator(diff_config.space_between_args);
|
formatter.options_mut().set_space_after_operand_separator(diff_config.space_between_args);
|
||||||
formatter
|
formatter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reloc_size(&self, flags: RelocationFlags) -> Option<usize> {
|
||||||
|
match self.arch {
|
||||||
|
Architecture::X86 => match flags {
|
||||||
|
RelocationFlags::Coff(typ) => match typ {
|
||||||
|
pe::IMAGE_REL_I386_DIR16 | pe::IMAGE_REL_I386_REL16 => Some(2),
|
||||||
|
pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32 => Some(4),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
Architecture::X86_64 => match flags {
|
||||||
|
RelocationFlags::Coff(typ) => match typ {
|
||||||
|
pe::IMAGE_REL_AMD64_ADDR32NB | pe::IMAGE_REL_AMD64_REL32 => Some(4),
|
||||||
|
pe::IMAGE_REL_AMD64_ADDR64 => Some(8),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arch for ArchX86 {
|
impl Arch for ArchX86 {
|
||||||
@@ -88,10 +128,9 @@ impl Arch for ArchX86 {
|
|||||||
// memory operand.
|
// memory operand.
|
||||||
let mut reloc_replace = None;
|
let mut reloc_replace = None;
|
||||||
if let Some(reloc) = resolved.relocation {
|
if let Some(reloc) = resolved.relocation {
|
||||||
const PLACEHOLDER: u64 = 0x7BDE3E7D; // chosen by fair dice roll.
|
const PLACEHOLDER: u64 = 0x7BDE3E7D; // chosen by fair dice roll. guaranteed to be random.
|
||||||
// guaranteed to be random.
|
|
||||||
let reloc_offset = reloc.relocation.address - resolved.ins_ref.address;
|
let reloc_offset = reloc.relocation.address - resolved.ins_ref.address;
|
||||||
let reloc_size = reloc_size(reloc.relocation.flags).unwrap_or(usize::MAX);
|
let reloc_size = self.reloc_size(reloc.relocation.flags).unwrap_or(usize::MAX);
|
||||||
let offsets = decoder.get_constant_offsets(&instruction);
|
let offsets = decoder.get_constant_offsets(&instruction);
|
||||||
if reloc_offset == offsets.displacement_offset() as u64
|
if reloc_offset == offsets.displacement_offset() as u64
|
||||||
&& reloc_size == offsets.displacement_size()
|
&& reloc_size == offsets.displacement_size()
|
||||||
@@ -148,12 +187,28 @@ impl Arch for ArchX86 {
|
|||||||
_relocation: &object::Relocation,
|
_relocation: &object::Relocation,
|
||||||
flags: RelocationFlags,
|
flags: RelocationFlags,
|
||||||
) -> Result<i64> {
|
) -> Result<i64> {
|
||||||
match flags {
|
match self.arch {
|
||||||
RelocationFlags::Coff(pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32) => {
|
Architecture::X86 => match flags {
|
||||||
let data = section.data()?[address as usize..address as usize + 4].try_into()?;
|
RelocationFlags::Coff(pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32) => {
|
||||||
Ok(self.endianness.read_i32_bytes(data) as i64)
|
let data =
|
||||||
}
|
section.data()?[address as usize..address as usize + 4].try_into()?;
|
||||||
flags => bail!("Unsupported x86 implicit relocation {flags:?}"),
|
Ok(self.endianness.read_i32_bytes(data) as i64)
|
||||||
|
}
|
||||||
|
flags => bail!("Unsupported x86 implicit relocation {flags:?}"),
|
||||||
|
},
|
||||||
|
Architecture::X86_64 => match flags {
|
||||||
|
RelocationFlags::Coff(pe::IMAGE_REL_AMD64_ADDR32NB | pe::IMAGE_REL_AMD64_REL32) => {
|
||||||
|
let data =
|
||||||
|
section.data()?[address as usize..address as usize + 4].try_into()?;
|
||||||
|
Ok(self.endianness.read_i32_bytes(data) as i64)
|
||||||
|
}
|
||||||
|
RelocationFlags::Coff(pe::IMAGE_REL_AMD64_ADDR64) => {
|
||||||
|
let data =
|
||||||
|
section.data()?[address as usize..address as usize + 8].try_into()?;
|
||||||
|
Ok(self.endianness.read_i64_bytes(data))
|
||||||
|
}
|
||||||
|
flags => bail!("Unsupported x86-64 implicit relocation {flags:?}"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,27 +223,29 @@ impl Arch for ArchX86 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_name(&self, flags: RelocationFlags) -> Option<&'static str> {
|
fn reloc_name(&self, flags: RelocationFlags) -> Option<&'static str> {
|
||||||
match flags {
|
match self.arch {
|
||||||
RelocationFlags::Coff(typ) => match typ {
|
Architecture::X86 => match flags {
|
||||||
pe::IMAGE_REL_I386_DIR32 => Some("IMAGE_REL_I386_DIR32"),
|
RelocationFlags::Coff(typ) => match typ {
|
||||||
pe::IMAGE_REL_I386_REL32 => Some("IMAGE_REL_I386_REL32"),
|
pe::IMAGE_REL_I386_DIR32 => Some("IMAGE_REL_I386_DIR32"),
|
||||||
|
pe::IMAGE_REL_I386_REL32 => Some("IMAGE_REL_I386_REL32"),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
Architecture::X86_64 => match flags {
|
||||||
|
RelocationFlags::Coff(typ) => match typ {
|
||||||
|
pe::IMAGE_REL_AMD64_ADDR64 => Some("IMAGE_REL_AMD64_ADDR64"),
|
||||||
|
pe::IMAGE_REL_AMD64_ADDR32NB => Some("IMAGE_REL_AMD64_ADDR32NB"),
|
||||||
|
pe::IMAGE_REL_AMD64_REL32 => Some("IMAGE_REL_AMD64_REL32"),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_reloc_size(&self, flags: RelocationFlags) -> usize { reloc_size(flags).unwrap_or(1) }
|
fn data_reloc_size(&self, flags: RelocationFlags) -> usize {
|
||||||
}
|
self.reloc_size(flags).unwrap_or(1)
|
||||||
|
|
||||||
fn reloc_size(flags: RelocationFlags) -> Option<usize> {
|
|
||||||
match flags {
|
|
||||||
RelocationFlags::Coff(typ) => match typ {
|
|
||||||
pe::IMAGE_REL_I386_DIR16 | pe::IMAGE_REL_I386_REL16 => Some(2),
|
|
||||||
pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32 => Some(4),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +400,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_scan_instructions() {
|
fn test_scan_instructions() {
|
||||||
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
|
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
|
||||||
let code = [
|
let code = [
|
||||||
0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0x85, 0x00,
|
0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0x85, 0x00,
|
||||||
0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00,
|
||||||
@@ -362,7 +419,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_instruction() {
|
fn test_process_instruction() {
|
||||||
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
|
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
|
||||||
let code = [0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00];
|
let code = [0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00];
|
||||||
let opcode = iced_x86::Mnemonic::Mov as u16;
|
let opcode = iced_x86::Mnemonic::Mov as u16;
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
@@ -398,7 +455,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_instruction_with_reloc_1() {
|
fn test_process_instruction_with_reloc_1() {
|
||||||
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
|
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
|
||||||
let code = [0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00];
|
let code = [0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00];
|
||||||
let opcode = iced_x86::Mnemonic::Mov as u16;
|
let opcode = iced_x86::Mnemonic::Mov as u16;
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
@@ -443,7 +500,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_instruction_with_reloc_2() {
|
fn test_process_instruction_with_reloc_2() {
|
||||||
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
|
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
|
||||||
let code = [0x8b, 0x04, 0x85, 0x00, 0x00, 0x00, 0x00];
|
let code = [0x8b, 0x04, 0x85, 0x00, 0x00, 0x00, 0x00];
|
||||||
let opcode = iced_x86::Mnemonic::Mov as u16;
|
let opcode = iced_x86::Mnemonic::Mov as u16;
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
@@ -486,7 +543,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_process_instruction_with_reloc_3() {
|
fn test_process_instruction_with_reloc_3() {
|
||||||
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
|
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
|
||||||
let code = [0xe8, 0x00, 0x00, 0x00, 0x00];
|
let code = [0xe8, 0x00, 0x00, 0x00, 0x00];
|
||||||
let opcode = iced_x86::Mnemonic::Call as u16;
|
let opcode = iced_x86::Mnemonic::Call as u16;
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ pub fn diff_code(
|
|||||||
left_section_idx,
|
left_section_idx,
|
||||||
diff_config,
|
diff_config,
|
||||||
)?;
|
)?;
|
||||||
let right_ops = left_obj.arch.scan_instructions(
|
let right_ops = right_obj.arch.scan_instructions(
|
||||||
right_symbol.address,
|
right_symbol.address,
|
||||||
right_data,
|
right_data,
|
||||||
right_section_idx,
|
right_section_idx,
|
||||||
@@ -437,7 +437,7 @@ fn diff_instruction(
|
|||||||
{
|
{
|
||||||
// If either the raw code bytes or relocations don't match, process instructions and compare args
|
// If either the raw code bytes or relocations don't match, process instructions and compare args
|
||||||
let left_ins = left_obj.arch.process_instruction(left_resolved, diff_config)?;
|
let left_ins = left_obj.arch.process_instruction(left_resolved, diff_config)?;
|
||||||
let right_ins = left_obj.arch.process_instruction(right_resolved, diff_config)?;
|
let right_ins = right_obj.arch.process_instruction(right_resolved, diff_config)?;
|
||||||
if left_ins.args.len() != right_ins.args.len() {
|
if left_ins.args.len() != right_ins.args.len() {
|
||||||
state.diff_score += PENALTY_REPLACE;
|
state.diff_score += PENALTY_REPLACE;
|
||||||
return Ok(InstructionDiffResult::new(InstructionDiffKind::Replace));
|
return Ok(InstructionDiffResult::new(InstructionDiffKind::Replace));
|
||||||
|
|||||||
@@ -14,3 +14,26 @@ fn read_mips() {
|
|||||||
let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config);
|
let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config);
|
||||||
insta::assert_snapshot!(output);
|
insta::assert_snapshot!(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "mips")]
|
||||||
|
fn cross_endian_diff() {
|
||||||
|
let diff_config = diff::DiffObjConfig::default();
|
||||||
|
let obj_be = obj::read::parse(include_object!("data/mips/code_be.o"), &diff_config).unwrap();
|
||||||
|
assert_eq!(obj_be.endianness, object::Endianness::Big);
|
||||||
|
let obj_le = obj::read::parse(include_object!("data/mips/code_le.o"), &diff_config).unwrap();
|
||||||
|
assert_eq!(obj_le.endianness, object::Endianness::Little);
|
||||||
|
let left_symbol_idx = obj_be.symbols.iter().position(|s| s.name == "func_00000000").unwrap();
|
||||||
|
let right_symbol_idx =
|
||||||
|
obj_le.symbols.iter().position(|s| s.name == "func_00000000__FPcPc").unwrap();
|
||||||
|
let (left_diff, right_diff) =
|
||||||
|
diff::code::diff_code(&obj_be, &obj_le, left_symbol_idx, right_symbol_idx, &diff_config)
|
||||||
|
.unwrap();
|
||||||
|
// Although the objects differ in endianness, the instructions should match.
|
||||||
|
assert_eq!(left_diff.instruction_rows[0].kind, diff::InstructionDiffKind::None);
|
||||||
|
assert_eq!(right_diff.instruction_rows[0].kind, diff::InstructionDiffKind::None);
|
||||||
|
assert_eq!(left_diff.instruction_rows[1].kind, diff::InstructionDiffKind::None);
|
||||||
|
assert_eq!(right_diff.instruction_rows[1].kind, diff::InstructionDiffKind::None);
|
||||||
|
assert_eq!(left_diff.instruction_rows[2].kind, diff::InstructionDiffKind::None);
|
||||||
|
assert_eq!(right_diff.instruction_rows[2].kind, diff::InstructionDiffKind::None);
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,3 +26,17 @@ fn read_x86_combine_sections() {
|
|||||||
let obj = obj::read::parse(include_object!("data/x86/rtest.obj"), &diff_config).unwrap();
|
let obj = obj::read::parse(include_object!("data/x86/rtest.obj"), &diff_config).unwrap();
|
||||||
insta::assert_debug_snapshot!(obj.sections);
|
insta::assert_debug_snapshot!(obj.sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "x86")]
|
||||||
|
fn read_x86_64() {
|
||||||
|
let diff_config = diff::DiffObjConfig::default();
|
||||||
|
let obj = obj::read::parse(include_object!("data/x86_64/vs2022.o"), &diff_config).unwrap();
|
||||||
|
insta::assert_debug_snapshot!(obj);
|
||||||
|
let symbol_idx =
|
||||||
|
obj.symbols.iter().position(|s| s.name == "?Dot@Vector@@QEAAMPEAU1@@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/mips/code_be.o
Normal file
BIN
objdiff-core/tests/data/mips/code_be.o
Normal file
Binary file not shown.
BIN
objdiff-core/tests/data/mips/code_le.o
Normal file
BIN
objdiff-core/tests/data/mips/code_le.o
Normal file
Binary file not shown.
BIN
objdiff-core/tests/data/x86_64/vs2022.o
Normal file
BIN
objdiff-core/tests/data/x86_64/vs2022.o
Normal file
Binary file not shown.
@@ -4,7 +4,7 @@ expression: obj
|
|||||||
---
|
---
|
||||||
Object {
|
Object {
|
||||||
arch: ArchX86 {
|
arch: ArchX86 {
|
||||||
bits: 32,
|
arch: X86,
|
||||||
endianness: Little,
|
endianness: Little,
|
||||||
},
|
},
|
||||||
endianness: Little,
|
endianness: Little,
|
||||||
|
|||||||
279
objdiff-core/tests/snapshots/arch_x86__read_x86_64-2.snap
Normal file
279
objdiff-core/tests/snapshots/arch_x86__read_x86_64-2.snap
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
---
|
||||||
|
source: objdiff-core/tests/arch_x86.rs
|
||||||
|
expression: diff.instruction_rows
|
||||||
|
---
|
||||||
|
[
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 0,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 5,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 10,
|
||||||
|
size: 1,
|
||||||
|
opcode: 640,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 11,
|
||||||
|
size: 4,
|
||||||
|
opcode: 740,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 15,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 20,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 25,
|
||||||
|
size: 4,
|
||||||
|
opcode: 448,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 29,
|
||||||
|
size: 4,
|
||||||
|
opcode: 460,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 33,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 38,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 43,
|
||||||
|
size: 5,
|
||||||
|
opcode: 448,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 48,
|
||||||
|
size: 5,
|
||||||
|
opcode: 460,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 53,
|
||||||
|
size: 4,
|
||||||
|
opcode: 11,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 57,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 62,
|
||||||
|
size: 5,
|
||||||
|
opcode: 414,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 67,
|
||||||
|
size: 5,
|
||||||
|
opcode: 448,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 72,
|
||||||
|
size: 5,
|
||||||
|
opcode: 460,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 77,
|
||||||
|
size: 4,
|
||||||
|
opcode: 11,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 81,
|
||||||
|
size: 4,
|
||||||
|
opcode: 7,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 85,
|
||||||
|
size: 1,
|
||||||
|
opcode: 590,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
InstructionDiffRow {
|
||||||
|
ins_ref: Some(
|
||||||
|
InstructionRef {
|
||||||
|
address: 86,
|
||||||
|
size: 1,
|
||||||
|
opcode: 662,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
kind: None,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
25
objdiff-core/tests/snapshots/arch_x86__read_x86_64-3.snap
Normal file
25
objdiff-core/tests/snapshots/arch_x86__read_x86_64-3.snap
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
source: objdiff-core/tests/arch_x86.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
[(Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(16)), Normal, 0), (Basic("]"), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Opaque("rdx")), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(5), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(8)), Normal, 0), (Basic("]"), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Opaque("rcx")), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(10), Normal, 5), (Spacing(4), Normal, 0), (Opcode("push", 640), Normal, 10), (Argument(Opaque("rdi")), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(11), Normal, 5), (Spacing(4), Normal, 0), (Opcode("sub", 740), Normal, 10), (Argument(Opaque("rsp")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(16)), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(15), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("rax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(32)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(20), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("rcx")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(40)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(25), Normal, 5), (Spacing(4), Normal, 0), (Opcode("movss", 448), Normal, 10), (Argument(Opaque("xmm0")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rax")), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(29), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mulss", 460), Normal, 10), (Argument(Opaque("xmm0")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rcx")), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(33), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("rax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(32)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(38), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("rcx")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(40)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(43), Normal, 5), (Spacing(4), Normal, 0), (Opcode("movss", 448), Normal, 10), (Argument(Opaque("xmm1")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rax")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(48), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mulss", 460), Normal, 10), (Argument(Opaque("xmm1")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rcx")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(53), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addss", 11), Normal, 10), (Argument(Opaque("xmm0")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Opaque("xmm1")), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(57), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("rax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(32)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(62), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("rcx")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rsp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(40)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(67), Normal, 5), (Spacing(4), Normal, 0), (Opcode("movss", 448), Normal, 10), (Argument(Opaque("xmm1")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rax")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(8)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mulss", 460), Normal, 10), (Argument(Opaque("xmm1")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("rcx")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(8)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(77), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addss", 11), Normal, 10), (Argument(Opaque("xmm0")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Opaque("xmm1")), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(81), Normal, 5), (Spacing(4), Normal, 0), (Opcode("add", 7), Normal, 10), (Argument(Opaque("rsp")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(16)), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(85), Normal, 5), (Spacing(4), Normal, 0), (Opcode("pop", 590), Normal, 10), (Argument(Opaque("rdi")), Normal, 0), (Eol, Normal, 0)]
|
||||||
|
[(Address(86), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ret", 662), Normal, 10), (Eol, Normal, 0)]
|
||||||
1505
objdiff-core/tests/snapshots/arch_x86__read_x86_64.snap
Normal file
1505
objdiff-core/tests/snapshots/arch_x86__read_x86_64.snap
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "objdiff-wasm",
|
"name": "objdiff-wasm",
|
||||||
"version": "3.0.0-beta.1",
|
"version": "3.0.0-beta.2",
|
||||||
"description": "A local diffing tool for decompilation projects.",
|
"description": "A local diffing tool for decompilation projects.",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Luke Street",
|
"name": "Luke Street",
|
||||||
|
|||||||
Reference in New Issue
Block a user