Compare commits

..

No commits in common. "main" and "v3.0.0-alpha.3" have entirely different histories.

115 changed files with 2008 additions and 15993 deletions

View File

@ -1,4 +1,5 @@
# statically link the C runtime so the executable does not depend on
# that shared/dynamic library.
[target.'cfg(all(target_env = "msvc", target_os = "windows"))']
rustflags = ["-C", "target-feature=+crt-static"]
[target.x86_64-pc-windows-msvc]
linker = "rust-lld"
[target.aarch64-pc-windows-msvc]
linker = "rust-lld"

View File

@ -1,2 +0,0 @@
[*.md]
trim_trailing_whitespace = false

View File

@ -4,14 +4,10 @@ on:
pull_request:
push:
paths-ignore:
- "*.md"
- "LICENSE*"
- '*.md'
- 'LICENSE*'
workflow_dispatch:
permissions:
# For npm publish provenance
id-token: write
env:
BUILD_PROFILE: release-lto
CARGO_INCREMENTAL: 0
@ -36,9 +32,9 @@ jobs:
- name: Cache Rust workspace
uses: Swatinem/rust-cache@v2
- name: Cargo check
run: cargo check --all-targets --all-features
run: cargo check --features all
- name: Cargo clippy
run: cargo clippy --all-targets --all-features
run: cargo clippy --features all
fmt:
name: Format
@ -253,30 +249,22 @@ jobs:
components: rust-src
- name: Cache Rust workspace
uses: Swatinem/rust-cache@v2
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm -C objdiff-wasm ci
run: npm -C objdiff-wasm install
- name: Build
run: npm -C objdiff-wasm run build
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: wasm
path: objdiff-wasm/dist/
if-no-files-found: error
check-version:
name: Check package versions
release:
name: Release
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
needs: [ build-cli, build-gui, build-wasm ]
needs: [ build-cli, build-gui ]
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check git tag against package versions
- name: Check git tag against Cargo version
shell: bash
run: |
set -eou pipefail
@ -288,24 +276,9 @@ jobs:
echo "::error::Git tag doesn't match the Cargo version! ($tag != $version)"
exit 1
fi
version="v$(jq -r .version objdiff-wasm/package.json)"
if [ "$tag" != "$version" ]; then
echo "::error::Git tag doesn't match the npm version! ($tag != $version)"
exit 1
fi
release-github:
name: Release (GitHub)
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
needs: [ check-version ]
permissions:
contents: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: objdiff-*
path: artifacts
- name: Rename artifacts
working-directory: artifacts
@ -335,53 +308,3 @@ jobs:
files: out/*
draft: true
generate_release_notes: true
release-cargo:
name: Release (Cargo)
if: 'false' # TODO re-enable when all dependencies are published
runs-on: ubuntu-latest
needs: [ check-version ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish -p objdiff-core
release-npm:
name: Release (npm)
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
needs: [ check-version ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
registry-url: 'https://registry.npmjs.org'
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: wasm
path: objdiff-wasm/dist
- name: Publish
working-directory: objdiff-wasm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
set -euo pipefail
version=$(jq -r '.version' package.json)
tag="latest"
# Check for prerelease by looking for a dash
case "$version" in
*-*)
tag=$(echo "$version" | sed -e 's/^[^-]*-//' -e 's/\..*$//')
;;
esac
echo "Publishing version $version with tag '$tag'..."
npm publish --provenance --access public --tag "$tag"

View File

@ -1,36 +0,0 @@
# 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

1290
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ members = [
"objdiff-gui",
"objdiff-wasm",
]
resolver = "3"
resolver = "2"
[profile.release-lto]
inherits = "release"
@ -14,9 +14,9 @@ strip = "debuginfo"
codegen-units = 1
[workspace.package]
version = "3.0.0-beta.9"
version = "3.0.0-alpha.3"
authors = ["Luke Street <luke@street.dev>"]
edition = "2024"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/encounter/objdiff"
rust-version = "1.85"
rust-version = "1.82"

View File

@ -16,12 +16,11 @@ Features:
Supports:
- ARM (GBA, DS, 3DS)
- ARM64 (Switch)
- PowerPC 750CL (GameCube, Wii)
- MIPS (N64, PS1, PS2, PSP)
- PowerPC (GameCube, Wii)
- SuperH (Saturn, Dreamcast)
- x86 (COFF only)
- x86 (COFF only at the moment)
- ARM (GBA, DS, 3DS)
- ARM64 (Switch, experimental)
See [Usage](#usage) for more information.
@ -174,21 +173,6 @@ $ 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

View File

@ -175,10 +175,6 @@
"type": "boolean",
"description": "If true, objdiff will run the build command with the context file as an argument to generate it.",
"default": false
},
"preset_id": {
"type": "number",
"description": "The decomp.me preset ID to use for the scratch.\nCompiler and flags in the config will take precedence over the preset, but the preset is useful for organizational purposes."
}
},
"required": [

View File

@ -73,7 +73,6 @@ ignore = [
#{ 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
#{ 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 false, then it uses a built-in git library.
@ -103,7 +102,6 @@ allow = [
"0BSD",
"OFL-1.1",
"Ubuntu-font-1.0",
"CDLA-Permissive-2.0",
]
# The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the
@ -241,6 +239,8 @@ allow-git = []
[sources.allow-org]
# github.com organizations to allow git sources for
github = [
"CelestialAmber", # cwextab, rlwinmdec
"Decompollaborate", # rabbitizer
"enarx", # flagset
"encounter",
]

View File

@ -28,7 +28,7 @@ supports-color = "3.0"
time = { version = "0.3", features = ["formatting", "local-offset"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
typed-path = "0.11"
typed-path = "0.10"
[target.'cfg(target_env = "musl")'.dependencies]
mimalloc = "0.1"

View File

@ -4,7 +4,7 @@
//! For now, this only adds a --version/-V option which causes early-exit.
use std::ffi::OsStr;
use argp::{EarlyExit, FromArgs, TopLevelCommand, parser::ParseGlobalOptions};
use argp::{parser::ParseGlobalOptions, EarlyExit, FromArgs, TopLevelCommand};
struct ArgsOrVersion<T>(T)
where T: FromArgs;

View File

@ -1,37 +1,42 @@
use std::{
io::stdout,
mem,
str::FromStr,
sync::{
Arc,
atomic::{AtomicBool, Ordering},
Arc,
},
task::{Wake, Waker},
time::Duration,
};
use anyhow::{Context, Result, anyhow, bail};
use anyhow::{anyhow, bail, Context, Result};
use argp::FromArgs;
use crossterm::{
event,
event::{DisableMouseCapture, EnableMouseCapture},
terminal::{
EnterAlternateScreen, LeaveAlternateScreen, SetTitle, disable_raw_mode, enable_raw_mode,
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, SetTitle,
},
};
use objdiff_core::{
bindings::diff::DiffResult,
build::{
BuildConfig, BuildStatus,
watcher::{Watcher, create_watcher},
watcher::{create_watcher, Watcher},
BuildConfig,
},
config::{
ProjectConfig, ProjectObject, ProjectObjectMetadata, build_globset,
build_globset,
path::{check_path_buf, platform_path, platform_path_serde_option},
ProjectConfig, ProjectObject, ProjectObjectMetadata,
},
diff::{
self, ConfigEnum, ConfigPropertyId, ConfigPropertyKind, DiffObjConfig, MappingConfig,
ObjectDiff,
},
diff::{self, DiffObjConfig, MappingConfig, ObjectDiff},
jobs::{
objdiff::{start_build, ObjDiffConfig},
Job, JobQueue, JobResult,
objdiff::{ObjDiffConfig, start_build},
},
obj::{self, Object},
};
@ -39,12 +44,11 @@ use ratatui::prelude::*;
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
use crate::{
cmd::apply_config_args,
util::{
output::{OutputFormat, write_output},
output::{write_output, OutputFormat},
term::crossterm_panic_handler,
},
views::{EventControlFlow, EventResult, UiView, function_diff::FunctionDiffUi},
views::{function_diff::FunctionDiffUi, EventControlFlow, EventResult, UiView},
};
#[derive(FromArgs, PartialEq, Debug)]
@ -180,7 +184,28 @@ pub fn run(args: Args) -> Result<()> {
fn build_config_from_args(args: &Args) -> Result<(DiffObjConfig, MappingConfig)> {
let mut diff_config = DiffObjConfig::default();
apply_config_args(&mut diff_config, &args.config)?;
for config in &args.config {
let (key, value) = config.split_once('=').context("--config expects \"key=value\"")?;
let property_id = ConfigPropertyId::from_str(key)
.map_err(|()| anyhow!("Invalid configuration property: {}", key))?;
diff_config.set_property_value_str(property_id, value).map_err(|()| {
let mut options = String::new();
match property_id.kind() {
ConfigPropertyKind::Boolean => {
options = "true, false".to_string();
}
ConfigPropertyKind::Choice(variants) => {
for (i, variant) in variants.iter().enumerate() {
if i > 0 {
options.push_str(", ");
}
options.push_str(variant.value);
}
}
}
anyhow!("Invalid value for {}. Expected one of: {}", property_id.name(), options)
})?;
}
let mut mapping_config = MappingConfig {
mappings: Default::default(),
selecting_left: args.selecting_left.clone(),
@ -227,8 +252,6 @@ pub struct AppState {
pub project_config: Option<ProjectConfig>,
pub target_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 right_obj: Option<(Object, ObjectDiff)>,
pub prev_obj: Option<(Object, ObjectDiff)>,
@ -326,8 +349,6 @@ impl AppState {
JobResult::None => unreachable!("Unexpected JobResult::None"),
JobResult::ObjDiff(result) => {
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.right_obj = result.second_obj;
self.reload_time = Some(result.time);
@ -368,8 +389,6 @@ fn run_interactive(
project_config,
target_path,
base_path,
left_status: None,
right_status: None,
left_obj: None,
right_obj: None,
prev_obj: None,
@ -407,17 +426,15 @@ fn run_interactive(
let mut result = EventResult { redraw: true, ..Default::default() };
'outer: loop {
if result.redraw {
terminal.draw(|f| {
loop {
result.redraw = false;
view.draw(&state, f, &mut result);
result.click_xy = None;
if !result.redraw {
break;
}
// Clear buffer on redraw
f.buffer_mut().reset();
terminal.draw(|f| loop {
result.redraw = false;
view.draw(&state, f, &mut result);
result.click_xy = None;
if !result.redraw {
break;
}
// Clear buffer on redraw
f.buffer_mut().reset();
})?;
}
loop {

View File

@ -1,33 +1,2 @@
pub mod diff;
pub mod report;
use std::str::FromStr;
use anyhow::{Context, Result, anyhow};
use objdiff_core::diff::{ConfigEnum, ConfigPropertyId, ConfigPropertyKind, DiffObjConfig};
pub fn apply_config_args(diff_config: &mut DiffObjConfig, args: &[String]) -> Result<()> {
for config in args {
let (key, value) = config.split_once('=').context("--config expects \"key=value\"")?;
let property_id = ConfigPropertyId::from_str(key)
.map_err(|()| anyhow!("Invalid configuration property: {}", key))?;
diff_config.set_property_value_str(property_id, value).map_err(|()| {
let mut options = String::new();
match property_id.kind() {
ConfigPropertyKind::Boolean => {
options = "true, false".to_string();
}
ConfigPropertyKind::Choice(variants) => {
for (i, variant) in variants.iter().enumerate() {
if i > 0 {
options.push_str(", ");
}
options.push_str(variant.value);
}
}
}
anyhow!("Invalid value for {}. Expected one of: {}", property_id.name(), options)
})?;
}
Ok(())
}

View File

@ -1,11 +1,12 @@
use std::{collections::HashSet, fs::File, io::Read, time::Instant};
use anyhow::{Context, Result, bail};
use anyhow::{bail, Context, Result};
use argp::FromArgs;
use objdiff_core::{
bindings::report::{
ChangeItem, ChangeItemInfo, ChangeUnit, Changes, ChangesInput, Measures, REPORT_VERSION,
Report, ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata,
ChangeItem, ChangeItemInfo, ChangeUnit, Changes, ChangesInput, Measures, Report,
ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata,
REPORT_VERSION,
},
config::path::platform_path,
diff, obj,
@ -17,8 +18,8 @@ use tracing::{info, warn};
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
use crate::{
cmd::{apply_config_args, diff::ObjectConfig},
util::output::{OutputFormat, write_output},
cmd::diff::ObjectConfig,
util::output::{write_output, OutputFormat},
};
#[derive(FromArgs, PartialEq, Debug)]
@ -52,9 +53,6 @@ pub struct GenerateArgs {
#[argp(option, short = 'f')]
/// Output format (json, json-pretty, proto) (default: json)
format: Option<String>,
#[argp(option, short = 'c')]
/// Configuration property (key=value)
config: Vec<String>,
}
#[derive(FromArgs, PartialEq, Debug)]
@ -83,15 +81,6 @@ pub fn run(args: Args) -> Result<()> {
}
fn generate(args: GenerateArgs) -> Result<()> {
let mut diff_config = diff::DiffObjConfig {
function_reloc_diffs: diff::FunctionRelocDiffs::None,
combine_data_sections: true,
combine_text_sections: true,
ppc_calculate_pool_relocations: false,
..Default::default()
};
apply_config_args(&mut diff_config, &args.config)?;
let output_format = OutputFormat::from_option(args.format.as_deref())?;
let project_dir = args.project.as_deref().unwrap_or_else(|| Utf8PlatformPath::new("."));
info!("Loading project {}", project_dir);
@ -126,15 +115,14 @@ fn generate(args: GenerateArgs) -> Result<()> {
if args.deduplicate {
// If deduplicating, we need to run single-threaded
for object in &objects {
if let Some(unit) = report_object(object, &diff_config, Some(&mut existing_functions))?
{
if let Some(unit) = report_object(object, Some(&mut existing_functions))? {
units.push(unit);
}
}
} else {
let vec = objects
.par_iter()
.map(|object| report_object(object, &diff_config, None))
.map(|object| report_object(object, None))
.collect::<Result<Vec<Option<ReportUnit>>>>()?;
units = vec.into_iter().flatten().collect();
}
@ -158,7 +146,6 @@ fn generate(args: GenerateArgs) -> Result<()> {
fn report_object(
object: &ObjectConfig,
diff_config: &diff::DiffObjConfig,
mut existing_functions: Option<&mut HashSet<String>>,
) -> Result<Option<ReportUnit>> {
match (&object.target_path, &object.base_path) {
@ -172,12 +159,16 @@ fn report_object(
}
_ => {}
}
let diff_config = diff::DiffObjConfig {
function_reloc_diffs: diff::FunctionRelocDiffs::None,
..Default::default()
};
let mapping_config = diff::MappingConfig::default();
let target = object
.target_path
.as_ref()
.map(|p| {
obj::read::read(p.as_ref(), diff_config)
obj::read::read(p.as_ref(), &diff_config)
.with_context(|| format!("Failed to open {}", p))
})
.transpose()?;
@ -185,12 +176,12 @@ fn report_object(
.base_path
.as_ref()
.map(|p| {
obj::read::read(p.as_ref(), diff_config)
obj::read::read(p.as_ref(), &diff_config)
.with_context(|| format!("Failed to open {}", p))
})
.transpose()?;
let result =
diff::diff_objs(target.as_ref(), base.as_ref(), None, diff_config, &mapping_config)?;
diff::diff_objs(target.as_ref(), base.as_ref(), None, &diff_config, &mapping_config)?;
let metadata = ReportUnitMetadata {
complete: object.metadata.complete,
@ -212,13 +203,14 @@ 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
if object.complete.unwrap_or(false) { 100.0 } else { 0.0 }
if object.complete.unwrap_or(false) {
100.0
} else {
0.0
}
});
sections.push(ReportItem {
name: section.name.clone(),
@ -228,7 +220,6 @@ fn report_object(
demangled_name: None,
virtual_address: section.virtual_address,
}),
address: None,
});
match section.kind {
@ -246,7 +237,6 @@ fn report_object(
if symbol.section != Some(section_idx)
|| symbol.size == 0
|| symbol.flags.contains(SymbolFlag::Hidden)
|| symbol.flags.contains(SymbolFlag::Ignored)
{
continue;
}
@ -261,7 +251,11 @@ fn report_object(
let match_percent = symbol_diff.match_percent.unwrap_or_else(|| {
// Support cases where we don't have a target object,
// assume complete means 100% match
if object.complete.unwrap_or(false) { 100.0 } else { 0.0 }
if object.complete.unwrap_or(false) {
100.0
} else {
0.0
}
});
measures.fuzzy_match_percent += match_percent * symbol.size as f32;
measures.total_code += symbol.size;
@ -276,7 +270,6 @@ fn report_object(
demangled_name: symbol.demangled_name.clone(),
virtual_address: symbol.virtual_address,
}),
address: symbol.address.checked_sub(section.address),
});
if match_percent == 100.0 {
measures.matched_functions += 1;
@ -284,16 +277,6 @@ fn report_object(
measures.total_functions += 1;
}
}
sections.sort_by(|a, b| a.name.cmp(&b.name));
let reverse_fn_order = object.metadata.reverse_fn_order.unwrap_or(false);
functions.sort_by(|a, b| {
if reverse_fn_order {
b.address.unwrap_or(0).cmp(&a.address.unwrap_or(0))
} else {
a.address.unwrap_or(u64::MAX).cmp(&b.address.unwrap_or(u64::MAX))
}
.then_with(|| a.size.cmp(&b.size))
});
if metadata.complete.unwrap_or(false) {
measures.complete_code = measures.total_code;
measures.complete_data = measures.total_data;

View File

@ -17,7 +17,7 @@ use anyhow::{Error, Result};
use argp::{FromArgValue, FromArgs};
use enable_ansi_support::enable_ansi_support;
use supports_color::Stream;
use tracing_subscriber::{EnvFilter, filter::LevelFilter};
use tracing_subscriber::{filter::LevelFilter, EnvFilter};
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
enum LogLevel {

View File

@ -5,7 +5,7 @@ use std::{
path::Path,
};
use anyhow::{Context, Result, bail};
use anyhow::{bail, Context, Result};
use tracing::info;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]

View File

@ -3,7 +3,7 @@ use std::{io::stdout, panic};
use crossterm::{
cursor::Show,
event::DisableMouseCapture,
terminal::{LeaveAlternateScreen, disable_raw_mode},
terminal::{disable_raw_mode, LeaveAlternateScreen},
};
pub fn crossterm_panic_handler() {

View File

@ -1,19 +1,18 @@
use core::cmp::Ordering;
use anyhow::Result;
use anyhow::{bail, Result};
use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers, MouseButton, MouseEventKind};
use objdiff_core::{
build::BuildStatus,
diff::{
display::{display_row, DiffText, DiffTextColor, HighlightKind},
DiffObjConfig, FunctionRelocDiffs, InstructionDiffKind, ObjectDiff, SymbolDiff,
display::{DiffText, DiffTextColor, HighlightKind, display_row},
},
obj::Object,
};
use ratatui::{
Frame,
prelude::*,
widgets::{Block, Borders, Clear, Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState},
Frame,
};
use super::{EventControlFlow, EventResult, UiView};
@ -127,11 +126,6 @@ impl UiView for FunctionDiffUi {
);
max_width = max_width.max(text.width());
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;
@ -161,11 +155,6 @@ impl UiView for FunctionDiffUi {
let rect = content_chunks[1].inner(Margin::new(1, 1));
self.print_margin(&mut text, symbol_diff, rect);
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;
@ -450,11 +439,11 @@ impl UiView for FunctionDiffUi {
fn reload(&mut self, state: &AppState) -> Result<()> {
let left_sym =
state.left_obj.as_ref().and_then(|(o, _)| o.symbol_by_name(&self.symbol_name));
state.left_obj.as_ref().and_then(|(o, _)| find_function(o, &self.symbol_name));
let right_sym =
state.right_obj.as_ref().and_then(|(o, _)| o.symbol_by_name(&self.symbol_name));
state.right_obj.as_ref().and_then(|(o, _)| find_function(o, &self.symbol_name));
let prev_sym =
state.prev_obj.as_ref().and_then(|(o, _)| o.symbol_by_name(&self.symbol_name));
state.prev_obj.as_ref().and_then(|(o, _)| find_function(o, &self.symbol_name));
self.num_rows = match (
get_symbol(state.left_obj.as_ref(), left_sym),
get_symbol(state.right_obj.as_ref(), right_sym),
@ -464,7 +453,7 @@ impl UiView for FunctionDiffUi {
}
(Some((_l, _ls, ld)), None) => ld.instruction_rows.len(),
(None, Some((_r, _rs, rd))) => rd.instruction_rows.len(),
(None, None) => 0,
(None, None) => bail!("Symbol not found: {}", self.symbol_name),
};
self.left_sym = left_sym;
self.right_sym = right_sym;
@ -607,18 +596,6 @@ 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] = [
@ -650,3 +627,12 @@ fn get_symbol(
let sym = sym?;
Some((obj, sym, &diff.symbols[sym]))
}
fn find_function(obj: &Object, name: &str) -> Option<usize> {
for (symbol_idx, symbol) in obj.symbols.iter().enumerate() {
if symbol.name == name {
return Some(symbol_idx);
}
}
None
}

View File

@ -27,7 +27,6 @@ all = [
"mips",
"ppc",
"x86",
"superh"
]
# Implicit, used to check if any arch is enabled
any-arch = [
@ -41,7 +40,6 @@ any-arch = [
"dep:regex",
"dep:similar",
"dep:syn",
"dep:encoding_rs"
]
bindings = [
"dep:prost",
@ -77,15 +75,12 @@ std = [
"object/std",
"prost?/std",
"serde?/std",
"similar?/std",
"typed-path?/std",
"dep:filetime",
"dep:memmap2",
]
mips = [
"any-arch",
"dep:cpp_demangle",
"dep:cwdemangle",
"dep:rabbitizer",
]
ppc = [
@ -113,9 +108,6 @@ arm64 = [
"dep:yaxpeax-arch",
"dep:yaxpeax-arm",
]
superh = [
"any-arch",
]
[package.metadata.docs.rs]
features = ["all"]
@ -128,13 +120,13 @@ itertools = { version = "0.14", default-features = false, features = ["use_alloc
log = { version = "0.4", default-features = false, optional = true }
memmap2 = { version = "0.9", optional = true }
num-traits = { version = "0.2", default-features = false, optional = true }
object = { git = "https://github.com/gimli-rs/object", rev = "a74579249e21ab8fcd3a86be588de336f18297cb", default-features = false, features = ["read_core", "elf", "pe"] }
object = { version = "0.36", default-features = false, features = ["read_core", "elf", "pe"] }
pbjson = { version = "0.7", default-features = false, optional = true }
prost = { version = "0.13", default-features = false, features = ["prost-derive"], optional = true }
regex = { version = "1.11", default-features = false, features = [], optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
similar = { version = "2.7", default-features = false, features = ["hashbrown"], optional = true, git = "https://github.com/encounter/similar.git", branch = "no_std" }
typed-path = { version = "0.11", default-features = false, optional = true }
similar = { version = "2.7", default-features = false, optional = true, git = "https://github.com/encounter/similar.git", branch = "no_std" }
typed-path = { version = "0.10", default-features = false, optional = true }
# config
globset = { version = "0.4", default-features = false, optional = true }
@ -146,12 +138,12 @@ gimli = { version = "0.31", default-features = false, features = ["read"], optio
# ppc
cwdemangle = { version = "1.0", optional = true }
cwextab = { version = "1.0", optional = true }
cwextab = { version = "1.0", optional = true, git = "https://github.com/CelestialAmber/cwextab.git" }
ppc750cl = { version = "0.3", optional = true }
rlwinmdec = { version = "1.1", optional = true }
rlwinmdec = { version = "1.1", optional = true, git = "https://github.com/CelestialAmber/rlwinmdec.git" }
# mips
rabbitizer = { version = "2.0.0-alpha.1", default-features = false, features = ["all_extensions"], optional = true }
rabbitizer = { git = "https://github.com/Decompollaborate/rabbitizer.git", branch = "🦀", default-features = false, features = ["all_extensions"], optional = true }
# x86
cpp_demangle = { version = "0.4", default-features = false, features = ["alloc"], optional = true }
@ -159,7 +151,7 @@ iced-x86 = { version = "1.21", default-features = false, features = ["decoder",
msvc-demangler = { version = "0.11", optional = true }
# arm
unarm = { version = "1.8", optional = true }
unarm = { version = "1.7", optional = true }
arm-attr = { version = "0.2", optional = true }
# arm64
@ -170,9 +162,8 @@ yaxpeax-arm = { version = "0.3", default-features = false, optional = true }
notify = { version = "8.0.0", optional = true }
notify-debouncer-full = { version = "0.5.0", optional = true }
shell-escape = { version = "0.1", optional = true }
tempfile = { version = "3.19", optional = true }
tempfile = { version = "3.17", optional = true }
time = { version = "0.3", optional = true }
encoding_rs = { version = "0.8.35", optional = true }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", optional = true }
@ -201,4 +192,4 @@ syn = { version = "2.0", optional = true }
[dev-dependencies]
# Enable all features for tests
objdiff-core = { path = ".", features = ["all"] }
insta = "1.43"
insta = "1.42"

View File

@ -5,12 +5,11 @@ objdiff-core contains the core functionality of [objdiff](https://github.com/enc
## Crate feature flags
- **`all`**: Enables all main features.
- **`bindings`**: Enables serialization and deserialization of objdiff data structures.
- **`config`**: Enables objdiff configuration file support.
- **`dwarf`**: Enables extraction of line number information from DWARF debug sections.
- **`arm64`**: Enables the ARM64 backend powered by [yaxpeax-arm](https://github.com/iximeow/yaxpeax-arm).
- **`arm`**: Enables the ARM backend powered by [unarm](https://github.com/AetiasHax/unarm).
- **`mips`**: Enables the MIPS backend powered by [rabbitizer](https://github.com/Decompollaborate/rabbitizer).
- **`mips`**: Enables the MIPS backend powered by [rabbitizer](https://github.com/Decompollaborate/rabbitizer). (Note: C library with Rust bindings)
- **`ppc`**: Enables the PowerPC backend powered by [ppc750cl](https://github.com/encounter/ppc750cl).
- **`superh`**: Enables the SuperH backend powered by an included disassembler.
- **`x86`**: Enables the x86 backend powered by [iced-x86](https://crates.io/crates/iced-x86).
- **`arm`**: Enables the ARM backend powered by [unarm](https://github.com/AetiasHax/unarm).
- **`arm64`**: Enables the ARM64 backend powered by [yaxpeax-arm](https://github.com/iximeow/yaxpeax-arm).
- **`bindings`**: Enables serialization and deserialization of objdiff data structures.

View File

@ -19,15 +19,7 @@ fn compile_protos() {
.map(|m| m.modified().unwrap())
.unwrap_or(std::time::SystemTime::UNIX_EPOCH);
let mut run_protoc = false;
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<_>>();
let proto_files = vec![root.join("report.proto")];
for proto_file in &proto_files {
println!("cargo:rerun-if-changed={}", proto_file.display());
let mtime = match std::fs::metadata(proto_file) {

View File

@ -194,13 +194,6 @@
"name": "Register '$' prefix",
"description": "Display MIPS register names with a '$' prefix."
},
{
"id": "ppc.calculatePoolRelocations",
"type": "boolean",
"default": true,
"name": "Calculate pooled data references",
"description": "Display pooled data references in functions as fake relocations."
},
{
"id": "x86.formatter",
"type": "choice",
@ -260,13 +253,6 @@
"mips.registerPrefix"
]
},
{
"id": "ppc",
"name": "PowerPC",
"properties": [
"ppc.calculatePoolRelocations"
]
},
{
"id": "x86",
"name": "x86",

View File

@ -1,59 +0,0 @@
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;
}

View File

@ -2,18 +2,6 @@ syntax = "proto3";
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
message Measures {
// Overall match percent, including partially matched functions and data
@ -50,6 +38,18 @@ message Measures {
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 {
// The ID of the category
string id = 1;
@ -99,8 +99,6 @@ message ReportItem {
float fuzzy_match_percent = 3;
// Extra metadata for this item
optional ReportItemMetadata metadata = 4;
// Address of the item (section-relative offset)
optional uint64 address = 5;
}
// Extra metadata for an item
@ -110,3 +108,57 @@ message ReportItemMetadata {
// The virtual address of the function or section
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;
}

View File

@ -5,17 +5,17 @@ use alloc::{
vec::Vec,
};
use anyhow::{Result, bail};
use arm_attr::{BuildAttrs, enums::CpuArch, tag::Tag};
use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf};
use anyhow::{bail, Result};
use arm_attr::{enums::CpuArch, tag::Tag, BuildAttrs};
use object::{elf, Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _};
use unarm::{args, arm, thumb};
use crate::{
arch::Arch,
diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig, display::InstructionPart},
diff::{display::InstructionPart, ArmArchVersion, ArmR9Usage, DiffObjConfig},
obj::{
InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
Section, SectionKind, Symbol, SymbolFlag, SymbolFlagSet, SymbolKind,
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
ScannedInstruction, SymbolFlag, SymbolFlagSet, SymbolKind,
},
};
@ -32,8 +32,7 @@ impl ArchArm {
let endianness = file.endianness();
match file {
object::File::Elf32(_) => {
// The disasm_modes mapping is populated later in the post_init step so that we have access to merged sections.
let disasm_modes = BTreeMap::new();
let disasm_modes = Self::elf_get_mapping_symbols(file);
let detected_version = Self::elf_detect_arm_version(file)?;
Ok(Self { disasm_modes, detected_version, endianness })
}
@ -59,7 +58,11 @@ impl ArchArm {
}
// Only checking first CpuArch tag. Others may exist, but that's very unlikely.
let cpu_arch = subsection.into_public_tag_iter()?.find_map(|(_, tag)| {
if let Tag::CpuArch(cpu_arch) = tag { Some(cpu_arch) } else { None }
if let Tag::CpuArch(cpu_arch) = tag {
Some(cpu_arch)
} else {
None
}
});
match cpu_arch {
Some(CpuArch::V4T) => return Ok(Some(unarm::ArmVersion::V4T)),
@ -74,26 +77,29 @@ impl ArchArm {
Ok(None)
}
fn get_mapping_symbols(
sections: &[Section],
symbols: &[Symbol],
) -> BTreeMap<usize, Vec<DisasmMode>> {
sections
.iter()
.enumerate()
.filter(|(_, section)| section.kind == SectionKind::Code)
.map(|(index, _)| {
let mut mapping_symbols: Vec<_> = symbols
.iter()
.filter(|s| s.section.map(|i| i == index).unwrap_or(false))
.filter_map(DisasmMode::from_symbol)
fn elf_get_mapping_symbols(file: &object::File) -> BTreeMap<usize, Vec<DisasmMode>> {
file.sections()
.filter(|s| s.kind() == object::SectionKind::Text)
.map(|s| {
let index = s.index();
let mut mapping_symbols: Vec<_> = file
.symbols()
.filter(|s| s.section_index().map(|i| i == index).unwrap_or(false))
.filter_map(|s| DisasmMode::from_symbol(&s))
.collect();
mapping_symbols.sort_unstable_by_key(|x| x.address);
(index, mapping_symbols)
(s.index().0, 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,
@ -128,31 +134,6 @@ 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) => {
@ -176,25 +157,24 @@ 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));
(unarm::Ins::Thumb(ins), parsed)
if ins.is_half_bl() {
todo!("Combine thumb BL instructions");
} else {
(unarm::Ins::Thumb(ins), parsed)
}
};
Ok((ins, parsed_ins))
}
}
impl Arch for ArchArm {
fn post_init(&mut self, sections: &[Section], symbols: &[Symbol]) {
self.disasm_modes = Self::get_mapping_symbols(sections, symbols);
}
fn scan_instructions_internal(
fn scan_instructions(
&self,
address: u64,
code: &[u8],
section_index: usize,
_relocations: &[Relocation],
diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
) -> Result<Vec<ScannedInstruction>> {
let start_addr = address as u32;
let end_addr = start_addr + code.len() as u32;
@ -208,126 +188,61 @@ 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.saturating_sub(1));
let mut mode = mapping_symbols[first_mapping_idx].mapping;
.unwrap_or_else(|idx| idx - 1);
let first_mapping = mapping_symbols[first_mapping_idx].mapping;
let mut mappings_iter = mapping_symbols
.iter()
.copied()
.skip(first_mapping_idx + 1)
.take_while(|x| x.address < end_addr);
let mut mappings_iter =
mapping_symbols.iter().skip(first_mapping_idx + 1).take_while(|x| x.address < end_addr);
let mut next_mapping = mappings_iter.next();
let ins_count = code.len() / mode.instruction_size(start_addr);
let mut ops = Vec::<InstructionRef>::with_capacity(ins_count);
let ins_count = code.len() / first_mapping.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);
let mut address = start_addr;
while address < end_addr {
while let Some(next) = next_mapping.filter(|x| address >= x.address) {
// Change mapping
mode = next.mapping;
next_mapping = mappings_iter.next();
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 {
// Change mapping
parser.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(InstructionRef {
address: address as u64,
size: data.len() as u8,
opcode: u16::MAX,
branch_dest: None,
});
break;
}
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(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 {
let (opcode, branch_dest) = match ins {
unarm::Ins::Arm(x) => {
let opcode = x.op as u16 | (1 << 15);
let branch_dest = match x.op {
arm::Opcode::B | arm::Opcode::Bl => {
address.checked_add_signed(ins.field_branch_offset())
address.checked_add_signed(x.field_branch_offset())
}
arm::Opcode::BlxI => address.checked_add_signed(ins.field_blx_offset()),
arm::Opcode::BlxI => address.checked_add_signed(x.field_blx_offset()),
_ => None,
};
(opcode, branch_dest)
}
unarm::ParseMode::Thumb => {
let ins = thumb::Ins::new(code, &parse_flags);
let opcode = ins.op as u16;
let branch_dest = match ins.op {
unarm::Ins::Thumb(x) => {
let opcode = x.op as u16;
let branch_dest = match x.op {
thumb::Opcode::B | thumb::Opcode::Bl => {
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
}
address.checked_add_signed(x.field_branch_offset_8())
}
thumb::Opcode::BLong => {
address.checked_add_signed(ins.field_branch_offset_11())
address.checked_add_signed(x.field_branch_offset_11())
}
_ => None,
};
(opcode, branch_dest)
}
unarm::ParseMode::Data => (u16::MAX, None),
unarm::Ins::Data => (u16::MAX, None),
};
ops.push(InstructionRef {
address: address as u64,
size: ins_size as u8,
opcode,
ops.push(ScannedInstruction {
ins_ref: InstructionRef { address: address as u64, size: size as u8, opcode },
branch_dest: branch_dest.map(|x| x as u64),
});
address += ins_size as u32;
}
Ok(ops)
@ -345,7 +260,6 @@ impl Arch for ArchArm {
cb(InstructionPart::reloc())?;
} else {
push_args(
ins,
&parsed_ins,
resolved.relocation,
resolved.ins_ref.address as u32,
@ -444,12 +358,16 @@ impl Arch for ArchArm {
}
fn symbol_address(&self, address: u64, kind: SymbolKind) -> u64 {
if kind == SymbolKind::Function { address & !1 } else { address }
if kind == SymbolKind::Function {
address & !1
} else {
address
}
}
fn extra_symbol_flags(&self, symbol: &object::Symbol) -> SymbolFlagSet {
let mut flags = SymbolFlagSet::default();
if DisasmMode::from_object_symbol(symbol).is_some() {
if DisasmMode::from_symbol(symbol).is_some() {
flags |= SymbolFlag::Hidden;
}
flags
@ -463,21 +381,15 @@ struct DisasmMode {
}
impl DisasmMode {
fn from_object_symbol<'a>(sym: &object::Symbol<'a, '_, &'a [u8]>) -> Option<Self> {
fn from_symbol<'a>(sym: &object::Symbol<'a, '_, &'a [u8]>) -> Option<Self> {
sym.name()
.ok()
.and_then(unarm::ParseMode::from_mapping_symbol)
.map(|mapping| DisasmMode { address: sym.address() as u32, mapping })
}
fn from_symbol(sym: &Symbol) -> Option<Self> {
unarm::ParseMode::from_mapping_symbol(&sym.name)
.map(|mapping| DisasmMode { address: sym.address as u32, mapping })
}
}
fn push_args(
ins: unarm::Ins,
parsed_ins: &unarm::ParsedIns,
relocation: Option<ResolvedRelocation>,
cur_addr: u32,
@ -487,7 +399,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 {
@ -559,19 +471,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) => {
@ -623,14 +535,6 @@ fn push_args(
arg_cb(InstructionPart::opaque("!"))?;
}
}
let branch_dest = get_pc_relative_load_address(ins, cur_addr);
if let Some(branch_dest) = branch_dest {
arg_cb(InstructionPart::basic(" (->"))?;
arg_cb(InstructionPart::branch_dest(branch_dest))?;
arg_cb(InstructionPart::basic(")"))?;
}
Ok(())
}
@ -658,21 +562,3 @@ fn find_reloc_arg(
None
}
}
fn get_pc_relative_load_address(ins: unarm::Ins, address: u32) -> Option<u32> {
match ins {
unarm::Ins::Arm(ins)
if ins.op == arm::Opcode::Ldr
&& ins.modifier_addr_ldr_str() == arm::AddrLdrStr::Imm
&& ins.field_rn_deref().reg == args::Register::Pc =>
{
let offset = ins.field_offset_12().value;
Some(address.wrapping_add_signed(offset + 8))
}
unarm::Ins::Thumb(ins) if ins.op == thumb::Opcode::LdrPc => {
let offset = ins.field_rel_immed_8().value;
Some((address & !3).wrapping_add_signed(offset + 4))
}
_ => None,
}
}

View File

@ -5,7 +5,7 @@ use alloc::{
};
use core::cmp::Ordering;
use anyhow::{Result, bail};
use anyhow::{bail, Result};
use object::elf;
use yaxpeax_arch::{Arch as YaxpeaxArch, Decoder, Reader, U8Reader};
use yaxpeax_arm::armv8::a64::{
@ -15,9 +15,10 @@ use yaxpeax_arm::armv8::a64::{
use crate::{
arch::Arch,
diff::{DiffObjConfig, display::InstructionPart},
diff::{display::InstructionPart, DiffObjConfig},
obj::{
InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
ScannedInstruction,
},
};
@ -29,16 +30,15 @@ impl ArchArm64 {
}
impl Arch for ArchArm64 {
fn scan_instructions_internal(
fn scan_instructions(
&self,
address: u64,
code: &[u8],
_section_index: usize,
_relocations: &[Relocation],
_diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
) -> Result<Vec<ScannedInstruction>> {
let start_address = address;
let mut ops = Vec::<InstructionRef>::with_capacity(code.len() / 4);
let mut ops = Vec::<ScannedInstruction>::with_capacity(code.len() / 4);
let mut reader = U8Reader::new(code);
let decoder = InstDecoder::default();
@ -57,10 +57,8 @@ impl Arch for ArchArm64 {
DecodeError::InvalidOpcode
| DecodeError::InvalidOperand
| DecodeError::IncompleteDecoder => {
ops.push(InstructionRef {
address,
size: 4,
opcode: u16::MAX,
ops.push(ScannedInstruction {
ins_ref: InstructionRef { address, size: 4, opcode: u16::MAX },
branch_dest: None,
});
continue;
@ -69,9 +67,9 @@ impl Arch for ArchArm64 {
}
let opcode = opcode_to_u16(ins.opcode);
let branch_dest =
branch_dest(opcode, address, &code[offset as usize..offset as usize + 4]);
ops.push(InstructionRef { address, size: 4, opcode, branch_dest });
let ins_ref = InstructionRef { address, size: 4, opcode };
let branch_dest = branch_dest(ins_ref, &code[offset as usize..offset as usize + 4]);
ops.push(ScannedInstruction { ins_ref, branch_dest });
}
Ok(ops)
@ -164,7 +162,7 @@ impl Arch for ArchArm64 {
}
}
fn branch_dest(opcode: u16, address: u64, code: &[u8]) -> Option<u64> {
fn branch_dest(ins_ref: InstructionRef, code: &[u8]) -> Option<u64> {
const OPCODE_B: u16 = opcode_to_u16(Opcode::B);
const OPCODE_BL: u16 = opcode_to_u16(Opcode::BL);
const OPCODE_BCC: u16 = opcode_to_u16(Opcode::Bcc(0));
@ -174,21 +172,21 @@ fn branch_dest(opcode: u16, address: u64, code: &[u8]) -> Option<u64> {
const OPCODE_TBNZ: u16 = opcode_to_u16(Opcode::TBNZ);
let word = u32::from_le_bytes(code.try_into().ok()?);
match opcode {
match ins_ref.opcode {
OPCODE_B | OPCODE_BL => {
let offset = ((word & 0x03ff_ffff) << 2) as i32;
let extended_offset = (offset << 4) >> 4;
address.checked_add_signed(extended_offset as i64)
ins_ref.address.checked_add_signed(extended_offset as i64)
}
OPCODE_BCC | OPCODE_CBZ | OPCODE_CBNZ => {
let offset = (word as i32 & 0x00ff_ffe0) >> 3;
let extended_offset = (offset << 11) >> 11;
address.checked_add_signed(extended_offset as i64)
ins_ref.address.checked_add_signed(extended_offset as i64)
}
OPCODE_TBZ | OPCODE_TBNZ => {
let offset = (word as i32 & 0x0007_ffe0) >> 3;
let extended_offset = (offset << 16) >> 16;
address.checked_add_signed(extended_offset as i64)
ins_ref.address.checked_add_signed(extended_offset as i64)
}
_ => None,
}
@ -218,7 +216,11 @@ where Cb: FnMut(InstructionPart<'static>) {
unreachable!("movn operand 1 is always ImmShift");
};
let imm = if let Operand::Register(size, _) = ins.operands[0] {
if size == SizeCode::W { imm as u32 as u64 } else { imm }
if size == SizeCode::W {
imm as u32 as u64
} else {
imm
}
} else {
unreachable!("movn operand 0 is always Register");
};
@ -235,7 +237,11 @@ where Cb: FnMut(InstructionPart<'static>) {
unreachable!("movz operand is always ImmShift");
};
let imm = if let Operand::Register(size, _) = ins.operands[0] {
if size == SizeCode::W { imm as u32 as u64 } else { imm }
if size == SizeCode::W {
imm as u32 as u64
} else {
imm
}
} else {
unreachable!("movz operand 0 is always Register");
};
@ -568,7 +574,11 @@ where Cb: FnMut(InstructionPart<'static>) {
{
if immr < imms {
let size = if let Operand::Register(size, _) = ins.operands[0] {
if size == SizeCode::W { 32 } else { 64 }
if size == SizeCode::W {
32
} else {
64
}
} else {
unreachable!("operand 0 is always a register");
};

View File

@ -1,24 +1,21 @@
use alloc::{
collections::{BTreeMap, BTreeSet},
string::{String, ToString},
vec::Vec,
};
use alloc::{collections::BTreeMap, string::ToString, vec::Vec};
use core::ops::Range;
use anyhow::{Result, bail};
use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf};
use anyhow::{bail, Result};
use object::{elf, Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _};
use rabbitizer::{
IsaExtension, IsaVersion, Vram,
abi::Abi,
operands::{IU16, ValuedOperand},
operands::{ValuedOperand, IU16},
registers_meta::Register,
IsaExtension, IsaVersion, Vram,
};
use crate::{
arch::Arch,
diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart},
diff::{display::InstructionPart, DiffObjConfig, MipsAbi, MipsInstrCategory},
obj::{
InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags,
ResolvedInstructionRef, ResolvedRelocation, SymbolFlag, SymbolFlagSet,
ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction,
},
};
@ -29,7 +26,6 @@ pub struct ArchMips {
pub isa_extension: Option<IsaExtension>,
pub ri_gp_value: i32,
pub paired_relocations: Vec<BTreeMap<u64, i64>>,
pub ignored_symbols: BTreeSet<usize>,
}
const EF_MIPS_ABI: u32 = 0x0000F000;
@ -122,25 +118,7 @@ impl ArchMips {
paired_relocations[section_index] = addends;
}
let mut ignored_symbols = BTreeSet::new();
for obj_symbol in object.symbols() {
let Ok(name) = obj_symbol.name() else { continue };
if let Some(prefix) = name.strip_suffix(".NON_MATCHING") {
ignored_symbols.insert(obj_symbol.index().0);
if let Some(target_symbol) = object.symbol_by_name(prefix) {
ignored_symbols.insert(target_symbol.index().0);
}
}
}
Ok(Self {
endianness,
abi,
isa_extension,
ri_gp_value,
paired_relocations,
ignored_symbols,
})
Ok(Self { endianness, abi, isa_extension, ri_gp_value, paired_relocations })
}
fn instruction_flags(&self, diff_config: &DiffObjConfig) -> rabbitizer::InstructionFlags {
@ -166,11 +144,9 @@ impl ArchMips {
fn instruction_display_flags(
&self,
diff_config: &DiffObjConfig,
_diff_config: &DiffObjConfig,
) -> rabbitizer::InstructionDisplayFlags {
rabbitizer::InstructionDisplayFlags::default()
.with_unknown_instr_comment(false)
.with_use_dollar(diff_config.mips_register_prefix)
rabbitizer::InstructionDisplayFlags::default().with_unknown_instr_comment(false)
}
fn parse_ins_ref(
@ -188,16 +164,15 @@ impl ArchMips {
}
impl Arch for ArchMips {
fn scan_instructions_internal(
fn scan_instructions(
&self,
address: u64,
code: &[u8],
_section_index: usize,
_relocations: &[Relocation],
diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
) -> Result<Vec<ScannedInstruction>> {
let instruction_flags = self.instruction_flags(diff_config);
let mut ops = Vec::<InstructionRef>::with_capacity(code.len() / 4);
let mut ops = Vec::<ScannedInstruction>::with_capacity(code.len() / 4);
let mut cur_addr = address as u32;
for chunk in code.chunks_exact(4) {
let code = self.endianness.read_u32_bytes(chunk.try_into()?);
@ -205,7 +180,10 @@ impl Arch for ArchMips {
rabbitizer::Instruction::new(code, Vram::new(cur_addr), instruction_flags);
let opcode = instruction.opcode() as u16;
let branch_dest = instruction.get_branch_vram_generic().map(|v| v.inner() as u64);
ops.push(InstructionRef { address: cur_addr as u64, size: 4, opcode, branch_dest });
ops.push(ScannedInstruction {
ins_ref: InstructionRef { address: cur_addr as u64, size: 4, opcode },
branch_dest,
});
cur_addr += 4;
}
Ok(ops)
@ -221,7 +199,17 @@ impl Arch for ArchMips {
let display_flags = self.instruction_display_flags(diff_config);
let opcode = instruction.opcode();
cb(InstructionPart::opcode(opcode.name(), opcode as u16))?;
push_args(&instruction, resolved.relocation, &display_flags, cb)?;
let start_address = resolved.symbol.address;
let function_range = start_address..start_address + resolved.symbol.size;
push_args(
&instruction,
resolved.relocation,
function_range,
resolved.section_index,
&display_flags,
diff_config,
cb,
)?;
Ok(())
}
@ -274,13 +262,6 @@ 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 {
@ -312,20 +293,15 @@ impl Arch for ArchMips {
_ => 1,
}
}
fn extra_symbol_flags(&self, symbol: &object::Symbol) -> SymbolFlagSet {
let mut flags = SymbolFlagSet::default();
if self.ignored_symbols.contains(&symbol.index().0) {
flags |= SymbolFlag::Ignored;
}
flags
}
}
fn push_args(
instruction: &rabbitizer::Instruction,
relocation: Option<ResolvedRelocation>,
function_range: Range<u64>,
section_index: usize,
display_flags: &rabbitizer::InstructionDisplayFlags,
diff_config: &DiffObjConfig,
mut arg_cb: impl FnMut(InstructionPart) -> Result<()>,
) -> Result<()> {
let operands = instruction.valued_operands_iter();
@ -347,7 +323,23 @@ fn push_args(
}
ValuedOperand::core_label(..) | ValuedOperand::core_branch_target_label(..) => {
if let Some(resolved) = relocation {
push_reloc(resolved.relocation, &mut arg_cb)?;
// If the relocation target is within the current function, we can
// convert it into a relative branch target. Note that we check
// target_address > start_address instead of >= so that recursive
// tail calls are not considered branch targets.
let target_address =
resolved.symbol.address.checked_add_signed(resolved.relocation.addend);
if resolved.symbol.section == Some(section_index)
&& target_address.is_some_and(|addr| {
addr > function_range.start && addr < function_range.end
})
{
// TODO move this logic up a level
let target_address = target_address.unwrap();
arg_cb(InstructionPart::branch_dest(target_address))?;
} else {
push_reloc(resolved.relocation, &mut arg_cb)?;
}
} else if let Some(branch_dest) = instruction
.get_branch_offset_generic()
.map(|o| (instruction.vram() + o).inner() as u64)
@ -369,11 +361,14 @@ fn push_args(
})))?;
}
arg_cb(InstructionPart::basic("("))?;
arg_cb(InstructionPart::opaque(base.either_name(
instruction.flags().abi(),
display_flags.named_gpr(),
!display_flags.use_dollar(),
)))?;
let mut value =
base.either_name(instruction.flags().abi(), display_flags.named_gpr());
if !diff_config.mips_register_prefix {
if let Some(trimmed) = value.strip_prefix('$') {
value = trimmed;
}
}
arg_cb(InstructionPart::opaque(value))?;
arg_cb(InstructionPart::basic(")"))?;
}
// ValuedOperand::r5900_immediate15(..) => match relocation {
@ -387,9 +382,14 @@ fn push_args(
// }
// },
_ => {
arg_cb(InstructionPart::opaque(
op.display(instruction, display_flags, None::<&str>).to_string(),
))?;
let value = op.display(instruction, display_flags, None::<&str>).to_string();
if !diff_config.mips_register_prefix {
if let Some(value) = value.strip_prefix('$') {
arg_cb(InstructionPart::opaque(value))?;
continue;
}
}
arg_cb(InstructionPart::opaque(value))?;
}
}
}

View File

@ -1,18 +1,17 @@
use alloc::{borrow::Cow, boxed::Box, format, string::String, vec::Vec};
use core::{ffi::CStr, fmt, fmt::Debug};
use anyhow::{Result, bail};
use encoding_rs::SHIFT_JIS;
use anyhow::{bail, Result};
use object::Endian as _;
use crate::{
diff::{
DiffObjConfig,
display::{ContextItem, HoverItem, InstructionPart},
DiffObjConfig,
},
obj::{
InstructionArg, InstructionRef, Object, ParsedInstruction, Relocation, RelocationFlags,
ResolvedInstructionRef, ResolvedSymbol, Section, Symbol, SymbolFlagSet, SymbolKind,
InstructionArg, Object, ParsedInstruction, RelocationFlags, ResolvedInstructionRef,
ScannedInstruction, SymbolFlagSet, SymbolKind,
},
util::ReallySigned,
};
@ -25,8 +24,6 @@ pub mod arm64;
pub mod mips;
#[cfg(feature = "ppc")]
pub mod ppc;
#[cfg(feature = "superh")]
pub mod superh;
#[cfg(feature = "x86")]
pub mod x86;
@ -60,23 +57,16 @@ impl fmt::Display for DataType {
impl DataType {
pub fn display_labels(&self, endian: object::Endianness, bytes: &[u8]) -> Vec<String> {
let mut strs = Vec::new();
for (literal, label_override) in self.display_literals(endian, bytes) {
let label = label_override.unwrap_or_else(|| format!("{}", self));
strs.push(format!("{}: {}", label, literal))
for literal in self.display_literals(endian, bytes) {
strs.push(format!("{}: {}", self, literal))
}
strs
}
pub fn display_literals(
&self,
endian: object::Endianness,
bytes: &[u8],
) -> Vec<(String, Option<String>)> {
pub fn display_literals(&self, endian: object::Endianness, bytes: &[u8]) -> Vec<String> {
let mut strs = Vec::new();
if self.required_len().is_some_and(|l| bytes.len() < l) {
log::warn!(
"Failed to display a symbol value for a symbol whose size is too small for instruction referencing it."
);
log::warn!("Failed to display a symbol value for a symbol whose size is too small for instruction referencing it.");
return strs;
}
let mut bytes = bytes;
@ -95,72 +85,56 @@ impl DataType {
match self {
DataType::Int8 => {
let i = i8::from_ne_bytes(bytes.try_into().unwrap());
strs.push((format!("{:#x}", i), None));
strs.push(format!("{:#x}", i));
if i < 0 {
strs.push((format!("{:#x}", ReallySigned(i)), None));
strs.push(format!("{:#x}", ReallySigned(i)));
}
}
DataType::Int16 => {
let i = endian.read_i16_bytes(bytes.try_into().unwrap());
strs.push((format!("{:#x}", i), None));
strs.push(format!("{:#x}", i));
if i < 0 {
strs.push((format!("{:#x}", ReallySigned(i)), None));
strs.push(format!("{:#x}", ReallySigned(i)));
}
}
DataType::Int32 => {
let i = endian.read_i32_bytes(bytes.try_into().unwrap());
strs.push((format!("{:#x}", i), None));
strs.push(format!("{:#x}", i));
if i < 0 {
strs.push((format!("{:#x}", ReallySigned(i)), None));
strs.push(format!("{:#x}", ReallySigned(i)));
}
}
DataType::Int64 => {
let i = endian.read_i64_bytes(bytes.try_into().unwrap());
strs.push((format!("{:#x}", i), None));
strs.push(format!("{:#x}", i));
if i < 0 {
strs.push((format!("{:#x}", ReallySigned(i)), None));
strs.push(format!("{:#x}", ReallySigned(i)));
}
}
DataType::Float => {
let bytes: [u8; 4] = bytes.try_into().unwrap();
strs.push((
format!("{:?}f", match endian {
object::Endianness::Little => f32::from_le_bytes(bytes),
object::Endianness::Big => f32::from_be_bytes(bytes),
}),
None,
));
strs.push(format!("{:?}f", match endian {
object::Endianness::Little => f32::from_le_bytes(bytes),
object::Endianness::Big => f32::from_be_bytes(bytes),
}));
}
DataType::Double => {
let bytes: [u8; 8] = bytes.try_into().unwrap();
strs.push((
format!("{:?}", match endian {
object::Endianness::Little => f64::from_le_bytes(bytes),
object::Endianness::Big => f64::from_be_bytes(bytes),
}),
None,
));
strs.push(format!("{:?}", match endian {
object::Endianness::Little => f64::from_le_bytes(bytes),
object::Endianness::Big => f64::from_be_bytes(bytes),
}));
}
DataType::Bytes => {
strs.push((format!("{:#?}", bytes), None));
strs.push(format!("{:#?}", bytes));
}
DataType::String => {
if let Ok(cstr) = CStr::from_bytes_until_nul(bytes) {
strs.push((format!("{:?}", cstr), None));
}
if let Some(nul_idx) = bytes.iter().position(|&c| c == b'\0') {
let (cow, _, had_errors) = SHIFT_JIS.decode(&bytes[..nul_idx]);
if !had_errors {
let str = format!("{:?}", cow);
// Only add the Shift JIS string if it's different from the ASCII string.
if !strs.iter().any(|x| x.0 == str) {
strs.push((str, Some("Shift JIS".into())));
}
}
strs.push(format!("{:?}", cstr));
}
}
}
@ -182,108 +156,42 @@ impl DataType {
}
}
impl dyn Arch {
pub trait Arch: Send + Sync + Debug {
/// Generate a list of instructions references (offset, size, opcode) from the given code.
///
/// See [`scan_instructions_internal`] for more details.
pub fn scan_instructions(
/// The opcode IDs are used to generate the initial diff. Implementations should do as little
/// parsing as possible here: just enough to identify the base instruction opcode, size, and
/// possible branch destination (for visual representation). As needed, instructions are parsed
/// via `process_instruction` to compare their arguments.
fn scan_instructions(
&self,
resolved: ResolvedSymbol,
address: u64,
code: &[u8],
section_index: usize,
diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
let mut result = self.scan_instructions_internal(
resolved.symbol.address,
resolved.data,
resolved.section_index,
&resolved.section.relocations,
diff_config,
)?;
let function_start = resolved.symbol.address;
let function_end = function_start + resolved.symbol.size;
// Remove any branch destinations that are outside the function range
for ins in result.iter_mut() {
if let Some(branch_dest) = ins.branch_dest {
if branch_dest < function_start || branch_dest >= function_end {
ins.branch_dest = None;
}
}
}
// Resolve relocation targets within the same function to branch destinations
let mut ins_iter = result.iter_mut().peekable();
'outer: for reloc in resolved
.section
.relocations
.iter()
.skip_while(|r| r.address < function_start)
.take_while(|r| r.address < function_end)
{
let ins = loop {
let Some(ins) = ins_iter.peek_mut() else {
break 'outer;
};
if reloc.address < ins.address {
continue 'outer;
}
let ins = ins_iter.next().unwrap();
if reloc.address >= ins.address && reloc.address < ins.address + ins.size as u64 {
break ins;
}
};
// Clear existing branch destination for instructions with relocations
ins.branch_dest = None;
let Some(target) = resolved.obj.symbols.get(reloc.target_symbol) else {
continue;
};
if target.section != Some(resolved.section_index) {
continue;
}
let Some(target_address) = target.address.checked_add_signed(reloc.addend) else {
continue;
};
// If the target address is within the function range, set it as a branch destination
if target_address >= function_start && target_address < function_end {
ins.branch_dest = Some(target_address);
}
}
Ok(result)
}
) -> Result<Vec<ScannedInstruction>>;
/// Parse an instruction to gather its mnemonic and arguments for more detailed comparison.
///
/// This is called only when we need to compare the arguments of an instruction.
pub fn process_instruction(
fn process_instruction(
&self,
resolved: ResolvedInstructionRef,
diff_config: &DiffObjConfig,
) -> Result<ParsedInstruction> {
let mut mnemonic = None;
let mut args = Vec::with_capacity(8);
let mut relocation_emitted = false;
self.display_instruction(resolved, diff_config, &mut |part| {
match part {
InstructionPart::Opcode(m, _) => mnemonic = Some(Cow::Owned(m.into_owned())),
InstructionPart::Arg(arg) => {
if arg == InstructionArg::Reloc {
relocation_emitted = true;
// If the relocation was resolved to a branch destination, emit that instead.
if let Some(dest) = resolved.ins_ref.branch_dest {
args.push(InstructionArg::BranchDest(dest));
return Ok(());
}
}
args.push(arg.into_static());
}
InstructionPart::Arg(arg) => args.push(arg.into_static()),
_ => {}
}
Ok(())
})?;
// If the instruction has a relocation, but we didn't format it in the display, add it to
// the end of the arguments list.
if resolved.relocation.is_some() && !relocation_emitted {
if resolved.relocation.is_some() && !args.contains(&InstructionArg::Reloc) {
args.push(InstructionArg::Reloc);
}
Ok(ParsedInstruction {
@ -292,26 +200,6 @@ impl dyn Arch {
args,
})
}
}
pub trait Arch: Send + Sync + Debug {
/// Finishes arch-specific initialization that must be done after sections have been combined.
fn post_init(&mut self, _sections: &[Section], _symbols: &[Symbol]) {}
/// Generate a list of instructions references (offset, size, opcode) from the given code.
///
/// The opcode IDs are used to generate the initial diff. Implementations should do as little
/// parsing as possible here: just enough to identify the base instruction opcode, size, and
/// possible branch destination (for visual representation). As needed, instructions are parsed
/// via `process_instruction` to compare their arguments.
fn scan_instructions_internal(
&self,
address: u64,
code: &[u8],
section_index: usize,
relocations: &[Relocation],
diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>>;
/// Format an instruction for display.
///
@ -324,17 +212,6 @@ pub trait Arch: Send + Sync + Debug {
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
) -> Result<()>;
/// Generate a list of fake relocations from the given code that represent pooled data accesses.
fn generate_pooled_relocations(
&self,
_address: u64,
_code: &[u8],
_relocations: &[Relocation],
_symbols: &[Symbol],
) -> Vec<Relocation> {
Vec::new()
}
fn implcit_addend(
&self,
file: &object::File<'_>,
@ -356,13 +233,7 @@ pub trait Arch: Send + Sync + Debug {
SymbolFlagSet::default()
}
fn guess_data_type(
&self,
_resolved: ResolvedInstructionRef,
_bytes: &[u8],
) -> Option<DataType> {
None
}
fn guess_data_type(&self, _resolved: ResolvedInstructionRef) -> Option<DataType> { None }
fn symbol_hover(&self, _obj: &Object, _symbol_index: usize) -> Vec<HoverItem> { Vec::new() }
@ -400,8 +271,6 @@ pub fn new_arch(object: &object::File) -> Result<Box<dyn Arch>> {
object::Architecture::Arm => Box::new(arm::ArchArm::new(object)?),
#[cfg(feature = "arm64")]
object::Architecture::Aarch64 => Box::new(arm64::ArchArm64::new(object)?),
#[cfg(feature = "superh")]
object::Architecture::SuperH => Box::new(superh::ArchSuperH::new(object)?),
arch => bail!("Unsupported architecture: {arch:?}"),
})
}
@ -414,14 +283,13 @@ impl ArchDummy {
}
impl Arch for ArchDummy {
fn scan_instructions_internal(
fn scan_instructions(
&self,
_address: u64,
_code: &[u8],
_section_index: usize,
_relocations: &[Relocation],
_diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
) -> Result<Vec<ScannedInstruction>> {
Ok(Vec::new())
}

View File

@ -1,25 +1,24 @@
use alloc::{
collections::{BTreeMap, BTreeSet},
collections::BTreeMap,
string::{String, ToString},
vec,
vec::Vec,
};
use anyhow::{Result, bail, ensure};
use cwextab::{ExceptionTableData, decode_extab};
use anyhow::{bail, ensure, Result};
use cwextab::{decode_extab, ExceptionTableData};
use flagset::Flags;
use object::{Object as _, ObjectSection as _, ObjectSymbol as _, elf};
use object::{elf, Object as _, ObjectSection as _, ObjectSymbol as _};
use crate::{
arch::{Arch, DataType},
diff::{
DiffObjConfig,
data::resolve_relocation,
display::{ContextItem, HoverItem, HoverItemColor, InstructionPart, SymbolNavigationKind},
DiffObjConfig,
},
obj::{
InstructionRef, Object, Relocation, RelocationFlags, ResolvedInstructionRef,
ResolvedRelocation, Symbol, SymbolFlag, SymbolFlagSet,
ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolFlagSet,
},
};
@ -82,22 +81,23 @@ impl ArchPpc {
}
impl Arch for ArchPpc {
fn scan_instructions_internal(
fn scan_instructions(
&self,
address: u64,
code: &[u8],
_section_index: usize,
_relocations: &[Relocation],
_diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
) -> Result<Vec<ScannedInstruction>> {
ensure!(code.len() & 3 == 0, "Code length must be a multiple of 4");
let ins_count = code.len() / 4;
let mut insts = Vec::<InstructionRef>::with_capacity(ins_count);
let mut insts = Vec::<ScannedInstruction>::with_capacity(ins_count);
for (cur_addr, ins) in ppc750cl::InsIter::new(code, address as u32) {
insts.push(InstructionRef {
address: cur_addr as u64,
size: 4,
opcode: u8::from(ins.op) as u16,
insts.push(ScannedInstruction {
ins_ref: InstructionRef {
address: cur_addr as u64,
size: 4,
opcode: u8::from(ins.op) as u16,
},
branch_dest: ins.branch_dest(cur_addr).map(u64::from),
});
}
@ -157,16 +157,6 @@ impl Arch for ArchPpc {
Ok(())
}
fn generate_pooled_relocations(
&self,
address: u64,
code: &[u8],
relocations: &[Relocation],
symbols: &[Symbol],
) -> Vec<Relocation> {
generate_fake_pool_relocations_for_function(address, code, relocations, symbols)
}
fn implcit_addend(
&self,
_file: &object::File<'_>,
@ -219,21 +209,12 @@ impl Arch for ArchPpc {
}
}
fn guess_data_type(&self, resolved: ResolvedInstructionRef, bytes: &[u8]) -> Option<DataType> {
fn guess_data_type(&self, resolved: ResolvedInstructionRef) -> Option<DataType> {
if resolved.relocation.is_some_and(|r| r.symbol.name.starts_with("@stringBase")) {
// Pooled string.
return Some(DataType::String);
}
let opcode = ppc750cl::Opcode::from(resolved.ins_ref.opcode as u8);
if let Some(ty) = guess_data_type_from_load_store_inst_op(opcode) {
// Numeric type.
return Some(ty);
}
if bytes.len() >= 2 && bytes.iter().position(|&c| c == b'\0') == Some(bytes.len() - 1) {
// It may be an unpooled string if the symbol contains exactly one null byte at the end of the symbol.
return Some(DataType::String);
}
None
guess_data_type_from_load_store_inst_op(opcode)
}
fn symbol_hover(&self, _obj: &Object, symbol_index: usize) -> Vec<HoverItem> {
@ -456,7 +437,7 @@ fn decode_exception_info(
log::warn!(
"Exception table decoding failed for function {}, reason: {}",
extab_func_name,
e
e.to_string()
);
return Ok(None);
}
@ -520,27 +501,21 @@ 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,
addr_dst_gpr: Option<ppc750cl::GPR>,
}
// Given an instruction, check if it could be accessing pooled data at the address in a register.
// If so, return information pertaining to where the instruction is getting that address from and
// what it's doing with the address (e.g. copying it into another register, adding an offset, etc).
fn get_pool_reference_for_inst(
// Given an instruction, determine if it could accessing data at the address in a register.
// If so, return the offset added to the register's address, the register containing that address,
// and (optionally) which destination register the address is being copied into.
#[expect(unused)]
fn get_offset_and_addr_gpr_for_possible_pool_reference(
opcode: ppc750cl::Opcode,
simplified: &ppc750cl::ParsedIns,
) -> Option<PoolReference> {
) -> Option<(i16, ppc750cl::GPR, Option<ppc750cl::GPR>)> {
use ppc750cl::{Argument, Opcode};
let args = &simplified.args;
if guess_data_type_from_load_store_inst_op(opcode).is_some() {
match (args[1], args[2]) {
(Argument::Offset(offset), Argument::GPR(addr_src_gpr)) => {
// e.g. lwz. Immediate offset.
Some(PoolReference { addr_src_gpr, addr_offset: offset.0, addr_dst_gpr: None })
Some((offset.0, addr_src_gpr, None))
}
(Argument::GPR(addr_src_gpr), Argument::GPR(_offset_gpr)) => {
// e.g. lwzx. The offset is in a register and was likely calculated from an index.
@ -548,7 +523,7 @@ fn get_pool_reference_for_inst(
// It may be possible to show all elements by figuring out the stride of the array
// from the calculations performed on the index before it's put into offset_gpr, but
// this would be much more complicated, so it's not currently done.
Some(PoolReference { addr_src_gpr, addr_offset: 0, addr_dst_gpr: None })
Some((0, addr_src_gpr, None))
}
_ => None,
}
@ -566,32 +541,20 @@ fn get_pool_reference_for_inst(
Argument::GPR(addr_dst_gpr),
Argument::GPR(addr_src_gpr),
Argument::Simm(simm),
) => Some(PoolReference {
addr_src_gpr,
addr_offset: simm.0,
addr_dst_gpr: Some(addr_dst_gpr),
}),
) => Some((simm.0, addr_src_gpr, Some(addr_dst_gpr))),
(
// `mr` or `mr.`
Opcode::Or,
Argument::GPR(addr_dst_gpr),
Argument::GPR(addr_src_gpr),
Argument::None,
) => Some(PoolReference {
addr_src_gpr,
addr_offset: 0,
addr_dst_gpr: Some(addr_dst_gpr),
}),
) => Some((0, addr_src_gpr, Some(addr_dst_gpr))),
(
Opcode::Add,
Argument::GPR(addr_dst_gpr),
Argument::GPR(addr_src_gpr),
Argument::GPR(_offset_gpr),
) => Some(PoolReference {
addr_src_gpr,
addr_offset: 0,
addr_dst_gpr: Some(addr_dst_gpr),
}),
) => Some((0, addr_src_gpr, Some(addr_dst_gpr))),
_ => None,
}
}
@ -599,6 +562,7 @@ fn get_pool_reference_for_inst(
// Remove the relocation we're keeping track of in a particular register when an instruction reuses
// that register to hold some other value, unrelated to pool relocation addresses.
#[expect(unused)]
fn clear_overwritten_gprs(ins: ppc750cl::Ins, gpr_pool_relocs: &mut BTreeMap<u8, Relocation>) {
use ppc750cl::{Argument, Arguments, Opcode};
let mut def_args = Arguments::default();
@ -618,238 +582,250 @@ fn clear_overwritten_gprs(ins: ppc750cl::Ins, gpr_pool_relocs: &mut BTreeMap<u8,
}
}
// We create a fake relocation for an instruction, vaguely simulating what the actual relocation
// might have looked like if it wasn't pooled. This is so minimal changes are needed to display
// pooled accesses vs non-pooled accesses. We set the relocation type to R_PPC_NONE to indicate that
// there isn't really a relocation here, as copying the pool relocation's type wouldn't make sense.
// Also, if this instruction is accessing the middle of a symbol instead of the start, we add an
// addend to indicate that.
fn make_fake_pool_reloc(
offset: i16,
cur_addr: u32,
pool_reloc: &Relocation,
symbols: &[Symbol],
) -> Option<Relocation> {
let pool_reloc = resolve_relocation(symbols, pool_reloc);
let offset_from_pool = pool_reloc.relocation.addend + offset as i64;
let target_address = pool_reloc.symbol.address.checked_add_signed(offset_from_pool)?;
let target_symbol;
let addend;
if let Some(section_index) = pool_reloc.symbol.section {
// Find the exact data symbol within the pool being accessed here based on the address.
target_symbol = symbols.iter().position(|s| {
s.section == Some(section_index)
&& s.size > 0
&& (s.address..s.address + s.size).contains(&target_address)
})?;
addend = target_address.checked_sub(symbols[target_symbol].address)? as i64;
} else {
// If the target symbol is in a different object (extern), we simply copy the pool
// relocation's target. This is because it's not possible to locate the actual symbol if
// it's extern. And doing that for external symbols would also be unnecessary, because when
// the compiler generates an instruction that accesses an external "pool" plus some offset,
// that won't be a normal pool that contains other symbols within it that we want to
// display. It will be something like a vtable for a class with multiple inheritance (for
// 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 = offset_from_pool;
}
Some(Relocation {
flags: RelocationFlags::Elf(elf::R_PPC_NONE),
address: cur_addr as u64,
target_symbol,
addend,
})
}
// Searches through all instructions in a function, determining which registers have the addresses
// of pooled data relocations in them, finding which instructions load data from those addresses,
// and returns a Vec of "fake pool relocations" that simulate what a relocation for that instruction
// would look like if data hadn't been pooled.
// This method tries to follow the function's proper control flow. It keeps track of a queue of
// states it hasn't traversed yet, where each state holds an instruction address and a HashMap of
// which registers hold which pool relocations at that point.
// When a conditional or unconditional branch is encountered, the destination of the branch is added
// to the queue. Conditional branches will traverse both the path where the branch is taken and the
// one where it's not. Unconditional branches only follow the branch, ignoring any code immediately
// after the branch instruction.
// Limitations: This method does not currently read switch statement jump tables.
// Instead, we guess that any parts of a function we missed were switch cases, and traverse them as
// if the last `bctr` before that address had branched there. This should be fairly accurate in
// practice - in testing the only instructions it seems to miss are double branches that the
// compiler generates in error which can never be reached during normal execution anyway.
// It should be possible to implement jump tables properly by reading them out of .data. But this
// will require keeping track of what value is loaded into each register so we can retrieve the jump
// table symbol when we encounter a `bctr`.
fn generate_fake_pool_relocations_for_function(
func_address: u64,
code: &[u8],
relocations: &[Relocation],
symbols: &[Symbol],
) -> Vec<Relocation> {
use ppc750cl::{Argument, InsIter, Opcode};
let mut visited_ins_addrs = BTreeSet::new();
let mut pool_reloc_for_addr = BTreeMap::new();
let mut ins_iters_with_gpr_state =
vec![(InsIter::new(code, func_address as u32), BTreeMap::new())];
let mut gpr_state_at_bctr = BTreeMap::new();
while let Some((ins_iter, mut gpr_pool_relocs)) = ins_iters_with_gpr_state.pop() {
for (cur_addr, ins) in ins_iter {
if visited_ins_addrs.contains(&cur_addr) {
// Avoid getting stuck in an infinite loop when following looping branches.
break;
}
visited_ins_addrs.insert(cur_addr);
let simplified = ins.simplified();
// First handle traversing the function's control flow.
let mut branch_dest = None;
for arg in simplified.args_iter() {
if let Argument::BranchDest(dest) = arg {
let dest = cur_addr.wrapping_add_signed(dest.0);
branch_dest = Some(dest);
break;
}
}
if let Some(branch_dest) = branch_dest {
if branch_dest >= func_address as u32
&& (branch_dest - func_address as u32) < code.len() as u32
{
let dest_offset_into_func = branch_dest - func_address as u32;
let dest_code_slice = &code[dest_offset_into_func as usize..];
match ins.op {
Opcode::Bc => {
// Conditional branch.
// Add the branch destination to the queue to do later.
ins_iters_with_gpr_state.push((
InsIter::new(dest_code_slice, branch_dest),
gpr_pool_relocs.clone(),
));
// Then continue on with the current iterator.
}
Opcode::B => {
if simplified.mnemonic != "bl" {
// Unconditional branch.
// Add the branch destination to the queue.
ins_iters_with_gpr_state.push((
InsIter::new(dest_code_slice, branch_dest),
gpr_pool_relocs.clone(),
));
// Break out of the current iterator so we can do the newly added one.
break;
}
}
_ => unreachable!(),
}
}
}
if let Opcode::Bcctr = ins.op {
if simplified.mnemonic == "bctr" {
// Unconditional branch to count register.
// Likely a jump table.
gpr_state_at_bctr.insert(cur_addr, gpr_pool_relocs.clone());
}
}
// Then handle keeping track of which GPR contains which pool relocation.
let reloc = relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
if let Some(reloc) = reloc {
// This instruction has a real relocation, so it may be a pool load we want to keep
// track of.
let args = &simplified.args;
match (ins.op, args[0], args[1], args[2]) {
(
// `lis` + `addi`
Opcode::Addi,
Argument::GPR(addr_dst_gpr),
Argument::GPR(_addr_src_gpr),
Argument::Simm(_simm),
) => {
gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
}
(
// `lis` + `ori`
Opcode::Ori,
Argument::GPR(addr_dst_gpr),
Argument::GPR(_addr_src_gpr),
Argument::Uimm(_uimm),
) => {
gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
}
(Opcode::B, _, _, _) => {
if simplified.mnemonic == "bl" {
// When encountering a function call, clear any active pool relocations from
// the volatile registers (r0, r3-r12), but not the nonvolatile registers.
gpr_pool_relocs.remove(&0);
for gpr in 3..12 {
gpr_pool_relocs.remove(&gpr);
}
}
}
_ => {
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
}
}
} else if let Some(pool_ref) = get_pool_reference_for_inst(ins.op, &simplified) {
// This instruction doesn't have a real relocation, so it may be a reference to one of
// the already-loaded pools.
if let Some(pool_reloc) = gpr_pool_relocs.get(&pool_ref.addr_src_gpr.0) {
if let Some(fake_pool_reloc) =
make_fake_pool_reloc(pool_ref.addr_offset, cur_addr, pool_reloc, symbols)
{
pool_reloc_for_addr.insert(cur_addr, fake_pool_reloc);
}
if let Some(addr_dst_gpr) = pool_ref.addr_dst_gpr {
// If the address of the pool relocation got copied into another register, we
// need to keep track of it in that register too as future instructions may
// reference the symbol indirectly via this new register, instead of the
// register the symbol's address was originally loaded into.
// For example, the start of the function might `lis` + `addi` the start of the
// ...data pool into r25, and then later the start of a loop will `addi` r25
// with the offset within the .data section of an array variable into r21.
// Then the body of the loop will `lwzx` one of the array elements from r21.
let mut new_reloc = pool_reloc.clone();
new_reloc.addend += pool_ref.addr_offset as i64;
gpr_pool_relocs.insert(addr_dst_gpr.0, new_reloc);
} else {
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
}
} else {
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
}
} else {
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
}
}
// Finally, if we're about to finish the outer loop and don't have any more control flow to
// follow, we check if there are any instruction addresses in this function that we missed.
// If so, and if there were any `bctr` instructions before those points in this function,
// then we try to traverse those missing spots as switch cases.
if ins_iters_with_gpr_state.is_empty() {
let unseen_addrs = (func_address as u32..func_address as u32 + code.len() as u32)
.step_by(4)
.filter(|addr| !visited_ins_addrs.contains(addr));
for unseen_addr in unseen_addrs {
let prev_bctr_gpr_state = gpr_state_at_bctr
.iter()
.filter(|&(&addr, _)| addr < unseen_addr)
.min_by_key(|&(&addr, _)| addr)
.map(|(_, gpr_state)| gpr_state);
if let Some(gpr_pool_relocs) = prev_bctr_gpr_state {
let dest_offset_into_func = unseen_addr - func_address as u32;
let dest_code_slice = &code[dest_offset_into_func as usize..];
ins_iters_with_gpr_state.push((
InsIter::new(dest_code_slice, unseen_addr),
gpr_pool_relocs.clone(),
));
break;
}
}
}
}
pool_reloc_for_addr.values().cloned().collect()
}
// TODO
// // We create a fake relocation for an instruction, vaguely simulating what the actual relocation
// // might have looked like if it wasn't pooled. This is so minimal changes are needed to display
// // pooled accesses vs non-pooled accesses. We set the relocation type to R_PPC_NONE to indicate that
// // there isn't really a relocation here, as copying the pool relocation's type wouldn't make sense.
// // Also, if this instruction is accessing the middle of a symbol instead of the start, we add an
// // addend to indicate that.
// fn make_fake_pool_reloc(offset: i16, cur_addr: u32, pool_reloc: &Relocation) -> Option<Relocation> {
// let offset_from_pool = pool_reloc.addend + offset as i64;
// let target_address = pool_reloc.sy.address.checked_add_signed(offset_from_pool)?;
// let target;
// let addend;
// if pool_reloc.target.orig_section_index.is_some() {
// // If the target symbol is within this current object, then we also need to create a fake
// // target symbol to go inside our fake relocation. This is because we don't have access to
// // list of all symbols in this section, so we can't find the real symbol within the pool
// // based on its address yet. Instead we make a placeholder that has the correct
// // `orig_section_index` and `address` fields, and then later on when this information is
// // displayed to the user, we can find the real symbol by searching through the object's
// // section's symbols for one that contains this address.
// target = ObjSymbol {
// name: "".to_string(),
// demangled_name: None,
// address: target_address,
// section_address: 0,
// size: 0,
// size_known: false,
// kind: Default::default(),
// flags: Default::default(),
// orig_section_index: pool_reloc.target.orig_section_index,
// virtual_address: None,
// original_index: None,
// bytes: vec![],
// };
// // The addend is also fake because we don't know yet if the `target_address` here is the exact
// // start of the symbol or if it's in the middle of it.
// addend = 0;
// } else {
// // But if the target symbol is in a different object (extern), then we simply copy the pool
// // relocation's target. This is because it won't be possible to locate the actual symbol
// // later on based only off of an offset without knowing the object or section it's in. And
// // doing that for external symbols would also be unnecessary, because when the compiler
// // generates an instruction that accesses an external "pool" plus some offset, that won't be
// // a normal pool that contains other symbols within it that we want to display. It will be
// // something like a vtable for a class with multiple inheritance (for 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, no fake symbol to hold an address is necessary.
// target = pool_reloc.target.clone();
// addend = pool_reloc.addend;
// };
// Some(ObjReloc {
// flags: RelocationFlags::Elf { r_type: elf::R_PPC_NONE },
// address: cur_addr as u64,
// target,
// addend,
// })
// }
//
// // Searches through all instructions in a function, determining which registers have the addresses
// // of pooled data relocations in them, finding which instructions load data from those addresses,
// // and constructing a mapping of the address of that instruction to a "fake pool relocation" that
// // simulates what that instruction's relocation would look like if data hadn't been pooled.
// // This method tries to follow the function's proper control flow. It keeps track of a queue of
// // states it hasn't traversed yet, where each state holds an instruction address and a HashMap of
// // which registers hold which pool relocations at that point.
// // When a conditional or unconditional branch is encountered, the destination of the branch is added
// // to the queue. Conditional branches will traverse both the path where the branch is taken and the
// // one where it's not. Unconditional branches only follow the branch, ignoring any code immediately
// // after the branch instruction.
// // Limitations: This method cannot read jump tables. This is because the jump tables are located in
// // the .data section, but ObjArch.process_code only has access to the .text section. In order to
// // work around this limitation and avoid completely missing most code inside switch statements that
// // use jump tables, we instead guess that any parts of a function we missed were switch cases, and
// // traverse them as if the last `bctr` before that address had branched there. This should be fairly
// // accurate in practice - in testing the only instructions it seems to miss are double branches that
// // the compiler generates in error which can never be reached during normal execution anyway.
// fn generate_fake_pool_reloc_for_addr_mapping(
// func_address: u64,
// code: &[u8],
// relocations: &[ObjReloc],
// ) -> BTreeMap<u32, ObjReloc> {
// let mut visited_ins_addrs = BTreeSet::new();
// let mut pool_reloc_for_addr = BTreeMap::new();
// let mut ins_iters_with_gpr_state =
// vec![(InsIter::new(code, func_address as u32), BTreeMap::new())];
// let mut gpr_state_at_bctr = BTreeMap::new();
// while let Some((ins_iter, mut gpr_pool_relocs)) = ins_iters_with_gpr_state.pop() {
// for (cur_addr, ins) in ins_iter {
// if visited_ins_addrs.contains(&cur_addr) {
// // Avoid getting stuck in an infinite loop when following looping branches.
// break;
// }
// visited_ins_addrs.insert(cur_addr);
//
// let simplified = ins.simplified();
//
// // First handle traversing the function's control flow.
// let mut branch_dest = None;
// for arg in simplified.args_iter() {
// if let Argument::BranchDest(dest) = arg {
// let dest = cur_addr.wrapping_add_signed(dest.0);
// branch_dest = Some(dest);
// break;
// }
// }
// if let Some(branch_dest) = branch_dest {
// if branch_dest >= func_address as u32
// && (branch_dest - func_address as u32) < code.len() as u32
// {
// let dest_offset_into_func = branch_dest - func_address as u32;
// let dest_code_slice = &code[dest_offset_into_func as usize..];
// match ins.op {
// Opcode::Bc => {
// // Conditional branch.
// // Add the branch destination to the queue to do later.
// ins_iters_with_gpr_state.push((
// InsIter::new(dest_code_slice, branch_dest),
// gpr_pool_relocs.clone(),
// ));
// // Then continue on with the current iterator.
// }
// Opcode::B => {
// if simplified.mnemonic != "bl" {
// // Unconditional branch.
// // Add the branch destination to the queue.
// ins_iters_with_gpr_state.push((
// InsIter::new(dest_code_slice, branch_dest),
// gpr_pool_relocs.clone(),
// ));
// // Break out of the current iterator so we can do the newly added one.
// break;
// }
// }
// _ => unreachable!(),
// }
// }
// }
// if let Opcode::Bcctr = ins.op {
// if simplified.mnemonic == "bctr" {
// // Unconditional branch to count register.
// // Likely a jump table.
// gpr_state_at_bctr.insert(cur_addr, gpr_pool_relocs.clone());
// }
// }
//
// // Then handle keeping track of which GPR contains which pool relocation.
// let reloc = relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
// if let Some(reloc) = reloc {
// // This instruction has a real relocation, so it may be a pool load we want to keep
// // track of.
// let args = &simplified.args;
// match (ins.op, args[0], args[1], args[2]) {
// (
// // `lis` + `addi`
// Opcode::Addi,
// Argument::GPR(addr_dst_gpr),
// Argument::GPR(_addr_src_gpr),
// Argument::Simm(_simm),
// ) => {
// gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
// }
// (
// // `lis` + `ori`
// Opcode::Ori,
// Argument::GPR(addr_dst_gpr),
// Argument::GPR(_addr_src_gpr),
// Argument::Uimm(_uimm),
// ) => {
// gpr_pool_relocs.insert(addr_dst_gpr.0, reloc.clone());
// }
// (Opcode::B, _, _, _) => {
// if simplified.mnemonic == "bl" {
// // When encountering a function call, clear any active pool relocations from
// // the volatile registers (r0, r3-r12), but not the nonvolatile registers.
// gpr_pool_relocs.remove(&0);
// for gpr in 3..12 {
// gpr_pool_relocs.remove(&gpr);
// }
// }
// }
// _ => {
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
// }
// }
// } else if let Some((offset, addr_src_gpr, addr_dst_gpr)) =
// get_offset_and_addr_gpr_for_possible_pool_reference(ins.op, &simplified)
// {
// // This instruction doesn't have a real relocation, so it may be a reference to one of
// // the already-loaded pools.
// if let Some(pool_reloc) = gpr_pool_relocs.get(&addr_src_gpr.0) {
// if let Some(fake_pool_reloc) =
// make_fake_pool_reloc(offset, cur_addr, pool_reloc)
// {
// pool_reloc_for_addr.insert(cur_addr, fake_pool_reloc);
// }
// if let Some(addr_dst_gpr) = addr_dst_gpr {
// // If the address of the pool relocation got copied into another register, we
// // need to keep track of it in that register too as future instructions may
// // reference the symbol indirectly via this new register, instead of the
// // register the symbol's address was originally loaded into.
// // For example, the start of the function might `lis` + `addi` the start of the
// // ...data pool into r25, and then later the start of a loop will `addi` r25
// // with the offset within the .data section of an array variable into r21.
// // Then the body of the loop will `lwzx` one of the array elements from r21.
// let mut new_reloc = pool_reloc.clone();
// new_reloc.addend += offset as i64;
// gpr_pool_relocs.insert(addr_dst_gpr.0, new_reloc);
// } else {
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
// }
// } else {
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
// }
// } else {
// clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
// }
// }
//
// // Finally, if we're about to finish the outer loop and don't have any more control flow to
// // follow, we check if there are any instruction addresses in this function that we missed.
// // If so, and if there were any `bctr` instructions before those points in this function,
// // then we try to traverse those missing spots as switch cases.
// if ins_iters_with_gpr_state.is_empty() {
// let unseen_addrs = (func_address as u32..func_address as u32 + code.len() as u32)
// .step_by(4)
// .filter(|addr| !visited_ins_addrs.contains(addr));
// for unseen_addr in unseen_addrs {
// let prev_bctr_gpr_state = gpr_state_at_bctr
// .iter()
// .filter(|(&addr, _)| addr < unseen_addr)
// .min_by_key(|(&addr, _)| addr)
// .map(|(_, gpr_state)| gpr_state);
// if let Some(gpr_pool_relocs) = prev_bctr_gpr_state {
// let dest_offset_into_func = unseen_addr - func_address as u32;
// let dest_code_slice = &code[dest_offset_into_func as usize..];
// ins_iters_with_gpr_state.push((
// InsIter::new(dest_code_slice, unseen_addr),
// gpr_pool_relocs.clone(),
// ));
// break;
// }
// }
// }
// }
//
// pool_reloc_for_addr
// }

File diff suppressed because it is too large Load Diff

View File

@ -1,821 +0,0 @@
use alloc::{collections::BTreeMap, format, string::String, vec, vec::Vec};
use anyhow::{Result, bail};
use object::elf;
use crate::{
arch::{Arch, superh::disasm::sh2_disasm},
diff::{DiffObjConfig, display::InstructionPart},
obj::{InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef},
};
pub mod disasm;
#[derive(Debug)]
pub struct ArchSuperH {}
impl ArchSuperH {
pub fn new(_file: &object::File) -> Result<Self> { Ok(Self {}) }
}
struct DataInfo {
address: u64,
size: u32,
}
impl Arch for ArchSuperH {
fn scan_instructions_internal(
&self,
address: u64,
code: &[u8],
_section_index: usize,
_relocations: &[Relocation],
_diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
let mut ops = Vec::<InstructionRef>::with_capacity(code.len() / 2);
let mut offset = address;
for chunk in code.chunks_exact(2) {
let opcode = u16::from_be_bytes(chunk.try_into().unwrap());
let mut parts: Vec<InstructionPart> = vec![];
let resolved: ResolvedInstructionRef = Default::default();
let mut branch_dest: Option<u64> = None;
sh2_disasm(
offset.try_into().unwrap(),
opcode,
true,
&mut parts,
&resolved,
&mut branch_dest,
);
let opcode_enum: u16 = match parts.first() {
Some(InstructionPart::Opcode(_, val)) => *val,
_ => 0,
};
ops.push(InstructionRef { address: offset, size: 2, opcode: opcode_enum, branch_dest });
offset += 2;
}
Ok(ops)
}
fn display_instruction(
&self,
resolved: ResolvedInstructionRef,
_diff_config: &DiffObjConfig,
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
) -> Result<()> {
let opcode = u16::from_be_bytes(resolved.code.try_into().unwrap());
let mut parts: Vec<InstructionPart> = vec![];
let mut branch_dest: Option<u64> = None;
sh2_disasm(0, opcode, true, &mut parts, &resolved, &mut branch_dest);
if let Some(symbol_data) =
resolved.section.data_range(resolved.symbol.address, resolved.symbol.size as usize)
{
// scan for data
// map of instruction offsets to data target offsets
let mut data_offsets = BTreeMap::<u64, DataInfo>::new();
let mut pos: u64 = 0;
for chunk in symbol_data.chunks_exact(2) {
let opcode = u16::from_be_bytes(chunk.try_into().unwrap());
// mov.w
if (opcode & 0xf000) == 0x9000 {
let target = (opcode as u64 & 0xff) * 2 + 4 + pos;
let data_info = DataInfo { address: target, size: 2 };
data_offsets.insert(pos, data_info);
}
// mov.l
else if (opcode & 0xf000) == 0xd000 {
let target = ((opcode as u64 & 0xff) * 4 + 4 + pos) & 0xfffffffc;
let data_info = DataInfo { address: target, size: 4 };
data_offsets.insert(pos, data_info);
}
pos += 2;
}
let pos = resolved.ins_ref.address - resolved.symbol.address;
// add the data info
if let Some(value) = data_offsets.get(&pos) {
if value.size == 2 && value.address as usize + 1 < symbol_data.len() {
let data = u16::from_be_bytes(
symbol_data[value.address as usize..value.address as usize + 2]
.try_into()
.unwrap(),
);
parts.push(InstructionPart::basic(" /* "));
parts.push(InstructionPart::basic("0x"));
parts.push(InstructionPart::basic(format!("{:04X}", data)));
parts.push(InstructionPart::basic(" */"));
} else if value.size == 4 && value.address as usize + 3 < symbol_data.len() {
let data = u32::from_be_bytes(
symbol_data[value.address as usize..value.address as usize + 4]
.try_into()
.unwrap(),
);
parts.push(InstructionPart::basic(" /* "));
parts.push(InstructionPart::basic("0x"));
parts.push(InstructionPart::basic(format!("{:08X}", data)));
parts.push(InstructionPart::basic(" */"));
}
}
}
for part in parts {
cb(part)?;
}
Ok(())
}
fn implcit_addend(
&self,
_file: &object::File<'_>,
_section: &object::Section,
address: u64,
_relocation: &object::Relocation,
flags: RelocationFlags,
) -> Result<i64> {
bail!("Unsupported SuperH implicit relocation {:#x}:{:?}", address, flags)
}
fn demangle(&self, name: &str) -> Option<String> {
cpp_demangle::Symbol::new(name)
.ok()
.and_then(|s| s.demangle(&cpp_demangle::DemangleOptions::default()).ok())
}
fn reloc_name(&self, flags: RelocationFlags) -> Option<&'static str> {
match flags {
RelocationFlags::Elf(r_type) => match r_type {
elf::R_SH_NONE => Some("R_SH_NONE"),
elf::R_SH_DIR32 => Some("R_SH_DIR32"),
elf::R_SH_REL32 => Some("R_SH_REL32"),
elf::R_SH_DIR8WPN => Some("R_SH_DIR8WPN"),
elf::R_SH_IND12W => Some("R_SH_IND12W"),
elf::R_SH_DIR8WPL => Some("R_SH_DIR8WPL"),
elf::R_SH_DIR8WPZ => Some("R_SH_DIR8WPZ"),
elf::R_SH_DIR8BP => Some("R_SH_DIR8BP"),
elf::R_SH_DIR8W => Some("R_SH_DIR8W"),
elf::R_SH_DIR8L => Some("R_SH_DIR8L"),
elf::R_SH_SWITCH16 => Some("R_SH_SWITCH16"),
elf::R_SH_SWITCH32 => Some("R_SH_SWITCH32"),
elf::R_SH_USES => Some("R_SH_USES"),
elf::R_SH_COUNT => Some("R_SH_COUNT"),
elf::R_SH_ALIGN => Some("R_SH_ALIGN"),
elf::R_SH_CODE => Some("R_SH_CODE"),
elf::R_SH_DATA => Some("R_SH_DATA"),
elf::R_SH_LABEL => Some("R_SH_LABEL"),
elf::R_SH_SWITCH8 => Some("R_SH_SWITCH8"),
elf::R_SH_GNU_VTINHERIT => Some("R_SH_GNU_VTINHERIT"),
elf::R_SH_GNU_VTENTRY => Some("R_SH_GNU_VTENTRY"),
elf::R_SH_TLS_GD_32 => Some("R_SH_TLS_GD_32"),
elf::R_SH_TLS_LD_32 => Some("R_SH_TLS_LD_32"),
elf::R_SH_TLS_LDO_32 => Some("R_SH_TLS_LDO_32"),
elf::R_SH_TLS_IE_32 => Some("R_SH_TLS_IE_32"),
elf::R_SH_TLS_LE_32 => Some("R_SH_TLS_LE_32"),
elf::R_SH_TLS_DTPMOD32 => Some("R_SH_TLS_DTPMOD32"),
elf::R_SH_TLS_DTPOFF32 => Some("R_SH_TLS_DTPOFF32"),
elf::R_SH_TLS_TPOFF32 => Some("R_SH_TLS_TPOFF32"),
elf::R_SH_GOT32 => Some("R_SH_GOT32"),
elf::R_SH_PLT32 => Some("R_SH_PLT32"),
elf::R_SH_COPY => Some("R_SH_COPY"),
elf::R_SH_GLOB_DAT => Some("R_SH_GLOB_DAT"),
elf::R_SH_JMP_SLOT => Some("R_SH_JMP_SLOT"),
elf::R_SH_RELATIVE => Some("R_SH_RELATIVE"),
elf::R_SH_GOTOFF => Some("R_SH_GOTOFF"),
elf::R_SH_GOTPC => Some("R_SH_GOTPC"),
_ => None,
},
_ => None,
}
}
fn data_reloc_size(&self, flags: RelocationFlags) -> usize {
match flags {
RelocationFlags::Elf(elf::R_SH_DIR32) => 4,
RelocationFlags::Elf(_) => 1,
_ => 1,
}
}
}
#[cfg(test)]
mod test {
use std::fmt::{self, Display};
use super::*;
use crate::obj::{InstructionArg, Section, SectionData, Symbol};
impl Display for InstructionPart<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InstructionPart::Basic(s) => write!(f, "{}", s),
InstructionPart::Opcode(s, _o) => write!(f, "{} ", s),
InstructionPart::Arg(arg) => write!(f, "{}", arg),
InstructionPart::Separator => write!(f, ", "),
}
}
}
impl Display for InstructionArg<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InstructionArg::Value(v) => write!(f, "{}", v),
InstructionArg::BranchDest(v) => write!(f, "{}", v),
InstructionArg::Reloc => write!(f, "reloc"),
}
}
}
#[test]
fn test_sh2_display_instruction_basic_ops() {
let arch = ArchSuperH {};
let ops: [(u16, &str); 8] = [
(0x0008, "clrt "),
(0x0028, "clrmac "),
(0x0019, "div0u "),
(0x0009, "nop "),
(0x002b, "rte "),
(0x000b, "rts "),
(0x0018, "sett "),
(0x001b, "sleep "),
];
for (opcode, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1000, size: 2, opcode, branch_dest: None },
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_display_instruction_f0ff_ops() {
let arch = ArchSuperH {};
let ops: [(u16, &str); 49] = [
(0x4015, "cmp/pl r0"),
(0x4115, "cmp/pl r1"),
(0x4215, "cmp/pl r2"),
(0x4315, "cmp/pl r3"),
(0x4011, "cmp/pz r0"),
(0x4010, "dt r0"),
(0x0029, "movt r0"),
(0x4004, "rotl r0"),
(0x4005, "rotr r0"),
(0x4024, "rotcl r0"),
(0x4025, "rotcr r0"),
(0x4020, "shal r0"),
(0x4021, "shar r0"),
(0x4000, "shll r0"),
(0x4001, "shlr r0"),
(0x4008, "shll2 r0"),
(0x4009, "shlr2 r0"),
(0x4018, "shll8 r0"),
(0x4019, "shlr8 r0"),
(0x4028, "shll16 r0"),
(0x4029, "shlr16 r0"),
(0x0002, "stc sr, r0"),
(0x0012, "stc gbr, r0"),
(0x0022, "stc vbr, r0"),
(0x000a, "sts mach, r0"),
(0x001a, "sts macl, r0"),
(0x402a, "lds r0, pr"),
(0x401b, "tas.b r0"),
(0x4003, "stc.l sr, @-r0"),
(0x4013, "stc.l gbr, @-r0"),
(0x4023, "stc.l vbr, @-r0"),
(0x4002, "sts.l mach, @-r0"),
(0x4012, "sts.l macl, @-r0"),
(0x4022, "sts.l pr, @-r0"),
(0x400e, "ldc r0, sr"),
(0x401e, "ldc r0, gbr"),
(0x402e, "ldc r0, vbr"),
(0x400a, "lds r0, mach"),
(0x401a, "lds r0, macl"),
(0x402b, "jmp @r0"),
(0x400b, "jsr @r0"),
(0x4007, "ldc.l @r0+, sr"),
(0x4017, "ldc.l @r0+, gbr"),
(0x4027, "ldc.l @r0+, vbr"),
(0x4006, "lds.l @r0+, mach"),
(0x4016, "lds.l @r0+, macl"),
(0x4026, "lds.l @r0+, pr"),
(0x0023, "braf r0"),
(0x0003, "bsrf r0"),
];
for (opcode, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1000, size: 2, opcode, branch_dest: None },
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_display_instructions_f00f() {
let arch = ArchSuperH {};
let ops: [(u16, &str); 54] = [
(0x300c, "add r0, r0"),
(0x300e, "addc r0, r0"),
(0x300f, "addv r0, r0"),
(0x2009, "and r0, r0"),
(0x3000, "cmp/eq r0, r0"),
(0x3002, "cmp/hs r0, r0"),
(0x3003, "cmp/ge r0, r0"),
(0x3006, "cmp/hi r0, r0"),
(0x3007, "cmp/gt r0, r0"),
(0x200c, "cmp/str r0, r0"),
(0x3004, "div1 r0, r0"),
(0x2007, "div0s r0, r0"),
(0x300d, "dmuls.l r0, r0"),
(0x3005, "dmulu.l r0, r0"),
(0x600e, "exts.b r0, r0"),
(0x600f, "exts.w r0, r0"),
(0x600c, "extu.b r0, r0"),
(0x600d, "extu.w r0, r0"),
(0x6003, "mov r0, r0"),
(0x0007, "mul.l r0, r0"),
(0x200f, "muls r0, r0"),
(0x200e, "mulu r0, r0"),
(0x600b, "neg r0, r0"),
(0x600a, "negc r0, r0"),
(0x6007, "not r0, r0"),
(0x200b, "or r0, r0"),
(0x3008, "sub r0, r0"),
(0x300a, "subc r0, r0"),
(0x300b, "subv r0, r0"),
(0x6008, "swap.b r0, r0"),
(0x6009, "swap.w r0, r0"),
(0x2008, "tst r0, r0"),
(0x200a, "xor r0, r0"),
(0x200d, "xtrct r0, r0"),
(0x2000, "mov.b r0, @r0"),
(0x2001, "mov.w r0, @r0"),
(0x2002, "mov.l r0, @r0"),
(0x6000, "mov.b @r0, r0"),
(0x6001, "mov.w @r0, r0"),
(0x6002, "mov.l @r0, r0"),
(0x000f, "mac.l @r0+, @r0+"),
(0x400f, "mac.w @r0+, @r0+"),
(0x6004, "mov.b @r0+, r0"),
(0x6005, "mov.w @r0+, r0"),
(0x6006, "mov.l @r0+, r0"),
(0x2004, "mov.b r0, @-r0"),
(0x2005, "mov.w r0, @-r0"),
(0x2006, "mov.l r0, @-r0"),
(0x0004, "mov.b r0, @(r0, r0)"),
(0x0005, "mov.w r0, @(r0, r0)"),
(0x0006, "mov.l r0, @(r0, r0)"),
(0x000c, "mov.b @(r0, r0), r0"),
(0x000d, "mov.w @(r0, r0), r0"),
(0x000e, "mov.l @(r0, r0), r0"),
];
for (opcode, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1000, size: 2, opcode, branch_dest: None },
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_display_instruction_mov_immediate_offset() {
let arch = ArchSuperH {};
let ops: [(u16, &str); 8] = [
(0x8000, "mov.b r0, @(0x0, r0)"),
(0x8011, "mov.b r0, @(0x1, r1)"),
(0x8102, "mov.w r0, @(0x4, r0)"),
(0x8113, "mov.w r0, @(0x6, r1)"),
(0x8404, "mov.b @(0x4, r0), r0"),
(0x8415, "mov.b @(0x5, r1), r0"),
(0x8506, "mov.w @(0xc, r0), r0"),
(0x8517, "mov.w @(0xe, r1), r0"),
];
for (opcode, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1000, size: 2, opcode, branch_dest: None },
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_display_instruction_gbr_and_branches() {
let arch = ArchSuperH {};
let ops: &[(u16, u32, &str)] = &[
(0xc000, 0x0000, "mov.b r0, @(0x0, gbr)"),
(0xc07f, 0x0000, "mov.b r0, @(0x7f, gbr)"),
(0xc100, 0x0000, "mov.w r0, @(0x0, gbr)"),
(0xc17f, 0x0000, "mov.w r0, @(0xfe, gbr)"),
(0xc200, 0x0000, "mov.l r0, @(0x0, gbr)"),
(0xc27f, 0x0000, "mov.l r0, @(0x1fc, gbr)"),
(0xc400, 0x0000, "mov.b @(0x0, gbr), r0"),
(0xc47f, 0x0000, "mov.b @(0x7f, gbr), r0"),
(0xc500, 0x0000, "mov.w @(0x0, gbr), r0"),
(0xc57f, 0x0000, "mov.w @(0xfe, gbr), r0"),
(0xc600, 0x0000, "mov.l @(0x0, gbr), r0"),
(0xc67f, 0x0000, "mov.l @(0x1fc, gbr), r0"),
(0x8b20, 0x1000, "bf 0x44"),
(0x8b80, 0x1000, "bf 0xffffff04"),
(0x8f10, 0x2000, "bf.s 0x24"),
(0x8f90, 0x2000, "bf.s 0xffffff24"),
(0x8904, 0x3000, "bt 0xc"),
(0x8980, 0x3000, "bt 0xffffff04"),
(0x8d04, 0x4000, "bt.s 0xc"),
(0x8d80, 0x4000, "bt.s 0xffffff04"),
];
for &(opcode, addr, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_display_instruction_mov_l() {
let arch = ArchSuperH {};
let ops: &[(u16, u32, &str)] = &[
// mov.l rX, @(0xXXX, rY)
(0x1000, 0x0000, "mov.l r0, @(0x0, r0)"),
(0x1001, 0x0000, "mov.l r0, @(0x4, r0)"),
(0x100f, 0x0000, "mov.l r0, @(0x3c, r0)"),
(0x101f, 0x0000, "mov.l r1, @(0x3c, r0)"),
// mov.l @(0xXXX, rY), rX
(0x5000, 0x0000, "mov.l @(0x0, r0), r0"),
];
for &(opcode, addr, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_display_instruction_bra_bsr() {
let arch: ArchSuperH = ArchSuperH {};
let ops: &[(u16, u32, &str)] = &[
// bra
(0xa000, 0x0000, "bra 0x4"),
(0xa001, 0x0000, "bra 0x6"),
(0xa800, 0x0000, "bra 0xfffff004"),
(0xa801, 0x0000, "bra 0xfffff006"),
// bsr
(0xb000, 0x0000, "bsr 0x4"),
(0xb001, 0x0000, "bsr 0x6"),
(0xb800, 0x0000, "bsr 0xfffff004"),
(0xb801, 0x0000, "bsr 0xfffff006"),
];
for &(opcode, addr, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_display_instruction_operations() {
let arch = ArchSuperH {};
let ops: &[(u16, u32, &str)] = &[
(0xcdff, 0x0000, "and.b #0xff, @(r0, gbr)"),
(0xcfff, 0x0000, "or.b #0xff, @(r0, gbr)"),
(0xccff, 0x0000, "tst.b #0xff, @(r0, gbr)"),
(0xceff, 0x0000, "xor.b #0xff, @(r0, gbr)"),
(0xc9ff, 0x0000, "and #0xff, r0"),
(0x88ff, 0x0000, "cmp/eq #0xff, r0"),
(0xcbff, 0x0000, "or #0xff, r0"),
(0xc8ff, 0x0000, "tst #0xff, r0"),
(0xcaff, 0x0000, "xor #0xff, r0"),
(0xc3ff, 0x0000, "trapa #0xff"),
];
for &(opcode, addr, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_add_mov_unknown_instructions() {
let arch = ArchSuperH {};
let ops: &[(u16, u32, &str)] = &[
(0x70FF, 0x0000, "add #0xff, r0"),
(0xE0FF, 0x0000, "mov #0xff, r0"),
(0x0000, 0x0000, ".word 0x0000 /* unknown instruction */"),
];
for &(opcode, addr, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_sh2_mov_instructions_with_labels() {
let arch = ArchSuperH {};
let ops: &[(u16, u32, &str)] =
&[(0x9000, 0x0000, "mov.w @(0x4, pc), r0"), (0xd000, 0x0000, "mov.l @(0x4, pc), r0")];
for &(opcode, addr, expected_str) in ops {
let code = opcode.to_be_bytes();
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &code,
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_func_0606_f378_mov_w_data_labeling() {
let arch = ArchSuperH {};
let ops: &[(u16, u32, &str)] = &[(0x9000, 0x0606F378, "mov.w @(0x4, pc), r0 /* 0x00B0 */")];
let mut code = Vec::new();
code.extend_from_slice(&0x9000_u16.to_be_bytes());
code.extend_from_slice(&0x0009_u16.to_be_bytes());
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
for &(opcode, addr, expected_str) in ops {
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &opcode.to_be_bytes(),
symbol: &Symbol {
address: 0x0606F378, // func base address
size: code.len() as u64,
..Default::default()
},
section: &Section {
address: 0x0606F378,
size: code.len() as u64,
data: SectionData(code.clone()),
..Default::default()
},
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
#[test]
fn test_func_0606_f378_mov_l_data_labeling() {
let arch = ArchSuperH {};
let ops: &[(u16, u32, &str)] =
&[(0xd000, 0x0606F378, "mov.l @(0x4, pc), r0 /* 0x00B000B0 */")];
let mut code = Vec::new();
code.extend_from_slice(&0xd000_u16.to_be_bytes());
code.extend_from_slice(&0x0009_u16.to_be_bytes());
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
for &(opcode, addr, expected_str) in ops {
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef {
address: addr as u64,
size: 2,
opcode,
branch_dest: None,
},
code: &opcode.to_be_bytes(),
symbol: &Symbol {
address: 0x0606F378, // func base address
size: code.len() as u64,
..Default::default()
},
section: &Section {
address: 0x0606F378,
size: code.len() as u64,
data: SectionData(code.clone()),
..Default::default()
},
..Default::default()
},
&DiffObjConfig::default(),
&mut |part| {
parts.push(part.into_static());
Ok(())
},
)
.unwrap();
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
assert_eq!(joined_str, expected_str.to_string());
}
}
}

View File

@ -1,51 +1,31 @@
use alloc::{boxed::Box, format, string::String, vec::Vec};
use core::cmp::Ordering;
use alloc::{boxed::Box, string::String, vec::Vec};
use anyhow::{Context, Result, anyhow, bail};
use anyhow::{anyhow, bail, Result};
use iced_x86::{
Decoder, DecoderOptions, DecoratorKind, FormatterOutput, FormatterTextKind, GasFormatter,
Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind, Register,
};
use object::{Endian as _, Object as _, ObjectSection as _, elf, pe};
use object::{pe, Endian as _, Object as _, ObjectSection as _};
use crate::{
arch::Arch,
diff::{DiffObjConfig, X86Formatter, display::InstructionPart},
obj::{InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef},
diff::{display::InstructionPart, DiffObjConfig, X86Formatter},
obj::{InstructionRef, RelocationFlags, ResolvedInstructionRef, ScannedInstruction},
};
#[derive(Debug)]
pub struct ArchX86 {
arch: Architecture,
bits: u32,
endianness: object::Endianness,
}
#[derive(Debug)]
enum Architecture {
X86,
X86_64,
}
impl ArchX86 {
pub fn new(object: &object::File) -> Result<Self> {
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() })
Ok(Self { bits: if object.is_64() { 64 } else { 32 }, endianness: object.endianness() })
}
fn decoder<'a>(&self, code: &'a [u8], address: u64) -> Decoder<'a> {
Decoder::with_ip(
match self.arch {
Architecture::X86 => 32,
Architecture::X86_64 => 64,
},
code,
address,
DecoderOptions::NONE,
)
Decoder::with_ip(self.bits, code, address, DecoderOptions::NONE)
}
fn formatter(&self, diff_config: &DiffObjConfig) -> Box<dyn iced_x86::Formatter> {
@ -58,79 +38,20 @@ impl ArchX86 {
formatter.options_mut().set_space_after_operand_separator(diff_config.space_between_args);
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,
},
RelocationFlags::Elf(typ) => match typ {
elf::R_386_32 | elf::R_386_PC32 => Some(4),
elf::R_386_16 => Some(2),
_ => 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,
},
RelocationFlags::Elf(typ) => match typ {
elf::R_X86_64_PC32 => Some(4),
elf::R_X86_64_64 => Some(8),
_ => None,
},
},
}
}
}
const DATA_OPCODE: u16 = u16::MAX - 1;
impl Arch for ArchX86 {
fn scan_instructions_internal(
fn scan_instructions(
&self,
address: u64,
code: &[u8],
_section_index: usize,
relocations: &[Relocation],
_diff_config: &DiffObjConfig,
) -> Result<Vec<InstructionRef>> {
) -> Result<Vec<ScannedInstruction>> {
let mut out = Vec::with_capacity(code.len() / 2);
let mut decoder = self.decoder(code, address);
let mut instruction = Instruction::default();
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(InstructionRef {
address,
size: size as u8,
opcode: DATA_OPCODE,
branch_dest: None,
});
reloc_iter.next();
continue 'outer;
}
}
Ordering::Greater => break,
}
}
while decoder.can_decode() {
decoder.decode_out(&mut instruction);
let branch_dest = match instruction.op0_kind() {
OpKind::NearBranch16 => Some(instruction.near_branch16() as u64),
@ -138,10 +59,12 @@ impl Arch for ArchX86 {
OpKind::NearBranch64 => Some(instruction.near_branch64()),
_ => None,
};
out.push(InstructionRef {
address,
size: instruction.len() as u8,
opcode: instruction.mnemonic() as u16,
out.push(ScannedInstruction {
ins_ref: InstructionRef {
address: instruction.ip(),
size: instruction.len() as u8,
opcode: instruction.mnemonic() as u16,
},
branch_dest,
});
}
@ -154,21 +77,6 @@ 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();
@ -180,16 +88,17 @@ impl Arch for ArchX86 {
// memory operand.
let mut reloc_replace = None;
if let Some(reloc) = resolved.relocation {
const PLACEHOLDER: u64 = 0x7BDE3E7D; // chosen by fair dice roll. guaranteed to be random.
const PLACEHOLDER: u64 = 0x7BDE3E7D; // chosen by fair dice roll.
// guaranteed to be random.
let reloc_offset = reloc.relocation.address - resolved.ins_ref.address;
let reloc_size = self.reloc_size(reloc.relocation.flags).unwrap_or(usize::MAX);
let reloc_size = reloc_size(reloc.relocation.flags).unwrap_or(usize::MAX);
let offsets = decoder.get_constant_offsets(&instruction);
if reloc_offset == offsets.displacement_offset() as u64
&& reloc_size == offsets.displacement_size()
{
instruction.set_memory_displacement64(PLACEHOLDER);
// Formatter always writes the displacement as Int32
reloc_replace = Some((OpKind::Memory, 4, PLACEHOLDER));
reloc_replace = Some((OpKind::Memory, NumberKind::Int32, PLACEHOLDER));
} else if reloc_offset == offsets.immediate_offset() as u64
&& reloc_size == offsets.immediate_size()
{
@ -207,12 +116,18 @@ impl Arch for ArchX86 {
_ => OpKind::default(),
}
};
let number_kind = match reloc_size {
2 => NumberKind::UInt16,
4 => NumberKind::UInt32,
8 => NumberKind::UInt64,
_ => NumberKind::default(),
};
if is_branch {
instruction.set_near_branch64(PLACEHOLDER);
} else {
instruction.set_immediate32(PLACEHOLDER as u32);
}
reloc_replace = Some((op_kind, reloc_size, PLACEHOLDER));
reloc_replace = Some((op_kind, number_kind, PLACEHOLDER));
}
}
@ -233,31 +148,12 @@ impl Arch for ArchX86 {
_relocation: &object::Relocation,
flags: RelocationFlags,
) -> Result<i64> {
match self.arch {
Architecture::X86 => match flags {
RelocationFlags::Coff(pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32)
| RelocationFlags::Elf(elf::R_386_32 | elf::R_386_PC32) => {
let data =
section.data()?[address as usize..address as usize + 4].try_into()?;
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)
| RelocationFlags::Elf(elf::R_X86_64_32 | elf::R_X86_64_PC32) => {
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)
| RelocationFlags::Elf(elf::R_X86_64_64) => {
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:?}"),
},
match flags {
RelocationFlags::Coff(pe::IMAGE_REL_I386_DIR32 | pe::IMAGE_REL_I386_REL32) => {
let data = section.data()?[address as usize..address as usize + 4].try_into()?;
Ok(self.endianness.read_i32_bytes(data) as i64)
}
flags => bail!("Unsupported x86 implicit relocation {flags:?}"),
}
}
@ -272,35 +168,33 @@ impl Arch for ArchX86 {
}
fn reloc_name(&self, flags: RelocationFlags) -> Option<&'static str> {
match self.arch {
Architecture::X86 => match flags {
RelocationFlags::Coff(typ) => match typ {
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,
},
match flags {
RelocationFlags::Coff(typ) => match typ {
pe::IMAGE_REL_I386_DIR32 => Some("IMAGE_REL_I386_DIR32"),
pe::IMAGE_REL_I386_REL32 => Some("IMAGE_REL_I386_REL32"),
_ => None,
},
_ => None,
}
}
fn data_reloc_size(&self, flags: RelocationFlags) -> usize {
self.reloc_size(flags).unwrap_or(1)
fn data_reloc_size(&self, flags: RelocationFlags) -> usize { 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,
}
}
struct InstructionFormatterOutput<'a> {
cb: &'a mut dyn FnMut(InstructionPart<'_>) -> Result<()>,
reloc_replace: Option<(OpKind, usize, u64)>,
reloc_replace: Option<(OpKind, NumberKind, u64)>,
error: Option<anyhow::Error>,
skip_next: bool,
}
@ -375,19 +269,11 @@ impl FormatterOutput for InstructionFormatterOutput<'_> {
return;
}
if let (Some(operand), Some((target_op_kind, reloc_size, target_value))) =
if let (Some(operand), Some((target_op_kind, target_number_kind, target_value))) =
(instruction_operand, self.reloc_replace)
{
#[allow(clippy::match_like_matches_macro)]
if instruction.op_kind(operand) == target_op_kind
&& match (number_kind, reloc_size) {
(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,
}
&& number_kind == target_number_kind
&& value == target_value
{
if let Err(e) = (self.cb)(InstructionPart::reloc()) {
@ -457,33 +343,32 @@ mod test {
#[test]
fn test_scan_instructions() {
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
let code = [
0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0x85, 0x00,
0x00, 0x00, 0x00,
];
let scanned =
arch.scan_instructions_internal(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].address, 0);
assert_eq!(scanned[0].size, 10);
assert_eq!(scanned[0].opcode, iced_x86::Mnemonic::Mov as u16);
assert_eq!(scanned[0].ins_ref.address, 0);
assert_eq!(scanned[0].ins_ref.size, 10);
assert_eq!(scanned[0].ins_ref.opcode, iced_x86::Mnemonic::Mov as u16);
assert_eq!(scanned[0].branch_dest, None);
assert_eq!(scanned[1].address, 10);
assert_eq!(scanned[1].size, 7);
assert_eq!(scanned[1].opcode, iced_x86::Mnemonic::Mov as u16);
assert_eq!(scanned[1].ins_ref.address, 10);
assert_eq!(scanned[1].ins_ref.size, 7);
assert_eq!(scanned[1].ins_ref.opcode, iced_x86::Mnemonic::Mov as u16);
assert_eq!(scanned[1].branch_dest, None);
}
#[test]
fn test_process_instruction() {
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
let code = [0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 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: 10, opcode, branch_dest: None },
ins_ref: InstructionRef { address: 0x1234, size: 10, opcode },
code: &code,
..Default::default()
},
@ -513,13 +398,13 @@ mod test {
#[test]
fn test_process_instruction_with_reloc_1() {
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
let code = [0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 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: 10, opcode, branch_dest: None },
ins_ref: InstructionRef { address: 0x1234, size: 10, opcode },
code: &code,
relocation: Some(ResolvedRelocation {
relocation: &Relocation {
@ -558,13 +443,13 @@ mod test {
#[test]
fn test_process_instruction_with_reloc_2() {
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
let arch = ArchX86 { bits: 32, endianness: object::Endianness::Little };
let code = [0x8b, 0x04, 0x85, 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, branch_dest: None },
ins_ref: InstructionRef { address: 0x1234, size: 7, opcode },
code: &code,
relocation: Some(ResolvedRelocation {
relocation: &Relocation {
@ -601,13 +486,13 @@ mod test {
#[test]
fn test_process_instruction_with_reloc_3() {
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
let arch = ArchX86 { bits: 32, 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, branch_dest: None },
ins_ref: InstructionRef { address: 0x1234, size: 5, opcode },
code: &code,
relocation: Some(ResolvedRelocation {
relocation: &Relocation {
@ -629,113 +514,4 @@ mod test {
.unwrap();
assert_eq!(parts, &[InstructionPart::opcode("call", opcode), InstructionPart::reloc()]);
}
#[test]
fn test_process_instruction_with_reloc_4() {
let arch = ArchX86 { arch: Architecture::X86, endianness: object::Endianness::Little };
let code = [0x8b, 0x15, 0xa4, 0x21, 0x7e, 0x00];
let opcode = iced_x86::Mnemonic::Mov as u16;
let mut parts = Vec::new();
arch.display_instruction(
ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1234, size: 6, opcode, branch_dest: None },
code: &code,
relocation: Some(ResolvedRelocation {
relocation: &Relocation {
flags: RelocationFlags::Coff(pe::IMAGE_REL_I386_DIR32),
address: 0x1234 + 2,
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("edx"),
InstructionPart::basic(","),
InstructionPart::basic(" "),
InstructionPart::basic("["),
InstructionPart::reloc(),
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, branch_dest: None },
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, branch_dest: None },
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()]);
}
}

View File

@ -7,7 +7,7 @@ use alloc::{
};
use core::ops::AddAssign;
use anyhow::{Result, bail};
use anyhow::{bail, Result};
use prost::Message;
// Protobuf report types
@ -434,7 +434,6 @@ impl From<LegacyReportItem> for ReportItem {
demangled_name: value.demangled_name,
virtual_address: value.address,
}),
address: None,
}
}
}
@ -442,7 +441,11 @@ impl From<LegacyReportItem> for ReportItem {
#[cfg(feature = "serde")]
fn serialize_hex<S>(x: &Option<u64>, s: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer {
if let Some(x) = x { s.serialize_str(&format!("{:#x}", x)) } else { s.serialize_none() }
if let Some(x) = x {
s.serialize_str(&format!("{:#x}", x))
} else {
s.serialize_none()
}
}
#[cfg(feature = "serde")]

View File

@ -2,8 +2,8 @@ use std::{
fs,
path::{Path, PathBuf},
sync::{
Arc,
atomic::{AtomicBool, Ordering},
Arc,
},
task::Waker,
time::Duration,
@ -11,7 +11,7 @@ use std::{
use globset::GlobSet;
use notify::RecursiveMode;
use notify_debouncer_full::{DebounceEventResult, new_debouncer_opt};
use notify_debouncer_full::{new_debouncer_opt, DebounceEventResult};
pub type Watcher = notify_debouncer_full::Debouncer<
notify::RecommendedWatcher,

View File

@ -6,7 +6,7 @@ use alloc::{
vec::Vec,
};
use anyhow::{Context, Result, anyhow};
use anyhow::{anyhow, Context, Result};
use globset::{Glob, GlobSet, GlobSetBuilder};
use path::unix_path_serde_option;
use typed_path::Utf8UnixPathBuf;

View File

@ -31,7 +31,11 @@ pub mod unix_path_serde_option {
pub fn serialize<S>(path: &Option<Utf8UnixPathBuf>, s: S) -> Result<S::Ok, S::Error>
where S: Serializer {
if let Some(path) = path { s.serialize_some(path.as_str()) } else { s.serialize_none() }
if let Some(path) = path {
s.serialize_some(path.as_str())
} else {
s.serialize_none()
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Utf8UnixPathBuf>, D::Error>
@ -47,7 +51,11 @@ pub mod platform_path_serde_option {
pub fn serialize<S>(path: &Option<Utf8PlatformPathBuf>, s: S) -> Result<S::Ok, S::Error>
where S: Serializer {
if let Some(path) = path { s.serialize_some(path.as_str()) } else { s.serialize_none() }
if let Some(path) = path {
s.serialize_some(path.as_str())
} else {
s.serialize_none()
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Utf8PlatformPathBuf>, D::Error>

View File

@ -1,28 +1,28 @@
use alloc::{
collections::{BTreeMap, btree_map},
collections::{btree_map, BTreeMap},
string::{String, ToString},
vec,
vec::Vec,
};
use anyhow::{Context, Result, anyhow, ensure};
use anyhow::{anyhow, ensure, Context, Result};
use super::{
DiffObjConfig, FunctionRelocDiffs, InstructionArgDiffIndex, InstructionBranchFrom,
InstructionBranchTo, InstructionDiffKind, InstructionDiffRow, SymbolDiff,
display::display_ins_data_literals,
display::display_ins_data_literals, DiffObjConfig, FunctionRelocDiffs, InstructionArgDiffIndex,
InstructionBranchFrom, InstructionBranchTo, InstructionDiffKind, InstructionDiffRow,
SymbolDiff,
};
use crate::obj::{
InstructionArg, InstructionArgValue, InstructionRef, Object, ResolvedInstructionRef,
ResolvedRelocation, ResolvedSymbol, SymbolFlag, SymbolKind,
ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolKind,
};
pub fn no_diff_code(
obj: &Object,
symbol_index: usize,
symbol_idx: usize,
diff_config: &DiffObjConfig,
) -> Result<SymbolDiff> {
let symbol = &obj.symbols[symbol_index];
let symbol = &obj.symbols[symbol_idx];
let section_index = symbol.section.ok_or_else(|| anyhow!("Missing section for symbol"))?;
let section = &obj.sections[section_index];
let data = section.data_range(symbol.address, symbol.size as usize).ok_or_else(|| {
@ -32,15 +32,13 @@ pub fn no_diff_code(
symbol.address + symbol.size
)
})?;
let ops = obj.arch.scan_instructions(
ResolvedSymbol { obj, symbol_index, symbol, section_index, section, data },
diff_config,
)?;
let ops = obj.arch.scan_instructions(symbol.address, data, section_index, diff_config)?;
let mut instruction_rows = Vec::<InstructionDiffRow>::new();
for i in &ops {
instruction_rows.push(InstructionDiffRow { ins_ref: Some(*i), ..Default::default() });
instruction_rows
.push(InstructionDiffRow { ins_ref: Some(i.ins_ref), ..Default::default() });
}
resolve_branches(&ops, &mut instruction_rows);
resolve_branches(obj, section_index, &ops, &mut instruction_rows);
Ok(SymbolDiff { target_symbol: None, match_percent: None, diff_score: None, instruction_rows })
}
@ -88,30 +86,20 @@ pub fn diff_code(
let left_section_idx = left_symbol.section.unwrap();
let right_section_idx = right_symbol.section.unwrap();
let left_ops = left_obj.arch.scan_instructions(
ResolvedSymbol {
obj: left_obj,
symbol_index: left_symbol_idx,
symbol: left_symbol,
section_index: left_section_idx,
section: left_section,
data: left_data,
},
left_symbol.address,
left_data,
left_section_idx,
diff_config,
)?;
let right_ops = right_obj.arch.scan_instructions(
ResolvedSymbol {
obj: right_obj,
symbol_index: right_symbol_idx,
symbol: right_symbol,
section_index: right_section_idx,
section: right_section,
data: right_data,
},
let right_ops = left_obj.arch.scan_instructions(
right_symbol.address,
right_data,
right_section_idx,
diff_config,
)?;
let (mut left_rows, mut right_rows) = diff_instructions(&left_ops, &right_ops)?;
resolve_branches(&left_ops, &mut left_rows);
resolve_branches(&right_ops, &mut right_rows);
resolve_branches(left_obj, left_section_idx, &left_ops, &mut left_rows);
resolve_branches(right_obj, right_section_idx, &right_ops, &mut right_rows);
let mut diff_state = InstructionDiffState::default();
for (left_row, right_row) in left_rows.iter_mut().zip(right_rows.iter_mut()) {
@ -158,21 +146,21 @@ pub fn diff_code(
}
fn diff_instructions(
left_insts: &[InstructionRef],
right_insts: &[InstructionRef],
left_insts: &[ScannedInstruction],
right_insts: &[ScannedInstruction],
) -> Result<(Vec<InstructionDiffRow>, Vec<InstructionDiffRow>)> {
let left_ops = left_insts.iter().map(|i| i.opcode).collect::<Vec<_>>();
let right_ops = right_insts.iter().map(|i| i.opcode).collect::<Vec<_>>();
let left_ops = left_insts.iter().map(|i| i.ins_ref.opcode).collect::<Vec<_>>();
let right_ops = right_insts.iter().map(|i| i.ins_ref.opcode).collect::<Vec<_>>();
let ops = similar::capture_diff_slices(similar::Algorithm::Patience, &left_ops, &right_ops);
if ops.is_empty() {
ensure!(left_insts.len() == right_insts.len());
let left_diff = left_insts
.iter()
.map(|i| InstructionDiffRow { ins_ref: Some(*i), ..Default::default() })
.map(|i| InstructionDiffRow { ins_ref: Some(i.ins_ref), ..Default::default() })
.collect();
let right_diff = right_insts
.iter()
.map(|i| InstructionDiffRow { ins_ref: Some(*i), ..Default::default() })
.map(|i| InstructionDiffRow { ins_ref: Some(i.ins_ref), ..Default::default() })
.collect();
return Ok((left_diff, right_diff));
}
@ -191,17 +179,14 @@ fn diff_instructions(
for op in ops {
let (_tag, left_range, right_range) = op.as_tag_tuple();
let len = left_range.len().max(right_range.len());
left_diff.extend(
left_range
.clone()
.map(|i| InstructionDiffRow { ins_ref: Some(left_insts[i]), ..Default::default() }),
);
right_diff.extend(
right_range.clone().map(|i| InstructionDiffRow {
ins_ref: Some(right_insts[i]),
..Default::default()
}),
);
left_diff.extend(left_range.clone().map(|i| InstructionDiffRow {
ins_ref: Some(left_insts[i].ins_ref),
..Default::default()
}));
right_diff.extend(right_range.clone().map(|i| InstructionDiffRow {
ins_ref: Some(right_insts[i].ins_ref),
..Default::default()
}));
if left_range.len() < len {
left_diff.extend((left_range.len()..len).map(|_| InstructionDiffRow::default()));
}
@ -222,7 +207,13 @@ fn arg_to_string(arg: &InstructionArg, reloc: Option<ResolvedRelocation>) -> Str
}
}
fn resolve_branches(ops: &[InstructionRef], rows: &mut [InstructionDiffRow]) {
fn resolve_branches(
obj: &Object,
section_index: usize,
ops: &[ScannedInstruction],
rows: &mut [InstructionDiffRow],
) {
let section = &obj.sections[section_index];
let mut branch_idx = 0u32;
// Map addresses to indices
let mut addr_map = BTreeMap::<u64, u32>::new();
@ -236,7 +227,17 @@ fn resolve_branches(ops: &[InstructionRef], rows: &mut [InstructionDiffRow]) {
for ((i, ins_diff), ins) in
rows.iter_mut().enumerate().filter(|(_, row)| row.ins_ref.is_some()).zip(ops)
{
if let Some(ins_idx) = ins.branch_dest.and_then(|a| addr_map.get(&a).copied()) {
let branch_dest = if let Some(resolved) = section.relocation_at(obj, ins.ins_ref) {
if resolved.symbol.section == Some(section_index) {
// If the relocation target is in the same section, use it as the branch destination
resolved.symbol.address.checked_add_signed(resolved.relocation.addend)
} else {
None
}
} else {
ins.branch_dest
};
if let Some(ins_idx) = branch_dest.and_then(|a| addr_map.get(&a).copied()) {
match branches.entry(ins_idx) {
btree_map::Entry::Vacant(e) => {
ins_diff.branch_to = Some(InstructionBranchTo { ins_idx, branch_idx });
@ -321,15 +322,15 @@ fn reloc_eq(
|| address_eq(left_reloc, right_reloc))
&& (diff_config.function_reloc_diffs == FunctionRelocDiffs::NameAddress
|| left_reloc.symbol.kind != SymbolKind::Object
|| right_reloc.symbol.size == 0 // Likely a pool symbol like ...data, don't treat this as a diff
|| display_ins_data_literals(left_obj, left_ins)
== display_ins_data_literals(right_obj, right_ins))
}
(Some(_), None) => false,
(None, Some(_)) => {
// Match if possibly stripped weak symbol
symbol_name_addend_matches && right_reloc.symbol.flags.contains(SymbolFlag::Weak)
}
(Some(_), None) | (None, None) => symbol_name_addend_matches,
(None, None) => symbol_name_addend_matches,
}
}
@ -436,7 +437,7 @@ fn diff_instruction(
{
// 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 right_ins = right_obj.arch.process_instruction(right_resolved, diff_config)?;
let right_ins = left_obj.arch.process_instruction(right_resolved, diff_config)?;
if left_ins.args.len() != right_ins.args.len() {
state.diff_score += PENALTY_REPLACE;
return Ok(InstructionDiffResult::new(InstructionDiffKind::Replace));
@ -501,3 +502,17 @@ fn diff_instruction(
Ok(InstructionDiffResult::new(InstructionDiffKind::None))
}
// TODO
// fn find_symbol_matching_fake_symbol_in_sections(
// fake_symbol: &ObjSymbol,
// sections: &[ObjSection],
// ) -> Option<ObjSymbol> {
// let orig_section_index = fake_symbol.orig_section_index?;
// let section = sections.iter().find(|s| s.orig_index == orig_section_index)?;
// let real_symbol = section
// .symbols
// .iter()
// .find(|s| s.size > 0 && (s.address..s.address + s.size).contains(&fake_symbol.address))?;
// Some(real_symbol.clone())
// }

View File

@ -1,14 +1,14 @@
use alloc::{vec, vec::Vec};
use core::{cmp::Ordering, ops::Range};
use anyhow::{Result, anyhow};
use similar::{Algorithm, capture_diff_slices, get_diff_ratio};
use anyhow::{anyhow, Result};
use similar::{capture_diff_slices, get_diff_ratio, Algorithm};
use super::{
DataDiff, DataDiffKind, DataRelocationDiff, ObjectDiff, SectionDiff, SymbolDiff,
code::{address_eq, section_name_eq},
DataDiff, DataDiffKind, DataRelocationDiff, ObjectDiff, SectionDiff, SymbolDiff,
};
use crate::obj::{Object, Relocation, ResolvedRelocation, Symbol, SymbolFlag, SymbolKind};
use crate::obj::{Object, Relocation, ResolvedRelocation, SymbolFlag, SymbolKind};
pub fn diff_bss_symbol(
left_obj: &Object,
@ -53,20 +53,21 @@ fn reloc_eq(
section_name_eq(left_obj, right_obj, sl, sr)
&& (symbol_name_addend_matches || address_eq(left, right))
}
(Some(_), None) => false,
(None, Some(_)) => {
// Match if possibly stripped weak symbol
symbol_name_addend_matches && right.symbol.flags.contains(SymbolFlag::Weak)
}
(Some(_), None) | (None, None) => symbol_name_addend_matches,
(None, None) => symbol_name_addend_matches,
}
}
#[inline]
pub fn resolve_relocation<'obj>(
symbols: &'obj [Symbol],
obj: &'obj Object,
reloc: &'obj Relocation,
) -> ResolvedRelocation<'obj> {
let symbol = &symbols[reloc.target_symbol];
let symbol = &obj.symbols[reloc.target_symbol];
ResolvedRelocation { relocation: reloc, symbol }
}
@ -87,7 +88,7 @@ fn diff_data_relocs_for_range<'left, 'right>(
continue;
}
let left_offset = left_reloc.address as usize - left_range.start;
let left_reloc = resolve_relocation(&left_obj.symbols, left_reloc);
let left_reloc = resolve_relocation(left_obj, left_reloc);
let Some(right_reloc) = right_section.relocations.iter().find(|r| {
if !right_range.contains(&(r.address as usize)) {
return false;
@ -98,7 +99,7 @@ fn diff_data_relocs_for_range<'left, 'right>(
diffs.push((DataDiffKind::Delete, Some(left_reloc), None));
continue;
};
let right_reloc = resolve_relocation(&right_obj.symbols, right_reloc);
let right_reloc = resolve_relocation(right_obj, right_reloc);
if reloc_eq(left_obj, right_obj, left_reloc, right_reloc) {
diffs.push((DataDiffKind::None, Some(left_reloc), Some(right_reloc)));
} else {
@ -110,7 +111,7 @@ fn diff_data_relocs_for_range<'left, 'right>(
continue;
}
let right_offset = right_reloc.address as usize - right_range.start;
let right_reloc = resolve_relocation(&right_obj.symbols, right_reloc);
let right_reloc = resolve_relocation(right_obj, right_reloc);
let Some(_) = left_section.relocations.iter().find(|r| {
if !left_range.contains(&(r.address as usize)) {
return false;
@ -138,13 +139,27 @@ pub fn diff_data_section(
) -> Result<(SectionDiff, SectionDiff)> {
let left_section = &left_obj.sections[left_section_idx];
let right_section = &right_obj.sections[right_section_idx];
let left_max = symbols_matching_section(&left_obj.symbols, left_section_idx)
.filter_map(|(_, s)| s.address.checked_sub(left_section.address).map(|a| a + s.size))
let left_max = left_obj
.symbols
.iter()
.filter_map(|s| {
if s.section != Some(left_section_idx) || s.kind == SymbolKind::Section {
return None;
}
s.address.checked_sub(left_section.address).map(|a| a + s.size)
})
.max()
.unwrap_or(0)
.min(left_section.size);
let right_max = symbols_matching_section(&right_obj.symbols, right_section_idx)
.filter_map(|(_, s)| s.address.checked_sub(right_section.address).map(|a| a + s.size))
let right_max = right_obj
.symbols
.iter()
.filter_map(|s| {
if s.section != Some(right_section_idx) || s.kind == SymbolKind::Section {
return None;
}
s.address.checked_sub(right_section.address).map(|a| a + s.size)
})
.max()
.unwrap_or(0)
.min(right_section.size);
@ -273,6 +288,7 @@ pub fn diff_data_section(
// We only do this when all relocations on the left side match.
if left_section_diff.match_percent.unwrap_or(-1.0) < match_percent {
left_section_diff.match_percent = Some(match_percent);
right_section_diff.match_percent = Some(match_percent);
}
}
Ok((left_section_diff, right_section_diff))
@ -396,22 +412,34 @@ pub fn diff_generic_section(
left_section_idx: usize,
_right_section_idx: usize,
) -> Result<(SectionDiff, SectionDiff)> {
let match_percent = if symbols_matching_section(&left_obj.symbols, left_section_idx)
let match_percent = if left_obj
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section)
.map(|(i, _)| &left_diff.symbols[i])
.all(|d| d.match_percent == Some(100.0))
{
100.0 // Avoid fp precision issues
} else {
let (matched, total) = symbols_matching_section(&left_obj.symbols, left_section_idx)
let (matched, total) = left_obj
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section)
.map(|(i, s)| (s, &left_diff.symbols[i]))
.fold((0.0, 0.0), |(matched, total), (s, d)| {
(matched + d.match_percent.unwrap_or(0.0) * s.size as f32, total + s.size as f32)
});
if total == 0.0 { 100.0 } else { matched / total }
if total == 0.0 {
100.0
} else {
matched / total
}
};
Ok((
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
SectionDiff { match_percent: None, data_diff: vec![], reloc_diff: vec![] },
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
))
}
@ -425,11 +453,19 @@ pub fn diff_bss_section(
right_section_idx: usize,
) -> Result<(SectionDiff, SectionDiff)> {
let left_section = &left_obj.sections[left_section_idx];
let left_sizes = symbols_matching_section(&left_obj.symbols, left_section_idx)
let left_sizes = left_obj
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(left_section_idx) && s.kind != SymbolKind::Section)
.filter_map(|(_, s)| s.address.checked_sub(left_section.address).map(|a| (a, s.size)))
.collect::<Vec<_>>();
let right_section = &right_obj.sections[right_section_idx];
let right_sizes = symbols_matching_section(&right_obj.symbols, right_section_idx)
let right_sizes = right_obj
.symbols
.iter()
.enumerate()
.filter(|(_, s)| s.section == Some(right_section_idx) && s.kind != SymbolKind::Section)
.filter_map(|(_, s)| s.address.checked_sub(right_section.address).map(|a| (a, s.size)))
.collect::<Vec<_>>();
let ops = capture_diff_slices(Algorithm::Patience, &left_sizes, &right_sizes);
@ -452,18 +488,6 @@ pub fn diff_bss_section(
Ok((
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
SectionDiff { match_percent: None, data_diff: vec![], reloc_diff: vec![] },
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
))
}
fn symbols_matching_section(
symbols: &[Symbol],
section_idx: usize,
) -> impl Iterator<Item = (usize, &Symbol)> + '_ {
symbols.iter().enumerate().filter(move |(_, s)| {
s.section == Some(section_idx)
&& s.kind != SymbolKind::Section
&& s.size > 0
&& !s.flags.contains(SymbolFlag::Ignored)
})
}

View File

@ -77,7 +77,7 @@ impl<'a> DiffTextSegment<'a> {
const EOL_SEGMENT: DiffTextSegment<'static> =
DiffTextSegment { text: DiffText::Eol, color: DiffTextColor::Normal, pad_to: 0 };
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub enum HighlightKind {
#[default]
None,
@ -205,18 +205,16 @@ pub fn display_row(
InstructionPart::Arg(arg) => {
let diff_index = ins_row.arg_diff.get(arg_idx).copied().unwrap_or_default();
arg_idx += 1;
if arg == InstructionArg::Reloc {
displayed_relocation = true;
}
match (arg, resolved.ins_ref.branch_dest) {
(InstructionArg::Value(value), _) => cb(DiffTextSegment {
match arg {
InstructionArg::Value(value) => cb(DiffTextSegment {
text: DiffText::Argument(value),
color: diff_index
.get()
.map_or(base_color, |i| DiffTextColor::Rotating(i as u8)),
pad_to: 0,
}),
(InstructionArg::Reloc, None) => {
InstructionArg::Reloc => {
displayed_relocation = true;
let resolved = resolved.relocation.unwrap();
let color = diff_index
.get()
@ -235,9 +233,7 @@ pub fn display_row(
}
Ok(())
}
(InstructionArg::BranchDest(dest), _) |
// If the relocation was resolved to a branch destination, emit that instead.
(InstructionArg::Reloc, Some(dest)) => {
InstructionArg::BranchDest(dest) => {
if let Some(addr) = dest.checked_sub(resolved.symbol.address) {
cb(DiffTextSegment {
text: DiffText::BranchDest(addr),
@ -288,18 +284,6 @@ pub fn display_row(
Ok(())
}
impl PartialEq<HighlightKind> for HighlightKind {
fn eq(&self, other: &HighlightKind) -> bool {
match (self, other) {
(HighlightKind::Opcode(a), HighlightKind::Opcode(b)) => a == b,
(HighlightKind::Argument(a), HighlightKind::Argument(b)) => a.loose_eq(b),
(HighlightKind::Symbol(a), HighlightKind::Symbol(b)) => a == b,
(HighlightKind::Address(a), HighlightKind::Address(b)) => a == b,
_ => false,
}
}
}
impl PartialEq<DiffText<'_>> for HighlightKind {
fn eq(&self, other: &DiffText) -> bool {
match (self, other) {
@ -341,14 +325,10 @@ pub enum SymbolNavigationKind {
Extab,
}
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub enum HoverItemColor {
#[default]
Normal, // Gray
Normal, // Gray
Emphasized, // White
Special, // Blue
Delete, // Red
Insert, // Green
}
pub enum HoverItem {
@ -375,12 +355,7 @@ pub fn symbol_context(obj: &Object, symbol_index: usize) -> Vec<ContextItem> {
out
}
pub fn symbol_hover(
obj: &Object,
symbol_index: usize,
addend: i64,
override_color: Option<HoverItemColor>,
) -> Vec<HoverItem> {
pub fn symbol_hover(obj: &Object, symbol_index: usize, addend: i64) -> Vec<HoverItem> {
let symbol = &obj.symbols[symbol_index];
let addend_str = match addend.cmp(&0i64) {
Ordering::Greater => format!("+{:x}", addend),
@ -391,51 +366,51 @@ pub fn symbol_hover(
out.push(HoverItem::Text {
label: "Name".into(),
value: format!("{}{}", symbol.name, addend_str),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
if let Some(demangled_name) = &symbol.demangled_name {
out.push(HoverItem::Text {
label: "Demangled".into(),
value: demangled_name.into(),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
}
if let Some(section) = symbol.section {
out.push(HoverItem::Text {
label: "Section".into(),
value: obj.sections[section].name.clone(),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
out.push(HoverItem::Text {
label: "Address".into(),
value: format!("{:x}{}", symbol.address, addend_str),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
if symbol.flags.contains(SymbolFlag::SizeInferred) {
out.push(HoverItem::Text {
label: "Size".into(),
value: format!("{:x} (inferred)", symbol.size),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
} else {
out.push(HoverItem::Text {
label: "Size".into(),
value: format!("{:x}", symbol.size),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
}
if let Some(align) = symbol.align {
out.push(HoverItem::Text {
label: "Alignment".into(),
value: align.get().to_string(),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
}
if let Some(address) = symbol.virtual_address {
out.push(HoverItem::Text {
label: "Virtual address".into(),
value: format!("{:x}", address),
color: override_color.clone().unwrap_or(HoverItemColor::Special),
color: HoverItemColor::Special,
});
}
} else {
@ -460,39 +435,30 @@ pub fn relocation_context(
let literals = display_ins_data_literals(obj, ins);
if !literals.is_empty() {
out.push(ContextItem::Separator);
for (literal, label_override) in literals {
out.push(ContextItem::Copy { value: literal, label: label_override });
for literal in literals {
out.push(ContextItem::Copy { value: literal, label: None });
}
}
}
out
}
pub fn relocation_hover(
obj: &Object,
reloc: ResolvedRelocation,
override_color: Option<HoverItemColor>,
) -> Vec<HoverItem> {
pub fn relocation_hover(obj: &Object, reloc: ResolvedRelocation) -> 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: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
} else {
out.push(HoverItem::Text {
label: "Relocation".into(),
value: format!("<{:?}>", reloc.relocation.flags),
color: override_color.clone().unwrap_or_default(),
color: HoverItemColor::Normal,
});
}
out.append(&mut symbol_hover(
obj,
reloc.relocation.target_symbol,
reloc.relocation.addend,
override_color,
));
out.append(&mut symbol_hover(obj, reloc.relocation.target_symbol, reloc.relocation.addend));
out
}
@ -579,15 +545,14 @@ pub fn instruction_hover(
}
if let Some(reloc) = resolved.relocation {
out.push(HoverItem::Separator);
out.append(&mut relocation_hover(obj, reloc, None));
let bytes = obj.symbol_data(reloc.relocation.target_symbol).unwrap_or(&[]);
if let Some(ty) = obj.arch.guess_data_type(resolved, bytes) {
out.append(&mut relocation_hover(obj, reloc));
if let Some(ty) = obj.arch.guess_data_type(resolved) {
let literals = display_ins_data_literals(obj, resolved);
if !literals.is_empty() {
out.push(HoverItem::Separator);
for (literal, label_override) in literals {
for literal in literals {
out.push(HoverItem::Text {
label: label_override.unwrap_or_else(|| format!("{}", ty)),
label: format!("{}", ty),
value: literal,
color: HoverItemColor::Normal,
});
@ -598,7 +563,7 @@ pub fn instruction_hover(
out
}
#[derive(Debug, Copy, Clone)]
#[derive(Copy, Clone)]
pub enum SymbolFilter<'a> {
None,
Search(&'a Regex),
@ -615,11 +580,7 @@ fn symbol_matches_filter(
if symbol.section.is_none() && !symbol.flags.contains(SymbolFlag::Common) {
return false;
}
if !show_hidden_symbols
&& (symbol.size == 0
|| symbol.flags.contains(SymbolFlag::Hidden)
|| symbol.flags.contains(SymbolFlag::Ignored))
{
if !show_hidden_symbols && (symbol.size == 0 || symbol.flags.contains(SymbolFlag::Hidden)) {
return false;
}
match filter {
@ -700,25 +661,24 @@ pub fn display_sections(
.collect::<Vec<_>>();
if let Some(section_idx) = section_idx {
let section = &obj.sections[section_idx];
if section.kind == SectionKind::Unknown {
if section.kind == SectionKind::Unknown || section.flags.contains(SectionFlag::Hidden) {
// Skip unknown and hidden sections
continue;
}
let section_diff = &diff.sections[section_idx];
let reverse_fn_order = section.kind == SectionKind::Code && reverse_fn_order;
symbols.sort_by(|a, b| {
let a = &obj.symbols[a.symbol];
let b = &obj.symbols[b.symbol];
section_symbol_sort(a, b)
.then_with(|| {
if reverse_fn_order {
b.address.cmp(&a.address)
} else {
a.address.cmp(&b.address)
}
})
.then_with(|| a.size.cmp(&b.size))
});
if section.kind == SectionKind::Code && reverse_fn_order {
symbols.sort_by(|a, b| {
let a_symbol = &obj.symbols[a.symbol];
let b_symbol = &obj.symbols[b.symbol];
symbol_sort_reverse(a_symbol, b_symbol)
});
} else {
symbols.sort_by(|a, b| {
let a_symbol = &obj.symbols[a.symbol];
let b_symbol = &obj.symbols[b.symbol];
symbol_sort(a_symbol, b_symbol)
});
}
sections.push(SectionDisplay {
id: section.id.clone(),
name: if section.flags.contains(SectionFlag::Combined) {
@ -741,7 +701,7 @@ pub fn display_sections(
});
}
}
sections.sort_by(|a, b| a.name.cmp(&b.name));
sections.sort_by(|a, b| a.id.cmp(&b.id));
sections
}
@ -756,6 +716,14 @@ fn section_symbol_sort(a: &Symbol, b: &Symbol) -> Ordering {
Ordering::Equal
}
fn symbol_sort(a: &Symbol, b: &Symbol) -> Ordering {
section_symbol_sort(a, b).then(a.address.cmp(&b.address)).then(a.size.cmp(&b.size))
}
fn symbol_sort_reverse(a: &Symbol, b: &Symbol) -> Ordering {
section_symbol_sort(a, b).then(b.address.cmp(&a.address)).then(b.size.cmp(&a.size))
}
pub fn display_ins_data_labels(obj: &Object, resolved: ResolvedInstructionRef) -> Vec<String> {
let Some(reloc) = resolved.relocation else {
return Vec::new();
@ -768,15 +736,12 @@ pub fn display_ins_data_labels(obj: &Object, resolved: ResolvedInstructionRef) -
};
let bytes = &data[reloc.relocation.addend as usize..];
obj.arch
.guess_data_type(resolved, bytes)
.guess_data_type(resolved)
.map(|ty| ty.display_labels(obj.endianness, bytes))
.unwrap_or_default()
}
pub fn display_ins_data_literals(
obj: &Object,
resolved: ResolvedInstructionRef,
) -> Vec<(String, Option<String>)> {
pub fn display_ins_data_literals(obj: &Object, resolved: ResolvedInstructionRef) -> Vec<String> {
let Some(reloc) = resolved.relocation else {
return Vec::new();
};
@ -788,7 +753,7 @@ pub fn display_ins_data_literals(
};
let bytes = &data[reloc.relocation.addend as usize..];
obj.arch
.guess_data_type(resolved, bytes)
.guess_data_type(resolved)
.map(|ty| ty.display_literals(obj.endianness, bytes))
.unwrap_or_default()
}

View File

@ -26,7 +26,13 @@ pub mod display;
include!(concat!(env!("OUT_DIR"), "/config.gen.rs"));
impl DiffObjConfig {
pub fn separator(&self) -> &'static str { if self.space_between_args { ", " } else { "," } }
pub fn separator(&self) -> &'static str {
if self.space_between_args {
", "
} else {
","
}
}
}
#[derive(Debug, Clone)]
@ -341,25 +347,11 @@ pub fn diff_objs(
if let (Some((right_obj, right_out)), Some((left_obj, left_out))) =
(right.as_mut(), left.as_mut())
{
if let Some(right_name) = mapping_config.selecting_left.as_deref() {
generate_mapping_symbols(
left_obj,
left_out,
right_obj,
right_out,
MappingSymbol::Right(right_name),
diff_config,
)?;
if let Some(right_name) = &mapping_config.selecting_left {
generate_mapping_symbols(right_obj, right_name, left_obj, left_out, diff_config)?;
}
if let Some(left_name) = mapping_config.selecting_right.as_deref() {
generate_mapping_symbols(
left_obj,
left_out,
right_obj,
right_out,
MappingSymbol::Left(left_name),
diff_config,
)?;
if let Some(left_name) = &mapping_config.selecting_right {
generate_mapping_symbols(left_obj, left_name, right_obj, right_out, diff_config)?;
}
}
@ -370,62 +362,50 @@ pub fn diff_objs(
})
}
#[derive(Clone, Copy)]
enum MappingSymbol<'a> {
Left(&'a str),
Right(&'a str),
}
/// When we're selecting a symbol to use as a comparison, we'll create comparisons for all
/// symbols in the other object that match the selected symbol's section and kind. This allows
/// us to display match percentages for all symbols in the other object that could be selected.
fn generate_mapping_symbols(
left_obj: &Object,
left_out: &mut ObjectDiff,
right_obj: &Object,
right_out: &mut ObjectDiff,
mapping_symbol: MappingSymbol,
base_obj: &Object,
base_name: &str,
target_obj: &Object,
target_out: &mut ObjectDiff,
config: &DiffObjConfig,
) -> Result<()> {
let (base_obj, base_name, target_obj) = match mapping_symbol {
MappingSymbol::Left(name) => (left_obj, name, right_obj),
MappingSymbol::Right(name) => (right_obj, name, left_obj),
};
let Some(base_symbol_ref) = base_obj.symbol_by_name(base_name) else {
let Some(base_symbol_ref) = symbol_ref_by_name(base_obj, base_name) else {
return Ok(());
};
let base_section_kind = symbol_section_kind(base_obj, &base_obj.symbols[base_symbol_ref]);
for (target_symbol_index, target_symbol) in target_obj.symbols.iter().enumerate() {
if target_symbol.size == 0
|| target_symbol.flags.contains(SymbolFlag::Ignored)
|| symbol_section_kind(target_obj, target_symbol) != base_section_kind
{
if symbol_section_kind(target_obj, target_symbol) != base_section_kind {
continue;
}
let (left_symbol_idx, right_symbol_idx) = match mapping_symbol {
MappingSymbol::Left(_) => (base_symbol_ref, target_symbol_index),
MappingSymbol::Right(_) => (target_symbol_index, base_symbol_ref),
};
let (left_diff, right_diff) = match base_section_kind {
match base_section_kind {
SectionKind::Code => {
diff_code(left_obj, right_obj, left_symbol_idx, right_symbol_idx, config)
let (left_diff, _right_diff) =
diff_code(target_obj, base_obj, target_symbol_index, base_symbol_ref, config)?;
target_out.mapping_symbols.push(MappingSymbolDiff {
symbol_index: target_symbol_index,
symbol_diff: left_diff,
});
}
SectionKind::Data => {
diff_data_symbol(left_obj, right_obj, left_symbol_idx, right_symbol_idx)
let (left_diff, _right_diff) =
diff_data_symbol(target_obj, base_obj, target_symbol_index, base_symbol_ref)?;
target_out.mapping_symbols.push(MappingSymbolDiff {
symbol_index: target_symbol_index,
symbol_diff: left_diff,
});
}
SectionKind::Bss | SectionKind::Common => {
diff_bss_symbol(left_obj, right_obj, left_symbol_idx, right_symbol_idx)
let (left_diff, _right_diff) =
diff_bss_symbol(target_obj, base_obj, target_symbol_index, base_symbol_ref)?;
target_out.mapping_symbols.push(MappingSymbolDiff {
symbol_index: target_symbol_index,
symbol_diff: left_diff,
});
}
SectionKind::Unknown => continue,
}?;
match mapping_symbol {
MappingSymbol::Left(_) => right_out.mapping_symbols.push(MappingSymbolDiff {
symbol_index: right_symbol_idx,
symbol_diff: right_diff,
}),
MappingSymbol::Right(_) => left_out
.mapping_symbols
.push(MappingSymbolDiff { symbol_index: left_symbol_idx, symbol_diff: left_diff }),
SectionKind::Unknown => {}
}
}
Ok(())
@ -457,6 +437,10 @@ pub struct MappingConfig {
pub selecting_right: Option<String>,
}
fn symbol_ref_by_name(obj: &Object, name: &str) -> Option<usize> {
obj.symbols.iter().position(|s| s.name == name)
}
fn apply_symbol_mappings(
left: &Object,
right: &Object,
@ -468,25 +452,25 @@ fn apply_symbol_mappings(
// If we're selecting a symbol to use as a comparison, mark it as used
// This ensures that we don't match it to another symbol at any point
if let Some(left_name) = &mapping_config.selecting_left {
if let Some(left_symbol) = left.symbol_by_name(left_name) {
if let Some(left_symbol) = symbol_ref_by_name(left, left_name) {
left_used.insert(left_symbol);
}
}
if let Some(right_name) = &mapping_config.selecting_right {
if let Some(right_symbol) = right.symbol_by_name(right_name) {
if let Some(right_symbol) = symbol_ref_by_name(right, right_name) {
right_used.insert(right_symbol);
}
}
// Apply manual symbol mappings
for (left_name, right_name) in &mapping_config.mappings {
let Some(left_symbol_index) = left.symbol_by_name(left_name) else {
let Some(left_symbol_index) = symbol_ref_by_name(left, left_name) else {
continue;
};
if left_used.contains(&left_symbol_index) {
continue;
}
let Some(right_symbol_index) = right.symbol_by_name(right_name) else {
let Some(right_symbol_index) = symbol_ref_by_name(right, right_name) else {
continue;
};
if right_used.contains(&right_symbol_index) {
@ -548,9 +532,6 @@ fn matching_symbols(
)?;
}
for (symbol_idx, symbol) in left.symbols.iter().enumerate() {
if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) {
continue;
}
let section_kind = symbol_section_kind(left, symbol);
if section_kind == SectionKind::Unknown {
continue;
@ -572,9 +553,6 @@ fn matching_symbols(
}
if let Some(right) = right {
for (symbol_idx, symbol) in right.symbols.iter().enumerate() {
if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) {
continue;
}
let section_kind = symbol_section_kind(right, symbol);
if section_kind == SectionKind::Unknown {
continue;
@ -600,10 +578,9 @@ fn unmatched_symbols<'obj, 'used>(
where
'obj: 'used,
{
obj.symbols.iter().enumerate().filter(move |&(symbol_idx, symbol)| {
!symbol.flags.contains(SymbolFlag::Ignored)
// Skip symbols that have already been matched
&& !used.is_some_and(|u| u.contains(&symbol_idx))
obj.symbols.iter().enumerate().filter(move |&(symbol_idx, _)| {
// Skip symbols that have already been matched
!used.is_some_and(|u| u.contains(&symbol_idx))
})
}
@ -677,11 +654,7 @@ fn find_symbol(
/// Find matching sections between each object.
fn matching_sections(left: Option<&Object>, right: Option<&Object>) -> Result<Vec<SectionMatch>> {
let mut matches = Vec::with_capacity(
left.as_ref()
.map_or(0, |o| o.sections.len())
.max(right.as_ref().map_or(0, |o| o.sections.len())),
);
let mut matches = Vec::new();
if let Some(left) = left {
for (section_idx, section) in left.sections.iter().enumerate() {
if section.kind == SectionKind::Unknown {
@ -689,7 +662,7 @@ fn matching_sections(left: Option<&Object>, right: Option<&Object>) -> Result<Ve
}
matches.push(SectionMatch {
left: Some(section_idx),
right: find_section(right, &section.name, section.kind, &matches),
right: find_section(right, &section.name, section.kind),
section_kind: section.kind,
});
}
@ -712,13 +685,6 @@ fn matching_sections(left: Option<&Object>, right: Option<&Object>) -> Result<Ve
Ok(matches)
}
fn find_section(
obj: Option<&Object>,
name: &str,
section_kind: SectionKind,
matches: &[SectionMatch],
) -> Option<usize> {
obj?.sections.iter().enumerate().position(|(i, s)| {
s.kind == section_kind && s.name == name && !matches.iter().any(|m| m.right == Some(i))
})
fn find_section(obj: Option<&Object>, name: &str, section_kind: SectionKind) -> Option<usize> {
obj?.sections.iter().position(|s| s.kind == section_kind && s.name == name)
}

View File

@ -6,7 +6,7 @@ use self_update::{
update::{Release, ReleaseUpdate},
};
use crate::jobs::{Job, JobContext, JobResult, JobState, start_job, update_status};
use crate::jobs::{start_job, update_status, Job, JobContext, JobResult, JobState};
pub struct CheckUpdateConfig {
pub build_updater: fn() -> Result<Box<dyn ReleaseUpdate>>,

View File

@ -1,11 +1,11 @@
use std::{fs, sync::mpsc::Receiver, task::Waker};
use anyhow::{Context, Result, anyhow, bail};
use anyhow::{anyhow, bail, Context, Result};
use typed_path::{Utf8PlatformPathBuf, Utf8UnixPathBuf};
use crate::{
build::{BuildConfig, BuildStatus, run_make},
jobs::{Job, JobContext, JobResult, JobState, start_job, update_status},
build::{run_make, BuildConfig, BuildStatus},
jobs::{start_job, update_status, Job, JobContext, JobResult, JobState},
};
#[derive(Debug, Clone)]

View File

@ -1,8 +1,8 @@
use std::{
sync::{
Arc, RwLock,
atomic::{AtomicUsize, Ordering},
mpsc::{Receiver, Sender, TryRecvError},
Arc, RwLock,
},
task::Waker,
thread::JoinHandle,

View File

@ -1,14 +1,14 @@
use std::{sync::mpsc::Receiver, task::Waker};
use anyhow::{Error, Result, bail};
use anyhow::{bail, Error, Result};
use time::OffsetDateTime;
use typed_path::Utf8PlatformPathBuf;
use crate::{
build::{BuildConfig, BuildStatus, run_make},
diff::{DiffObjConfig, MappingConfig, ObjectDiff, diff_objs},
jobs::{Job, JobContext, JobResult, JobState, start_job, update_status},
obj::{Object, read},
build::{run_make, BuildConfig, BuildStatus},
diff::{diff_objs, DiffObjConfig, MappingConfig, ObjectDiff},
jobs::{start_job, update_status, Job, JobContext, JobResult, JobState},
obj::{read, Object},
};
pub struct ObjDiffConfig {

View File

@ -10,7 +10,7 @@ use anyhow::{Context, Result};
pub use self_update; // Re-export self_update crate
use self_update::update::ReleaseUpdate;
use crate::jobs::{Job, JobContext, JobResult, JobState, start_job, update_status};
use crate::jobs::{start_job, update_status, Job, JobContext, JobResult, JobState};
pub struct UpdateConfig {
pub build_updater: fn() -> Result<Box<dyn ReleaseUpdate>>,

View File

@ -9,12 +9,9 @@ use alloc::{
vec,
vec::Vec,
};
use core::{
fmt,
num::{NonZeroU32, NonZeroU64},
};
use core::{fmt, num::NonZeroU32};
use flagset::{FlagSet, flags};
use flagset::{flags, FlagSet};
use crate::{
arch::{Arch, ArchDummy},
@ -45,8 +42,6 @@ flags! {
HasExtra,
/// Symbol size was missing and was inferred
SizeInferred,
/// Symbol should be ignored by any diffing
Ignored,
}
}
@ -57,6 +52,7 @@ flags! {
pub enum SectionFlag: u8 {
/// Section combined from multiple input sections
Combined,
Hidden,
}
}
@ -72,7 +68,6 @@ pub struct Section {
pub kind: SectionKind,
pub data: SectionData,
pub flags: SectionFlagSet,
pub align: Option<NonZeroU64>,
pub relocations: Vec<Relocation>,
/// Line number info (.line or .debug_line section)
pub line_info: BTreeMap<u64, u32>,
@ -98,14 +93,14 @@ impl fmt::Debug for SectionData {
impl Section {
pub fn data_range(&self, address: u64, size: usize) -> Option<&[u8]> {
let offset = address.checked_sub(self.address)?;
self.data.get(offset as usize..offset as usize + size)
}
// The alignment to use when "Combine data/text sections" is enabled.
pub fn combined_alignment(&self) -> u64 {
const MIN_ALIGNMENT: u64 = 4;
self.align.map(|align| align.get().max(MIN_ALIGNMENT)).unwrap_or(MIN_ALIGNMENT)
let start = self.address;
let end = start + self.size;
if address >= start && address + size as u64 <= end {
let offset = (address - start) as usize;
Some(&self.data[offset..offset + size])
} else {
None
}
}
pub fn relocation_at<'obj>(
@ -118,7 +113,7 @@ impl Section {
Err(i) => self
.relocations
.get(i)
.filter(|r| r.address < ins_ref.address + ins_ref.size as u64),
.take_if(|r| r.address < ins_ref.address + ins_ref.size as u64),
}
.and_then(|relocation| {
let symbol = obj.symbols.get(relocation.target_symbol)?;
@ -214,6 +209,11 @@ pub struct InstructionRef {
pub address: u64,
pub size: u8,
pub opcode: u16,
}
#[derive(Copy, Clone, Debug)]
pub struct ScannedInstruction {
pub ins_ref: InstructionRef,
pub branch_dest: Option<u64>,
}
@ -308,10 +308,6 @@ impl Object {
let offset = symbol.address.checked_sub(section.address)?;
section.data.get(offset as usize..offset as usize + symbol.size as usize)
}
pub fn symbol_by_name(&self, name: &str) -> Option<usize> {
self.symbols.iter().position(|symbol| symbol.section.is_some() && symbol.name == name)
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
@ -334,16 +330,6 @@ pub struct ResolvedRelocation<'a> {
pub symbol: &'a Symbol,
}
#[derive(Debug, Copy, Clone)]
pub struct ResolvedSymbol<'obj> {
pub obj: &'obj Object,
pub symbol_index: usize,
pub symbol: &'obj Symbol,
pub section_index: usize,
pub section: &'obj Section,
pub data: &'obj [u8],
}
#[derive(Debug, Copy, Clone)]
pub struct ResolvedInstructionRef<'obj> {
pub ins_ref: InstructionRef,
@ -375,7 +361,6 @@ static DUMMY_SECTION: Section = Section {
kind: SectionKind::Unknown,
data: SectionData(Vec::new()),
flags: SectionFlagSet::empty(),
align: None,
relocations: Vec::new(),
line_info: BTreeMap::new(),
virtual_address: None,

View File

@ -4,20 +4,20 @@ use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{cmp::Ordering, num::NonZeroU64};
use core::cmp::Ordering;
use anyhow::{Context, Result, anyhow, bail, ensure};
use anyhow::{bail, ensure, Context, Result};
use object::{Object as _, ObjectSection as _, ObjectSymbol as _};
use crate::{
arch::{Arch, new_arch},
arch::{new_arch, Arch},
diff::DiffObjConfig,
obj::{
split_meta::{SplitMeta, SPLITMETA_SECTION},
Object, Relocation, RelocationFlags, Section, SectionData, SectionFlag, SectionKind,
Symbol, SymbolFlag, SymbolKind,
split_meta::{SPLITMETA_SECTION, SplitMeta},
},
util::{align_data_slice_to, align_u64_to, read_u16, read_u32},
util::{read_u16, read_u32},
};
fn map_section_kind(section: &object::Section) -> SectionKind {
@ -121,15 +121,6 @@ fn map_symbols(
Ok((symbols, symbol_indices))
}
/// When inferring a symbol's size, we ignore symbols that start with specific prefixes. They are
/// usually emitted as branch targets and do not represent the start of a function or object.
fn is_local_label(symbol: &Symbol) -> bool {
const LABEL_PREFIXES: &[&str] = &[".L", "LAB_"];
symbol.size == 0
&& symbol.flags.contains(SymbolFlag::Local)
&& LABEL_PREFIXES.iter().any(|p| symbol.name.starts_with(p))
}
fn infer_symbol_sizes(symbols: &mut [Symbol], sections: &[Section]) {
// Create a sorted list of symbol indices by section
let mut symbols_with_section = Vec::<usize>::with_capacity(symbols.len());
@ -176,28 +167,27 @@ fn infer_symbol_sizes(symbols: &mut [Symbol], sections: &[Section]) {
if last_end.0 == section_idx && last_end.1 > symbol.address {
continue;
}
let next_symbol = loop {
if iter_idx >= symbols_with_section.len() {
break None;
}
let next_symbol = &symbols[symbols_with_section[iter_idx]];
if next_symbol.section != Some(section_idx) {
break None;
}
if match symbol.kind {
SymbolKind::Function | SymbolKind::Object => {
// For function/object symbols, find the next function/object
matches!(next_symbol.kind, SymbolKind::Function | SymbolKind::Object)
let next_symbol = match symbol.kind {
// For function/object symbols, find the next function/object symbol (in other words:
// skip over labels)
SymbolKind::Function | SymbolKind::Object => loop {
if iter_idx >= symbols_with_section.len() {
break None;
}
SymbolKind::Unknown | SymbolKind::Section => {
// For labels (or anything else), stop at any symbol
true
let next_symbol = &symbols[symbols_with_section[iter_idx]];
if next_symbol.section != Some(section_idx) {
break None;
}
} && !is_local_label(next_symbol)
{
break Some(next_symbol);
}
iter_idx += 1;
if let SymbolKind::Function | SymbolKind::Object = next_symbol.kind {
break Some(next_symbol);
}
iter_idx += 1;
},
// For labels (or anything else), simply use the next symbol's address
SymbolKind::Unknown | SymbolKind::Section => symbols_with_section
.get(iter_idx)
.map(|&i| &symbols[i])
.take_if(|s| s.section == Some(section_idx)),
};
let next_address = next_symbol.map(|s| s.address).unwrap_or_else(|| {
let section = &sections[section_idx];
@ -267,7 +257,6 @@ fn map_sections(
kind,
data: SectionData(data),
flags: Default::default(),
align: NonZeroU64::new(section.align()),
relocations: Default::default(),
virtual_address,
line_info: Default::default(),
@ -351,7 +340,7 @@ fn map_section_relocations(
let idx = if let Some(section_symbol) = obj_file
.symbol_by_index(idx)
.ok()
.filter(|s| s.kind() == object::SymbolKind::Section)
.take_if(|s| s.kind() == object::SymbolKind::Section)
{
let section_index =
section_symbol.section_index().context("Section symbol without section")?;
@ -432,44 +421,6 @@ fn map_relocations(
Ok(())
}
fn calculate_pooled_relocations(
arch: &dyn Arch,
sections: &mut [Section],
symbols: &[Symbol],
) -> Result<()> {
for (section_index, section) in sections.iter_mut().enumerate() {
if section.kind != SectionKind::Code {
continue;
}
let mut fake_pool_relocs = Vec::new();
for symbol in symbols {
if symbol.section != Some(section_index) {
continue;
}
if symbol.kind != SymbolKind::Function {
continue;
}
let code =
section.data_range(symbol.address, symbol.size as usize).ok_or_else(|| {
anyhow!(
"Symbol data out of bounds: {:#x}..{:#x}",
symbol.address,
symbol.address + symbol.size
)
})?;
fake_pool_relocs.append(&mut arch.generate_pooled_relocations(
symbol.address,
code,
&section.relocations,
symbols,
));
}
section.relocations.append(&mut fake_pool_relocs);
section.relocations.sort_by_key(|r| r.address);
}
Ok(())
}
fn parse_line_info(
obj_file: &object::File,
sections: &mut [Section],
@ -750,10 +701,7 @@ fn do_combine_sections(
}
offsets.push(current_offset);
current_offset += section.size;
let align = section.combined_alignment();
current_offset = align_u64_to(current_offset, align);
data_size += section.data.len();
data_size = align_u64_to(data_size as u64, align) as usize;
num_relocations += section.relocations.len();
}
if data_size > 0 {
@ -768,13 +716,12 @@ fn do_combine_sections(
let section = &mut sections[i];
section.size = 0;
data.append(&mut section.data.0);
align_data_slice_to(&mut data, section.combined_alignment());
section.relocations.iter_mut().for_each(|r| r.address += offset);
relocations.append(&mut section.relocations);
line_info.append(&mut section.line_info.iter().map(|(&a, &l)| (a + offset, l)).collect());
section.line_info.clear();
if offset > 0 {
section.kind = SectionKind::Unknown;
section.flags |= SectionFlag::Hidden;
}
}
{
@ -858,21 +805,17 @@ pub fn read(obj_path: &std::path::Path, config: &DiffObjConfig) -> Result<Object
pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<Object> {
let obj_file = object::File::parse(data)?;
let mut arch = new_arch(&obj_file)?;
let arch = new_arch(&obj_file)?;
let split_meta = parse_split_meta(&obj_file)?;
let (mut sections, section_indices) =
map_sections(arch.as_ref(), &obj_file, split_meta.as_ref())?;
let (mut symbols, symbol_indices) =
map_symbols(arch.as_ref(), &obj_file, &sections, &section_indices, split_meta.as_ref())?;
map_relocations(arch.as_ref(), &obj_file, &mut sections, &section_indices, &symbol_indices)?;
if config.ppc_calculate_pool_relocations {
calculate_pooled_relocations(arch.as_ref(), &mut sections, &symbols)?;
}
parse_line_info(&obj_file, &mut sections, &section_indices, data)?;
if config.combine_data_sections || config.combine_text_sections {
combine_sections(&mut sections, &mut symbols, config)?;
}
arch.post_init(&sections, &symbols);
Ok(Object {
arch,
endianness: obj_file.endianness(),

View File

@ -14,7 +14,6 @@ expression: "(sections, symbols)"
8,
),
flags: FlagSet(),
align: None,
relocations: [
Relocation {
flags: Elf(
@ -54,7 +53,6 @@ expression: "(sections, symbols)"
12,
),
flags: FlagSet(Combined),
align: None,
relocations: [
Relocation {
flags: Elf(
@ -84,12 +82,11 @@ expression: "(sections, symbols)"
name: ".data",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: None,
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -99,12 +96,11 @@ expression: "(sections, symbols)"
name: ".data",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: None,
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,

View File

@ -1,11 +1,7 @@
use alloc::{string::String, vec, vec::Vec};
use anyhow::{Result, anyhow};
use object::{Endian, ObjectSection, elf::SHT_NOTE};
#[cfg(feature = "std")]
use crate::util::align_data_to_4;
use crate::util::align_size_to_4;
use anyhow::{anyhow, Result};
use object::{elf::SHT_NOTE, Endian, ObjectSection};
pub const SPLITMETA_SECTION: &str = ".note.split";
pub const SHT_SPLITMETA: u32 = SHT_NOTE;
@ -194,6 +190,17 @@ where E: Endian
}
}
fn align_size_to_4(size: usize) -> usize { (size + 3) & !3 }
#[cfg(feature = "std")]
fn align_data_to_4<W: std::io::Write + ?Sized>(writer: &mut W, len: usize) -> std::io::Result<()> {
const ALIGN_BYTES: &[u8] = &[0; 4];
if len % 4 != 0 {
writer.write_all(&ALIGN_BYTES[..4 - len % 4])?;
}
Ok(())
}
// ELF note format:
// Name Size | 4 bytes (integer)
// Desc Size | 4 bytes (integer)

View File

@ -1,7 +1,7 @@
use alloc::{format, vec::Vec};
use alloc::format;
use core::fmt;
use anyhow::{Result, ensure};
use anyhow::{ensure, Result};
use num_traits::PrimInt;
use object::{Endian, Object};
@ -39,23 +39,3 @@ pub fn read_u16(obj_file: &object::File, reader: &mut &[u8]) -> Result<u16> {
*reader = &reader[2..];
Ok(obj_file.endianness().read_u16(value))
}
pub fn align_size_to_4(size: usize) -> usize { (size + 3) & !3 }
#[cfg(feature = "std")]
pub fn align_data_to_4<W: std::io::Write + ?Sized>(
writer: &mut W,
len: usize,
) -> std::io::Result<()> {
const ALIGN_BYTES: &[u8] = &[0; 4];
if len % 4 != 0 {
writer.write_all(&ALIGN_BYTES[..4 - len % 4])?;
}
Ok(())
}
pub fn align_u64_to(len: u64, align: u64) -> u64 { len + ((align - (len % align)) % align) }
pub fn align_data_slice_to(data: &mut Vec<u8>, align: u64) {
data.resize(align_u64_to(data.len() as u64, align) as usize, 0);
}

View File

@ -5,7 +5,7 @@ mod common;
#[test]
#[cfg(feature = "arm")]
fn read_arm() {
let diff_config = diff::DiffObjConfig { ..Default::default() };
let diff_config = diff::DiffObjConfig { mips_register_prefix: true, ..Default::default() };
let obj = obj::read::parse(include_object!("data/arm/LinkStateItem.o"), &diff_config).unwrap();
insta::assert_debug_snapshot!(obj);
let symbol_idx =
@ -15,32 +15,3 @@ 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 { ..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);
}
#[test]
#[cfg(feature = "arm")]
fn combine_text_sections() {
let diff_config = diff::DiffObjConfig { combine_text_sections: true, ..Default::default() };
let obj = obj::read::parse(include_object!("data/arm/enemy300.o"), &diff_config).unwrap();
let symbol_idx = obj.symbols.iter().position(|s| s.name == "Enemy300Draw").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);
}

View File

@ -14,34 +14,3 @@ fn read_mips() {
let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config);
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);
}
#[test]
#[cfg(feature = "mips")]
fn filter_non_matching() {
let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/mips/vw_main.c.o"), &diff_config).unwrap();
insta::assert_debug_snapshot!(obj.symbols);
}

View File

@ -61,7 +61,7 @@ fn diff_ppc() {
let base_diff = diff.right.as_ref().unwrap();
let sections_display = display::display_sections(
&target_obj,
target_diff,
&target_diff,
display::SymbolFilter::None,
false,
false,

View File

@ -1,4 +1,4 @@
use objdiff_core::{diff, diff::display::SymbolFilter, obj};
use objdiff_core::{diff, obj};
mod common;
@ -26,54 +26,3 @@ fn read_x86_combine_sections() {
let obj = obj::read::parse(include_object!("data/x86/rtest.obj"), &diff_config).unwrap();
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);
}
#[test]
#[cfg(feature = "x86")]
fn display_section_ordering() {
let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/x86/basenode.obj"), &diff_config).unwrap();
let obj_diff =
diff::diff_objs(Some(&obj), None, None, &diff_config, &diff::MappingConfig::default())
.unwrap()
.left
.unwrap();
let section_display =
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);
}
// Inferred size of functions should ignore symbols with specific prefixes
#[test]
#[cfg(feature = "x86")]
fn read_x86_local_labels() {
let diff_config = diff::DiffObjConfig::default();
let obj = obj::read::parse(include_object!("data/x86/local_labels.obj"), &diff_config).unwrap();
insta::assert_debug_snapshot!(obj);
}

View File

@ -1,5 +1,5 @@
use objdiff_core::{
diff::{DiffObjConfig, SymbolDiff, display::DiffTextSegment},
diff::{display::DiffTextSegment, DiffObjConfig, SymbolDiff},
obj::Object,
};
@ -13,7 +13,7 @@ pub fn display_diff(
for row in &diff.instruction_rows {
output.push('[');
let mut separator = false;
objdiff_core::diff::display::display_row(obj, symbol_idx, row, diff_config, |segment| {
objdiff_core::diff::display::display_row(&obj, symbol_idx, row, &diff_config, |segment| {
if separator {
output.push_str(", ");
} else {
@ -47,6 +47,6 @@ macro_rules! include_bytes_align_as {
#[macro_export]
macro_rules! include_object {
($path:literal) => {
include_bytes_align_as!(u64, $path)
include_bytes_align_as!(u32, $path)
};
}

Binary file not shown.

View File

@ -1,7 +0,0 @@
---
source: objdiff-core/tests/arch_arm.rs
expression: output
---
[(Line(90), Dim, 5), (Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 32799), Normal, 10), (Argument(Opaque("r12")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("]"), Normal, 0), (Basic(" (->"), Normal, 0), (BranchDest(8), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Line(90), Dim, 5), (Address(4), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bx", 32779), Normal, 10), (Argument(Opaque("r12")), Normal, 0), (Eol, Normal, 0)]
[(Line(90), Dim, 5), (Address(8), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".word", 65535), Normal, 10), (Symbol(Symbol { name: "esEnemyDraw", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)]

View File

@ -1,48 +0,0 @@
---
source: objdiff-core/tests/arch_arm.rs
expression: diff.instruction_rows
---
[
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 76,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 80,
size: 4,
opcode: 32779,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 84,
size: 4,
opcode: 65535,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
]

View File

@ -9,7 +9,6 @@ expression: diff.instruction_rows
address: 40,
size: 4,
opcode: 32895,
branch_dest: None,
},
),
kind: None,
@ -23,7 +22,6 @@ expression: diff.instruction_rows
address: 44,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -37,7 +35,6 @@ expression: diff.instruction_rows
address: 48,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -51,7 +48,6 @@ expression: diff.instruction_rows
address: 52,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -65,7 +61,6 @@ expression: diff.instruction_rows
address: 56,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -79,7 +74,6 @@ expression: diff.instruction_rows
address: 60,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -93,7 +87,6 @@ expression: diff.instruction_rows
address: 64,
size: 4,
opcode: 32770,
branch_dest: None,
},
),
kind: None,
@ -107,9 +100,6 @@ expression: diff.instruction_rows
address: 68,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -128,9 +118,6 @@ expression: diff.instruction_rows
address: 72,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -149,9 +136,6 @@ expression: diff.instruction_rows
address: 76,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -170,9 +154,6 @@ expression: diff.instruction_rows
address: 80,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -191,9 +172,6 @@ expression: diff.instruction_rows
address: 84,
size: 4,
opcode: 32773,
branch_dest: Some(
232,
),
},
),
kind: None,
@ -212,9 +190,6 @@ expression: diff.instruction_rows
address: 88,
size: 4,
opcode: 32773,
branch_dest: Some(
164,
),
},
),
kind: None,
@ -233,9 +208,6 @@ expression: diff.instruction_rows
address: 92,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -254,9 +226,6 @@ expression: diff.instruction_rows
address: 96,
size: 4,
opcode: 32773,
branch_dest: Some(
180,
),
},
),
kind: None,
@ -275,9 +244,6 @@ expression: diff.instruction_rows
address: 100,
size: 4,
opcode: 32773,
branch_dest: Some(
116,
),
},
),
kind: None,
@ -296,9 +262,6 @@ expression: diff.instruction_rows
address: 104,
size: 4,
opcode: 32773,
branch_dest: Some(
192,
),
},
),
kind: None,
@ -317,9 +280,6 @@ expression: diff.instruction_rows
address: 108,
size: 4,
opcode: 32773,
branch_dest: Some(
204,
),
},
),
kind: None,
@ -338,9 +298,6 @@ expression: diff.instruction_rows
address: 112,
size: 4,
opcode: 32773,
branch_dest: Some(
204,
),
},
),
kind: None,
@ -359,7 +316,6 @@ expression: diff.instruction_rows
address: 116,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -380,7 +336,6 @@ expression: diff.instruction_rows
address: 120,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -394,7 +349,6 @@ expression: diff.instruction_rows
address: 124,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -408,7 +362,6 @@ expression: diff.instruction_rows
address: 128,
size: 4,
opcode: 32800,
branch_dest: None,
},
),
kind: None,
@ -422,7 +375,6 @@ expression: diff.instruction_rows
address: 132,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -436,9 +388,6 @@ expression: diff.instruction_rows
address: 136,
size: 4,
opcode: 32773,
branch_dest: Some(
148,
),
},
),
kind: None,
@ -457,9 +406,6 @@ expression: diff.instruction_rows
address: 140,
size: 4,
opcode: 32774,
branch_dest: Some(
464,
),
},
),
kind: None,
@ -478,7 +424,6 @@ expression: diff.instruction_rows
address: 144,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -492,7 +437,6 @@ expression: diff.instruction_rows
address: 148,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -513,7 +457,6 @@ expression: diff.instruction_rows
address: 152,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -527,7 +470,6 @@ expression: diff.instruction_rows
address: 156,
size: 4,
opcode: 32777,
branch_dest: None,
},
),
kind: None,
@ -541,9 +483,6 @@ expression: diff.instruction_rows
address: 160,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -562,7 +501,6 @@ expression: diff.instruction_rows
address: 164,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -583,7 +521,6 @@ expression: diff.instruction_rows
address: 168,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -597,7 +534,6 @@ expression: diff.instruction_rows
address: 172,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -611,9 +547,6 @@ expression: diff.instruction_rows
address: 176,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -632,7 +565,6 @@ expression: diff.instruction_rows
address: 180,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -653,7 +585,6 @@ expression: diff.instruction_rows
address: 184,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -667,9 +598,6 @@ expression: diff.instruction_rows
address: 188,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -688,7 +616,6 @@ expression: diff.instruction_rows
address: 192,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -709,7 +636,6 @@ expression: diff.instruction_rows
address: 196,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -723,9 +649,6 @@ expression: diff.instruction_rows
address: 200,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -744,7 +667,6 @@ expression: diff.instruction_rows
address: 204,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -766,7 +688,6 @@ expression: diff.instruction_rows
address: 208,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -780,7 +701,6 @@ expression: diff.instruction_rows
address: 212,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -794,7 +714,6 @@ expression: diff.instruction_rows
address: 216,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -808,7 +727,6 @@ expression: diff.instruction_rows
address: 220,
size: 4,
opcode: 32899,
branch_dest: None,
},
),
kind: None,
@ -822,7 +740,6 @@ expression: diff.instruction_rows
address: 224,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -836,9 +753,6 @@ expression: diff.instruction_rows
address: 228,
size: 4,
opcode: 32773,
branch_dest: Some(
240,
),
},
),
kind: None,
@ -857,7 +771,6 @@ expression: diff.instruction_rows
address: 232,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -878,7 +791,6 @@ expression: diff.instruction_rows
address: 236,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -892,7 +804,6 @@ expression: diff.instruction_rows
address: 240,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -922,7 +833,6 @@ expression: diff.instruction_rows
address: 244,
size: 4,
opcode: 32829,
branch_dest: None,
},
),
kind: None,
@ -936,7 +846,6 @@ expression: diff.instruction_rows
address: 248,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -950,9 +859,6 @@ expression: diff.instruction_rows
address: 252,
size: 4,
opcode: 32773,
branch_dest: Some(
276,
),
},
),
kind: None,
@ -971,7 +877,6 @@ expression: diff.instruction_rows
address: 256,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -985,7 +890,6 @@ expression: diff.instruction_rows
address: 260,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -999,7 +903,6 @@ expression: diff.instruction_rows
address: 264,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -1013,7 +916,6 @@ expression: diff.instruction_rows
address: 268,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -1027,7 +929,6 @@ expression: diff.instruction_rows
address: 272,
size: 4,
opcode: 32778,
branch_dest: None,
},
),
kind: None,
@ -1041,7 +942,6 @@ expression: diff.instruction_rows
address: 276,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -1062,7 +962,6 @@ expression: diff.instruction_rows
address: 280,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1076,9 +975,6 @@ expression: diff.instruction_rows
address: 284,
size: 4,
opcode: 32773,
branch_dest: Some(
328,
),
},
),
kind: None,
@ -1097,9 +993,6 @@ expression: diff.instruction_rows
address: 288,
size: 4,
opcode: 32773,
branch_dest: Some(
336,
),
},
),
kind: None,
@ -1118,7 +1011,6 @@ expression: diff.instruction_rows
address: 292,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1132,9 +1024,6 @@ expression: diff.instruction_rows
address: 296,
size: 4,
opcode: 32773,
branch_dest: Some(
348,
),
},
),
kind: None,
@ -1153,7 +1042,6 @@ expression: diff.instruction_rows
address: 300,
size: 4,
opcode: 32829,
branch_dest: None,
},
),
kind: None,
@ -1167,7 +1055,6 @@ expression: diff.instruction_rows
address: 304,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1181,9 +1068,6 @@ expression: diff.instruction_rows
address: 308,
size: 4,
opcode: 32773,
branch_dest: Some(
348,
),
},
),
kind: None,
@ -1202,7 +1086,6 @@ expression: diff.instruction_rows
address: 312,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1216,7 +1099,6 @@ expression: diff.instruction_rows
address: 316,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1230,9 +1112,6 @@ expression: diff.instruction_rows
address: 320,
size: 4,
opcode: 32773,
branch_dest: Some(
380,
),
},
),
kind: None,
@ -1251,9 +1130,6 @@ expression: diff.instruction_rows
address: 324,
size: 4,
opcode: 32773,
branch_dest: Some(
348,
),
},
),
kind: None,
@ -1272,7 +1148,6 @@ expression: diff.instruction_rows
address: 328,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1293,9 +1168,6 @@ expression: diff.instruction_rows
address: 332,
size: 4,
opcode: 32773,
branch_dest: Some(
348,
),
},
),
kind: None,
@ -1314,7 +1186,6 @@ expression: diff.instruction_rows
address: 336,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -1335,7 +1206,6 @@ expression: diff.instruction_rows
address: 340,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -1349,9 +1219,6 @@ expression: diff.instruction_rows
address: 344,
size: 4,
opcode: 32773,
branch_dest: Some(
380,
),
},
),
kind: None,
@ -1370,7 +1237,6 @@ expression: diff.instruction_rows
address: 348,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -1394,7 +1260,6 @@ expression: diff.instruction_rows
address: 352,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -1408,7 +1273,6 @@ expression: diff.instruction_rows
address: 356,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1422,7 +1286,6 @@ expression: diff.instruction_rows
address: 360,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1436,9 +1299,6 @@ expression: diff.instruction_rows
address: 364,
size: 4,
opcode: 32773,
branch_dest: Some(
380,
),
},
),
kind: None,
@ -1457,7 +1317,6 @@ expression: diff.instruction_rows
address: 368,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -1471,7 +1330,6 @@ expression: diff.instruction_rows
address: 372,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -1485,7 +1343,6 @@ expression: diff.instruction_rows
address: 376,
size: 4,
opcode: 32899,
branch_dest: None,
},
),
kind: None,
@ -1499,7 +1356,6 @@ expression: diff.instruction_rows
address: 380,
size: 4,
opcode: 32829,
branch_dest: None,
},
),
kind: None,
@ -1522,7 +1378,6 @@ expression: diff.instruction_rows
address: 384,
size: 4,
opcode: 32770,
branch_dest: None,
},
),
kind: None,
@ -1536,7 +1391,6 @@ expression: diff.instruction_rows
address: 388,
size: 4,
opcode: 32770,
branch_dest: None,
},
),
kind: None,
@ -1550,7 +1404,6 @@ expression: diff.instruction_rows
address: 392,
size: 4,
opcode: 32898,
branch_dest: None,
},
),
kind: None,
@ -1564,7 +1417,6 @@ expression: diff.instruction_rows
address: 396,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1578,9 +1430,6 @@ expression: diff.instruction_rows
address: 400,
size: 4,
opcode: 32773,
branch_dest: Some(
424,
),
},
),
kind: None,
@ -1599,7 +1448,6 @@ expression: diff.instruction_rows
address: 404,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -1620,7 +1468,6 @@ expression: diff.instruction_rows
address: 408,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -1634,7 +1481,6 @@ expression: diff.instruction_rows
address: 412,
size: 4,
opcode: 32770,
branch_dest: None,
},
),
kind: None,
@ -1648,7 +1494,6 @@ expression: diff.instruction_rows
address: 416,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1662,9 +1507,6 @@ expression: diff.instruction_rows
address: 420,
size: 4,
opcode: 32773,
branch_dest: Some(
404,
),
},
),
kind: None,
@ -1683,7 +1525,6 @@ expression: diff.instruction_rows
address: 424,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -1704,7 +1545,6 @@ expression: diff.instruction_rows
address: 428,
size: 4,
opcode: 32799,
branch_dest: None,
},
),
kind: None,
@ -1718,7 +1558,6 @@ expression: diff.instruction_rows
address: 432,
size: 4,
opcode: 32800,
branch_dest: None,
},
),
kind: None,
@ -1732,7 +1571,6 @@ expression: diff.instruction_rows
address: 436,
size: 4,
opcode: 32786,
branch_dest: None,
},
),
kind: None,
@ -1746,9 +1584,6 @@ expression: diff.instruction_rows
address: 440,
size: 4,
opcode: 32773,
branch_dest: Some(
448,
),
},
),
kind: None,
@ -1767,7 +1602,6 @@ expression: diff.instruction_rows
address: 444,
size: 4,
opcode: 32774,
branch_dest: None,
},
),
kind: None,
@ -1781,7 +1615,6 @@ expression: diff.instruction_rows
address: 448,
size: 4,
opcode: 32818,
branch_dest: None,
},
),
kind: None,
@ -1802,7 +1635,6 @@ expression: diff.instruction_rows
address: 452,
size: 4,
opcode: 32899,
branch_dest: None,
},
),
kind: None,
@ -1816,7 +1648,6 @@ expression: diff.instruction_rows
address: 456,
size: 4,
opcode: 32793,
branch_dest: None,
},
),
kind: None,
@ -1829,8 +1660,7 @@ expression: diff.instruction_rows
InstructionRef {
address: 460,
size: 4,
opcode: 65535,
branch_dest: None,
opcode: 32771,
},
),
kind: None,
@ -1843,8 +1673,7 @@ expression: diff.instruction_rows
InstructionRef {
address: 464,
size: 4,
opcode: 65535,
branch_dest: None,
opcode: 32771,
},
),
kind: None,
@ -1864,8 +1693,7 @@ expression: diff.instruction_rows
InstructionRef {
address: 468,
size: 4,
opcode: 65535,
branch_dest: None,
opcode: 32771,
},
),
kind: None,

View File

@ -21,15 +21,15 @@ expression: output
[(Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 32773), Normal, 10), (BranchDest(152), Normal, 0), (Basic(" ~>"), Rotating(5), 0), (Eol, Normal, 0)]
[(Address(68), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 32773), Normal, 10), (BranchDest(164), Normal, 0), (Basic(" ~>"), Rotating(6), 0), (Eol, Normal, 0)]
[(Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 32773), Normal, 10), (BranchDest(164), Normal, 0), (Basic(" ~>"), Rotating(6), 0), (Eol, Normal, 0)]
[(Address(76), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("ldr", 32799), 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(336)), Normal, 0), (Basic("]"), Normal, 0), (Basic(" (->"), Normal, 0), (BranchDest(420), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(76), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("ldr", 32799), 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(336)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(80), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 32799), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(84), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 32774), Normal, 10), (Symbol(Symbol { name: "_ZN18UnkStruct_027e103c19func_ov000_020cf01cEv", demangled_name: Some("UnkStruct_027e103c::func_ov000_020cf01c()"), address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Addend(-8), Bright, 0), (Eol, Normal, 0)]
[(Address(88), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldrb", 32800), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(224)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(92), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 32786), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
[(Address(96), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 32773), Normal, 10), (BranchDest(108), Normal, 0), (Basic(" ~>"), Rotating(7), 0), (Eol, Normal, 0)]
[(Address(100), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 32774), Normal, 10), (BranchDest(424), Normal, 0), (Basic(" ~>"), Rotating(8), 0), (Eol, Normal, 0)]
[(Address(100), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 32774), Normal, 10), (Symbol(Symbol { name: "_ZN13LinkStateItem15GetEquipBombchuEv", demangled_name: Some("LinkStateItem::GetEquipBombchu()"), address: 472, size: 16, kind: Function, section: Some(0), flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-8), Bright, 0), (Basic(" ~>"), Rotating(8), 0), (Eol, Normal, 0)]
[(Address(104), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 32774), Normal, 10), (Symbol(Symbol { name: "_ZN12EquipBombchu19func_ov014_0213ec64Ev", demangled_name: Some("EquipBombchu::func_ov014_0213ec64()"), address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Addend(-8), Bright, 0), (Eol, Normal, 0)]
[(Address(108), Normal, 5), (Basic(" ~> "), Rotating(7), 0), (Opcode("ldr", 32799), 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(308)), Normal, 0), (Basic("]"), Normal, 0), (Basic(" (->"), Normal, 0), (BranchDest(424), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(108), Normal, 5), (Basic(" ~> "), Rotating(7), 0), (Opcode("ldr", 32799), 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(308)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(112), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 32799), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(116), Normal, 5), (Spacing(4), Normal, 0), (Opcode("blx", 32777), Normal, 10), (Symbol(Symbol { name: "_Z19func_ov014_0211fd04Pi", demangled_name: Some("func_ov014_0211fd04(int*)"), address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Addend(-8), Bright, 0), (Eol, Normal, 0)]
[(Address(120), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 32773), Normal, 10), (BranchDest(200), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)]
@ -43,7 +43,7 @@ expression: output
[(Address(152), Normal, 5), (Basic(" ~> "), Rotating(5), 0), (Opcode("mov", 32818), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
[(Address(156), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 32774), Normal, 10), (Symbol(Symbol { name: "_ZN13LinkStateItem15StopUsingHammerEv", demangled_name: Some("LinkStateItem::StopUsingHammer()"), address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global | Weak), align: None, virtual_address: None }), Bright, 0), (Addend(-8), Bright, 0), (Eol, Normal, 0)]
[(Address(160), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 32773), Normal, 10), (BranchDest(200), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)]
[(Address(164), Normal, 5), (Basic(" ~> "), Rotating(6), 0), (Opcode("ldr", 32799), 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(248)), Normal, 0), (Basic("]"), Normal, 0), (Basic(" (->"), Normal, 0), (BranchDest(420), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(164), Normal, 5), (Basic(" ~> "), Rotating(6), 0), (Opcode("ldr", 32799), 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(248)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(168), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 32818), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
[(Address(172), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 32799), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(176), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 32818), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r1")), Normal, 0), (Eol, Normal, 0)]
@ -98,7 +98,7 @@ expression: output
[(Address(372), Normal, 5), (Spacing(4), Normal, 0), (Opcode("add", 32770), Normal, 10), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(4)), Normal, 0), (Eol, Normal, 0)]
[(Address(376), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 32786), Normal, 10), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Eol, Normal, 0)]
[(Address(380), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 32773), Normal, 10), (BranchDest(364), Normal, 0), (Basic(" ~>"), Rotating(15), 0), (Eol, Normal, 0)]
[(Address(384), Normal, 5), (Basic(" ~> "), Rotating(14), 0), (Opcode("ldr", 32799), 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(36)), Normal, 0), (Basic("]"), Normal, 0), (Basic(" (->"), Normal, 0), (BranchDest(428), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(384), Normal, 5), (Basic(" ~> "), Rotating(14), 0), (Opcode("ldr", 32799), 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(36)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(388), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 32799), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(392), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldrb", 32800), 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(128)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(396), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 32786), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Unsigned(0)), Normal, 0), (Eol, Normal, 0)]
@ -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(".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)]
[(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)]

View File

@ -5,7 +5,7 @@ expression: obj
Object {
arch: ArchArm {
disasm_modes: {
0: [
1: [
DisasmMode {
address: 0,
mapping: Thumb,
@ -1519,9 +1519,6 @@ Object {
556,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [
Relocation {
flags: Elf(
@ -1721,9 +1718,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1738,9 +1732,6 @@ Object {
76,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [
Relocation {
flags: Elf(
@ -1892,9 +1883,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1909,9 +1897,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1926,9 +1911,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1943,9 +1925,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,

File diff suppressed because it is too large Load Diff

View File

@ -1,111 +0,0 @@
---
source: objdiff-core/tests/arch_arm.rs
assertion_line: 33
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), (Basic(" (->"), Normal, 0), (BranchDest(216), 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), (Basic(" (->"), Normal, 0), (BranchDest(220), 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), (Basic(" (->"), Normal, 0), (BranchDest(224), 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), (Basic(" (->"), Normal, 0), (BranchDest(228), 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), (Basic(" (->"), Normal, 0), (BranchDest(220), 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), (Basic(" (->"), Normal, 0), (BranchDest(232), 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), (Basic(" (->"), Normal, 0), (BranchDest(236), 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), (Basic(" (->"), Normal, 0), (BranchDest(224), 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), (Basic(" (->"), Normal, 0), (BranchDest(240), 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)]

File diff suppressed because it is too large Load Diff

View File

@ -1,452 +0,0 @@
---
source: objdiff-core/tests/arch_mips.rs
expression: obj.symbols
---
[
Symbol {
name: "build/src/bodyprog/view/vw_main.i",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.text]",
demangled_name: None,
address: 0,
size: 0,
kind: Section,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.data]",
demangled_name: None,
address: 0,
size: 0,
kind: Section,
section: Some(
2,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.bss]",
demangled_name: None,
address: 0,
size: 0,
kind: Section,
section: Some(
3,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "gcc2_compiled.",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "__gnu_compiled_c",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: ".endfunc_80048AF4",
demangled_name: None,
address: 424,
size: 0,
kind: Unknown,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: ".endfunc_80048DA8",
demangled_name: None,
address: 1028,
size: 0,
kind: Unknown,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: ".endfunc_80048E3C",
demangled_name: None,
address: 1264,
size: 0,
kind: Unknown,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.reginfo]",
demangled_name: None,
address: 0,
size: 24,
kind: Section,
section: Some(
4,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.MIPS.abiflags]",
demangled_name: None,
address: 0,
size: 24,
kind: Section,
section: Some(
5,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.pdr]",
demangled_name: None,
address: 0,
size: 320,
kind: Section,
section: Some(
6,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.gnu.attributes]",
demangled_name: None,
address: 0,
size: 16,
kind: Section,
section: Some(
8,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "vwInitViewInfo",
demangled_name: None,
address: 0,
size: 88,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vwViewPointInfo",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "GsInitCoordinate2",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vwSetViewInfo",
demangled_name: None,
address: 784,
size: 96,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vwGetViewCoord",
demangled_name: None,
address: 88,
size: 12,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vwGetViewPosition",
demangled_name: None,
address: 100,
size: 40,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vwGetViewAngle",
demangled_name: None,
address: 140,
size: 48,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80048AF4",
demangled_name: None,
address: 188,
size: 236,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global | Ignored),
align: None,
virtual_address: None,
},
Symbol {
name: "ratan2",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "SquareRoot0",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80096C94",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vwSetViewInfoDirectMatrix",
demangled_name: None,
address: 696,
size: 88,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80048AF4.NON_MATCHING",
demangled_name: None,
address: 188,
size: 236,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global | Ignored),
align: None,
virtual_address: None,
},
Symbol {
name: "vwSetCoordRefAndEntou",
demangled_name: None,
address: 424,
size: 272,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80096E78",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "shRsin",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "shRcos",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vbSetRefView",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "vwMatrixToAngleYXZ",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Global),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80048DA8",
demangled_name: None,
address: 880,
size: 148,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global | Ignored),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80048DA8.NON_MATCHING",
demangled_name: None,
address: 880,
size: 148,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global | Ignored),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80048E3C",
demangled_name: None,
address: 1028,
size: 236,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global | Ignored),
align: None,
virtual_address: None,
},
Symbol {
name: "func_80048E3C.NON_MATCHING",
demangled_name: None,
address: 1028,
size: 236,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global | Ignored),
align: None,
virtual_address: None,
},
]

View File

@ -9,7 +9,6 @@ expression: diff.instruction_rows
address: 0,
size: 4,
opcode: 12,
branch_dest: None,
},
),
kind: None,
@ -23,7 +22,6 @@ expression: diff.instruction_rows
address: 4,
size: 4,
opcode: 44,
branch_dest: None,
},
),
kind: None,
@ -37,7 +35,6 @@ expression: diff.instruction_rows
address: 8,
size: 4,
opcode: 44,
branch_dest: None,
},
),
kind: None,
@ -51,7 +48,6 @@ expression: diff.instruction_rows
address: 12,
size: 4,
opcode: 44,
branch_dest: None,
},
),
kind: None,
@ -65,7 +61,6 @@ expression: diff.instruction_rows
address: 16,
size: 4,
opcode: 44,
branch_dest: None,
},
),
kind: None,
@ -79,7 +74,6 @@ expression: diff.instruction_rows
address: 20,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -93,7 +87,6 @@ expression: diff.instruction_rows
address: 24,
size: 4,
opcode: 113,
branch_dest: None,
},
),
kind: None,
@ -107,7 +100,6 @@ expression: diff.instruction_rows
address: 28,
size: 4,
opcode: 26,
branch_dest: None,
},
),
kind: None,
@ -121,7 +113,6 @@ expression: diff.instruction_rows
address: 32,
size: 4,
opcode: 20,
branch_dest: None,
},
),
kind: None,
@ -135,7 +126,6 @@ expression: diff.instruction_rows
address: 36,
size: 4,
opcode: 97,
branch_dest: None,
},
),
kind: None,
@ -149,7 +139,6 @@ expression: diff.instruction_rows
address: 40,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -163,7 +152,6 @@ expression: diff.instruction_rows
address: 44,
size: 4,
opcode: 12,
branch_dest: None,
},
),
kind: None,
@ -177,7 +165,6 @@ expression: diff.instruction_rows
address: 48,
size: 4,
opcode: 20,
branch_dest: None,
},
),
kind: None,
@ -191,7 +178,6 @@ expression: diff.instruction_rows
address: 52,
size: 4,
opcode: 26,
branch_dest: None,
},
),
kind: None,
@ -205,7 +191,6 @@ expression: diff.instruction_rows
address: 56,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -219,7 +204,6 @@ expression: diff.instruction_rows
address: 60,
size: 4,
opcode: 12,
branch_dest: None,
},
),
kind: None,
@ -233,7 +217,6 @@ expression: diff.instruction_rows
address: 64,
size: 4,
opcode: 26,
branch_dest: None,
},
),
kind: None,
@ -247,7 +230,6 @@ expression: diff.instruction_rows
address: 68,
size: 4,
opcode: 97,
branch_dest: None,
},
),
kind: None,
@ -261,7 +243,6 @@ expression: diff.instruction_rows
address: 72,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -275,7 +256,6 @@ expression: diff.instruction_rows
address: 76,
size: 4,
opcode: 97,
branch_dest: None,
},
),
kind: None,
@ -289,7 +269,6 @@ expression: diff.instruction_rows
address: 80,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -310,7 +289,6 @@ expression: diff.instruction_rows
address: 84,
size: 4,
opcode: 97,
branch_dest: None,
},
),
kind: None,
@ -324,9 +302,6 @@ expression: diff.instruction_rows
address: 88,
size: 4,
opcode: 56,
branch_dest: Some(
80,
),
},
),
kind: None,
@ -345,7 +320,6 @@ expression: diff.instruction_rows
address: 92,
size: 4,
opcode: 113,
branch_dest: None,
},
),
kind: None,
@ -359,7 +333,6 @@ expression: diff.instruction_rows
address: 96,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -373,7 +346,6 @@ expression: diff.instruction_rows
address: 100,
size: 4,
opcode: 20,
branch_dest: None,
},
),
kind: None,
@ -387,7 +359,6 @@ expression: diff.instruction_rows
address: 104,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -401,7 +372,6 @@ expression: diff.instruction_rows
address: 108,
size: 4,
opcode: 12,
branch_dest: None,
},
),
kind: None,
@ -415,7 +385,6 @@ expression: diff.instruction_rows
address: 112,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -429,7 +398,6 @@ expression: diff.instruction_rows
address: 116,
size: 4,
opcode: 16,
branch_dest: None,
},
),
kind: None,
@ -443,7 +411,6 @@ expression: diff.instruction_rows
address: 120,
size: 4,
opcode: 20,
branch_dest: None,
},
),
kind: None,
@ -457,7 +424,6 @@ expression: diff.instruction_rows
address: 124,
size: 4,
opcode: 12,
branch_dest: None,
},
),
kind: None,
@ -471,7 +437,6 @@ expression: diff.instruction_rows
address: 128,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -494,7 +459,6 @@ expression: diff.instruction_rows
address: 132,
size: 4,
opcode: 12,
branch_dest: None,
},
),
kind: None,
@ -508,7 +472,6 @@ expression: diff.instruction_rows
address: 136,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -522,7 +485,6 @@ expression: diff.instruction_rows
address: 140,
size: 4,
opcode: 113,
branch_dest: None,
},
),
kind: None,
@ -536,9 +498,6 @@ expression: diff.instruction_rows
address: 144,
size: 4,
opcode: 55,
branch_dest: Some(
128,
),
},
),
kind: None,
@ -557,7 +516,6 @@ expression: diff.instruction_rows
address: 148,
size: 4,
opcode: 90,
branch_dest: None,
},
),
kind: None,
@ -571,9 +529,6 @@ expression: diff.instruction_rows
address: 152,
size: 4,
opcode: 3,
branch_dest: Some(
128,
),
},
),
kind: None,
@ -592,7 +547,6 @@ expression: diff.instruction_rows
address: 156,
size: 4,
opcode: 113,
branch_dest: None,
},
),
kind: None,
@ -606,7 +560,6 @@ expression: diff.instruction_rows
address: 160,
size: 4,
opcode: 2,
branch_dest: None,
},
),
kind: None,
@ -620,7 +573,6 @@ expression: diff.instruction_rows
address: 164,
size: 4,
opcode: 60,
branch_dest: None,
},
),
kind: None,
@ -634,7 +586,6 @@ expression: diff.instruction_rows
address: 168,
size: 4,
opcode: 77,
branch_dest: None,
},
),
kind: None,
@ -648,7 +599,6 @@ expression: diff.instruction_rows
address: 172,
size: 4,
opcode: 113,
branch_dest: None,
},
),
kind: None,
@ -662,9 +612,6 @@ expression: diff.instruction_rows
address: 176,
size: 4,
opcode: 54,
branch_dest: Some(
128,
),
},
),
kind: None,
@ -683,7 +630,6 @@ expression: diff.instruction_rows
address: 180,
size: 4,
opcode: 113,
branch_dest: None,
},
),
kind: None,

