Compare commits

...

38 Commits

Author SHA1 Message Date
0c48d711c7 Improve local branch relocation handling
Reworks the local-branch handling logic to be more
unified: scan_instructions does all the work up front,
and process_instruction / display_instruction can
simply use the calculated branch destination instead
of performing their own is-relocation-target-
function-local checks.

(Hopefully) Fixes #192
2025-05-07 22:53:10 -06:00
34220a8e26 Add address to ReportItem, stabilize sections/functions ordering 2025-05-07 17:36:49 -06:00
0c9e5526d4 Combine sections when generating report 2025-05-07 16:47:20 -06:00
3db0727469 Omit match % for right sections, improve multi-section diffing
Fixes #120
2025-05-07 16:47:20 -06:00
8b5bf21f38 Mark combined sections as SectionKind::Unknown 2025-05-07 16:45:00 -06:00
b77df77000 Minor cleanup, remove Section::symbol_data 2025-05-07 16:43:34 -06:00
7e08f9715b Update dependencies 2025-05-07 16:42:02 -06:00
3c05852d00 Document SuperH support 2025-05-06 23:25:29 -06:00
a51ff44be1 Fix superh wasm (no_std) build 2025-05-06 23:21:07 -06:00
d225cac205 Add superh feature to wasm build 2025-05-06 23:14:38 -06:00
737b3782db ci: Add id-token write permission 2025-05-06 22:51:11 -06:00
sozud
1d782243e0 Add data info for superh (#198)
* Add data info for superh

* fmt

* Fetch symbol data dynamically from resolved.section

* Remove unused var

---------

Co-authored-by: Luke Street <luke@street.dev>
2025-05-06 22:30:53 -06:00
a1499f475d Update test snapshot 2025-05-06 22:07:21 -06:00
LagoLunatic
f263e490e3 Combine data/text sections: Pad sections to alignment (#197)
* Combine data/text sections: Pad all sections to 4-byte minimum alignment

* Update x86 test snapshot

* Read and store object section alignment

* Combine data/text sections: Pad sections to more than 4-byte alignment if they have alignment specified
2025-05-06 21:47:08 -06:00
Aetias
d0e6c5c057 Display branch destinations after PC-relative loads (#194) 2025-05-06 21:45:03 -06:00
LagoLunatic
e1c51ac297 ARM: Fix "Combine text sections" confusing code and data (#195)
* ARM: Fix parsing of mapping symbols when "Combine text sections" is enabled

* Add test
2025-04-26 11:14:16 -06:00
39b1b49985 cli: Add --config arg to report generate 2025-04-22 18:13:12 -06:00
6c7160ab7e Use rabbitizer 2.0.0-alpha.1 2025-04-22 18:13:12 -06:00
sozud
644d4762f0 Preliminary SuperH support (#186)
* Preliminary SuperH support

* fixes

* clippy

* clippy
2025-04-17 14:20:30 -06:00
LagoLunatic
b40fae5140 Allow copying Shift JIS encoded string literals (#189)
* Update openssl and tokio for Cargo deny

* Allow copying Shift JIS encoded strings

* Override data type label for Shift JIS strings
2025-04-17 10:07:05 -06:00
LagoLunatic
fbf85632ab PPC: Detect unpooled string literal references (#188)
* Update openssl and tokio for Cargo deny

* PPC: Detect unpooled string literal references
2025-04-16 23:33:55 -06:00
73a89d2768 Version v3.0.0-beta.6 2025-04-02 11:03:40 -06:00
a162c2f840 Fix to_string_in_format_args warning 2025-04-01 23:36:47 -06:00
a474b27d55 Update dependencies 2025-04-01 23:33:17 -06:00
3d7f2b70dc Replace some git dependencies with cargo registry 2025-04-01 22:56:16 -06:00
fe886f862d ci: Auto cargo publish / npm publish 2025-04-01 21:49:01 -06:00
2bcbc34850 wasm: Improve API error handling 2025-04-01 21:45:13 -06:00
Steven Casper
9b557e4c8e Limit left-panel scrollview to the file tree (#185)
* Limit left-panel scrollview to the file tree

Removes the redundant build button

* Expand ScrollArea to full side panel width

* Use auto_shrink(false) instead of set_width

---------

Co-authored-by: Luke Street <luke@street.dev>
2025-04-01 12:35:17 -06:00
LagoLunatic
b9ba5796ed PPC: Fix pooled relocation addends being added twice sometimes (#184) 2025-03-30 22:00:36 -06:00
LagoLunatic
e101610416 ARM: Fix subtract with overflow error when no mapping symbol at address 0 (#183) 2025-03-30 22:00:06 -06:00
LagoLunatic
196c003a92 Reimplement colorized data relocation hover diffs (#182)
* Reimplement colorized data relocation hover diffs

* Fix objdiff-wasm build

Data diffing doesn't seem to be fully implemented in objdiff-wasm yet, so just putting placeholders in so it compiles.

* Reloc hover: Add separators, override special color too
2025-03-28 21:48:14 -06:00
7b00a9e9f2 wasm: Cache objects via data hash (XXH3) 2025-03-21 08:27:19 -06:00
311de887ec Update test snapshot 2025-03-19 19:00:57 -06:00
485b259c32 Apply clippy suggestion 2025-03-19 19:00:01 -06:00
d8fdfaa2c0 Fix no_std build 2025-03-19 18:57:41 -06:00
2612cda1fb objdiff-cli report: Skip unknown sections
Regression in v3.0.0-alpha.1

Fixes #171
2025-03-19 18:54:34 -06:00
bc46e17824 x86_64: Fix relocation placement in instruction 2025-03-19 18:54:34 -06:00
e735adbd3d x86: Support inline data for jumptables 2025-03-19 18:54:34 -06:00
69 changed files with 6413 additions and 1100 deletions

View File

@@ -8,6 +8,10 @@ on:
- "LICENSE*" - "LICENSE*"
workflow_dispatch: workflow_dispatch:
permissions:
# For npm publish provenance
id-token: write
env: env:
BUILD_PROFILE: release-lto BUILD_PROFILE: release-lto
CARGO_INCREMENTAL: 0 CARGO_INCREMENTAL: 0
@@ -72,7 +76,7 @@ jobs:
name: Test name: Test
strategy: strategy:
matrix: matrix:
platform: [ubuntu-latest, windows-latest, macos-latest] platform: [ ubuntu-latest, windows-latest, macos-latest ]
fail-fast: false fail-fast: false
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
@@ -249,22 +253,30 @@ jobs:
components: rust-src components: rust-src
- name: Cache Rust workspace - name: Cache Rust workspace
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies - name: Install dependencies
run: npm -C objdiff-wasm install run: npm -C objdiff-wasm ci
- name: Build - name: Build
run: npm -C objdiff-wasm run 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
release: check-version:
name: Release name: Check package versions
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build-cli, build-gui] needs: [ build-cli, build-gui, build-wasm ]
permissions:
contents: write
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Check git tag against Cargo version - name: Check git tag against package versions
shell: bash shell: bash
run: | run: |
set -eou pipefail set -eou pipefail
@@ -276,9 +288,24 @@ jobs:
echo "::error::Git tag doesn't match the Cargo version! ($tag != $version)" echo "::error::Git tag doesn't match the Cargo version! ($tag != $version)"
exit 1 exit 1
fi 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 - name: Download artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
pattern: objdiff-*
path: artifacts path: artifacts
- name: Rename artifacts - name: Rename artifacts
working-directory: artifacts working-directory: artifacts
@@ -308,3 +335,53 @@ jobs:
files: out/* files: out/*
draft: true draft: true
generate_release_notes: 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"

1298
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@ strip = "debuginfo"
codegen-units = 1 codegen-units = 1
[workspace.package] [workspace.package]
version = "3.0.0-beta.4" version = "3.0.0-beta.7"
authors = ["Luke Street <luke@street.dev>"] authors = ["Luke Street <luke@street.dev>"]
edition = "2024" edition = "2024"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

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

View File

@@ -103,6 +103,7 @@ allow = [
"0BSD", "0BSD",
"OFL-1.1", "OFL-1.1",
"Ubuntu-font-1.0", "Ubuntu-font-1.0",
"CDLA-Permissive-2.0",
] ]
# The confidence threshold for detecting a license from license text. # The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the # The higher the value, the more closely the license text must be to the
@@ -240,8 +241,6 @@ allow-git = []
[sources.allow-org] [sources.allow-org]
# github.com organizations to allow git sources for # github.com organizations to allow git sources for
github = [ github = [
"CelestialAmber", # cwextab, rlwinmdec
"Decompollaborate", # rabbitizer
"enarx", # flagset "enarx", # flagset
"encounter", "encounter",
] ]

View File

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

View File

@@ -1,7 +1,6 @@
use std::{ use std::{
io::stdout, io::stdout,
mem, mem,
str::FromStr,
sync::{ sync::{
Arc, Arc,
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
@@ -29,10 +28,7 @@ use objdiff_core::{
ProjectConfig, ProjectObject, ProjectObjectMetadata, build_globset, ProjectConfig, ProjectObject, ProjectObjectMetadata, build_globset,
path::{check_path_buf, platform_path, platform_path_serde_option}, path::{check_path_buf, platform_path, platform_path_serde_option},
}, },
diff::{ diff::{self, DiffObjConfig, MappingConfig, ObjectDiff},
self, ConfigEnum, ConfigPropertyId, ConfigPropertyKind, DiffObjConfig, MappingConfig,
ObjectDiff,
},
jobs::{ jobs::{
Job, JobQueue, JobResult, Job, JobQueue, JobResult,
objdiff::{ObjDiffConfig, start_build}, objdiff::{ObjDiffConfig, start_build},
@@ -43,6 +39,7 @@ use ratatui::prelude::*;
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf}; use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
use crate::{ use crate::{
cmd::apply_config_args,
util::{ util::{
output::{OutputFormat, write_output}, output::{OutputFormat, write_output},
term::crossterm_panic_handler, term::crossterm_panic_handler,
@@ -183,28 +180,7 @@ pub fn run(args: Args) -> Result<()> {
fn build_config_from_args(args: &Args) -> Result<(DiffObjConfig, MappingConfig)> { fn build_config_from_args(args: &Args) -> Result<(DiffObjConfig, MappingConfig)> {
let mut diff_config = DiffObjConfig::default(); let mut diff_config = DiffObjConfig::default();
for config in &args.config { apply_config_args(&mut diff_config, &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 { let mut mapping_config = MappingConfig {
mappings: Default::default(), mappings: Default::default(),
selecting_left: args.selecting_left.clone(), selecting_left: args.selecting_left.clone(),

View File

@@ -1,2 +1,33 @@
pub mod diff; pub mod diff;
pub mod report; 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

@@ -17,7 +17,7 @@ use tracing::{info, warn};
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf}; use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
use crate::{ use crate::{
cmd::diff::ObjectConfig, cmd::{apply_config_args, diff::ObjectConfig},
util::output::{OutputFormat, write_output}, util::output::{OutputFormat, write_output},
}; };
@@ -52,6 +52,9 @@ pub struct GenerateArgs {
#[argp(option, short = 'f')] #[argp(option, short = 'f')]
/// Output format (json, json-pretty, proto) (default: json) /// Output format (json, json-pretty, proto) (default: json)
format: Option<String>, format: Option<String>,
#[argp(option, short = 'c')]
/// Configuration property (key=value)
config: Vec<String>,
} }
#[derive(FromArgs, PartialEq, Debug)] #[derive(FromArgs, PartialEq, Debug)]
@@ -80,6 +83,15 @@ pub fn run(args: Args) -> Result<()> {
} }
fn generate(args: GenerateArgs) -> 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 output_format = OutputFormat::from_option(args.format.as_deref())?;
let project_dir = args.project.as_deref().unwrap_or_else(|| Utf8PlatformPath::new(".")); let project_dir = args.project.as_deref().unwrap_or_else(|| Utf8PlatformPath::new("."));
info!("Loading project {}", project_dir); info!("Loading project {}", project_dir);
@@ -114,14 +126,15 @@ fn generate(args: GenerateArgs) -> Result<()> {
if args.deduplicate { if args.deduplicate {
// If deduplicating, we need to run single-threaded // If deduplicating, we need to run single-threaded
for object in &objects { for object in &objects {
if let Some(unit) = report_object(object, Some(&mut existing_functions))? { if let Some(unit) = report_object(object, &diff_config, Some(&mut existing_functions))?
{
units.push(unit); units.push(unit);
} }
} }
} else { } else {
let vec = objects let vec = objects
.par_iter() .par_iter()
.map(|object| report_object(object, None)) .map(|object| report_object(object, &diff_config, None))
.collect::<Result<Vec<Option<ReportUnit>>>>()?; .collect::<Result<Vec<Option<ReportUnit>>>>()?;
units = vec.into_iter().flatten().collect(); units = vec.into_iter().flatten().collect();
} }
@@ -145,6 +158,7 @@ fn generate(args: GenerateArgs) -> Result<()> {
fn report_object( fn report_object(
object: &ObjectConfig, object: &ObjectConfig,
diff_config: &diff::DiffObjConfig,
mut existing_functions: Option<&mut HashSet<String>>, mut existing_functions: Option<&mut HashSet<String>>,
) -> Result<Option<ReportUnit>> { ) -> Result<Option<ReportUnit>> {
match (&object.target_path, &object.base_path) { match (&object.target_path, &object.base_path) {
@@ -158,16 +172,12 @@ fn report_object(
} }
_ => {} _ => {}
} }
let diff_config = diff::DiffObjConfig {
function_reloc_diffs: diff::FunctionRelocDiffs::None,
..Default::default()
};
let mapping_config = diff::MappingConfig::default(); let mapping_config = diff::MappingConfig::default();
let target = object let target = object
.target_path .target_path
.as_ref() .as_ref()
.map(|p| { .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)) .with_context(|| format!("Failed to open {}", p))
}) })
.transpose()?; .transpose()?;
@@ -175,12 +185,12 @@ fn report_object(
.base_path .base_path
.as_ref() .as_ref()
.map(|p| { .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)) .with_context(|| format!("Failed to open {}", p))
}) })
.transpose()?; .transpose()?;
let result = 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 { let metadata = ReportUnitMetadata {
complete: object.metadata.complete, complete: object.metadata.complete,
@@ -202,6 +212,9 @@ fn report_object(
for ((section_idx, section), section_diff) in for ((section_idx, section), section_diff) in
obj.sections.iter().enumerate().zip(&obj_diff.sections) 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(|| { let section_match_percent = section_diff.match_percent.unwrap_or_else(|| {
// Support cases where we don't have a target object, // Support cases where we don't have a target object,
// assume complete means 100% match // assume complete means 100% match
@@ -215,6 +228,7 @@ fn report_object(
demangled_name: None, demangled_name: None,
virtual_address: section.virtual_address, virtual_address: section.virtual_address,
}), }),
address: None,
}); });
match section.kind { match section.kind {
@@ -231,14 +245,12 @@ fn report_object(
for (symbol, symbol_diff) in obj.symbols.iter().zip(&obj_diff.symbols) { for (symbol, symbol_diff) in obj.symbols.iter().zip(&obj_diff.symbols) {
if symbol.section != Some(section_idx) if symbol.section != Some(section_idx)
|| symbol.size == 0 || symbol.size == 0
|| symbol.flags.contains(SymbolFlag::Hidden) || symbol.flags.contains(SymbolFlag::Hidden | SymbolFlag::Ignored)
|| symbol.flags.contains(SymbolFlag::Ignored)
{ {
continue; continue;
} }
if let Some(existing_functions) = &mut existing_functions { if let Some(existing_functions) = &mut existing_functions {
if (symbol.flags.contains(SymbolFlag::Global) if symbol.flags.contains(SymbolFlag::Global | SymbolFlag::Weak)
|| symbol.flags.contains(SymbolFlag::Weak))
&& !existing_functions.insert(symbol.name.clone()) && !existing_functions.insert(symbol.name.clone())
{ {
continue; continue;
@@ -262,6 +274,7 @@ fn report_object(
demangled_name: symbol.demangled_name.clone(), demangled_name: symbol.demangled_name.clone(),
virtual_address: symbol.virtual_address, virtual_address: symbol.virtual_address,
}), }),
address: symbol.address.checked_sub(section.address),
}); });
if match_percent == 100.0 { if match_percent == 100.0 {
measures.matched_functions += 1; measures.matched_functions += 1;
@@ -269,6 +282,16 @@ fn report_object(
measures.total_functions += 1; 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) { if metadata.complete.unwrap_or(false) {
measures.complete_code = measures.total_code; measures.complete_code = measures.total_code;
measures.complete_data = measures.total_data; measures.complete_data = measures.total_data;

View File

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

View File

@@ -5,11 +5,12 @@ objdiff-core contains the core functionality of [objdiff](https://github.com/enc
## Crate feature flags ## Crate feature flags
- **`all`**: Enables all main features. - **`all`**: Enables all main features.
- **`bindings`**: Enables serialization and deserialization of objdiff data structures.
- **`config`**: Enables objdiff configuration file support. - **`config`**: Enables objdiff configuration file support.
- **`dwarf`**: Enables extraction of line number information from DWARF debug sections. - **`dwarf`**: Enables extraction of line number information from DWARF debug sections.
- **`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).
- **`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). - **`arm64`**: Enables the ARM64 backend powered by [yaxpeax-arm](https://github.com/iximeow/yaxpeax-arm).
- **`bindings`**: Enables serialization and deserialization of objdiff data structures. - **`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).
- **`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).

View File

@@ -99,6 +99,8 @@ message ReportItem {
float fuzzy_match_percent = 3; float fuzzy_match_percent = 3;
// Extra metadata for this item // Extra metadata for this item
optional ReportItemMetadata metadata = 4; optional ReportItemMetadata metadata = 4;
// Address of the item (section-relative offset)
optional uint64 address = 5;
} }
// Extra metadata for an item // Extra metadata for an item

View File

@@ -14,8 +14,8 @@ use crate::{
arch::Arch, arch::Arch,
diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig, display::InstructionPart}, diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig, display::InstructionPart},
obj::{ obj::{
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation, InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
ScannedInstruction, SymbolFlag, SymbolFlagSet, SymbolKind, Section, SectionKind, Symbol, SymbolFlag, SymbolFlagSet, SymbolKind,
}, },
}; };
@@ -32,7 +32,8 @@ impl ArchArm {
let endianness = file.endianness(); let endianness = file.endianness();
match file { match file {
object::File::Elf32(_) => { object::File::Elf32(_) => {
let disasm_modes = Self::elf_get_mapping_symbols(file); // 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 detected_version = Self::elf_detect_arm_version(file)?; let detected_version = Self::elf_detect_arm_version(file)?;
Ok(Self { disasm_modes, detected_version, endianness }) Ok(Self { disasm_modes, detected_version, endianness })
} }
@@ -73,18 +74,22 @@ impl ArchArm {
Ok(None) Ok(None)
} }
fn elf_get_mapping_symbols(file: &object::File) -> BTreeMap<usize, Vec<DisasmMode>> { fn get_mapping_symbols(
file.sections() sections: &[Section],
.filter(|s| s.kind() == object::SectionKind::Text) symbols: &[Symbol],
.map(|s| { ) -> BTreeMap<usize, Vec<DisasmMode>> {
let index = s.index(); sections
let mut mapping_symbols: Vec<_> = file .iter()
.symbols() .enumerate()
.filter(|s| s.section_index().map(|i| i == index).unwrap_or(false)) .filter(|(_, section)| section.kind == SectionKind::Code)
.filter_map(|s| DisasmMode::from_symbol(&s)) .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)
.collect(); .collect();
mapping_symbols.sort_unstable_by_key(|x| x.address); mapping_symbols.sort_unstable_by_key(|x| x.address);
(s.index().0 - 1, mapping_symbols) (index, mapping_symbols)
}) })
.collect() .collect()
} }
@@ -178,13 +183,18 @@ impl ArchArm {
} }
impl Arch for ArchArm { impl Arch for ArchArm {
fn scan_instructions( fn post_init(&mut self, sections: &[Section], symbols: &[Symbol]) {
self.disasm_modes = Self::get_mapping_symbols(sections, symbols);
}
fn scan_instructions_internal(
&self, &self,
address: u64, address: u64,
code: &[u8], code: &[u8],
section_index: usize, section_index: usize,
_relocations: &[Relocation],
diff_config: &DiffObjConfig, diff_config: &DiffObjConfig,
) -> Result<Vec<ScannedInstruction>> { ) -> Result<Vec<InstructionRef>> {
let start_addr = address as u32; let start_addr = address as u32;
let end_addr = start_addr + code.len() as u32; let end_addr = start_addr + code.len() as u32;
@@ -198,7 +208,7 @@ impl Arch for ArchArm {
.unwrap_or(&fallback_mappings); .unwrap_or(&fallback_mappings);
let first_mapping_idx = mapping_symbols let first_mapping_idx = mapping_symbols
.binary_search_by_key(&start_addr, |x| x.address) .binary_search_by_key(&start_addr, |x| x.address)
.unwrap_or_else(|idx| idx - 1); .unwrap_or_else(|idx| idx.saturating_sub(1));
let mut mode = mapping_symbols[first_mapping_idx].mapping; let mut mode = mapping_symbols[first_mapping_idx].mapping;
let mut mappings_iter = mapping_symbols let mut mappings_iter = mapping_symbols
@@ -209,7 +219,7 @@ impl Arch for ArchArm {
let mut next_mapping = mappings_iter.next(); let mut next_mapping = mappings_iter.next();
let ins_count = code.len() / mode.instruction_size(start_addr); let ins_count = code.len() / mode.instruction_size(start_addr);
let mut ops = Vec::<ScannedInstruction>::with_capacity(ins_count); let mut ops = Vec::<InstructionRef>::with_capacity(ins_count);
let parse_flags = self.parse_flags(diff_config); let parse_flags = self.parse_flags(diff_config);
@@ -225,12 +235,10 @@ impl Arch for ArchArm {
let data = &code[(address - start_addr) as usize..]; let data = &code[(address - start_addr) as usize..];
if data.len() < ins_size { if data.len() < ins_size {
// Push the remainder as data // Push the remainder as data
ops.push(ScannedInstruction { ops.push(InstructionRef {
ins_ref: InstructionRef { address: address as u64,
address: address as u64, size: data.len() as u8,
size: data.len() as u8, opcode: u16::MAX,
opcode: u16::MAX,
},
branch_dest: None, branch_dest: None,
}); });
break; break;
@@ -246,12 +254,10 @@ impl Arch for ArchArm {
} }
_ => { _ => {
// Invalid instruction size // Invalid instruction size
ops.push(ScannedInstruction { ops.push(InstructionRef {
ins_ref: InstructionRef { address: address as u64,
address: address as u64, size: ins_size as u8,
size: ins_size as u8, opcode: u16::MAX,
opcode: u16::MAX,
},
branch_dest: None, branch_dest: None,
}); });
address += ins_size as u32; address += ins_size as u32;
@@ -315,8 +321,10 @@ impl Arch for ArchArm {
unarm::ParseMode::Data => (u16::MAX, None), unarm::ParseMode::Data => (u16::MAX, None),
}; };
ops.push(ScannedInstruction { ops.push(InstructionRef {
ins_ref: InstructionRef { address: address as u64, size: ins_size as u8, opcode }, address: address as u64,
size: ins_size as u8,
opcode,
branch_dest: branch_dest.map(|x| x as u64), branch_dest: branch_dest.map(|x| x as u64),
}); });
address += ins_size as u32; address += ins_size as u32;
@@ -337,6 +345,7 @@ impl Arch for ArchArm {
cb(InstructionPart::reloc())?; cb(InstructionPart::reloc())?;
} else { } else {
push_args( push_args(
ins,
&parsed_ins, &parsed_ins,
resolved.relocation, resolved.relocation,
resolved.ins_ref.address as u32, resolved.ins_ref.address as u32,
@@ -440,7 +449,7 @@ impl Arch for ArchArm {
fn extra_symbol_flags(&self, symbol: &object::Symbol) -> SymbolFlagSet { fn extra_symbol_flags(&self, symbol: &object::Symbol) -> SymbolFlagSet {
let mut flags = SymbolFlagSet::default(); let mut flags = SymbolFlagSet::default();
if DisasmMode::from_symbol(symbol).is_some() { if DisasmMode::from_object_symbol(symbol).is_some() {
flags |= SymbolFlag::Hidden; flags |= SymbolFlag::Hidden;
} }
flags flags
@@ -454,15 +463,21 @@ struct DisasmMode {
} }
impl DisasmMode { impl DisasmMode {
fn from_symbol<'a>(sym: &object::Symbol<'a, '_, &'a [u8]>) -> Option<Self> { fn from_object_symbol<'a>(sym: &object::Symbol<'a, '_, &'a [u8]>) -> Option<Self> {
sym.name() sym.name()
.ok() .ok()
.and_then(unarm::ParseMode::from_mapping_symbol) .and_then(unarm::ParseMode::from_mapping_symbol)
.map(|mapping| DisasmMode { address: sym.address() as u32, mapping }) .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( fn push_args(
ins: unarm::Ins,
parsed_ins: &unarm::ParsedIns, parsed_ins: &unarm::ParsedIns,
relocation: Option<ResolvedRelocation>, relocation: Option<ResolvedRelocation>,
cur_addr: u32, cur_addr: u32,
@@ -608,6 +623,14 @@ fn push_args(
arg_cb(InstructionPart::opaque("!"))?; 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(()) Ok(())
} }
@@ -635,3 +658,21 @@ fn find_reloc_arg(
None 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

@@ -17,8 +17,7 @@ use crate::{
arch::Arch, arch::Arch,
diff::{DiffObjConfig, display::InstructionPart}, diff::{DiffObjConfig, display::InstructionPart},
obj::{ obj::{
InstructionRef, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation, InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ResolvedRelocation,
ScannedInstruction,
}, },
}; };
@@ -30,15 +29,16 @@ impl ArchArm64 {
} }
impl Arch for ArchArm64 { impl Arch for ArchArm64 {
fn scan_instructions( fn scan_instructions_internal(
&self, &self,
address: u64, address: u64,
code: &[u8], code: &[u8],
_section_index: usize, _section_index: usize,
_relocations: &[Relocation],
_diff_config: &DiffObjConfig, _diff_config: &DiffObjConfig,
) -> Result<Vec<ScannedInstruction>> { ) -> Result<Vec<InstructionRef>> {
let start_address = address; let start_address = address;
let mut ops = Vec::<ScannedInstruction>::with_capacity(code.len() / 4); let mut ops = Vec::<InstructionRef>::with_capacity(code.len() / 4);
let mut reader = U8Reader::new(code); let mut reader = U8Reader::new(code);
let decoder = InstDecoder::default(); let decoder = InstDecoder::default();
@@ -57,8 +57,10 @@ impl Arch for ArchArm64 {
DecodeError::InvalidOpcode DecodeError::InvalidOpcode
| DecodeError::InvalidOperand | DecodeError::InvalidOperand
| DecodeError::IncompleteDecoder => { | DecodeError::IncompleteDecoder => {
ops.push(ScannedInstruction { ops.push(InstructionRef {
ins_ref: InstructionRef { address, size: 4, opcode: u16::MAX }, address,
size: 4,
opcode: u16::MAX,
branch_dest: None, branch_dest: None,
}); });
continue; continue;
@@ -67,9 +69,9 @@ impl Arch for ArchArm64 {
} }
let opcode = opcode_to_u16(ins.opcode); let opcode = opcode_to_u16(ins.opcode);
let ins_ref = InstructionRef { address, size: 4, opcode }; let branch_dest =
let branch_dest = branch_dest(ins_ref, &code[offset as usize..offset as usize + 4]); branch_dest(opcode, address, &code[offset as usize..offset as usize + 4]);
ops.push(ScannedInstruction { ins_ref, branch_dest }); ops.push(InstructionRef { address, size: 4, opcode, branch_dest });
} }
Ok(ops) Ok(ops)
@@ -162,7 +164,7 @@ impl Arch for ArchArm64 {
} }
} }
fn branch_dest(ins_ref: InstructionRef, code: &[u8]) -> Option<u64> { fn branch_dest(opcode: u16, address: u64, code: &[u8]) -> Option<u64> {
const OPCODE_B: u16 = opcode_to_u16(Opcode::B); const OPCODE_B: u16 = opcode_to_u16(Opcode::B);
const OPCODE_BL: u16 = opcode_to_u16(Opcode::BL); const OPCODE_BL: u16 = opcode_to_u16(Opcode::BL);
const OPCODE_BCC: u16 = opcode_to_u16(Opcode::Bcc(0)); const OPCODE_BCC: u16 = opcode_to_u16(Opcode::Bcc(0));
@@ -172,21 +174,21 @@ fn branch_dest(ins_ref: InstructionRef, code: &[u8]) -> Option<u64> {
const OPCODE_TBNZ: u16 = opcode_to_u16(Opcode::TBNZ); const OPCODE_TBNZ: u16 = opcode_to_u16(Opcode::TBNZ);
let word = u32::from_le_bytes(code.try_into().ok()?); let word = u32::from_le_bytes(code.try_into().ok()?);
match ins_ref.opcode { match opcode {
OPCODE_B | OPCODE_BL => { OPCODE_B | OPCODE_BL => {
let offset = ((word & 0x03ff_ffff) << 2) as i32; let offset = ((word & 0x03ff_ffff) << 2) as i32;
let extended_offset = (offset << 4) >> 4; let extended_offset = (offset << 4) >> 4;
ins_ref.address.checked_add_signed(extended_offset as i64) address.checked_add_signed(extended_offset as i64)
} }
OPCODE_BCC | OPCODE_CBZ | OPCODE_CBNZ => { OPCODE_BCC | OPCODE_CBZ | OPCODE_CBNZ => {
let offset = (word as i32 & 0x00ff_ffe0) >> 3; let offset = (word as i32 & 0x00ff_ffe0) >> 3;
let extended_offset = (offset << 11) >> 11; let extended_offset = (offset << 11) >> 11;
ins_ref.address.checked_add_signed(extended_offset as i64) address.checked_add_signed(extended_offset as i64)
} }
OPCODE_TBZ | OPCODE_TBNZ => { OPCODE_TBZ | OPCODE_TBNZ => {
let offset = (word as i32 & 0x0007_ffe0) >> 3; let offset = (word as i32 & 0x0007_ffe0) >> 3;
let extended_offset = (offset << 16) >> 16; let extended_offset = (offset << 16) >> 16;
ins_ref.address.checked_add_signed(extended_offset as i64) address.checked_add_signed(extended_offset as i64)
} }
_ => None, _ => None,
} }

View File

@@ -3,7 +3,6 @@ use alloc::{
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
use core::ops::Range;
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf}; use object::{Endian as _, Object as _, ObjectSection as _, ObjectSymbol as _, elf};
@@ -19,7 +18,7 @@ use crate::{
diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart}, diff::{DiffObjConfig, MipsAbi, MipsInstrCategory, display::InstructionPart},
obj::{ obj::{
InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags, InstructionArg, InstructionArgValue, InstructionRef, Relocation, RelocationFlags,
ResolvedInstructionRef, ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolFlagSet, ResolvedInstructionRef, ResolvedRelocation, SymbolFlag, SymbolFlagSet,
}, },
}; };
@@ -189,15 +188,16 @@ impl ArchMips {
} }
impl Arch for ArchMips { impl Arch for ArchMips {
fn scan_instructions( fn scan_instructions_internal(
&self, &self,
address: u64, address: u64,
code: &[u8], code: &[u8],
_section_index: usize, _section_index: usize,
_relocations: &[Relocation],
diff_config: &DiffObjConfig, diff_config: &DiffObjConfig,
) -> Result<Vec<ScannedInstruction>> { ) -> Result<Vec<InstructionRef>> {
let instruction_flags = self.instruction_flags(diff_config); let instruction_flags = self.instruction_flags(diff_config);
let mut ops = Vec::<ScannedInstruction>::with_capacity(code.len() / 4); let mut ops = Vec::<InstructionRef>::with_capacity(code.len() / 4);
let mut cur_addr = address as u32; let mut cur_addr = address as u32;
for chunk in code.chunks_exact(4) { for chunk in code.chunks_exact(4) {
let code = self.endianness.read_u32_bytes(chunk.try_into()?); let code = self.endianness.read_u32_bytes(chunk.try_into()?);
@@ -205,10 +205,7 @@ impl Arch for ArchMips {
rabbitizer::Instruction::new(code, Vram::new(cur_addr), instruction_flags); rabbitizer::Instruction::new(code, Vram::new(cur_addr), instruction_flags);
let opcode = instruction.opcode() as u16; let opcode = instruction.opcode() as u16;
let branch_dest = instruction.get_branch_vram_generic().map(|v| v.inner() as u64); let branch_dest = instruction.get_branch_vram_generic().map(|v| v.inner() as u64);
ops.push(ScannedInstruction { ops.push(InstructionRef { address: cur_addr as u64, size: 4, opcode, branch_dest });
ins_ref: InstructionRef { address: cur_addr as u64, size: 4, opcode },
branch_dest,
});
cur_addr += 4; cur_addr += 4;
} }
Ok(ops) Ok(ops)
@@ -224,16 +221,7 @@ impl Arch for ArchMips {
let display_flags = self.instruction_display_flags(diff_config); let display_flags = self.instruction_display_flags(diff_config);
let opcode = instruction.opcode(); let opcode = instruction.opcode();
cb(InstructionPart::opcode(opcode.name(), opcode as u16))?; cb(InstructionPart::opcode(opcode.name(), opcode as u16))?;
let start_address = resolved.symbol.address; push_args(&instruction, resolved.relocation, &display_flags, cb)?;
let function_range = start_address..start_address + resolved.symbol.size;
push_args(
&instruction,
resolved.relocation,
function_range,
resolved.section_index,
&display_flags,
cb,
)?;
Ok(()) Ok(())
} }
@@ -337,8 +325,6 @@ impl Arch for ArchMips {
fn push_args( fn push_args(
instruction: &rabbitizer::Instruction, instruction: &rabbitizer::Instruction,
relocation: Option<ResolvedRelocation>, relocation: Option<ResolvedRelocation>,
function_range: Range<u64>,
section_index: usize,
display_flags: &rabbitizer::InstructionDisplayFlags, display_flags: &rabbitizer::InstructionDisplayFlags,
mut arg_cb: impl FnMut(InstructionPart) -> Result<()>, mut arg_cb: impl FnMut(InstructionPart) -> Result<()>,
) -> Result<()> { ) -> Result<()> {
@@ -361,23 +347,7 @@ fn push_args(
} }
ValuedOperand::core_label(..) | ValuedOperand::core_branch_target_label(..) => { ValuedOperand::core_label(..) | ValuedOperand::core_branch_target_label(..) => {
if let Some(resolved) = relocation { if let Some(resolved) = relocation {
// If the relocation target is within the current function, we can push_reloc(resolved.relocation, &mut arg_cb)?;
// 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 } else if let Some(branch_dest) = instruction
.get_branch_offset_generic() .get_branch_offset_generic()
.map(|o| (instruction.vram() + o).inner() as u64) .map(|o| (instruction.vram() + o).inner() as u64)

View File

@@ -2,6 +2,7 @@ use alloc::{borrow::Cow, boxed::Box, format, string::String, vec::Vec};
use core::{ffi::CStr, fmt, fmt::Debug}; use core::{ffi::CStr, fmt, fmt::Debug};
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use encoding_rs::SHIFT_JIS;
use object::Endian as _; use object::Endian as _;
use crate::{ use crate::{
@@ -10,8 +11,8 @@ use crate::{
display::{ContextItem, HoverItem, InstructionPart}, display::{ContextItem, HoverItem, InstructionPart},
}, },
obj::{ obj::{
InstructionArg, Object, ParsedInstruction, Relocation, RelocationFlags, InstructionArg, InstructionRef, Object, ParsedInstruction, Relocation, RelocationFlags,
ResolvedInstructionRef, ScannedInstruction, Symbol, SymbolFlagSet, SymbolKind, ResolvedInstructionRef, ResolvedSymbol, Section, Symbol, SymbolFlagSet, SymbolKind,
}, },
util::ReallySigned, util::ReallySigned,
}; };
@@ -24,6 +25,8 @@ pub mod arm64;
pub mod mips; pub mod mips;
#[cfg(feature = "ppc")] #[cfg(feature = "ppc")]
pub mod ppc; pub mod ppc;
#[cfg(feature = "superh")]
pub mod superh;
#[cfg(feature = "x86")] #[cfg(feature = "x86")]
pub mod x86; pub mod x86;
@@ -57,13 +60,18 @@ impl fmt::Display for DataType {
impl DataType { impl DataType {
pub fn display_labels(&self, endian: object::Endianness, bytes: &[u8]) -> Vec<String> { pub fn display_labels(&self, endian: object::Endianness, bytes: &[u8]) -> Vec<String> {
let mut strs = Vec::new(); let mut strs = Vec::new();
for literal in self.display_literals(endian, bytes) { for (literal, label_override) in self.display_literals(endian, bytes) {
strs.push(format!("{}: {}", self, literal)) let label = label_override.unwrap_or_else(|| format!("{}", self));
strs.push(format!("{}: {}", label, literal))
} }
strs strs
} }
pub fn display_literals(&self, endian: object::Endianness, bytes: &[u8]) -> Vec<String> { pub fn display_literals(
&self,
endian: object::Endianness,
bytes: &[u8],
) -> Vec<(String, Option<String>)> {
let mut strs = Vec::new(); let mut strs = Vec::new();
if self.required_len().is_some_and(|l| bytes.len() < l) { if self.required_len().is_some_and(|l| bytes.len() < l) {
log::warn!( log::warn!(
@@ -87,56 +95,72 @@ impl DataType {
match self { match self {
DataType::Int8 => { DataType::Int8 => {
let i = i8::from_ne_bytes(bytes.try_into().unwrap()); let i = i8::from_ne_bytes(bytes.try_into().unwrap());
strs.push(format!("{:#x}", i)); strs.push((format!("{:#x}", i), None));
if i < 0 { if i < 0 {
strs.push(format!("{:#x}", ReallySigned(i))); strs.push((format!("{:#x}", ReallySigned(i)), None));
} }
} }
DataType::Int16 => { DataType::Int16 => {
let i = endian.read_i16_bytes(bytes.try_into().unwrap()); let i = endian.read_i16_bytes(bytes.try_into().unwrap());
strs.push(format!("{:#x}", i)); strs.push((format!("{:#x}", i), None));
if i < 0 { if i < 0 {
strs.push(format!("{:#x}", ReallySigned(i))); strs.push((format!("{:#x}", ReallySigned(i)), None));
} }
} }
DataType::Int32 => { DataType::Int32 => {
let i = endian.read_i32_bytes(bytes.try_into().unwrap()); let i = endian.read_i32_bytes(bytes.try_into().unwrap());
strs.push(format!("{:#x}", i)); strs.push((format!("{:#x}", i), None));
if i < 0 { if i < 0 {
strs.push(format!("{:#x}", ReallySigned(i))); strs.push((format!("{:#x}", ReallySigned(i)), None));
} }
} }
DataType::Int64 => { DataType::Int64 => {
let i = endian.read_i64_bytes(bytes.try_into().unwrap()); let i = endian.read_i64_bytes(bytes.try_into().unwrap());
strs.push(format!("{:#x}", i)); strs.push((format!("{:#x}", i), None));
if i < 0 { if i < 0 {
strs.push(format!("{:#x}", ReallySigned(i))); strs.push((format!("{:#x}", ReallySigned(i)), None));
} }
} }
DataType::Float => { DataType::Float => {
let bytes: [u8; 4] = bytes.try_into().unwrap(); let bytes: [u8; 4] = bytes.try_into().unwrap();
strs.push(format!("{:?}f", match endian { strs.push((
object::Endianness::Little => f32::from_le_bytes(bytes), format!("{:?}f", match endian {
object::Endianness::Big => f32::from_be_bytes(bytes), object::Endianness::Little => f32::from_le_bytes(bytes),
})); object::Endianness::Big => f32::from_be_bytes(bytes),
}),
None,
));
} }
DataType::Double => { DataType::Double => {
let bytes: [u8; 8] = bytes.try_into().unwrap(); let bytes: [u8; 8] = bytes.try_into().unwrap();
strs.push(format!("{:?}", match endian { strs.push((
object::Endianness::Little => f64::from_le_bytes(bytes), format!("{:?}", match endian {
object::Endianness::Big => f64::from_be_bytes(bytes), object::Endianness::Little => f64::from_le_bytes(bytes),
})); object::Endianness::Big => f64::from_be_bytes(bytes),
}),
None,
));
} }
DataType::Bytes => { DataType::Bytes => {
strs.push(format!("{:#?}", bytes)); strs.push((format!("{:#?}", bytes), None));
} }
DataType::String => { DataType::String => {
if let Ok(cstr) = CStr::from_bytes_until_nul(bytes) { if let Ok(cstr) = CStr::from_bytes_until_nul(bytes) {
strs.push(format!("{:?}", cstr)); 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())));
}
}
} }
} }
} }
@@ -158,42 +182,108 @@ impl DataType {
} }
} }
pub trait Arch: Send + Sync + Debug { impl dyn Arch {
/// Generate a list of instructions references (offset, size, opcode) from the given code. /// 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 /// See [`scan_instructions_internal`] for more details.
/// parsing as possible here: just enough to identify the base instruction opcode, size, and pub fn scan_instructions(
/// possible branch destination (for visual representation). As needed, instructions are parsed
/// via `process_instruction` to compare their arguments.
fn scan_instructions(
&self, &self,
address: u64, resolved: ResolvedSymbol,
code: &[u8],
section_index: usize,
diff_config: &DiffObjConfig, diff_config: &DiffObjConfig,
) -> Result<Vec<ScannedInstruction>>; ) -> 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)
}
/// Parse an instruction to gather its mnemonic and arguments for more detailed comparison. /// 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. /// This is called only when we need to compare the arguments of an instruction.
fn process_instruction( pub fn process_instruction(
&self, &self,
resolved: ResolvedInstructionRef, resolved: ResolvedInstructionRef,
diff_config: &DiffObjConfig, diff_config: &DiffObjConfig,
) -> Result<ParsedInstruction> { ) -> Result<ParsedInstruction> {
let mut mnemonic = None; let mut mnemonic = None;
let mut args = Vec::with_capacity(8); let mut args = Vec::with_capacity(8);
let mut relocation_emitted = false;
self.display_instruction(resolved, diff_config, &mut |part| { self.display_instruction(resolved, diff_config, &mut |part| {
match part { match part {
InstructionPart::Opcode(m, _) => mnemonic = Some(Cow::Owned(m.into_owned())), InstructionPart::Opcode(m, _) => mnemonic = Some(Cow::Owned(m.into_owned())),
InstructionPart::Arg(arg) => args.push(arg.into_static()), 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());
}
_ => {} _ => {}
} }
Ok(()) Ok(())
})?; })?;
// If the instruction has a relocation, but we didn't format it in the display, add it to // If the instruction has a relocation, but we didn't format it in the display, add it to
// the end of the arguments list. // the end of the arguments list.
if resolved.relocation.is_some() && !args.contains(&InstructionArg::Reloc) { if resolved.relocation.is_some() && !relocation_emitted {
args.push(InstructionArg::Reloc); args.push(InstructionArg::Reloc);
} }
Ok(ParsedInstruction { Ok(ParsedInstruction {
@@ -202,6 +292,26 @@ pub trait Arch: Send + Sync + Debug {
args, 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. /// Format an instruction for display.
/// ///
@@ -246,7 +356,13 @@ pub trait Arch: Send + Sync + Debug {
SymbolFlagSet::default() SymbolFlagSet::default()
} }
fn guess_data_type(&self, _resolved: ResolvedInstructionRef) -> Option<DataType> { None } fn guess_data_type(
&self,
_resolved: ResolvedInstructionRef,
_bytes: &[u8],
) -> Option<DataType> {
None
}
fn symbol_hover(&self, _obj: &Object, _symbol_index: usize) -> Vec<HoverItem> { Vec::new() } fn symbol_hover(&self, _obj: &Object, _symbol_index: usize) -> Vec<HoverItem> { Vec::new() }
@@ -284,6 +400,8 @@ pub fn new_arch(object: &object::File) -> Result<Box<dyn Arch>> {
object::Architecture::Arm => Box::new(arm::ArchArm::new(object)?), object::Architecture::Arm => Box::new(arm::ArchArm::new(object)?),
#[cfg(feature = "arm64")] #[cfg(feature = "arm64")]
object::Architecture::Aarch64 => Box::new(arm64::ArchArm64::new(object)?), 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:?}"), arch => bail!("Unsupported architecture: {arch:?}"),
}) })
} }
@@ -296,13 +414,14 @@ impl ArchDummy {
} }
impl Arch for ArchDummy { impl Arch for ArchDummy {
fn scan_instructions( fn scan_instructions_internal(
&self, &self,
_address: u64, _address: u64,
_code: &[u8], _code: &[u8],
_section_index: usize, _section_index: usize,
_relocations: &[Relocation],
_diff_config: &DiffObjConfig, _diff_config: &DiffObjConfig,
) -> Result<Vec<ScannedInstruction>> { ) -> Result<Vec<InstructionRef>> {
Ok(Vec::new()) Ok(Vec::new())
} }

View File

@@ -19,7 +19,7 @@ use crate::{
}, },
obj::{ obj::{
InstructionRef, Object, Relocation, RelocationFlags, ResolvedInstructionRef, InstructionRef, Object, Relocation, RelocationFlags, ResolvedInstructionRef,
ResolvedRelocation, ScannedInstruction, Symbol, SymbolFlag, SymbolFlagSet, ResolvedRelocation, Symbol, SymbolFlag, SymbolFlagSet,
}, },
}; };
@@ -82,23 +82,22 @@ impl ArchPpc {
} }
impl Arch for ArchPpc { impl Arch for ArchPpc {
fn scan_instructions( fn scan_instructions_internal(
&self, &self,
address: u64, address: u64,
code: &[u8], code: &[u8],
_section_index: usize, _section_index: usize,
_relocations: &[Relocation],
_diff_config: &DiffObjConfig, _diff_config: &DiffObjConfig,
) -> Result<Vec<ScannedInstruction>> { ) -> Result<Vec<InstructionRef>> {
ensure!(code.len() & 3 == 0, "Code length must be a multiple of 4"); ensure!(code.len() & 3 == 0, "Code length must be a multiple of 4");
let ins_count = code.len() / 4; let ins_count = code.len() / 4;
let mut insts = Vec::<ScannedInstruction>::with_capacity(ins_count); let mut insts = Vec::<InstructionRef>::with_capacity(ins_count);
for (cur_addr, ins) in ppc750cl::InsIter::new(code, address as u32) { for (cur_addr, ins) in ppc750cl::InsIter::new(code, address as u32) {
insts.push(ScannedInstruction { insts.push(InstructionRef {
ins_ref: InstructionRef { address: cur_addr as u64,
address: cur_addr as u64, size: 4,
size: 4, opcode: u8::from(ins.op) as u16,
opcode: u8::from(ins.op) as u16,
},
branch_dest: ins.branch_dest(cur_addr).map(u64::from), branch_dest: ins.branch_dest(cur_addr).map(u64::from),
}); });
} }
@@ -220,12 +219,21 @@ impl Arch for ArchPpc {
} }
} }
fn guess_data_type(&self, resolved: ResolvedInstructionRef) -> Option<DataType> { fn guess_data_type(&self, resolved: ResolvedInstructionRef, bytes: &[u8]) -> Option<DataType> {
if resolved.relocation.is_some_and(|r| r.symbol.name.starts_with("@stringBase")) { if resolved.relocation.is_some_and(|r| r.symbol.name.starts_with("@stringBase")) {
// Pooled string.
return Some(DataType::String); return Some(DataType::String);
} }
let opcode = ppc750cl::Opcode::from(resolved.ins_ref.opcode as u8); let opcode = ppc750cl::Opcode::from(resolved.ins_ref.opcode as u8);
guess_data_type_from_load_store_inst_op(opcode) 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
} }
fn symbol_hover(&self, _obj: &Object, symbol_index: usize) -> Vec<HoverItem> { fn symbol_hover(&self, _obj: &Object, symbol_index: usize) -> Vec<HoverItem> {
@@ -448,7 +456,7 @@ fn decode_exception_info(
log::warn!( log::warn!(
"Exception table decoding failed for function {}, reason: {}", "Exception table decoding failed for function {}, reason: {}",
extab_func_name, extab_func_name,
e.to_string() e
); );
return Ok(None); return Ok(None);
} }
@@ -512,6 +520,7 @@ fn guess_data_type_from_load_store_inst_op(inst_op: ppc750cl::Opcode) -> Option<
} }
} }
#[derive(Debug)]
struct PoolReference { struct PoolReference {
addr_src_gpr: ppc750cl::GPR, addr_src_gpr: ppc750cl::GPR,
addr_offset: i16, addr_offset: i16,
@@ -644,7 +653,7 @@ fn make_fake_pool_reloc(
// example, dCcD_Cyl in The Wind Waker). So just showing that vtable symbol plus an addend // 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. // to represent the offset into it works fine in this case.
target_symbol = pool_reloc.relocation.target_symbol; target_symbol = pool_reloc.relocation.target_symbol;
addend = pool_reloc.relocation.addend + offset_from_pool; addend = offset_from_pool;
} }
Some(Relocation { Some(Relocation {
flags: RelocationFlags::Elf(elf::R_PPC_NONE), flags: RelocationFlags::Elf(elf::R_PPC_NONE),

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,821 @@
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,6 +1,7 @@
use alloc::{boxed::Box, string::String, vec::Vec}; use alloc::{boxed::Box, format, string::String, vec::Vec};
use core::cmp::Ordering;
use anyhow::{Result, anyhow, bail}; use anyhow::{Context, Result, anyhow, bail};
use iced_x86::{ use iced_x86::{
Decoder, DecoderOptions, DecoratorKind, FormatterOutput, FormatterTextKind, GasFormatter, Decoder, DecoderOptions, DecoratorKind, FormatterOutput, FormatterTextKind, GasFormatter,
Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind, Register, Instruction, IntelFormatter, MasmFormatter, NasmFormatter, NumberKind, OpKind, Register,
@@ -10,7 +11,7 @@ use object::{Endian as _, Object as _, ObjectSection as _, pe};
use crate::{ use crate::{
arch::Arch, arch::Arch,
diff::{DiffObjConfig, X86Formatter, display::InstructionPart}, diff::{DiffObjConfig, X86Formatter, display::InstructionPart},
obj::{InstructionRef, RelocationFlags, ResolvedInstructionRef, ScannedInstruction}, obj::{InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef},
}; };
#[derive(Debug)] #[derive(Debug)]
@@ -80,18 +81,48 @@ impl ArchX86 {
} }
} }
const DATA_OPCODE: u16 = u16::MAX - 1;
impl Arch for ArchX86 { impl Arch for ArchX86 {
fn scan_instructions( fn scan_instructions_internal(
&self, &self,
address: u64, address: u64,
code: &[u8], code: &[u8],
_section_index: usize, _section_index: usize,
relocations: &[Relocation],
_diff_config: &DiffObjConfig, _diff_config: &DiffObjConfig,
) -> Result<Vec<ScannedInstruction>> { ) -> Result<Vec<InstructionRef>> {
let mut out = Vec::with_capacity(code.len() / 2); let mut out = Vec::with_capacity(code.len() / 2);
let mut decoder = self.decoder(code, address); let mut decoder = self.decoder(code, address);
let mut instruction = Instruction::default(); let mut instruction = Instruction::default();
while decoder.can_decode() { let mut reloc_iter = relocations.iter().peekable();
'outer: while decoder.can_decode() {
let address = decoder.ip();
while let Some(reloc) = reloc_iter.peek() {
match reloc.address.cmp(&address) {
Ordering::Less => {
reloc_iter.next();
}
Ordering::Equal => {
// If the instruction starts at a relocation, it's inline data
let size = self.reloc_size(reloc.flags).with_context(|| {
format!("Unsupported inline x86 relocation {:?}", reloc.flags)
})?;
if decoder.set_position(decoder.position() + size).is_ok() {
decoder.set_ip(address + size as u64);
out.push(InstructionRef {
address,
size: size as u8,
opcode: DATA_OPCODE,
branch_dest: None,
});
reloc_iter.next();
continue 'outer;
}
}
Ordering::Greater => break,
}
}
decoder.decode_out(&mut instruction); decoder.decode_out(&mut instruction);
let branch_dest = match instruction.op0_kind() { let branch_dest = match instruction.op0_kind() {
OpKind::NearBranch16 => Some(instruction.near_branch16() as u64), OpKind::NearBranch16 => Some(instruction.near_branch16() as u64),
@@ -99,12 +130,10 @@ impl Arch for ArchX86 {
OpKind::NearBranch64 => Some(instruction.near_branch64()), OpKind::NearBranch64 => Some(instruction.near_branch64()),
_ => None, _ => None,
}; };
out.push(ScannedInstruction { out.push(InstructionRef {
ins_ref: InstructionRef { address,
address: instruction.ip(), size: instruction.len() as u8,
size: instruction.len() as u8, opcode: instruction.mnemonic() as u16,
opcode: instruction.mnemonic() as u16,
},
branch_dest, branch_dest,
}); });
} }
@@ -117,6 +146,21 @@ impl Arch for ArchX86 {
diff_config: &DiffObjConfig, diff_config: &DiffObjConfig,
cb: &mut dyn FnMut(InstructionPart) -> Result<()>, cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
) -> 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 decoder = self.decoder(resolved.code, resolved.ins_ref.address);
let mut formatter = self.formatter(diff_config); let mut formatter = self.formatter(diff_config);
let mut instruction = Instruction::default(); let mut instruction = Instruction::default();
@@ -329,6 +373,7 @@ impl FormatterOutput for InstructionFormatterOutput<'_> {
(NumberKind::Int8 | NumberKind::UInt8, 1) (NumberKind::Int8 | NumberKind::UInt8, 1)
| (NumberKind::Int16 | NumberKind::UInt16, 2) | (NumberKind::Int16 | NumberKind::UInt16, 2)
| (NumberKind::Int32 | NumberKind::UInt32, 4) | (NumberKind::Int32 | NumberKind::UInt32, 4)
| (NumberKind::Int64 | NumberKind::UInt64, 4) // x86_64
| (NumberKind::Int64 | NumberKind::UInt64, 8) => true, | (NumberKind::Int64 | NumberKind::UInt64, 8) => true,
_ => false, _ => false,
} }
@@ -406,15 +451,16 @@ mod test {
0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0x85, 0x00, 0xc7, 0x85, 0x68, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0x85, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let scanned = arch.scan_instructions(0, &code, 0, &DiffObjConfig::default()).unwrap(); let scanned =
arch.scan_instructions_internal(0, &code, 0, &[], &DiffObjConfig::default()).unwrap();
assert_eq!(scanned.len(), 2); assert_eq!(scanned.len(), 2);
assert_eq!(scanned[0].ins_ref.address, 0); assert_eq!(scanned[0].address, 0);
assert_eq!(scanned[0].ins_ref.size, 10); assert_eq!(scanned[0].size, 10);
assert_eq!(scanned[0].ins_ref.opcode, iced_x86::Mnemonic::Mov as u16); assert_eq!(scanned[0].opcode, iced_x86::Mnemonic::Mov as u16);
assert_eq!(scanned[0].branch_dest, None); assert_eq!(scanned[0].branch_dest, None);
assert_eq!(scanned[1].ins_ref.address, 10); assert_eq!(scanned[1].address, 10);
assert_eq!(scanned[1].ins_ref.size, 7); assert_eq!(scanned[1].size, 7);
assert_eq!(scanned[1].ins_ref.opcode, iced_x86::Mnemonic::Mov as u16); assert_eq!(scanned[1].opcode, iced_x86::Mnemonic::Mov as u16);
assert_eq!(scanned[1].branch_dest, None); assert_eq!(scanned[1].branch_dest, None);
} }
@@ -426,7 +472,7 @@ mod test {
let mut parts = Vec::new(); let mut parts = Vec::new();
arch.display_instruction( arch.display_instruction(
ResolvedInstructionRef { ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1234, size: 10, opcode }, ins_ref: InstructionRef { address: 0x1234, size: 10, opcode, branch_dest: None },
code: &code, code: &code,
..Default::default() ..Default::default()
}, },
@@ -462,7 +508,7 @@ mod test {
let mut parts = Vec::new(); let mut parts = Vec::new();
arch.display_instruction( arch.display_instruction(
ResolvedInstructionRef { ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1234, size: 10, opcode }, ins_ref: InstructionRef { address: 0x1234, size: 10, opcode, branch_dest: None },
code: &code, code: &code,
relocation: Some(ResolvedRelocation { relocation: Some(ResolvedRelocation {
relocation: &Relocation { relocation: &Relocation {
@@ -507,7 +553,7 @@ mod test {
let mut parts = Vec::new(); let mut parts = Vec::new();
arch.display_instruction( arch.display_instruction(
ResolvedInstructionRef { ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1234, size: 7, opcode }, ins_ref: InstructionRef { address: 0x1234, size: 7, opcode, branch_dest: None },
code: &code, code: &code,
relocation: Some(ResolvedRelocation { relocation: Some(ResolvedRelocation {
relocation: &Relocation { relocation: &Relocation {
@@ -550,7 +596,7 @@ mod test {
let mut parts = Vec::new(); let mut parts = Vec::new();
arch.display_instruction( arch.display_instruction(
ResolvedInstructionRef { ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1234, size: 5, opcode }, ins_ref: InstructionRef { address: 0x1234, size: 5, opcode, branch_dest: None },
code: &code, code: &code,
relocation: Some(ResolvedRelocation { relocation: Some(ResolvedRelocation {
relocation: &Relocation { relocation: &Relocation {
@@ -581,7 +627,7 @@ mod test {
let mut parts = Vec::new(); let mut parts = Vec::new();
arch.display_instruction( arch.display_instruction(
ResolvedInstructionRef { ResolvedInstructionRef {
ins_ref: InstructionRef { address: 0x1234, size: 6, opcode }, ins_ref: InstructionRef { address: 0x1234, size: 6, opcode, branch_dest: None },
code: &code, code: &code,
relocation: Some(ResolvedRelocation { relocation: Some(ResolvedRelocation {
relocation: &Relocation { relocation: &Relocation {
@@ -611,4 +657,74 @@ mod test {
InstructionPart::basic("]"), 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

@@ -434,6 +434,7 @@ impl From<LegacyReportItem> for ReportItem {
demangled_name: value.demangled_name, demangled_name: value.demangled_name,
virtual_address: value.address, virtual_address: value.address,
}), }),
address: None,
} }
} }
} }

View File

@@ -14,15 +14,15 @@ use super::{
}; };
use crate::obj::{ use crate::obj::{
InstructionArg, InstructionArgValue, InstructionRef, Object, ResolvedInstructionRef, InstructionArg, InstructionArgValue, InstructionRef, Object, ResolvedInstructionRef,
ResolvedRelocation, ScannedInstruction, SymbolFlag, SymbolKind, ResolvedRelocation, ResolvedSymbol, SymbolFlag, SymbolKind,
}; };
pub fn no_diff_code( pub fn no_diff_code(
obj: &Object, obj: &Object,
symbol_idx: usize, symbol_index: usize,
diff_config: &DiffObjConfig, diff_config: &DiffObjConfig,
) -> Result<SymbolDiff> { ) -> Result<SymbolDiff> {
let symbol = &obj.symbols[symbol_idx]; let symbol = &obj.symbols[symbol_index];
let section_index = symbol.section.ok_or_else(|| anyhow!("Missing section for symbol"))?; let section_index = symbol.section.ok_or_else(|| anyhow!("Missing section for symbol"))?;
let section = &obj.sections[section_index]; let section = &obj.sections[section_index];
let data = section.data_range(symbol.address, symbol.size as usize).ok_or_else(|| { let data = section.data_range(symbol.address, symbol.size as usize).ok_or_else(|| {
@@ -32,13 +32,15 @@ pub fn no_diff_code(
symbol.address + symbol.size symbol.address + symbol.size
) )
})?; })?;
let ops = obj.arch.scan_instructions(symbol.address, data, section_index, diff_config)?; let ops = obj.arch.scan_instructions(
ResolvedSymbol { obj, symbol_index, symbol, section_index, section, data },
diff_config,
)?;
let mut instruction_rows = Vec::<InstructionDiffRow>::new(); let mut instruction_rows = Vec::<InstructionDiffRow>::new();
for i in &ops { for i in &ops {
instruction_rows instruction_rows.push(InstructionDiffRow { ins_ref: Some(*i), ..Default::default() });
.push(InstructionDiffRow { ins_ref: Some(i.ins_ref), ..Default::default() });
} }
resolve_branches(obj, section_index, &ops, &mut instruction_rows); resolve_branches(&ops, &mut instruction_rows);
Ok(SymbolDiff { target_symbol: None, match_percent: None, diff_score: None, instruction_rows }) Ok(SymbolDiff { target_symbol: None, match_percent: None, diff_score: None, instruction_rows })
} }
@@ -86,20 +88,30 @@ pub fn diff_code(
let left_section_idx = left_symbol.section.unwrap(); let left_section_idx = left_symbol.section.unwrap();
let right_section_idx = right_symbol.section.unwrap(); let right_section_idx = right_symbol.section.unwrap();
let left_ops = left_obj.arch.scan_instructions( let left_ops = left_obj.arch.scan_instructions(
left_symbol.address, ResolvedSymbol {
left_data, obj: left_obj,
left_section_idx, symbol_index: left_symbol_idx,
symbol: left_symbol,
section_index: left_section_idx,
section: left_section,
data: left_data,
},
diff_config, diff_config,
)?; )?;
let right_ops = right_obj.arch.scan_instructions( let right_ops = right_obj.arch.scan_instructions(
right_symbol.address, ResolvedSymbol {
right_data, obj: right_obj,
right_section_idx, symbol_index: right_symbol_idx,
symbol: right_symbol,
section_index: right_section_idx,
section: right_section,
data: right_data,
},
diff_config, diff_config,
)?; )?;
let (mut left_rows, mut right_rows) = diff_instructions(&left_ops, &right_ops)?; let (mut left_rows, mut right_rows) = diff_instructions(&left_ops, &right_ops)?;
resolve_branches(left_obj, left_section_idx, &left_ops, &mut left_rows); resolve_branches(&left_ops, &mut left_rows);
resolve_branches(right_obj, right_section_idx, &right_ops, &mut right_rows); resolve_branches(&right_ops, &mut right_rows);
let mut diff_state = InstructionDiffState::default(); let mut diff_state = InstructionDiffState::default();
for (left_row, right_row) in left_rows.iter_mut().zip(right_rows.iter_mut()) { for (left_row, right_row) in left_rows.iter_mut().zip(right_rows.iter_mut()) {
@@ -146,21 +158,21 @@ pub fn diff_code(
} }
fn diff_instructions( fn diff_instructions(
left_insts: &[ScannedInstruction], left_insts: &[InstructionRef],
right_insts: &[ScannedInstruction], right_insts: &[InstructionRef],
) -> Result<(Vec<InstructionDiffRow>, Vec<InstructionDiffRow>)> { ) -> Result<(Vec<InstructionDiffRow>, Vec<InstructionDiffRow>)> {
let left_ops = left_insts.iter().map(|i| i.ins_ref.opcode).collect::<Vec<_>>(); let left_ops = left_insts.iter().map(|i| i.opcode).collect::<Vec<_>>();
let right_ops = right_insts.iter().map(|i| i.ins_ref.opcode).collect::<Vec<_>>(); let right_ops = right_insts.iter().map(|i| i.opcode).collect::<Vec<_>>();
let ops = similar::capture_diff_slices(similar::Algorithm::Patience, &left_ops, &right_ops); let ops = similar::capture_diff_slices(similar::Algorithm::Patience, &left_ops, &right_ops);
if ops.is_empty() { if ops.is_empty() {
ensure!(left_insts.len() == right_insts.len()); ensure!(left_insts.len() == right_insts.len());
let left_diff = left_insts let left_diff = left_insts
.iter() .iter()
.map(|i| InstructionDiffRow { ins_ref: Some(i.ins_ref), ..Default::default() }) .map(|i| InstructionDiffRow { ins_ref: Some(*i), ..Default::default() })
.collect(); .collect();
let right_diff = right_insts let right_diff = right_insts
.iter() .iter()
.map(|i| InstructionDiffRow { ins_ref: Some(i.ins_ref), ..Default::default() }) .map(|i| InstructionDiffRow { ins_ref: Some(*i), ..Default::default() })
.collect(); .collect();
return Ok((left_diff, right_diff)); return Ok((left_diff, right_diff));
} }
@@ -179,14 +191,17 @@ fn diff_instructions(
for op in ops { for op in ops {
let (_tag, left_range, right_range) = op.as_tag_tuple(); let (_tag, left_range, right_range) = op.as_tag_tuple();
let len = left_range.len().max(right_range.len()); let len = left_range.len().max(right_range.len());
left_diff.extend(left_range.clone().map(|i| InstructionDiffRow { left_diff.extend(
ins_ref: Some(left_insts[i].ins_ref), left_range
..Default::default() .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].ins_ref), right_diff.extend(
..Default::default() right_range.clone().map(|i| InstructionDiffRow {
})); ins_ref: Some(right_insts[i]),
..Default::default()
}),
);
if left_range.len() < len { if left_range.len() < len {
left_diff.extend((left_range.len()..len).map(|_| InstructionDiffRow::default())); left_diff.extend((left_range.len()..len).map(|_| InstructionDiffRow::default()));
} }
@@ -207,13 +222,7 @@ fn arg_to_string(arg: &InstructionArg, reloc: Option<ResolvedRelocation>) -> Str
} }
} }
fn resolve_branches( fn resolve_branches(ops: &[InstructionRef], rows: &mut [InstructionDiffRow]) {
obj: &Object,
section_index: usize,
ops: &[ScannedInstruction],
rows: &mut [InstructionDiffRow],
) {
let section = &obj.sections[section_index];
let mut branch_idx = 0u32; let mut branch_idx = 0u32;
// Map addresses to indices // Map addresses to indices
let mut addr_map = BTreeMap::<u64, u32>::new(); let mut addr_map = BTreeMap::<u64, u32>::new();
@@ -227,17 +236,7 @@ fn resolve_branches(
for ((i, ins_diff), ins) in for ((i, ins_diff), ins) in
rows.iter_mut().enumerate().filter(|(_, row)| row.ins_ref.is_some()).zip(ops) rows.iter_mut().enumerate().filter(|(_, row)| row.ins_ref.is_some()).zip(ops)
{ {
let branch_dest = if let Some(resolved) = section.relocation_at(obj, ins.ins_ref) { if let Some(ins_idx) = ins.branch_dest.and_then(|a| addr_map.get(&a).copied()) {
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) { match branches.entry(ins_idx) {
btree_map::Entry::Vacant(e) => { btree_map::Entry::Vacant(e) => {
ins_diff.branch_to = Some(InstructionBranchTo { ins_idx, branch_idx }); ins_diff.branch_to = Some(InstructionBranchTo { ins_idx, branch_idx });
@@ -322,6 +321,7 @@ fn reloc_eq(
|| address_eq(left_reloc, right_reloc)) || address_eq(left_reloc, right_reloc))
&& (diff_config.function_reloc_diffs == FunctionRelocDiffs::NameAddress && (diff_config.function_reloc_diffs == FunctionRelocDiffs::NameAddress
|| left_reloc.symbol.kind != SymbolKind::Object || 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(left_obj, left_ins)
== display_ins_data_literals(right_obj, right_ins)) == display_ins_data_literals(right_obj, right_ins))
} }

View File

@@ -274,7 +274,6 @@ pub fn diff_data_section(
// We only do this when all relocations on the left side match. // We only do this when all relocations on the left side match.
if left_section_diff.match_percent.unwrap_or(-1.0) < match_percent { if left_section_diff.match_percent.unwrap_or(-1.0) < match_percent {
left_section_diff.match_percent = Some(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)) Ok((left_section_diff, right_section_diff))
@@ -413,7 +412,7 @@ pub fn diff_generic_section(
}; };
Ok(( Ok((
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] }, SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] }, SectionDiff { match_percent: None, data_diff: vec![], reloc_diff: vec![] },
)) ))
} }
@@ -454,7 +453,7 @@ pub fn diff_bss_section(
Ok(( Ok((
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] }, SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] },
SectionDiff { match_percent: Some(match_percent), data_diff: vec![], reloc_diff: vec![] }, SectionDiff { match_percent: None, data_diff: vec![], reloc_diff: vec![] },
)) ))
} }

View File

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

View File

@@ -658,7 +658,11 @@ fn find_symbol(
/// Find matching sections between each object. /// Find matching sections between each object.
fn matching_sections(left: Option<&Object>, right: Option<&Object>) -> Result<Vec<SectionMatch>> { fn matching_sections(left: Option<&Object>, right: Option<&Object>) -> Result<Vec<SectionMatch>> {
let mut matches = Vec::new(); 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())),
);
if let Some(left) = left { if let Some(left) = left {
for (section_idx, section) in left.sections.iter().enumerate() { for (section_idx, section) in left.sections.iter().enumerate() {
if section.kind == SectionKind::Unknown { if section.kind == SectionKind::Unknown {
@@ -666,7 +670,7 @@ fn matching_sections(left: Option<&Object>, right: Option<&Object>) -> Result<Ve
} }
matches.push(SectionMatch { matches.push(SectionMatch {
left: Some(section_idx), left: Some(section_idx),
right: find_section(right, &section.name, section.kind), right: find_section(right, &section.name, section.kind, &matches),
section_kind: section.kind, section_kind: section.kind,
}); });
} }
@@ -689,6 +693,13 @@ fn matching_sections(left: Option<&Object>, right: Option<&Object>) -> Result<Ve
Ok(matches) Ok(matches)
} }
fn find_section(obj: Option<&Object>, name: &str, section_kind: SectionKind) -> Option<usize> { fn find_section(
obj?.sections.iter().position(|s| s.kind == section_kind && s.name == name) 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))
})
} }

View File

@@ -9,7 +9,10 @@ use alloc::{
vec, vec,
vec::Vec, vec::Vec,
}; };
use core::{fmt, num::NonZeroU32}; use core::{
fmt,
num::{NonZeroU32, NonZeroU64},
};
use flagset::{FlagSet, flags}; use flagset::{FlagSet, flags};
@@ -54,7 +57,6 @@ flags! {
pub enum SectionFlag: u8 { pub enum SectionFlag: u8 {
/// Section combined from multiple input sections /// Section combined from multiple input sections
Combined, Combined,
Hidden,
} }
} }
@@ -70,6 +72,7 @@ pub struct Section {
pub kind: SectionKind, pub kind: SectionKind,
pub data: SectionData, pub data: SectionData,
pub flags: SectionFlagSet, pub flags: SectionFlagSet,
pub align: Option<NonZeroU64>,
pub relocations: Vec<Relocation>, pub relocations: Vec<Relocation>,
/// Line number info (.line or .debug_line section) /// Line number info (.line or .debug_line section)
pub line_info: BTreeMap<u64, u32>, pub line_info: BTreeMap<u64, u32>,
@@ -95,14 +98,14 @@ impl fmt::Debug for SectionData {
impl Section { impl Section {
pub fn data_range(&self, address: u64, size: usize) -> Option<&[u8]> { pub fn data_range(&self, address: u64, size: usize) -> Option<&[u8]> {
let start = self.address; let offset = address.checked_sub(self.address)?;
let end = start + self.size; self.data.get(offset as usize..offset as usize + size)
if address >= start && address + size as u64 <= end { }
let offset = (address - start) as usize;
Some(&self.data[offset..offset + size]) // The alignment to use when "Combine data/text sections" is enabled.
} else { pub fn combined_alignment(&self) -> u64 {
None const MIN_ALIGNMENT: u64 = 4;
} self.align.map(|align| align.get().max(MIN_ALIGNMENT)).unwrap_or(MIN_ALIGNMENT)
} }
pub fn relocation_at<'obj>( pub fn relocation_at<'obj>(
@@ -211,11 +214,6 @@ pub struct InstructionRef {
pub address: u64, pub address: u64,
pub size: u8, pub size: u8,
pub opcode: u16, pub opcode: u16,
}
#[derive(Copy, Clone, Debug)]
pub struct ScannedInstruction {
pub ins_ref: InstructionRef,
pub branch_dest: Option<u64>, pub branch_dest: Option<u64>,
} }
@@ -332,6 +330,16 @@ pub struct ResolvedRelocation<'a> {
pub symbol: &'a Symbol, 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)] #[derive(Debug, Copy, Clone)]
pub struct ResolvedInstructionRef<'obj> { pub struct ResolvedInstructionRef<'obj> {
pub ins_ref: InstructionRef, pub ins_ref: InstructionRef,
@@ -363,6 +371,7 @@ static DUMMY_SECTION: Section = Section {
kind: SectionKind::Unknown, kind: SectionKind::Unknown,
data: SectionData(Vec::new()), data: SectionData(Vec::new()),
flags: SectionFlagSet::empty(), flags: SectionFlagSet::empty(),
align: None,
relocations: Vec::new(), relocations: Vec::new(),
line_info: BTreeMap::new(), line_info: BTreeMap::new(),
virtual_address: None, virtual_address: None,

View File

@@ -4,7 +4,7 @@ use alloc::{
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
use core::cmp::Ordering; use core::{cmp::Ordering, num::NonZeroU64};
use anyhow::{Context, Result, anyhow, bail, ensure}; use anyhow::{Context, Result, anyhow, bail, ensure};
use object::{Object as _, ObjectSection as _, ObjectSymbol as _}; use object::{Object as _, ObjectSection as _, ObjectSymbol as _};
@@ -17,7 +17,7 @@ use crate::{
Symbol, SymbolFlag, SymbolKind, Symbol, SymbolFlag, SymbolKind,
split_meta::{SPLITMETA_SECTION, SplitMeta}, split_meta::{SPLITMETA_SECTION, SplitMeta},
}, },
util::{read_u16, read_u32}, util::{align_data_slice_to, align_u64_to, read_u16, read_u32},
}; };
fn map_section_kind(section: &object::Section) -> SectionKind { fn map_section_kind(section: &object::Section) -> SectionKind {
@@ -257,6 +257,7 @@ fn map_sections(
kind, kind,
data: SectionData(data), data: SectionData(data),
flags: Default::default(), flags: Default::default(),
align: NonZeroU64::new(section.align()),
relocations: Default::default(), relocations: Default::default(),
virtual_address, virtual_address,
line_info: Default::default(), line_info: Default::default(),
@@ -739,7 +740,10 @@ fn do_combine_sections(
} }
offsets.push(current_offset); offsets.push(current_offset);
current_offset += section.size; current_offset += section.size;
let align = section.combined_alignment();
current_offset = align_u64_to(current_offset, align);
data_size += section.data.len(); data_size += section.data.len();
data_size = align_u64_to(data_size as u64, align) as usize;
num_relocations += section.relocations.len(); num_relocations += section.relocations.len();
} }
if data_size > 0 { if data_size > 0 {
@@ -754,12 +758,13 @@ fn do_combine_sections(
let section = &mut sections[i]; let section = &mut sections[i];
section.size = 0; section.size = 0;
data.append(&mut section.data.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); section.relocations.iter_mut().for_each(|r| r.address += offset);
relocations.append(&mut section.relocations); relocations.append(&mut section.relocations);
line_info.append(&mut section.line_info.iter().map(|(&a, &l)| (a + offset, l)).collect()); line_info.append(&mut section.line_info.iter().map(|(&a, &l)| (a + offset, l)).collect());
section.line_info.clear(); section.line_info.clear();
if offset > 0 { if offset > 0 {
section.flags |= SectionFlag::Hidden; section.kind = SectionKind::Unknown;
} }
} }
{ {
@@ -843,7 +848,7 @@ pub fn read(obj_path: &std::path::Path, config: &DiffObjConfig) -> Result<Object
pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<Object> { pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<Object> {
let obj_file = object::File::parse(data)?; let obj_file = object::File::parse(data)?;
let arch = new_arch(&obj_file)?; let mut arch = new_arch(&obj_file)?;
let split_meta = parse_split_meta(&obj_file)?; let split_meta = parse_split_meta(&obj_file)?;
let (mut sections, section_indices) = let (mut sections, section_indices) =
map_sections(arch.as_ref(), &obj_file, split_meta.as_ref())?; map_sections(arch.as_ref(), &obj_file, split_meta.as_ref())?;
@@ -857,6 +862,7 @@ pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<Object> {
if config.combine_data_sections || config.combine_text_sections { if config.combine_data_sections || config.combine_text_sections {
combine_sections(&mut sections, &mut symbols, config)?; combine_sections(&mut sections, &mut symbols, config)?;
} }
arch.post_init(&sections, &symbols);
Ok(Object { Ok(Object {
arch, arch,
endianness: obj_file.endianness(), endianness: obj_file.endianness(),

View File

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

View File

@@ -3,6 +3,10 @@ use alloc::{string::String, vec, vec::Vec};
use anyhow::{Result, anyhow}; use anyhow::{Result, anyhow};
use object::{Endian, ObjectSection, elf::SHT_NOTE}; use object::{Endian, ObjectSection, elf::SHT_NOTE};
#[cfg(feature = "std")]
use crate::util::align_data_to_4;
use crate::util::align_size_to_4;
pub const SPLITMETA_SECTION: &str = ".note.split"; pub const SPLITMETA_SECTION: &str = ".note.split";
pub const SHT_SPLITMETA: u32 = SHT_NOTE; pub const SHT_SPLITMETA: u32 = SHT_NOTE;
pub const ELF_NOTE_SPLIT: &[u8] = b"Split"; pub const ELF_NOTE_SPLIT: &[u8] = b"Split";
@@ -190,17 +194,6 @@ 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: // ELF note format:
// Name Size | 4 bytes (integer) // Name Size | 4 bytes (integer)
// Desc Size | 4 bytes (integer) // Desc Size | 4 bytes (integer)

View File

@@ -1,4 +1,4 @@
use alloc::format; use alloc::{format, vec::Vec};
use core::fmt; use core::fmt;
use anyhow::{Result, ensure}; use anyhow::{Result, ensure};
@@ -39,3 +39,23 @@ pub fn read_u16(obj_file: &object::File, reader: &mut &[u8]) -> Result<u16> {
*reader = &reader[2..]; *reader = &reader[2..];
Ok(obj_file.endianness().read_u16(value)) 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] #[test]
#[cfg(feature = "arm")] #[cfg(feature = "arm")]
fn read_arm() { fn read_arm() {
let diff_config = diff::DiffObjConfig { mips_register_prefix: true, ..Default::default() }; let diff_config = diff::DiffObjConfig { ..Default::default() };
let obj = obj::read::parse(include_object!("data/arm/LinkStateItem.o"), &diff_config).unwrap(); let obj = obj::read::parse(include_object!("data/arm/LinkStateItem.o"), &diff_config).unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = let symbol_idx =
@@ -19,7 +19,7 @@ fn read_arm() {
#[test] #[test]
#[cfg(feature = "arm")] #[cfg(feature = "arm")]
fn read_thumb() { fn read_thumb() {
let diff_config = diff::DiffObjConfig { mips_register_prefix: true, ..Default::default() }; let diff_config = diff::DiffObjConfig { ..Default::default() };
let obj = obj::read::parse(include_object!("data/arm/thumb.o"), &diff_config).unwrap(); let obj = obj::read::parse(include_object!("data/arm/thumb.o"), &diff_config).unwrap();
insta::assert_debug_snapshot!(obj); insta::assert_debug_snapshot!(obj);
let symbol_idx = obj let symbol_idx = obj
@@ -32,3 +32,15 @@ fn read_thumb() {
let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config); let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config);
insta::assert_snapshot!(output); insta::assert_snapshot!(output);
} }
#[test]
#[cfg(feature = "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

@@ -55,3 +55,16 @@ fn display_section_ordering() {
diff::display::display_sections(&obj, &obj_diff, SymbolFilter::None, false, false, false); diff::display::display_sections(&obj, &obj_diff, SymbolFilter::None, false, false, false);
insta::assert_debug_snapshot!(section_display); 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);
}

Binary file not shown.

Binary file not shown.

View File

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

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

View File

@@ -1519,6 +1519,9 @@ Object {
556, 556,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Elf( flags: Elf(
@@ -1718,6 +1721,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1732,6 +1738,9 @@ Object {
76, 76,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Elf( flags: Elf(
@@ -1883,6 +1892,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1897,6 +1909,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1911,6 +1926,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1925,6 +1943,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,

View File

@@ -9,6 +9,7 @@ expression: diff.instruction_rows
address: 0, address: 0,
size: 2, size: 2,
opcode: 56, opcode: 56,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -22,6 +23,7 @@ expression: diff.instruction_rows
address: 2, address: 2,
size: 2, size: 2,
opcode: 74, opcode: 74,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -35,6 +37,7 @@ expression: diff.instruction_rows
address: 4, address: 4,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -48,6 +51,7 @@ expression: diff.instruction_rows
address: 6, address: 6,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -61,6 +65,7 @@ expression: diff.instruction_rows
address: 8, address: 8,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -74,6 +79,7 @@ expression: diff.instruction_rows
address: 10, address: 10,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -87,6 +93,7 @@ expression: diff.instruction_rows
address: 12, address: 12,
size: 2, size: 2,
opcode: 66, opcode: 66,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -100,6 +107,7 @@ expression: diff.instruction_rows
address: 14, address: 14,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -113,6 +121,7 @@ expression: diff.instruction_rows
address: 18, address: 18,
size: 2, size: 2,
opcode: 25, opcode: 25,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -126,6 +135,9 @@ expression: diff.instruction_rows
address: 20, address: 20,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
212,
),
}, },
), ),
kind: None, kind: None,
@@ -144,6 +156,7 @@ expression: diff.instruction_rows
address: 22, address: 22,
size: 2, size: 2,
opcode: 38, opcode: 38,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -157,6 +170,7 @@ expression: diff.instruction_rows
address: 24, address: 24,
size: 2, size: 2,
opcode: 25, opcode: 25,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -170,6 +184,9 @@ expression: diff.instruction_rows
address: 26, address: 26,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
48,
),
}, },
), ),
kind: None, kind: None,
@@ -188,6 +205,7 @@ expression: diff.instruction_rows
address: 28, address: 28,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -201,6 +219,7 @@ expression: diff.instruction_rows
address: 30, address: 30,
size: 2, size: 2,
opcode: 26, opcode: 26,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -214,6 +233,9 @@ expression: diff.instruction_rows
address: 32, address: 32,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
94,
),
}, },
), ),
kind: None, kind: None,
@@ -232,6 +254,7 @@ expression: diff.instruction_rows
address: 34, address: 34,
size: 2, size: 2,
opcode: 35, opcode: 35,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -245,6 +268,7 @@ expression: diff.instruction_rows
address: 36, address: 36,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -258,6 +282,7 @@ expression: diff.instruction_rows
address: 38, address: 38,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -271,6 +296,7 @@ expression: diff.instruction_rows
address: 40, address: 40,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -284,6 +310,7 @@ expression: diff.instruction_rows
address: 44, address: 44,
size: 2, size: 2,
opcode: 7, opcode: 7,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -297,6 +324,7 @@ expression: diff.instruction_rows
address: 46, address: 46,
size: 2, size: 2,
opcode: 55, opcode: 55,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -310,6 +338,7 @@ expression: diff.instruction_rows
address: 48, address: 48,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -330,6 +359,7 @@ expression: diff.instruction_rows
address: 50, address: 50,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -343,6 +373,7 @@ expression: diff.instruction_rows
address: 52, address: 52,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -356,6 +387,7 @@ expression: diff.instruction_rows
address: 56, address: 56,
size: 2, size: 2,
opcode: 25, opcode: 25,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -369,6 +401,9 @@ expression: diff.instruction_rows
address: 58, address: 58,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
212,
),
}, },
), ),
kind: None, kind: None,
@@ -387,6 +422,7 @@ expression: diff.instruction_rows
address: 60, address: 60,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -400,6 +436,7 @@ expression: diff.instruction_rows
address: 62, address: 62,
size: 2, size: 2,
opcode: 33, opcode: 33,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -413,6 +450,7 @@ expression: diff.instruction_rows
address: 64, address: 64,
size: 2, size: 2,
opcode: 36, opcode: 36,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -426,6 +464,7 @@ expression: diff.instruction_rows
address: 66, address: 66,
size: 2, size: 2,
opcode: 42, opcode: 42,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -439,6 +478,7 @@ expression: diff.instruction_rows
address: 68, address: 68,
size: 2, size: 2,
opcode: 44, opcode: 44,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -452,6 +492,9 @@ expression: diff.instruction_rows
address: 70, address: 70,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
212,
),
}, },
), ),
kind: None, kind: None,
@@ -470,6 +513,7 @@ expression: diff.instruction_rows
address: 72, address: 72,
size: 2, size: 2,
opcode: 46, opcode: 46,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -483,6 +527,7 @@ expression: diff.instruction_rows
address: 74, address: 74,
size: 2, size: 2,
opcode: 17, opcode: 17,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -496,6 +541,7 @@ expression: diff.instruction_rows
address: 76, address: 76,
size: 2, size: 2,
opcode: 46, opcode: 46,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -509,6 +555,7 @@ expression: diff.instruction_rows
address: 78, address: 78,
size: 2, size: 2,
opcode: 54, opcode: 54,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -522,6 +569,7 @@ expression: diff.instruction_rows
address: 80, address: 80,
size: 2, size: 2,
opcode: 67, opcode: 67,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -535,6 +583,7 @@ expression: diff.instruction_rows
address: 82, address: 82,
size: 2, size: 2,
opcode: 36, opcode: 36,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -548,6 +597,7 @@ expression: diff.instruction_rows
address: 84, address: 84,
size: 2, size: 2,
opcode: 46, opcode: 46,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -561,6 +611,7 @@ expression: diff.instruction_rows
address: 86, address: 86,
size: 2, size: 2,
opcode: 7, opcode: 7,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -574,6 +625,7 @@ expression: diff.instruction_rows
address: 88, address: 88,
size: 2, size: 2,
opcode: 54, opcode: 54,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -587,6 +639,7 @@ expression: diff.instruction_rows
address: 90, address: 90,
size: 2, size: 2,
opcode: 67, opcode: 67,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -600,6 +653,7 @@ expression: diff.instruction_rows
address: 92, address: 92,
size: 2, size: 2,
opcode: 55, opcode: 55,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -613,6 +667,7 @@ expression: diff.instruction_rows
address: 94, address: 94,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -633,6 +688,7 @@ expression: diff.instruction_rows
address: 96, address: 96,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -646,6 +702,7 @@ expression: diff.instruction_rows
address: 98, address: 98,
size: 2, size: 2,
opcode: 4, opcode: 4,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -659,6 +716,7 @@ expression: diff.instruction_rows
address: 100, address: 100,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -672,6 +730,7 @@ expression: diff.instruction_rows
address: 104, address: 104,
size: 2, size: 2,
opcode: 66, opcode: 66,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -685,6 +744,7 @@ expression: diff.instruction_rows
address: 106, address: 106,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -698,6 +758,7 @@ expression: diff.instruction_rows
address: 108, address: 108,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -711,6 +772,7 @@ expression: diff.instruction_rows
address: 112, address: 112,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -724,6 +786,7 @@ expression: diff.instruction_rows
address: 114, address: 114,
size: 2, size: 2,
opcode: 6, opcode: 6,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -737,6 +800,7 @@ expression: diff.instruction_rows
address: 116, address: 116,
size: 2, size: 2,
opcode: 66, opcode: 66,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -750,6 +814,7 @@ expression: diff.instruction_rows
address: 118, address: 118,
size: 2, size: 2,
opcode: 35, opcode: 35,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -763,6 +828,7 @@ expression: diff.instruction_rows
address: 120, address: 120,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -776,6 +842,7 @@ expression: diff.instruction_rows
address: 122, address: 122,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -789,6 +856,7 @@ expression: diff.instruction_rows
address: 124, address: 124,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -802,6 +870,7 @@ expression: diff.instruction_rows
address: 126, address: 126,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -815,6 +884,7 @@ expression: diff.instruction_rows
address: 130, address: 130,
size: 2, size: 2,
opcode: 25, opcode: 25,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -828,6 +898,9 @@ expression: diff.instruction_rows
address: 132, address: 132,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
168,
),
}, },
), ),
kind: None, kind: None,
@@ -846,6 +919,7 @@ expression: diff.instruction_rows
address: 134, address: 134,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -859,6 +933,7 @@ expression: diff.instruction_rows
address: 136, address: 136,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -872,6 +947,7 @@ expression: diff.instruction_rows
address: 140, address: 140,
size: 2, size: 2,
opcode: 47, opcode: 47,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -885,6 +961,7 @@ expression: diff.instruction_rows
address: 142, address: 142,
size: 2, size: 2,
opcode: 25, opcode: 25,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -898,6 +975,9 @@ expression: diff.instruction_rows
address: 144, address: 144,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
168,
),
}, },
), ),
kind: None, kind: None,
@@ -916,6 +996,7 @@ expression: diff.instruction_rows
address: 146, address: 146,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -929,6 +1010,7 @@ expression: diff.instruction_rows
address: 148, address: 148,
size: 2, size: 2,
opcode: 33, opcode: 33,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -942,6 +1024,7 @@ expression: diff.instruction_rows
address: 150, address: 150,
size: 2, size: 2,
opcode: 36, opcode: 36,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -955,6 +1038,7 @@ expression: diff.instruction_rows
address: 152, address: 152,
size: 2, size: 2,
opcode: 42, opcode: 42,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -968,6 +1052,7 @@ expression: diff.instruction_rows
address: 154, address: 154,
size: 2, size: 2,
opcode: 44, opcode: 44,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -981,6 +1066,9 @@ expression: diff.instruction_rows
address: 156, address: 156,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
168,
),
}, },
), ),
kind: None, kind: None,
@@ -999,6 +1087,7 @@ expression: diff.instruction_rows
address: 158, address: 158,
size: 2, size: 2,
opcode: 46, opcode: 46,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1012,6 +1101,7 @@ expression: diff.instruction_rows
address: 160, address: 160,
size: 2, size: 2,
opcode: 17, opcode: 17,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1025,6 +1115,7 @@ expression: diff.instruction_rows
address: 162, address: 162,
size: 2, size: 2,
opcode: 46, opcode: 46,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1038,6 +1129,7 @@ expression: diff.instruction_rows
address: 164, address: 164,
size: 2, size: 2,
opcode: 54, opcode: 54,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1051,6 +1143,7 @@ expression: diff.instruction_rows
address: 166, address: 166,
size: 2, size: 2,
opcode: 67, opcode: 67,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1064,6 +1157,7 @@ expression: diff.instruction_rows
address: 168, address: 168,
size: 2, size: 2,
opcode: 25, opcode: 25,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1086,6 +1180,9 @@ expression: diff.instruction_rows
address: 170, address: 170,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
200,
),
}, },
), ),
kind: None, kind: None,
@@ -1104,6 +1201,7 @@ expression: diff.instruction_rows
address: 172, address: 172,
size: 2, size: 2,
opcode: 35, opcode: 35,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1117,6 +1215,7 @@ expression: diff.instruction_rows
address: 174, address: 174,
size: 2, size: 2,
opcode: 25, opcode: 25,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1130,6 +1229,9 @@ expression: diff.instruction_rows
address: 176, address: 176,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
200,
),
}, },
), ),
kind: None, kind: None,
@@ -1148,6 +1250,7 @@ expression: diff.instruction_rows
address: 178, address: 178,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1161,6 +1264,7 @@ expression: diff.instruction_rows
address: 180, address: 180,
size: 2, size: 2,
opcode: 37, opcode: 37,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1174,6 +1278,7 @@ expression: diff.instruction_rows
address: 182, address: 182,
size: 2, size: 2,
opcode: 42, opcode: 42,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1187,6 +1292,7 @@ expression: diff.instruction_rows
address: 184, address: 184,
size: 2, size: 2,
opcode: 44, opcode: 44,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1200,6 +1306,9 @@ expression: diff.instruction_rows
address: 186, address: 186,
size: 2, size: 2,
opcode: 15, opcode: 15,
branch_dest: Some(
200,
),
}, },
), ),
kind: None, kind: None,
@@ -1218,6 +1327,7 @@ expression: diff.instruction_rows
address: 188, address: 188,
size: 2, size: 2,
opcode: 32, opcode: 32,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1231,6 +1341,7 @@ expression: diff.instruction_rows
address: 190, address: 190,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1244,6 +1355,7 @@ expression: diff.instruction_rows
address: 192, address: 192,
size: 2, size: 2,
opcode: 46, opcode: 46,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1257,6 +1369,7 @@ expression: diff.instruction_rows
address: 194, address: 194,
size: 2, size: 2,
opcode: 46, opcode: 46,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1270,6 +1383,7 @@ expression: diff.instruction_rows
address: 196, address: 196,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1283,6 +1397,7 @@ expression: diff.instruction_rows
address: 200, address: 200,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1305,6 +1420,7 @@ expression: diff.instruction_rows
address: 202, address: 202,
size: 2, size: 2,
opcode: 35, opcode: 35,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1318,6 +1434,7 @@ expression: diff.instruction_rows
address: 204, address: 204,
size: 2, size: 2,
opcode: 34, opcode: 34,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1331,6 +1448,7 @@ expression: diff.instruction_rows
address: 206, address: 206,
size: 2, size: 2,
opcode: 4, opcode: 4,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1344,6 +1462,7 @@ expression: diff.instruction_rows
address: 208, address: 208,
size: 4, size: 4,
opcode: 19, opcode: 19,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1357,6 +1476,7 @@ expression: diff.instruction_rows
address: 212, address: 212,
size: 2, size: 2,
opcode: 7, opcode: 7,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1379,6 +1499,7 @@ expression: diff.instruction_rows
address: 214, address: 214,
size: 2, size: 2,
opcode: 55, opcode: 55,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1392,6 +1513,7 @@ expression: diff.instruction_rows
address: 216, address: 216,
size: 4, size: 4,
opcode: 65535, opcode: 65535,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1405,6 +1527,7 @@ expression: diff.instruction_rows
address: 220, address: 220,
size: 4, size: 4,
opcode: 65535, opcode: 65535,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1418,6 +1541,7 @@ expression: diff.instruction_rows
address: 224, address: 224,
size: 4, size: 4,
opcode: 65535, opcode: 65535,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1431,6 +1555,7 @@ expression: diff.instruction_rows
address: 228, address: 228,
size: 4, size: 4,
opcode: 65535, opcode: 65535,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1444,6 +1569,7 @@ expression: diff.instruction_rows
address: 232, address: 232,
size: 4, size: 4,
opcode: 65535, opcode: 65535,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1457,6 +1583,7 @@ expression: diff.instruction_rows
address: 236, address: 236,
size: 4, size: 4,
opcode: 65535, opcode: 65535,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -1470,6 +1597,7 @@ expression: diff.instruction_rows
address: 240, address: 240,
size: 4, size: 4,
opcode: 65535, opcode: 65535,
branch_dest: None,
}, },
), ),
kind: None, kind: None,

View File

@@ -1,5 +1,6 @@
--- ---
source: objdiff-core/tests/arch_arm.rs source: objdiff-core/tests/arch_arm.rs
assertion_line: 33
expression: output 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(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)]
@@ -15,7 +16,7 @@ expression: output
[(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(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(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(26), Normal, 5), (Spacing(4), Normal, 0), (Opcode("beq", 15), Normal, 10), (BranchDest(48), Normal, 0), (Basic(" ~>"), Rotating(1), 0), (Eol, Normal, 0)]
[(Line(44), Dim, 5), (Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(184)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(44), Dim, 5), (Address(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(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(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(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)]
@@ -29,7 +30,7 @@ expression: output
[(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(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(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(50), Dim, 5), (Address(58), Normal, 5), (Spacing(4), Normal, 0), (Opcode("beq", 15), Normal, 10), (BranchDest(212), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)]
[(Line(52), Dim, 5), (Address(60), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(156)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(52), Dim, 5), (Address(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(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(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(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)]
@@ -46,8 +47,8 @@ expression: output
[(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(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(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(86), Dim, 5), (Address(92), Normal, 5), (Spacing(4), Normal, 0), (Opcode("pop", 55), Normal, 10), (Basic("{"), Normal, 0), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r4")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r6")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("r7")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic("}"), Normal, 0), (Eol, Normal, 0)]
[(Line(57), Dim, 5), (Address(94), Normal, 5), (Basic(" ~> "), Rotating(2), 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(128)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(57), Dim, 5), (Address(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), (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(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(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(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)]
@@ -68,7 +69,7 @@ expression: output
[(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(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(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(66), Dim, 5), (Address(144), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bne", 15), Normal, 10), (BranchDest(168), Normal, 0), (Basic(" ~>"), Rotating(3), 0), (Eol, Normal, 0)]
[(Line(68), Dim, 5), (Address(146), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(72)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(68), Dim, 5), (Address(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(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(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(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)]
@@ -84,19 +85,19 @@ expression: output
[(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(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(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(176), Normal, 5), (Spacing(4), Normal, 0), (Opcode("beq", 15), Normal, 10), (BranchDest(200), Normal, 0), (Basic(" ~>"), Rotating(4), 0), (Eol, Normal, 0)]
[(Line(75), Dim, 5), (Address(178), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(52)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(75), Dim, 5), (Address(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(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(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(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(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(188), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 32), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("r5")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(12)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Line(77), Dim, 5), (Address(190), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r3")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(44)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(77), Dim, 5), (Address(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(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(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(77), Dim, 5), (Address(196), Normal, 5), (Spacing(4), Normal, 0), (Opcode("bl", 19), Normal, 10), (Symbol(Symbol { name: "SCQUE_PUT_MsgImpl", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Addend(-4), Bright, 0), (Eol, Normal, 0)]
[(Line(81), Dim, 5), (Address(200), Normal, 5), (Basic(" ~> "), Rotating(4), 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(20)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(81), Dim, 5), (Address(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(202), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 35), Normal, 10), (Argument(Opaque("r1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("sp")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(8)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Line(81), Dim, 5), (Address(204), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ldr", 34), Normal, 10), (Argument(Opaque("r2")), Normal, 0), (Basic(", "), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("pc")), Normal, 0), (Basic(", "), Normal, 0), (Basic("#"), Normal, 0), (Argument(Signed(32)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)] [(Line(81), Dim, 5), (Address(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(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(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(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)]

View File

@@ -3449,6 +3449,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3463,6 +3464,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3477,6 +3479,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3491,6 +3494,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3505,6 +3509,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3519,6 +3524,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3533,6 +3539,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3547,6 +3554,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3561,6 +3569,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3575,6 +3584,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3589,6 +3599,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3603,6 +3614,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3617,6 +3629,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3631,6 +3644,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3645,6 +3659,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3659,6 +3674,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3673,6 +3689,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -3687,6 +3704,9 @@ Object {
244, 244,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Elf( flags: Elf(
@@ -3797,6 +3817,7 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: None,
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,

View File

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

View File

@@ -683,6 +683,9 @@ Object {
632, 632,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
8,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Elf( flags: Elf(
@@ -1306,6 +1309,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1320,6 +1326,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1334,6 +1343,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1348,6 +1360,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1362,6 +1377,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1376,6 +1394,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1390,6 +1411,9 @@ Object {
43, 43,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
8,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1404,6 +1428,9 @@ Object {
76, 76,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
8,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1418,6 +1445,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1432,6 +1462,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1446,6 +1479,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
--- ---
source: objdiff-core/tests/arch_ppc.rs source: objdiff-core/tests/arch_ppc.rs
assertion_line: 14
expression: obj expression: obj
--- ---
Object { Object {
@@ -167,6 +166,9 @@ Object {
284, 284,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Elf( flags: Elf(
@@ -392,6 +394,9 @@ Object {
4, 4,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Elf( flags: Elf(
@@ -417,6 +422,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
8,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: Some( virtual_address: Some(
@@ -433,6 +441,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -447,6 +458,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -461,6 +475,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -475,6 +492,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -489,6 +509,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -503,6 +526,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -517,6 +543,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,

View File

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

View File

@@ -136,6 +136,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -150,6 +153,9 @@ Object {
10, 10,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -173,6 +179,9 @@ Object {
18, 18,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(

View File

@@ -9,6 +9,7 @@ expression: diff.instruction_rows
address: 0, address: 0,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -22,6 +23,7 @@ expression: diff.instruction_rows
address: 5, address: 5,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -35,6 +37,7 @@ expression: diff.instruction_rows
address: 10, address: 10,
size: 1, size: 1,
opcode: 640, opcode: 640,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -48,6 +51,7 @@ expression: diff.instruction_rows
address: 11, address: 11,
size: 4, size: 4,
opcode: 740, opcode: 740,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -61,6 +65,7 @@ expression: diff.instruction_rows
address: 15, address: 15,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -74,6 +79,7 @@ expression: diff.instruction_rows
address: 20, address: 20,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -87,6 +93,7 @@ expression: diff.instruction_rows
address: 25, address: 25,
size: 4, size: 4,
opcode: 448, opcode: 448,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -100,6 +107,7 @@ expression: diff.instruction_rows
address: 29, address: 29,
size: 4, size: 4,
opcode: 460, opcode: 460,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -113,6 +121,7 @@ expression: diff.instruction_rows
address: 33, address: 33,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -126,6 +135,7 @@ expression: diff.instruction_rows
address: 38, address: 38,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -139,6 +149,7 @@ expression: diff.instruction_rows
address: 43, address: 43,
size: 5, size: 5,
opcode: 448, opcode: 448,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -152,6 +163,7 @@ expression: diff.instruction_rows
address: 48, address: 48,
size: 5, size: 5,
opcode: 460, opcode: 460,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -165,6 +177,7 @@ expression: diff.instruction_rows
address: 53, address: 53,
size: 4, size: 4,
opcode: 11, opcode: 11,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -178,6 +191,7 @@ expression: diff.instruction_rows
address: 57, address: 57,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -191,6 +205,7 @@ expression: diff.instruction_rows
address: 62, address: 62,
size: 5, size: 5,
opcode: 414, opcode: 414,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -204,6 +219,7 @@ expression: diff.instruction_rows
address: 67, address: 67,
size: 5, size: 5,
opcode: 448, opcode: 448,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -217,6 +233,7 @@ expression: diff.instruction_rows
address: 72, address: 72,
size: 5, size: 5,
opcode: 460, opcode: 460,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -230,6 +247,7 @@ expression: diff.instruction_rows
address: 77, address: 77,
size: 4, size: 4,
opcode: 11, opcode: 11,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -243,6 +261,7 @@ expression: diff.instruction_rows
address: 81, address: 81,
size: 4, size: 4,
opcode: 7, opcode: 7,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -256,6 +275,7 @@ expression: diff.instruction_rows
address: 85, address: 85,
size: 1, size: 1,
opcode: 590, opcode: 590,
branch_dest: None,
}, },
), ),
kind: None, kind: None,
@@ -269,6 +289,7 @@ expression: diff.instruction_rows
address: 86, address: 86,
size: 1, size: 1,
opcode: 662, opcode: 662,
branch_dest: None,
}, },
), ),
kind: None, kind: None,

View File

@@ -866,6 +866,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -880,6 +883,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
1,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -894,6 +900,9 @@ Object {
429, 429,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1029,6 +1038,9 @@ Object {
141, 141,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1043,6 +1055,9 @@ Object {
87, 87,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1057,6 +1072,9 @@ Object {
105, 105,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1071,6 +1089,9 @@ Object {
82, 82,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1085,6 +1106,9 @@ Object {
8, 8,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1099,6 +1123,9 @@ Object {
12, 12,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1138,6 +1165,9 @@ Object {
8, 8,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1152,6 +1182,9 @@ Object {
12, 12,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1191,6 +1224,9 @@ Object {
8, 8,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1205,6 +1241,9 @@ Object {
12, 12,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1244,6 +1283,9 @@ Object {
8, 8,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1258,6 +1300,9 @@ Object {
12, 12,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1297,6 +1342,9 @@ Object {
256, 256,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1344,6 +1392,9 @@ Object {
20, 20,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1367,6 +1418,9 @@ Object {
12, 12,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1406,6 +1460,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1420,6 +1477,9 @@ Object {
8, 8,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
8,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1443,6 +1503,9 @@ Object {
8, 8,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
8,
),
relocations: [ relocations: [
Relocation { Relocation {
flags: Coff( flags: Coff(
@@ -1466,6 +1529,9 @@ Object {
4, 4,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1480,6 +1546,9 @@ Object {
4, 4,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
4,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,
@@ -1494,6 +1563,9 @@ Object {
0, 0,
), ),
flags: FlagSet(), flags: FlagSet(),
align: Some(
16,
),
relocations: [], relocations: [],
line_info: {}, line_info: {},
virtual_address: None, virtual_address: None,

View File

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

View File

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

@@ -0,0 +1,39 @@
---
source: objdiff-core/tests/arch_x86.rs
expression: output
---
[(Address(0), Normal, 5), (Spacing(4), Normal, 0), (Opcode("mov", 414), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("esp")), Normal, 0), (Argument(Opaque("+")), Normal, 0), (Argument(Signed(4)), Normal, 0), (Basic("]"), Normal, 0), (Eol, Normal, 0)]
[(Address(4), Normal, 5), (Spacing(4), Normal, 0), (Opcode("dec", 137), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Eol, Normal, 0)]
[(Address(5), Normal, 5), (Spacing(4), Normal, 0), (Opcode("cmp", 93), Normal, 10), (Argument(Opaque("eax")), Normal, 0), (Basic(","), Normal, 0), (Spacing(1), Normal, 0), (Argument(Unsigned(6)), Normal, 0), (Eol, Normal, 0)]
[(Address(8), Normal, 5), (Spacing(4), Normal, 0), (Opcode("ja", 297), Normal, 10), (Argument(Opaque("short")), Normal, 0), (Spacing(1), Normal, 0), (BranchDest(58), Normal, 0), (Basic(" ~>"), Rotating(0), 0), (Eol, Normal, 0)]
[(Address(10), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jmp", 308), Normal, 10), (Argument(Opaque("dword")), Normal, 0), (Spacing(1), Normal, 0), (Argument(Opaque("ptr")), Normal, 0), (Spacing(1), Normal, 0), (Basic("["), Normal, 0), (Argument(Opaque("eax")), Normal, 0), (Argument(Opaque("*")), Normal, 0), (Argument(Signed(4)), Normal, 0), (Argument(Opaque("+")), Normal, 0), (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

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

@@ -42,11 +42,11 @@ png = "0.17"
pollster = "0.4" pollster = "0.4"
regex = "1.11" regex = "1.11"
rfd = { version = "0.15" } #, default-features = false, features = ['xdg-portal'] rfd = { version = "0.15" } #, default-features = false, features = ['xdg-portal']
rlwinmdec = { version = "1.0", git = "https://github.com/CelestialAmber/rlwinmdec.git" } rlwinmdec = "1.1"
ron = "0.8" ron = "0.8"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
time = { version = "0.3", features = ["formatting", "local-offset"] } time = { version = "0.3", features = ["formatting", "local-offset"] }
typed-path = "0.10" typed-path = "0.11"
winit = { version = "0.30", features = ["wayland-csd-adwaita"] } winit = { version = "0.30", features = ["wayland-csd-adwaita"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] }

View File

@@ -775,9 +775,7 @@ impl eframe::App for App {
if side_panel_available { if side_panel_available {
egui::SidePanel::left("side_panel").show_animated(ctx, *show_side_panel, |ui| { egui::SidePanel::left("side_panel").show_animated(ctx, *show_side_panel, |ui| {
egui::ScrollArea::both().show(ui, |ui| { config_ui(ui, state, show_project_config, config_state, appearance);
config_ui(ui, state, show_project_config, config_state, appearance);
});
}); });
} }

View File

@@ -297,27 +297,36 @@ pub fn config_ui(
node_open = NodeOpen::Open; node_open = NodeOpen::Open;
} }
CollapsingHeader::new(RichText::new("🗀 Objects").font(FontId { egui::ScrollArea::both().auto_shrink(false).show(ui, |ui| {
size: appearance.ui_font.size, CollapsingHeader::new(RichText::new("🗀 Objects").font(FontId {
family: appearance.code_font.family.clone(), size: appearance.ui_font.size,
})) family: appearance.code_font.family.clone(),
.open(root_open) }))
.default_open(true) .open(root_open)
.show(ui, |ui| { .default_open(true)
let search = config_state.object_search.to_ascii_lowercase(); .show(ui, |ui| {
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend); let search = config_state.object_search.to_ascii_lowercase();
for node in object_nodes.iter().filter_map(|node| { ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
filter_node( for node in object_nodes.iter().filter_map(|node| {
objects, filter_node(
node, objects,
&search, node,
config_state.filter_diffable, &search,
config_state.filter_incomplete, config_state.filter_diffable,
config_state.show_hidden, config_state.filter_incomplete,
) config_state.show_hidden,
}) { )
display_node(ui, &mut new_selected_index, objects, &node, appearance, node_open); }) {
} display_node(
ui,
&mut new_selected_index,
objects,
&node,
appearance,
node_open,
);
}
});
}); });
} }
if new_selected_index != selected_index { if new_selected_index != selected_index {
@@ -327,11 +336,6 @@ pub fn config_ui(
state_guard.set_selected_obj(config); state_guard.set_selected_obj(config);
} }
} }
if state_guard.config.selected_obj.is_some()
&& ui.add_enabled(!config_state.build_running, egui::Button::new("Build")).clicked()
{
config_state.queue_build = true;
}
} }
fn display_unit( fn display_unit(

View File

@@ -5,7 +5,7 @@ use objdiff_core::{
diff::{ diff::{
DataDiff, DataDiffKind, DataRelocationDiff, DataDiff, DataDiffKind, DataRelocationDiff,
data::resolve_relocation, data::resolve_relocation,
display::{ContextItem, HoverItem, relocation_context, relocation_hover}, display::{ContextItem, HoverItem, HoverItemColor, relocation_context, relocation_hover},
}, },
obj::Object, obj::Object,
}; };
@@ -19,6 +19,7 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
let mut out = Vec::new(); let mut out = Vec::new();
let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs); let reloc_diffs = diffs.iter().flat_map(|(_, reloc_diffs)| reloc_diffs);
let mut prev_reloc = None; let mut prev_reloc = None;
let mut first = true;
for reloc_diff in reloc_diffs { for reloc_diff in reloc_diffs {
let reloc = &reloc_diff.reloc; let reloc = &reloc_diff.reloc;
if prev_reloc == Some(reloc) { if prev_reloc == Some(reloc) {
@@ -29,11 +30,16 @@ fn data_row_hover(obj: &Object, diffs: &[(DataDiff, Vec<DataRelocationDiff>)]) -
} }
prev_reloc = Some(reloc); prev_reloc = Some(reloc);
// TODO: Change hover text color depending on Insert/Delete/Replace kind if first {
// let color = get_color_for_diff_kind(reloc_diff.kind, appearance); first = false;
} else {
out.push(HoverItem::Separator);
}
let color = get_hover_item_color_for_diff_kind(reloc_diff.kind);
let reloc = resolve_relocation(&obj.symbols, reloc); let reloc = resolve_relocation(&obj.symbols, reloc);
out.append(&mut relocation_hover(obj, reloc)); out.append(&mut relocation_hover(obj, reloc, Some(color)));
} }
out out
} }
@@ -97,6 +103,15 @@ fn get_color_for_diff_kind(diff_kind: DataDiffKind, appearance: &Appearance) ->
} }
} }
fn get_hover_item_color_for_diff_kind(diff_kind: DataDiffKind) -> HoverItemColor {
match diff_kind {
DataDiffKind::None => HoverItemColor::Normal,
DataDiffKind::Replace => HoverItemColor::Special,
DataDiffKind::Delete => HoverItemColor::Delete,
DataDiffKind::Insert => HoverItemColor::Insert,
}
}
pub(crate) fn data_row_ui( pub(crate) fn data_row_ui(
ui: &mut egui::Ui, ui: &mut egui::Ui,
obj: Option<&Object>, obj: Option<&Object>,

View File

@@ -795,6 +795,8 @@ pub fn hover_items_ui(ui: &mut Ui, items: Vec<HoverItem>, appearance: &Appearanc
if !label.is_empty() { if !label.is_empty() {
let label_color = match color { let label_color = match color {
HoverItemColor::Special => appearance.replace_color, HoverItemColor::Special => appearance.replace_color,
HoverItemColor::Delete => appearance.delete_color,
HoverItemColor::Insert => appearance.insert_color,
_ => appearance.highlight_color, _ => appearance.highlight_color,
}; };
write_text(&label, label_color, &mut job, appearance.code_font.clone()); write_text(&label, label_color, &mut job, appearance.code_font.clone());

View File

@@ -512,7 +512,7 @@ pub fn symbol_hover_ui(
ui.scope(|ui| { ui.scope(|ui| {
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap); ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap);
hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0), appearance); hover_items_ui(ui, symbol_hover(ctx.obj, symbol_idx, 0, None), appearance);
}); });
} }

View File

@@ -1,9 +1,7 @@
[package] [package]
name = "objdiff-wasm" name = "objdiff-wasm"
version.workspace = true version.workspace = true
# TODO: Update to 2024 edition = "2024"
# https://github.com/bytecodealliance/wit-bindgen/pull/1183
edition = "2021"
rust-version.workspace = true rust-version.workspace = true
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
@@ -25,17 +23,18 @@ std = ["objdiff-core/std"]
[dependencies] [dependencies]
log = { version = "0.4", default-features = false } log = { version = "0.4", default-features = false }
regex = { version = "1.11", default-features = false, features = ["unicode-case"] } regex = { version = "1.11", default-features = false, features = ["unicode-case"] }
xxhash-rust = { version = "0.8", default-features = false, features = ["xxh3"] }
[dependencies.objdiff-core] [dependencies.objdiff-core]
path = "../objdiff-core" path = "../objdiff-core"
default-features = false default-features = false
features = ["arm", "arm64", "mips", "ppc", "x86", "dwarf"] features = ["arm", "arm64", "mips", "ppc", "superh", "x86", "dwarf"]
[target.'cfg(target_family = "wasm")'.dependencies] [target.'cfg(target_family = "wasm")'.dependencies]
talc = { version = "4.4", default-features = false, features = ["lock_api"] } talc = { version = "4.4", default-features = false, features = ["lock_api"] }
[target.'cfg(target_os = "wasi")'.dependencies] [target.'cfg(target_os = "wasi")'.dependencies]
wit-bindgen = { version = "0.40", default-features = false, features = ["macros"] } wit-bindgen = { version = "0.42", default-features = false, features = ["macros"] }
[build-dependencies] [build-dependencies]
wit-deps = "0.5" wit-deps = "0.5"

View File

@@ -1,12 +1,12 @@
{ {
"name": "objdiff-wasm", "name": "objdiff-wasm",
"version": "3.0.0-beta.4", "version": "3.0.0-beta.7",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "objdiff-wasm", "name": "objdiff-wasm",
"version": "3.0.0-beta.4", "version": "3.0.0-beta.7",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.3", "@biomejs/biome": "^1.9.3",

View File

@@ -1,6 +1,6 @@
{ {
"name": "objdiff-wasm", "name": "objdiff-wasm",
"version": "3.0.0-beta.4", "version": "3.0.0-beta.7",
"description": "A local diffing tool for decompilation projects.", "description": "A local diffing tool for decompilation projects.",
"author": { "author": {
"name": "Luke Street", "name": "Luke Street",

View File

@@ -1,14 +1,16 @@
use alloc::{ use alloc::{
format, format,
rc::Rc, rc::{Rc, Weak},
str::FromStr, str::FromStr,
string::{String, ToString}, string::{String, ToString},
vec,
vec::Vec, vec::Vec,
}; };
use core::cell::RefCell; use core::cell::RefCell;
use objdiff_core::{diff, obj}; use objdiff_core::{diff, obj};
use regex::{Regex, RegexBuilder}; use regex::{Regex, RegexBuilder};
use xxhash_rust::xxh3::xxh3_64;
use super::logging; use super::logging;
@@ -41,8 +43,7 @@ impl Guest for Component {
fn version() -> String { env!("CARGO_PKG_VERSION").to_string() } fn version() -> String { env!("CARGO_PKG_VERSION").to_string() }
} }
#[repr(transparent)] struct ResourceObject(Rc<obj::Object>, u64);
struct ResourceObject(Rc<obj::Object>);
struct ResourceObjectDiff(Rc<obj::Object>, diff::ObjectDiff); struct ResourceObjectDiff(Rc<obj::Object>, diff::ObjectDiff);
@@ -153,16 +154,17 @@ impl GuestDisplay for Component {
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
let symbol_idx = symbol_display.symbol as usize; let symbol_idx = symbol_display.symbol as usize;
let symbol = &obj.symbols[symbol_idx]; let Some(symbol) = obj.symbols.get(symbol_idx) else {
return SymbolDisplay { name: "<unknown>".to_string(), ..Default::default() };
};
let symbol_diff = if symbol_display.is_mapping_symbol { let symbol_diff = if symbol_display.is_mapping_symbol {
obj_diff obj_diff
.mapping_symbols .mapping_symbols
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_idx)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
.unwrap()
} else { } else {
&obj_diff.symbols[symbol_idx] obj_diff.symbols.get(symbol_idx)
}; };
SymbolDisplay { SymbolDisplay {
name: symbol.name.clone(), name: symbol.name.clone(),
@@ -174,10 +176,10 @@ impl GuestDisplay for Component {
flags: SymbolFlags::from(symbol.flags), flags: SymbolFlags::from(symbol.flags),
align: symbol.align.map(|a| a.get()), align: symbol.align.map(|a| a.get()),
virtual_address: symbol.virtual_address, virtual_address: symbol.virtual_address,
target_symbol: symbol_diff.target_symbol.map(|s| s as u32), target_symbol: symbol_diff.and_then(|sd| sd.target_symbol.map(|s| s as u32)),
match_percent: symbol_diff.match_percent, match_percent: symbol_diff.and_then(|sd| sd.match_percent),
diff_score: symbol_diff.diff_score, diff_score: symbol_diff.and_then(|sd| sd.diff_score),
row_count: symbol_diff.instruction_rows.len() as u32, row_count: symbol_diff.map_or(0, |sd| sd.instruction_rows.len() as u32),
} }
} }
@@ -187,7 +189,6 @@ impl GuestDisplay for Component {
row_index: u32, row_index: u32,
diff_config: DiffConfigBorrow, diff_config: DiffConfigBorrow,
) -> InstructionDiffRow { ) -> InstructionDiffRow {
let mut segments = Vec::with_capacity(16);
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
@@ -198,12 +199,15 @@ impl GuestDisplay for Component {
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_idx)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
.unwrap()
} else { } else {
&obj_diff.symbols[symbol_idx] obj_diff.symbols.get(symbol_idx)
};
let Some(row) = symbol_diff.and_then(|sd| sd.instruction_rows.get(row_index as usize))
else {
return InstructionDiffRow::default();
}; };
let row = &symbol_diff.instruction_rows[row_index as usize];
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let mut segments = Vec::with_capacity(16);
diff::display::display_row(obj, symbol_idx, row, &diff_config, |segment| { diff::display::display_row(obj, symbol_idx, row, &diff_config, |segment| {
segments.push(DiffTextSegment::from(segment)); segments.push(DiffTextSegment::from(segment));
Ok(()) Ok(())
@@ -230,7 +234,9 @@ impl GuestDisplay for Component {
) -> Vec<HoverItem> { ) -> Vec<HoverItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0 /* TODO */) let addend = 0; // TODO
let override_color = None; // TODO: colorize replaced/deleted/inserted relocations
diff::display::symbol_hover(obj, symbol_display.symbol as usize, addend, override_color)
.into_iter() .into_iter()
.map(|item| HoverItem::from(item)) .map(|item| HoverItem::from(item))
.collect() .collect()
@@ -241,7 +247,7 @@ impl GuestDisplay for Component {
symbol_display: SectionDisplaySymbol, symbol_display: SectionDisplaySymbol,
row_index: u32, row_index: u32,
diff_config: DiffConfigBorrow, diff_config: DiffConfigBorrow,
) -> Result<Vec<ContextItem>, String> { ) -> Vec<ContextItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
@@ -252,24 +258,35 @@ impl GuestDisplay for Component {
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_idx)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
.unwrap()
} else { } else {
&obj_diff.symbols[symbol_idx] obj_diff.symbols.get(symbol_idx)
}; };
let row = &symbol_diff.instruction_rows[row_index as usize]; let Some(ins_ref) = symbol_diff
let Some(ins_ref) = row.ins_ref else { .and_then(|sd| sd.instruction_rows.get(row_index as usize))
return Ok(Vec::new()); .and_then(|row| row.ins_ref)
else {
return Vec::new();
}; };
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else { let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
return Err("Failed to resolve instruction".into()); return vec![ContextItem::Copy(ContextItemCopy {
value: "Failed to resolve instruction".to_string(),
label: Some("error".to_string()),
})];
}; };
let ins = let ins = match obj.arch.process_instruction(resolved, &diff_config) {
obj.arch.process_instruction(resolved, &diff_config).map_err(|e| e.to_string())?; Ok(ins) => ins,
Ok(diff::display::instruction_context(obj, resolved, &ins) Err(e) => {
return vec![ContextItem::Copy(ContextItemCopy {
value: e.to_string(),
label: Some("error".to_string()),
})];
}
};
diff::display::instruction_context(obj, resolved, &ins)
.into_iter() .into_iter()
.map(|item| ContextItem::from(item)) .map(|item| ContextItem::from(item))
.collect()) .collect()
} }
fn instruction_hover( fn instruction_hover(
@@ -277,7 +294,7 @@ impl GuestDisplay for Component {
symbol_display: SectionDisplaySymbol, symbol_display: SectionDisplaySymbol,
row_index: u32, row_index: u32,
diff_config: DiffConfigBorrow, diff_config: DiffConfigBorrow,
) -> Result<Vec<HoverItem>, String> { ) -> Vec<HoverItem> {
let obj_diff = diff.get::<ResourceObjectDiff>(); let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref(); let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1; let obj_diff = &obj_diff.1;
@@ -288,24 +305,37 @@ impl GuestDisplay for Component {
.iter() .iter()
.find(|s| s.symbol_index == symbol_idx) .find(|s| s.symbol_index == symbol_idx)
.map(|s| &s.symbol_diff) .map(|s| &s.symbol_diff)
.unwrap()
} else { } else {
&obj_diff.symbols[symbol_idx] obj_diff.symbols.get(symbol_idx)
}; };
let row = &symbol_diff.instruction_rows[row_index as usize]; let Some(ins_ref) = symbol_diff
let Some(ins_ref) = row.ins_ref else { .and_then(|sd| sd.instruction_rows.get(row_index as usize))
return Ok(Vec::new()); .and_then(|row| row.ins_ref)
else {
return Vec::new();
}; };
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else { let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
return Err("Failed to resolve instruction".into()); return vec![HoverItem::Text(HoverItemText {
label: "Error".to_string(),
value: "Failed to resolve instruction".to_string(),
color: HoverItemColor::Delete,
})];
}; };
let ins = let ins = match obj.arch.process_instruction(resolved, &diff_config) {
obj.arch.process_instruction(resolved, &diff_config).map_err(|e| e.to_string())?; Ok(ins) => ins,
Ok(diff::display::instruction_hover(obj, resolved, &ins) Err(e) => {
return vec![HoverItem::Text(HoverItemText {
label: "Error".to_string(),
value: e.to_string(),
color: HoverItemColor::Delete,
})];
}
};
diff::display::instruction_hover(obj, resolved, &ins)
.into_iter() .into_iter()
.map(|item| HoverItem::from(item)) .map(|item| HoverItem::from(item))
.collect()) .collect()
} }
} }
@@ -421,13 +451,49 @@ impl GuestDiffConfig for ResourceDiffConfig {
} }
} }
struct CachedObject(Weak<obj::Object>, u64);
struct ObjectCache(RefCell<Vec<CachedObject>>);
impl ObjectCache {
#[inline]
const fn new() -> Self { Self(RefCell::new(Vec::new())) }
}
impl core::ops::Deref for ObjectCache {
type Target = RefCell<Vec<CachedObject>>;
fn deref(&self) -> &Self::Target { &self.0 }
}
// Assume single-threaded environment
unsafe impl Sync for ObjectCache {}
static OBJECT_CACHE: ObjectCache = ObjectCache::new();
impl GuestObject for ResourceObject { impl GuestObject for ResourceObject {
fn parse(data: Vec<u8>, diff_config: DiffConfigBorrow) -> Result<Object, String> { fn parse(data: Vec<u8>, diff_config: DiffConfigBorrow) -> Result<Object, String> {
let hash = xxh3_64(&data);
let mut cached = None;
OBJECT_CACHE.borrow_mut().retain(|c| {
if c.0.strong_count() == 0 {
return false;
}
if c.1 == hash {
cached = c.0.upgrade();
}
true
});
if let Some(obj) = cached {
return Ok(Object::new(ResourceObject(obj, hash)));
}
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow(); let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
obj::read::parse(&data, &diff_config) let obj = Rc::new(obj::read::parse(&data, &diff_config).map_err(|e| e.to_string())?);
.map(|o| Object::new(ResourceObject(Rc::new(o)))) OBJECT_CACHE.borrow_mut().push(CachedObject(Rc::downgrade(&obj), hash));
.map_err(|e| e.to_string()) Ok(Object::new(ResourceObject(obj, hash)))
} }
fn hash(&self) -> u64 { self.1 }
} }
impl GuestObjectDiff for ResourceObjectDiff { impl GuestObjectDiff for ResourceObjectDiff {
@@ -465,6 +531,8 @@ impl From<diff::display::HoverItemColor> for HoverItemColor {
diff::display::HoverItemColor::Normal => HoverItemColor::Normal, diff::display::HoverItemColor::Normal => HoverItemColor::Normal,
diff::display::HoverItemColor::Emphasized => HoverItemColor::Emphasized, diff::display::HoverItemColor::Emphasized => HoverItemColor::Emphasized,
diff::display::HoverItemColor::Special => HoverItemColor::Special, diff::display::HoverItemColor::Special => HoverItemColor::Special,
diff::display::HoverItemColor::Delete => HoverItemColor::Delete,
diff::display::HoverItemColor::Insert => HoverItemColor::Insert,
} }
} }
} }
@@ -496,4 +564,40 @@ impl From<diff::display::SymbolNavigationKind> for SymbolNavigationKind {
} }
} }
impl Default for InstructionDiffKind {
fn default() -> Self { Self::None }
}
impl Default for InstructionDiffRow {
fn default() -> Self { Self { segments: Default::default(), diff_kind: Default::default() } }
}
impl Default for SymbolKind {
fn default() -> Self { Self::Unknown }
}
impl Default for SymbolFlags {
fn default() -> Self { Self::empty() }
}
impl Default for SymbolDisplay {
fn default() -> Self {
Self {
name: Default::default(),
demangled_name: Default::default(),
address: Default::default(),
size: Default::default(),
kind: Default::default(),
section: Default::default(),
flags: Default::default(),
align: Default::default(),
virtual_address: Default::default(),
target_symbol: Default::default(),
match_percent: Default::default(),
diff_score: Default::default(),
row_count: Default::default(),
}
}
}
export!(Component); export!(Component);