View File

@ -50,7 +50,6 @@ Object {
{},
{},
],
ignored_symbols: {},
},
endianness: Little,
symbols: [
@ -683,9 +682,6 @@ Object {
632,
),
flags: FlagSet(),
align: Some(
8,
),
relocations: [
Relocation {
flags: Elf(
@ -1309,9 +1305,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1326,9 +1319,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1343,9 +1333,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1360,9 +1347,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1377,9 +1361,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1394,9 +1375,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1411,9 +1389,6 @@ Object {
43,
),
flags: FlagSet(),
align: Some(
8,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1428,9 +1403,6 @@ Object {
76,
),
flags: FlagSet(),
align: Some(
8,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1445,9 +1417,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1462,9 +1431,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -1479,9 +1445,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
---
source: objdiff-core/tests/arch_ppc.rs
assertion_line: 70
expression: sections_display
---
[
@ -47,7 +46,7 @@ expression: sections_display
name: ".text",
size: 3060,
match_percent: Some(
58.662746,
59.02353,
),
symbols: [
SectionDisplaySymbol {

View File

@ -317,9 +317,6 @@ Object {
552,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [
Relocation {
flags: Elf(
@ -343,9 +340,6 @@ Object {
40,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [
Relocation {
flags: Elf(
@ -369,9 +363,6 @@ Object {
36,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [
Relocation {
flags: Elf(
@ -435,9 +426,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -452,9 +440,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -469,9 +454,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -486,9 +468,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -503,9 +482,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -520,9 +496,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -537,9 +510,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,

View File

@ -9,7 +9,6 @@ expression: diff.instruction_rows
address: 0,
size: 4,
opcode: 60,
branch_dest: None,
},
),
kind: None,
@ -23,7 +22,6 @@ expression: diff.instruction_rows
address: 4,
size: 4,
opcode: 38,
branch_dest: None,
},
),
kind: None,
@ -37,9 +35,6 @@ expression: diff.instruction_rows
address: 8,
size: 4,
opcode: 43,
branch_dest: Some(
20,
),
},
),
kind: None,
@ -58,7 +53,6 @@ expression: diff.instruction_rows
address: 12,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -72,9 +66,6 @@ expression: diff.instruction_rows
address: 16,
size: 4,
opcode: 45,
branch_dest: Some(
32,
),
},
),
kind: None,
@ -93,7 +84,6 @@ expression: diff.instruction_rows
address: 20,
size: 4,
opcode: 42,
branch_dest: None,
},
),
kind: None,
@ -114,7 +104,6 @@ expression: diff.instruction_rows
address: 24,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -128,7 +117,6 @@ expression: diff.instruction_rows
address: 28,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -142,7 +130,6 @@ expression: diff.instruction_rows
address: 32,
size: 4,
opcode: 60,
branch_dest: None,
},
),
kind: None,
@ -163,7 +150,6 @@ expression: diff.instruction_rows
address: 36,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -177,7 +163,6 @@ expression: diff.instruction_rows
address: 40,
size: 4,
opcode: 38,
branch_dest: None,
},
),
kind: None,
@ -191,9 +176,6 @@ expression: diff.instruction_rows
address: 44,
size: 4,
opcode: 43,
branch_dest: Some(
56,
),
},
),
kind: None,
@ -212,7 +194,6 @@ expression: diff.instruction_rows
address: 48,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -226,9 +207,6 @@ expression: diff.instruction_rows
address: 52,
size: 4,
opcode: 45,
branch_dest: Some(
68,
),
},
),
kind: None,
@ -247,7 +225,6 @@ expression: diff.instruction_rows
address: 56,
size: 4,
opcode: 42,
branch_dest: None,
},
),
kind: None,
@ -268,7 +245,6 @@ expression: diff.instruction_rows
address: 60,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -282,7 +258,6 @@ expression: diff.instruction_rows
address: 64,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -296,7 +271,6 @@ expression: diff.instruction_rows
address: 68,
size: 4,
opcode: 60,
branch_dest: None,
},
),
kind: None,
@ -317,7 +291,6 @@ expression: diff.instruction_rows
address: 72,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -331,7 +304,6 @@ expression: diff.instruction_rows
address: 76,
size: 4,
opcode: 38,
branch_dest: None,
},
),
kind: None,
@ -345,7 +317,6 @@ expression: diff.instruction_rows
address: 80,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -359,9 +330,6 @@ expression: diff.instruction_rows
address: 84,
size: 4,
opcode: 43,
branch_dest: Some(
96,
),
},
),
kind: None,
@ -380,7 +348,6 @@ expression: diff.instruction_rows
address: 88,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -394,9 +361,6 @@ expression: diff.instruction_rows
address: 92,
size: 4,
opcode: 45,
branch_dest: Some(
108,
),
},
),
kind: None,
@ -415,7 +379,6 @@ expression: diff.instruction_rows
address: 96,
size: 4,
opcode: 42,
branch_dest: None,
},
),
kind: None,
@ -436,7 +399,6 @@ expression: diff.instruction_rows
address: 100,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -450,7 +412,6 @@ expression: diff.instruction_rows
address: 104,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -464,7 +425,6 @@ expression: diff.instruction_rows
address: 108,
size: 4,
opcode: 60,
branch_dest: None,
},
),
kind: None,
@ -485,7 +445,6 @@ expression: diff.instruction_rows
address: 112,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -499,7 +458,6 @@ expression: diff.instruction_rows
address: 116,
size: 4,
opcode: 38,
branch_dest: None,
},
),
kind: None,
@ -513,7 +471,6 @@ expression: diff.instruction_rows
address: 120,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -527,9 +484,6 @@ expression: diff.instruction_rows
address: 124,
size: 4,
opcode: 43,
branch_dest: Some(
136,
),
},
),
kind: None,
@ -548,7 +502,6 @@ expression: diff.instruction_rows
address: 128,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -562,9 +515,6 @@ expression: diff.instruction_rows
address: 132,
size: 4,
opcode: 45,
branch_dest: Some(
148,
),
},
),
kind: None,
@ -583,7 +533,6 @@ expression: diff.instruction_rows
address: 136,
size: 4,
opcode: 42,
branch_dest: None,
},
),
kind: None,
@ -604,7 +553,6 @@ expression: diff.instruction_rows
address: 140,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -618,7 +566,6 @@ expression: diff.instruction_rows
address: 144,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -632,7 +579,6 @@ expression: diff.instruction_rows
address: 148,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -653,7 +599,6 @@ expression: diff.instruction_rows
address: 152,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -667,7 +612,6 @@ expression: diff.instruction_rows
address: 156,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -681,7 +625,6 @@ expression: diff.instruction_rows
address: 160,
size: 4,
opcode: 42,
branch_dest: None,
},
),
kind: None,
@ -695,7 +638,6 @@ expression: diff.instruction_rows
address: 164,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -709,7 +651,6 @@ expression: diff.instruction_rows
address: 168,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -723,7 +664,6 @@ expression: diff.instruction_rows
address: 172,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -737,7 +677,6 @@ expression: diff.instruction_rows
address: 176,
size: 4,
opcode: 162,
branch_dest: None,
},
),
kind: None,
@ -751,7 +690,6 @@ expression: diff.instruction_rows
address: 180,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -765,7 +703,6 @@ expression: diff.instruction_rows
address: 184,
size: 4,
opcode: 66,
branch_dest: None,
},
),
kind: None,
@ -779,9 +716,6 @@ expression: diff.instruction_rows
address: 188,
size: 4,
opcode: 43,
branch_dest: Some(
196,
),
},
),
kind: None,
@ -800,7 +734,6 @@ expression: diff.instruction_rows
address: 192,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -814,7 +747,6 @@ expression: diff.instruction_rows
address: 196,
size: 4,
opcode: 163,
branch_dest: None,
},
),
kind: None,
@ -835,7 +767,6 @@ expression: diff.instruction_rows
address: 200,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -849,7 +780,6 @@ expression: diff.instruction_rows
address: 204,
size: 4,
opcode: 66,
branch_dest: None,
},
),
kind: None,
@ -863,9 +793,6 @@ expression: diff.instruction_rows
address: 208,
size: 4,
opcode: 43,
branch_dest: Some(
216,
),
},
),
kind: None,
@ -884,7 +811,6 @@ expression: diff.instruction_rows
address: 212,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -898,7 +824,6 @@ expression: diff.instruction_rows
address: 216,
size: 4,
opcode: 163,
branch_dest: None,
},
),
kind: None,
@ -919,7 +844,6 @@ expression: diff.instruction_rows
address: 220,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -933,7 +857,6 @@ expression: diff.instruction_rows
address: 224,
size: 4,
opcode: 66,
branch_dest: None,
},
),
kind: None,
@ -947,9 +870,6 @@ expression: diff.instruction_rows
address: 228,
size: 4,
opcode: 43,
branch_dest: Some(
236,
),
},
),
kind: None,
@ -968,7 +888,6 @@ expression: diff.instruction_rows
address: 232,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -982,7 +901,6 @@ expression: diff.instruction_rows
address: 236,
size: 4,
opcode: 163,
branch_dest: None,
},
),
kind: None,
@ -1003,7 +921,6 @@ expression: diff.instruction_rows
address: 240,
size: 4,
opcode: 94,
branch_dest: None,
},
),
kind: None,
@ -1017,7 +934,6 @@ expression: diff.instruction_rows
address: 244,
size: 4,
opcode: 66,
branch_dest: None,
},
),
kind: None,
@ -1031,9 +947,6 @@ expression: diff.instruction_rows
address: 248,
size: 4,
opcode: 43,
branch_dest: Some(
256,
),
},
),
kind: None,
@ -1052,7 +965,6 @@ expression: diff.instruction_rows
address: 252,
size: 4,
opcode: 166,
branch_dest: None,
},
),
kind: None,
@ -1066,7 +978,6 @@ expression: diff.instruction_rows
address: 256,
size: 4,
opcode: 41,
branch_dest: None,
},
),
kind: None,
@ -1087,7 +998,6 @@ expression: diff.instruction_rows
address: 260,
size: 4,
opcode: 47,
branch_dest: None,
},
),
kind: None,

View File

@ -1,6 +1,5 @@
---
source: objdiff-core/tests/arch_ppc.rs
assertion_line: 20
expression: output
---
[(Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("srwi", 60), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("24")), Normal, 0), (Eol, Normal, 0)]
@ -10,7 +9,7 @@ expression: output
[(Address(16), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(32), Normal, 0), (Basic(" ~>"), Rotating(1), 0), (Eol, Normal, 0)]
[(Address(20), Normal, 5), (Basic(" ~> "), Rotating(0), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
[(Address(24), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
[(Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r0")), Normal, 0), (Eol, Normal, 0)]
[(Address(32), Normal, 5), (Basic(" ~> "), Rotating(1), 0), (Opcode("extrwi", 60), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Eol, Normal, 0)]
[(Address(36), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
[(Address(40), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
@ -19,7 +18,7 @@ expression: output
[(Address(52), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(68), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
[(Address(56), Normal, 5), (Basic(" ~> "), Rotating(2), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
[(Address(60), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
[(Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
[(Address(68), Normal, 5), (Basic(" ~> "), Rotating(3), 0), (Opcode("extrwi", 60), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("8")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("16")), Normal, 0), (Eol, Normal, 0)]
[(Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
[(Address(76), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
@ -29,7 +28,7 @@ expression: output
[(Address(92), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(108), Normal, 0), (Basic(" ~>"), Rotating(5), 0), (Eol, Normal, 0)]
[(Address(96), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
[(Address(100), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
[(Address(104), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(104), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Eol, Normal, 0)]
[(Address(108), Normal, 5), (Basic(" ~> "), Rotating(5), 0), (Opcode("clrlwi", 60), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("24")), Normal, 0), (Eol, Normal, 0)]
[(Address(112), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
[(Address(116), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmpwi", 38), Normal, 10), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(-1)), Normal, 0), (Eol, Normal, 0)]
@ -39,7 +38,7 @@ expression: output
[(Address(132), Normal, 5), (Spacing(4), Normal, 0), (Opcode("b", 45), Normal, 10), (BranchDest(148), Normal, 0), (Basic(" ~>"), Rotating(7), 0), (Eol, Normal, 0)]
[(Address(136), Normal, 5), (Basic(" ~> "), Rotating(6), 0), (Opcode("lis", 42), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@ha"), Normal, 0), (Eol, Normal, 0)]
[(Address(140), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addi", 41), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic("@l"), Normal, 0), (Eol, Normal, 0)]
[(Address(144), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__upper_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(144), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Eol, Normal, 0)]
[(Address(148), Normal, 5), (Basic(" ~> "), Rotating(7), 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
[(Address(152), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Eol, Normal, 0)]
[(Address(156), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(3)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
@ -48,22 +47,22 @@ expression: output
[(Address(168), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(172), Normal, 5), (Spacing(4), Normal, 0), (Opcode("li", 41), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(45)), Normal, 0), (Eol, Normal, 0)]
[(Address(176), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbz", 162), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Symbol(Symbol { name: "text$52", demangled_name: None, address: 8, size: 5, kind: Object, section: Some(2), flags: FlagSet(Local), align: None, virtual_address: Some(2153420056) }), Bright, 0), (Basic("@sda21"), Normal, 0), (Eol, Normal, 0)]
[(Address(180), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(180), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
[(Address(184), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
[(Address(188), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(196), Normal, 0), (Basic(" ~>"), Rotating(8), 0), (Eol, Normal, 0)]
[(Address(192), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(196), Normal, 5), (Basic(" ~> "), Rotating(8), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(200), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(200), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
[(Address(204), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
[(Address(208), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(216), Normal, 0), (Basic(" ~>"), Rotating(9), 0), (Eol, Normal, 0)]
[(Address(212), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(216), Normal, 5), (Basic(" ~> "), Rotating(9), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(220), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(220), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
[(Address(224), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
[(Address(228), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(236), Normal, 0), (Basic(" ~>"), Rotating(10), 0), (Eol, Normal, 0)]
[(Address(232), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(236), Normal, 5), (Basic(" ~> "), Rotating(10), 0), (Opcode("lbzu", 163), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(1)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(240), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(" <"), Normal, 0), (Symbol(Symbol { name: "__ctype_map", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: Some(0) }), Bright, 0), (Basic(">"), Normal, 0), (Eol, Normal, 0)]
[(Address(240), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lbzx", 94), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Eol, Normal, 0)]
[(Address(244), Normal, 5), (Spacing(4), Normal, 0), (Opcode("andi.", 66), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Unsigned(220)), Normal, 0), (Eol, Normal, 0)]
[(Address(248), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 43), Normal, 10), (BranchDest(256), Normal, 0), (Basic(" ~>"), Rotating(11), 0), (Eol, Normal, 0)]
[(Address(252), Normal, 5), (Spacing(4), Normal, 0), (Opcode("stb", 166), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Signed(0)), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]

View File

@ -166,9 +166,6 @@ Object {
284,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [
Relocation {
flags: Elf(
@ -186,14 +183,6 @@ Object {
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 28,
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
109,
@ -218,14 +207,6 @@ Object {
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 64,
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
109,
@ -250,14 +231,6 @@ Object {
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 104,
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
109,
@ -282,14 +255,6 @@ Object {
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 144,
target_symbol: 8,
addend: 0,
},
Relocation {
flags: Elf(
109,
@ -322,38 +287,6 @@ Object {
target_symbol: 5,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 180,
target_symbol: 9,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 200,
target_symbol: 9,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 220,
target_symbol: 9,
addend: 0,
},
Relocation {
flags: Elf(
0,
),
address: 240,
target_symbol: 9,
addend: 0,
},
Relocation {
flags: Elf(
109,
@ -394,9 +327,6 @@ Object {
4,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [
Relocation {
flags: Elf(
@ -422,9 +352,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
8,
),
relocations: [],
line_info: {},
virtual_address: Some(
@ -441,9 +368,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -458,9 +382,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -475,9 +396,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -492,9 +410,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -509,9 +424,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -526,9 +438,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -543,9 +452,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [],
line_info: {},
virtual_address: None,

View File

@ -1,210 +0,0 @@
---
source: objdiff-core/tests/arch_x86.rs
expression: section_display
---
[
SectionDisplay {
id: ".text-0",
name: ".text",
size: 47,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 28,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-1",
name: ".text",
size: 65,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 29,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-2",
name: ".text",
size: 5,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 30,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-3",
name: ".text",
size: 141,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 31,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-4",
name: ".text",
size: 120,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 34,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-5",
name: ".text",
size: 378,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 37,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-6",
name: ".text",
size: 130,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 38,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-7",
name: ".text",
size: 123,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 39,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-8",
name: ".text",
size: 70,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 40,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-9",
name: ".text",
size: 90,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 41,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-10",
name: ".text",
size: 82,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 42,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-11",
name: ".text",
size: 336,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 43,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-12",
name: ".text",
size: 193,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 50,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-13",
name: ".text",
size: 544,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 53,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-14",
name: ".text",
size: 250,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 56,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-15",
name: ".text",
size: 89,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 57,
is_mapping_symbol: false,
},
],
},
SectionDisplay {
id: ".text-16",
name: ".text",
size: 119,
match_percent: None,
symbols: [
SectionDisplaySymbol {
symbol: 60,
is_mapping_symbol: false,
},
],
},
]

View File

@ -9,7 +9,6 @@ expression: diff.instruction_rows
address: 0,
size: 1,
opcode: 640,
branch_dest: None,
},
),
kind: None,
@ -23,7 +22,6 @@ expression: diff.instruction_rows
address: 1,
size: 2,
opcode: 414,
branch_dest: None,
},
),
kind: None,
@ -37,7 +35,6 @@ expression: diff.instruction_rows
address: 3,
size: 5,
opcode: 640,
branch_dest: None,
},
),
kind: None,
@ -51,7 +48,6 @@ expression: diff.instruction_rows
address: 8,
size: 5,
opcode: 59,
branch_dest: None,
},
),
kind: None,
@ -65,7 +61,6 @@ expression: diff.instruction_rows
address: 13,
size: 3,
opcode: 7,
branch_dest: None,
},
),
kind: None,
@ -79,7 +74,6 @@ expression: diff.instruction_rows
address: 16,
size: 1,
opcode: 590,
branch_dest: None,
},
),
kind: None,
@ -93,7 +87,6 @@ expression: diff.instruction_rows
address: 17,
size: 1,
opcode: 662,
branch_dest: None,
},
),
kind: None,

View File

@ -4,7 +4,7 @@ expression: obj
---
Object {
arch: ArchX86 {
arch: X86,
bits: 32,
endianness: Little,
},
endianness: Little,
@ -136,9 +136,6 @@ Object {
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -153,9 +150,6 @@ Object {
10,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [
Relocation {
flags: Coff(
@ -179,9 +173,6 @@ Object {
18,
),
flags: FlagSet(),
align: Some(
16,
),
relocations: [
Relocation {
flags: Coff(

View File

@ -1,300 +0,0 @@
---
source: objdiff-core/tests/arch_x86.rs
expression: diff.instruction_rows
---
[
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 0,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 5,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 10,
size: 1,
opcode: 640,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 11,
size: 4,
opcode: 740,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 15,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 20,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 25,
size: 4,
opcode: 448,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 29,
size: 4,
opcode: 460,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 33,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 38,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 43,
size: 5,
opcode: 448,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 48,
size: 5,
opcode: 460,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 53,
size: 4,
opcode: 11,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 57,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 62,
size: 5,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 67,
size: 5,
opcode: 448,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 72,
size: 5,
opcode: 460,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 77,
size: 4,
opcode: 11,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 81,
size: 4,
opcode: 7,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 85,
size: 1,
opcode: 590,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 86,
size: 1,
opcode: 662,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
]

View File

@ -1,25 +0,0 @@
---
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)]

File diff suppressed because it is too large Load Diff

View File

@ -13,9 +13,6 @@ expression: obj.sections
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -30,9 +27,6 @@ expression: obj.sections
0,
),
flags: FlagSet(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
@ -42,14 +36,11 @@ expression: obj.sections
name: ".rdata",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -59,14 +50,11 @@ expression: obj.sections
name: ".rdata",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -76,14 +64,11 @@ expression: obj.sections
name: ".text$mn",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
16,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -98,9 +83,6 @@ expression: obj.sections
56,
),
flags: FlagSet(Combined),
align: Some(
4,
),
relocations: [
Relocation {
flags: Coff(
@ -150,15 +132,12 @@ expression: obj.sections
id: ".rdata-combined",
name: ".rdata",
address: 0,
size: 304,
size: 295,
kind: Data,
data: SectionData(
304,
295,
),
flags: FlagSet(Combined),
align: Some(
4,
),
relocations: [
Relocation {
flags: Coff(
@ -180,7 +159,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 24,
address: 21,
target_symbol: 13,
addend: 0,
},
@ -188,7 +167,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 48,
address: 45,
target_symbol: 15,
addend: 0,
},
@ -196,7 +175,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 64,
address: 61,
target_symbol: 25,
addend: 0,
},
@ -204,7 +183,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 68,
address: 65,
target_symbol: 27,
addend: 0,
},
@ -212,7 +191,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 76,
address: 70,
target_symbol: 21,
addend: 0,
},
@ -220,7 +199,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 100,
address: 94,
target_symbol: 23,
addend: 0,
},
@ -228,7 +207,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 116,
address: 110,
target_symbol: 31,
addend: 0,
},
@ -236,7 +215,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 120,
address: 114,
target_symbol: 33,
addend: 0,
},
@ -244,7 +223,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 136,
address: 130,
target_symbol: 35,
addend: 0,
},
@ -252,7 +231,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 140,
address: 134,
target_symbol: 37,
addend: 0,
},
@ -260,7 +239,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 144,
address: 138,
target_symbol: 19,
addend: 0,
},
@ -268,7 +247,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 148,
address: 142,
target_symbol: 39,
addend: 0,
},
@ -276,7 +255,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 156,
address: 147,
target_symbol: 31,
addend: 0,
},
@ -284,7 +263,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 180,
address: 171,
target_symbol: 33,
addend: 0,
},
@ -292,7 +271,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 184,
address: 175,
target_symbol: 21,
addend: 0,
},
@ -300,7 +279,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 208,
address: 199,
target_symbol: 23,
addend: 0,
},
@ -308,7 +287,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 224,
address: 215,
target_symbol: 31,
addend: 0,
},
@ -316,7 +295,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 228,
address: 219,
target_symbol: 33,
addend: 0,
},
@ -324,7 +303,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 244,
address: 235,
target_symbol: 13,
addend: 0,
},
@ -332,7 +311,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 248,
address: 239,
target_symbol: 15,
addend: 0,
},
@ -340,7 +319,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 264,
address: 255,
target_symbol: 21,
addend: 0,
},
@ -348,7 +327,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 268,
address: 259,
target_symbol: 23,
addend: 0,
},
@ -356,7 +335,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 272,
address: 263,
target_symbol: 29,
addend: 0,
},
@ -364,7 +343,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 276,
address: 267,
target_symbol: 11,
addend: 0,
},
@ -372,7 +351,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 280,
address: 271,
target_symbol: 43,
addend: 0,
},
@ -380,7 +359,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 284,
address: 275,
target_symbol: 41,
addend: 0,
},
@ -388,7 +367,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 288,
address: 279,
target_symbol: 70,
addend: 0,
},
@ -396,7 +375,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 292,
address: 283,
target_symbol: 56,
addend: 0,
},
@ -404,7 +383,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 296,
address: 287,
target_symbol: 72,
addend: 0,
},
@ -412,7 +391,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 300,
address: 291,
target_symbol: 59,
addend: 0,
},
@ -425,14 +404,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -442,14 +418,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -459,14 +432,11 @@ expression: obj.sections
name: ".data$rs",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -476,14 +446,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -493,14 +460,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -510,14 +474,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -527,14 +488,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -544,14 +502,11 @@ expression: obj.sections
name: ".data$rs",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -561,14 +516,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -578,14 +530,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -595,14 +544,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -612,14 +558,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -629,14 +572,11 @@ expression: obj.sections
name: ".text$mn",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
1,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -646,14 +586,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -663,14 +600,11 @@ expression: obj.sections
name: ".text$mn",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
16,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -680,14 +614,11 @@ expression: obj.sections
name: ".text$mn",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
16,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -697,14 +628,11 @@ expression: obj.sections
name: ".text$mn",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
16,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -714,14 +642,11 @@ expression: obj.sections
name: ".text$mn",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
16,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -731,14 +656,11 @@ expression: obj.sections
name: ".text$mn",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
16,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -747,15 +669,12 @@ expression: obj.sections
id: ".text-combined",
name: ".text",
address: 0,
size: 320,
size: 268,
kind: Code,
data: SectionData(
320,
268,
),
flags: FlagSet(Combined),
align: Some(
16,
),
relocations: [
Relocation {
flags: Coff(
@ -777,7 +696,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 43,
address: 29,
target_symbol: 60,
addend: 0,
},
@ -785,7 +704,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 62,
address: 48,
target_symbol: 52,
addend: 0,
},
@ -793,7 +712,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 84,
address: 68,
target_symbol: 11,
addend: 0,
},
@ -801,7 +720,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 100,
address: 84,
target_symbol: 64,
addend: 0,
},
@ -809,7 +728,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 124,
address: 104,
target_symbol: 66,
addend: 0,
},
@ -817,7 +736,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 156,
address: 124,
target_symbol: 6,
addend: 0,
},
@ -825,7 +744,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 166,
address: 134,
target_symbol: 8,
addend: 0,
},
@ -833,7 +752,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 177,
address: 145,
target_symbol: 57,
addend: 0,
},
@ -841,7 +760,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 185,
address: 153,
target_symbol: 54,
addend: 0,
},
@ -849,7 +768,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 219,
address: 172,
target_symbol: 54,
addend: 0,
},
@ -857,7 +776,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 238,
address: 191,
target_symbol: 52,
addend: 0,
},
@ -865,7 +784,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 267,
address: 218,
target_symbol: 57,
addend: 0,
},
@ -873,7 +792,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 286,
address: 237,
target_symbol: 52,
addend: 0,
},
@ -881,7 +800,7 @@ expression: obj.sections
flags: Coff(
6,
),
address: 308,
address: 257,
target_symbol: 68,
addend: 0,
},
@ -889,7 +808,7 @@ expression: obj.sections
flags: Coff(
20,
),
address: 313,
address: 262,
target_symbol: 60,
addend: 0,
},
@ -902,14 +821,11 @@ expression: obj.sections
name: ".text$yd",
address: 0,
size: 0,
kind: Unknown,
kind: Code,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
16,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -919,14 +835,11 @@ expression: obj.sections
name: ".rdata",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -936,14 +849,11 @@ expression: obj.sections
name: ".rdata",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -953,14 +863,11 @@ expression: obj.sections
name: ".data",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -970,14 +877,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -987,14 +891,11 @@ expression: obj.sections
name: ".rdata$r",
address: 0,
size: 0,
kind: Unknown,
kind: Data,
data: SectionData(
0,
),
flags: FlagSet(),
align: Some(
4,
),
flags: FlagSet(Hidden),
relocations: [],
line_info: {},
virtual_address: None,
@ -1009,9 +910,6 @@ expression: obj.sections
4,
),
flags: FlagSet(),
align: Some(
4,
),
relocations: [
Relocation {
flags: Coff(
@ -1035,9 +933,6 @@ expression: obj.sections
0,
),
flags: FlagSet(),
align: Some(
16,
),
relocations: [],
line_info: {},
virtual_address: None,

View File

@ -1,622 +0,0 @@
---
source: objdiff-core/tests/arch_x86.rs
expression: diff.instruction_rows
---
[
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 0,
size: 4,
opcode: 414,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 4,
size: 1,
opcode: 137,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 5,
size: 3,
opcode: 93,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 8,
size: 2,
opcode: 297,
branch_dest: Some(
58,
),
},
),
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,
branch_dest: Some(
60,
),
},
),
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,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 23,
size: 5,
opcode: 414,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 29,
size: 5,
opcode: 414,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 35,
size: 5,
opcode: 414,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 41,
size: 5,
opcode: 414,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 47,
size: 5,
opcode: 414,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 53,
size: 5,
opcode: 414,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 60,
size: 4,
opcode: 65534,
branch_dest: Some(
17,
),
},
),
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,
branch_dest: Some(
23,
),
},
),
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,
branch_dest: Some(
29,
),
},
),
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,
branch_dest: Some(
35,
),
},
),
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,
branch_dest: Some(
41,
),
},
),
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,
branch_dest: Some(
47,
),
},
),
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,
branch_dest: Some(
53,
),
},
),
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,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 89,
size: 1,
opcode: 465,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 90,
size: 1,
opcode: 465,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 91,
size: 1,
opcode: 465,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 92,
size: 1,
opcode: 465,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 93,
size: 1,
opcode: 465,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 94,
size: 1,
opcode: 465,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
InstructionDiffRow {
ins_ref: Some(
InstructionRef {
address: 95,
size: 1,
opcode: 465,
branch_dest: None,
},
),
kind: None,
branch_from: None,
branch_to: None,
arg_diff: [],
},
]

View File

@ -1,39 +0,0 @@
---
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), (BranchDest(60), Normal, 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), (BranchDest(17), Normal, 0), (Basic(" ~>"), Rotating(2), 0), (Eol, Normal, 0)]
[(Address(64), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".dword", 65534), Normal, 10), (BranchDest(23), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
[(Address(68), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".dword", 65534), Normal, 10), (BranchDest(29), Normal, 0), (Basic(" ~>"), Rotating(4), 0), (Eol, Normal, 0)]
[(Address(72), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".dword", 65534), Normal, 10), (BranchDest(35), Normal, 0), (Basic(" ~>"), Rotating(5), 0), (Eol, Normal, 0)]
[(Address(76), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".dword", 65534), Normal, 10), (BranchDest(41), Normal, 0), (Basic(" ~>"), Rotating(6), 0), (Eol, Normal, 0)]
[(Address(80), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".dword", 65534), Normal, 10), (BranchDest(47), Normal, 0), (Basic(" ~>"), Rotating(7), 0), (Eol, Normal, 0)]
[(Address(84), Normal, 5), (Spacing(4), Normal, 0), (Opcode(".dword", 65534), Normal, 10), (BranchDest(53), Normal, 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)]