View File

@@ -20,7 +20,7 @@
//! this is defined as a "weak" symbol. This means that other definitions are //! this is defined as a "weak" symbol. This means that other definitions are
//! allowed to overwrite it if they are present in a compilation. //! allowed to overwrite it if they are present in a compilation.
use alloc::{alloc, Layout}; use alloc::{Layout, alloc};
use core::ptr; use core::ptr;
#[used] #[used]
@@ -31,24 +31,32 @@ static FORCE_CODEGEN_OF_CABI_REALLOC: unsafe extern "C" fn(
usize, usize,
) -> *mut u8 = cabi_realloc; ) -> *mut u8 = cabi_realloc;
#[no_mangle] #[unsafe(no_mangle)]
pub unsafe extern "C" fn cabi_realloc( pub unsafe extern "C" fn cabi_realloc(
old_ptr: *mut u8, old_ptr: *mut u8,
old_len: usize, old_len: usize,
align: usize, mut align: usize,
new_len: usize, new_len: usize,
) -> *mut u8 { ) -> *mut u8 {
// HACK: The object crate requires the data alignment for 64-bit objects to be 8,
// but in wasm32, our allocator will have a minimum alignment of 4. We can't specify
// the alignment of `list<u8>` in the component model, so we work around this here.
// https://github.com/WebAssembly/component-model/issues/258
#[cfg(target_pointer_width = "32")]
if align == 1 {
align = 8;
}
let layout; let layout;
let ptr = if old_len == 0 { let ptr = if old_len == 0 {
if new_len == 0 { if new_len == 0 {
return ptr::without_provenance_mut(align); return ptr::without_provenance_mut(align);
} }
layout = Layout::from_size_align_unchecked(new_len, align); layout = unsafe { Layout::from_size_align_unchecked(new_len, align) };
alloc::alloc(layout) unsafe { alloc::alloc(layout) }
} else { } else {
debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!"); debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!");
layout = Layout::from_size_align_unchecked(old_len, align); layout = unsafe { Layout::from_size_align_unchecked(old_len, align) };
alloc::realloc(old_ptr, layout, new_len) unsafe { alloc::realloc(old_ptr, layout, new_len) }
}; };
if ptr.is_null() { if ptr.is_null() {
// Print a nice message in debug mode, but in release mode don't // Print a nice message in debug mode, but in release mode don't

View File

@@ -20,6 +20,8 @@ interface diff {
data: list<u8>, data: list<u8>,
config: borrow<diff-config>, config: borrow<diff-config>,
) -> result<object, string>; ) -> result<object, string>;
hash: func() -> u64;
} }
resource object-diff { resource object-diff {
@@ -135,6 +137,8 @@ interface display {
normal, normal,
emphasized, emphasized,
special, special,
delete,
insert,
} }
record hover-item-text { record hover-item-text {
@@ -253,14 +257,14 @@ interface display {
symbol: section-display-symbol, symbol: section-display-symbol,
row-index: u32, row-index: u32,
config: borrow<diff-config>, config: borrow<diff-config>,
) -> result<list<context-item>, string>; ) -> list<context-item>;
instruction-hover: func( instruction-hover: func(
diff: borrow<object-diff>, diff: borrow<object-diff>,
symbol: section-display-symbol, symbol: section-display-symbol,
row-index: u32, row-index: u32,
config: borrow<diff-config>, config: borrow<diff-config>,
) -> result<list<hover-item>, string>; ) -> list<hover-item>;
} }
world api { world api {