View File

@ -1,314 +0,0 @@
---
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(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
},
Section {
id: ".text-0",
name: ".text",
address: 0,
size: 96,
kind: Code,
data: SectionData(
96,
),
flags: FlagSet(),
align: Some(
16,
),
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(),
align: Some(
1,
),
relocations: [],
line_info: {},
virtual_address: None,
},
],
split_meta: None,
path: None,
timestamp: None,
}

View File

@ -1,163 +0,0 @@
---
source: objdiff-core/tests/arch_x86.rs
expression: obj
---
Object {
arch: ArchX86 {
arch: X86,
endianness: Little,
},
endianness: Little,
symbols: [
Symbol {
name: "42b830_convertToUppercaseShiftJIS.obj",
demangled_name: None,
address: 0,
size: 0,
kind: Unknown,
section: None,
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.text]",
demangled_name: None,
address: 0,
size: 0,
kind: Section,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "LAB_0042b850",
demangled_name: None,
address: 32,
size: 0,
kind: Object,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "LAB_0042b883",
demangled_name: None,
address: 83,
size: 0,
kind: Object,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "LAB_0042b87c",
demangled_name: None,
address: 76,
size: 0,
kind: Object,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "LAB_0042b884",
demangled_name: None,
address: 84,
size: 0,
kind: Object,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "LAB_0042b889",
demangled_name: None,
address: 89,
size: 0,
kind: Object,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "LAB_0042b845",
demangled_name: None,
address: 21,
size: 0,
kind: Object,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "LAB_0042b869",
demangled_name: None,
address: 57,
size: 0,
kind: Object,
section: Some(
0,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "ConvertToUppercaseShiftJIS",
demangled_name: None,
address: 0,
size: 92,
kind: Function,
section: Some(
0,
),
flags: FlagSet(Global | SizeInferred),
align: None,
virtual_address: None,
},
],
sections: [
Section {
id: ".text-0",
name: ".text",
address: 0,
size: 92,
kind: Code,
data: SectionData(
92,
),
flags: FlagSet(),
align: Some(
16,
),
relocations: [],
line_info: {},
virtual_address: None,
},
],
split_meta: None,
path: None,
timestamp: None,
}

View File

@ -28,6 +28,7 @@ anyhow = "1.0"
cfg-if = "1.0"
const_format = "0.2"
cwdemangle = "1.0"
cwextab = { version = "1.0", git = "https://github.com/CelestialAmber/cwextab.git" }
dirs = "6.0"
egui = "0.31"
egui_extras = "0.31"
@ -42,11 +43,13 @@ png = "0.17"
pollster = "0.4"
regex = "1.11"
rfd = { version = "0.15" } #, default-features = false, features = ['xdg-portal']
rlwinmdec = "1.1"
rlwinmdec = { version = "1.0", git = "https://github.com/CelestialAmber/rlwinmdec.git" }
ron = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
shell-escape = "0.1"
time = { version = "0.3", features = ["formatting", "local-offset"] }
typed-path = "0.11"
typed-path = "0.10"
winit = { version = "0.30", features = ["wayland-csd-adwaita"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

View File

@ -5,8 +5,8 @@ use std::{
path::{Path, PathBuf},
rc::Rc,
sync::{
Arc, Mutex, RwLock,
atomic::{AtomicBool, Ordering},
Arc, Mutex, RwLock,
},
time::Instant,
};
@ -14,11 +14,11 @@ use std::{
use filetime::FileTime;
use globset::Glob;
use objdiff_core::{
build::watcher::{Watcher, create_watcher},
build::watcher::{create_watcher, Watcher},
config::{
DEFAULT_WATCH_PATTERNS, ProjectConfig, ProjectConfigInfo, ProjectObject, ScratchConfig,
build_globset, default_watch_patterns, path::platform_path_serde_option,
save_project_config,
save_project_config, ProjectConfig, ProjectConfigInfo, ProjectObject, ScratchConfig,
DEFAULT_WATCH_PATTERNS,
},
diff::DiffObjConfig,
jobs::{Job, JobQueue, JobResult},
@ -27,22 +27,22 @@ use time::UtcOffset;
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
use crate::{
app_config::{AppConfigVersion, deserialize_config},
config::{ProjectObjectNode, load_project_config},
app_config::{deserialize_config, AppConfigVersion},
config::{load_project_config, ProjectObjectNode},
jobs::{create_objdiff_config, egui_waker, start_build},
views::{
appearance::{Appearance, appearance_window},
appearance::{appearance_window, Appearance},
config::{
CONFIG_DISABLED_TEXT, ConfigViewState, arch_config_window, config_ui,
general_config_ui, project_window,
arch_config_window, config_ui, general_config_ui, project_window, ConfigViewState,
CONFIG_DISABLED_TEXT,
},
debug::debug_window,
demangle::{DemangleViewState, demangle_window},
demangle::{demangle_window, DemangleViewState},
diff::diff_view_ui,
frame_history::FrameHistory,
graphics::{GraphicsConfig, GraphicsViewState, graphics_window},
graphics::{graphics_window, GraphicsConfig, GraphicsViewState},
jobs::{jobs_menu_ui, jobs_window},
rlwinm::{RlwinmDecodeViewState, rlwinm_decode_window},
rlwinm::{rlwinm_decode_window, RlwinmDecodeViewState},
symbol_diff::{DiffViewAction, DiffViewState, ResolvedNavigation, View},
},
};
@ -775,7 +775,9 @@ impl eframe::App for App {
if side_panel_available {
egui::SidePanel::left("side_panel").show_animated(ctx, *show_side_panel, |ui| {
config_ui(ui, state, show_project_config, config_state, appearance);
egui::ScrollArea::both().show(ui, |ui| {
config_ui(ui, state, show_project_config, config_state, appearance);
});
});
}

View File

@ -11,7 +11,7 @@ use objdiff_core::{
};
use typed_path::{Utf8PlatformPathBuf, Utf8UnixPathBuf};
use crate::app::{AppConfig, CONFIG_KEY, ObjectConfig};
use crate::app::{AppConfig, ObjectConfig, CONFIG_KEY};
#[derive(Clone, serde::Deserialize, serde::Serialize)]
pub struct AppConfigVersion {

View File

@ -1,6 +1,6 @@
use anyhow::Result;
use globset::Glob;
use objdiff_core::config::{DEFAULT_WATCH_PATTERNS, try_project_config};
use objdiff_core::config::{try_project_config, DEFAULT_WATCH_PATTERNS};
use typed_path::{Utf8UnixComponent, Utf8UnixPath};
use crate::app::{AppState, ObjectConfig};

View File

@ -94,7 +94,7 @@ pub fn load_font_if_needed(
// FIXME clean up
let default_font_ref = family.fonts.get(family.default_index).unwrap();
let default_font = family.handles.get(family.default_index).unwrap();
let default_font_data = load_font(default_font)?;
let default_font_data = load_font(default_font).unwrap();
log::info!("Loaded font family '{}'", family.family_name);
fonts.font_data.insert(default_font_ref.full_name(), Arc::new(default_font_data.font_data));
fonts

View File

@ -1,5 +1,5 @@
use egui::{
Context, Key, KeyboardShortcut, Modifiers, PointerButton, style::ScrollAnimation, vec2,
style::ScrollAnimation, vec2, Context, Key, KeyboardShortcut, Modifiers, PointerButton,
};
fn any_widget_focused(ctx: &Context) -> bool { ctx.memory(|mem| mem.focused().is_some()) }

View File

@ -3,18 +3,18 @@ use std::{
task::{Wake, Waker},
};
use anyhow::{Result, bail};
use anyhow::{bail, Result};
use jobs::create_scratch;
use objdiff_core::{
build::BuildConfig,
diff::MappingConfig,
jobs,
jobs::{Job, JobQueue, check_update::CheckUpdateConfig, objdiff, update::UpdateConfig},
jobs::{check_update::CheckUpdateConfig, objdiff, update::UpdateConfig, Job, JobQueue},
};
use crate::{
app::{AppConfig, AppState},
update::{BIN_NAME_NEW, BIN_NAME_OLD, build_updater},
update::{build_updater, BIN_NAME_NEW, BIN_NAME_OLD},
};
struct EguiWaker(egui::Context);

Some files were not shown because too many files have changed in this diff Show More