mirror of
https://github.com/encounter/objdiff.git
synced 2026-07-10 12:18:36 -07:00
Compare commits
54 Commits
v2.0.0-beta.6
...
v2.3.4
| Author | SHA1 | Date | |
|---|---|---|---|
| d2b7a9ef25 | |||
| 2cf9cf24d6 | |||
| 5ef3416457 | |||
| 6ff8d002f7 | |||
| 9ca157d717 | |||
| 67b63311fc | |||
| 72ea1c8911 | |||
| d4a540857d | |||
| 676488433f | |||
| 83de98b5ee | |||
| c1ba4e91d1 | |||
| 575900024d | |||
| cbe299e859 | |||
| 741d93e211 | |||
| 603dbd6882 | |||
| 6fb0a63de2 | |||
| ab2e84a2c6 | |||
| 9596051cb4 | |||
| a5d9d8282e | |||
| 3287a0f65c | |||
| fab9c62dfb | |||
| 08cd768260 | |||
| 8acaaf528c | |||
| 6e881a74e1 | |||
| cc1bc44e69 | |||
| c7b85518ab | |||
| bb039a1445 | |||
| 8fc142d316 | |||
| b0123b3f83 | |||
| 2ec17aee9b | |||
| ec9731e1e5 | |||
| a06382c27e | |||
| e013638c5a | |||
| 70ab82f1f7 | |||
| c5896689cf | |||
| 67719dd93e | |||
| 258e141017 | |||
| dbdda55065 | |||
| a43320af1f | |||
| 35bbd40f5d | |||
| c1cb4b0b19 | |||
| 2379853faa | |||
| 5e1aff180f | |||
| 3846a7d315 | |||
| dcf209aac5 | |||
| c7e6394628 | |||
| 235dc7f517 | |||
| 199c07e975 | |||
| 56a5a61825 | |||
| 3d2236de82 | |||
| bcc5871cd8 | |||
| 7d0d7df54c | |||
| 0221a2d54d | |||
| bc687173c0 |
@@ -0,0 +1,5 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
linker = "rust-lld"
|
||||
|
||||
[target.aarch64-pc-windows-msvc]
|
||||
linker = "rust-lld"
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
env:
|
||||
BUILD_PROFILE: release-lto
|
||||
CARGO_TARGET_DIR: target
|
||||
CARGO_INCREMENTAL: 0
|
||||
|
||||
jobs:
|
||||
check:
|
||||
@@ -25,37 +26,16 @@ jobs:
|
||||
sudo apt-get -y install libgtk-3-dev
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Check git tag against Cargo version
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
shell: bash
|
||||
run: |
|
||||
set -eou pipefail
|
||||
tag='${{github.ref}}'
|
||||
tag="${tag#refs/tags/}"
|
||||
for file in */Cargo.toml; do
|
||||
version=$(grep '^version' $file | head -1 | awk -F' = ' '{print $2}' | tr -d '"')
|
||||
version="v$version"
|
||||
if [ "$tag" != "$version" ]; then
|
||||
echo "::error::Git tag doesn't match the Cargo version! ($tag != $version)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.4
|
||||
- name: Cache Rust workspace
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- name: Cargo check
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
run: cargo check
|
||||
run: cargo check --all-features --all-targets
|
||||
- name: Cargo clippy
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
run: cargo clippy
|
||||
run: cargo clippy --all-features --all-targets
|
||||
|
||||
fmt:
|
||||
name: Format
|
||||
@@ -107,13 +87,10 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.4
|
||||
- name: Cache Rust workspace
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- name: Cargo test
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
run: cargo test --release
|
||||
run: cargo test --release --all-features
|
||||
|
||||
build-cli:
|
||||
name: Build objdiff-cli
|
||||
@@ -137,10 +114,10 @@ jobs:
|
||||
name: linux-aarch64
|
||||
build: zigbuild
|
||||
features: default
|
||||
- platform: ubuntu-latest
|
||||
target: armv7-unknown-linux-musleabi
|
||||
name: linux-armv7l
|
||||
build: zigbuild
|
||||
- platform: windows-latest
|
||||
target: i686-pc-windows-msvc
|
||||
name: windows-x86
|
||||
build: build
|
||||
features: default
|
||||
- platform: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
@@ -169,11 +146,19 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
- name: Install cargo-zigbuild
|
||||
if: matrix.build == 'zigbuild'
|
||||
run: pip install ziglang==0.13.0 cargo-zigbuild==0.19.1
|
||||
run: |
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
echo PATH=$PATH >> $GITHUB_ENV
|
||||
pip install ziglang==0.13.0 cargo-zigbuild==0.19.1
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
- name: Cache Rust workspace
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: ${{ matrix.target }}
|
||||
- name: Cargo build
|
||||
run: >
|
||||
cargo ${{ matrix.build }} --profile ${{ env.BUILD_PROFILE }} --target ${{ matrix.target }}
|
||||
@@ -225,12 +210,11 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.4
|
||||
- name: Cache Rust workspace
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: ${{ matrix.target }}
|
||||
- name: Cargo build
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
run: >
|
||||
cargo build --profile ${{ env.BUILD_PROFILE }} --target ${{ matrix.target }}
|
||||
--bin ${{ env.CARGO_BIN_NAME }} --features ${{ matrix.features }}
|
||||
@@ -247,10 +231,24 @@ jobs:
|
||||
name: Release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ check, build-cli, build-gui ]
|
||||
needs: [ build-cli, build-gui ]
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Check git tag against Cargo version
|
||||
shell: bash
|
||||
run: |
|
||||
set -eou pipefail
|
||||
tag='${{github.ref}}'
|
||||
tag="${tag#refs/tags/}"
|
||||
version=$(grep '^version' Cargo.toml | head -1 | awk -F' = ' '{print $2}' | tr -d '"')
|
||||
version="v$version"
|
||||
if [ "$tag" != "$version" ]; then
|
||||
echo "::error::Git tag doesn't match the Cargo version! ($tag != $version)"
|
||||
exit 1
|
||||
fi
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -278,6 +276,8 @@ jobs:
|
||||
done
|
||||
ls -R ../out
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: out/*
|
||||
draft: true
|
||||
generate_release_notes: true
|
||||
|
||||
@@ -3,10 +3,6 @@ target/
|
||||
**/*.rs.bk
|
||||
generated/
|
||||
|
||||
# cargo-mobile
|
||||
.cargo/
|
||||
/gen
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
|
||||
Generated
+1256
-1100
File diff suppressed because it is too large
Load Diff
+10
-1
@@ -8,5 +8,14 @@ resolver = "2"
|
||||
|
||||
[profile.release-lto]
|
||||
inherits = "release"
|
||||
lto = "thin"
|
||||
lto = "fat"
|
||||
strip = "debuginfo"
|
||||
codegen-units = 1
|
||||
|
||||
[workspace.package]
|
||||
version = "2.3.4"
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/encounter/objdiff"
|
||||
rust-version = "1.74"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
A local diffing tool for decompilation projects. Inspired by [decomp.me](https://decomp.me) and [asm-differ](https://github.com/simonlindholm/asm-differ).
|
||||
|
||||
Features:
|
||||
|
||||
- Compare entire object files: functions and data.
|
||||
- Built-in symbol demangling for C++. (CodeWarrior, Itanium & MSVC)
|
||||
- Automatic rebuild on source file changes.
|
||||
@@ -14,6 +15,7 @@ Features:
|
||||
- Click to highlight all instances of values and registers.
|
||||
|
||||
Supports:
|
||||
|
||||
- PowerPC 750CL (GameCube, Wii)
|
||||
- MIPS (N64, PS1, PS2, PSP)
|
||||
- x86 (COFF only at the moment)
|
||||
@@ -21,6 +23,25 @@ Supports:
|
||||
|
||||
See [Usage](#usage) for more information.
|
||||
|
||||
## Downloads
|
||||
|
||||
To build from source, see [Building](#building).
|
||||
|
||||
### GUI
|
||||
|
||||
- [Windows (x86_64)](https://github.com/encounter/objdiff/releases/latest/download/objdiff-windows-x86_64.exe)
|
||||
- [Linux (x86_64)](https://github.com/encounter/objdiff/releases/latest/download/objdiff-linux-x86_64)
|
||||
- [macOS (arm64)](https://github.com/encounter/objdiff/releases/latest/download/objdiff-macos-arm64)
|
||||
- [macOS (x86_64)](https://github.com/encounter/objdiff/releases/latest/download/objdiff-macos-x86_64)
|
||||
|
||||
For Linux and macOS, run `chmod +x objdiff-*` to make the binary executable.
|
||||
|
||||
### CLI
|
||||
|
||||
CLI binaries can be found on the [releases page](https://github.com/encounter/objdiff/releases).
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -141,16 +162,22 @@ Install Rust via [rustup](https://rustup.rs).
|
||||
$ git clone https://github.com/encounter/objdiff.git
|
||||
$ cd objdiff
|
||||
$ cargo run --release
|
||||
# or, for wgpu backend (recommended on macOS)
|
||||
$ cargo run --release --features wgpu
|
||||
```
|
||||
|
||||
Or using `cargo install`.
|
||||
|
||||
```shell
|
||||
$ cargo install --locked --git https://github.com/encounter/objdiff.git objdiff-gui objdiff-cli
|
||||
```
|
||||
|
||||
The binaries will be installed to `~/.cargo/bin` as `objdiff` and `objdiff-cli`.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
|
||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
|
||||
|
||||
at your option.
|
||||
|
||||
|
||||
@@ -133,6 +133,13 @@
|
||||
},
|
||||
"metadata": {
|
||||
"ref": "#/$defs/metadata"
|
||||
},
|
||||
"symbol_mappings": {
|
||||
"type": "object",
|
||||
"description": "Manual symbol mappings from target to base.",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
# The values provided in this template are the default values that will be used
|
||||
# when any section or field is not specified in your own configuration
|
||||
|
||||
# Root options
|
||||
|
||||
# The graph table configures how the dependency graph is constructed and thus
|
||||
# which crates the checks are performed against
|
||||
[graph]
|
||||
# If 1 or more target triples (and optionally, target_features) are specified,
|
||||
# only the specified targets will be checked when running `cargo deny check`.
|
||||
# This means, if a particular package is only ever used as a target specific
|
||||
@@ -20,51 +25,66 @@
|
||||
targets = [
|
||||
# The triple can be any string, but only the target triples built in to
|
||||
# rustc (as of 1.40) can be checked against actual config expressions
|
||||
#{ triple = "x86_64-unknown-linux-musl" },
|
||||
#"x86_64-unknown-linux-musl",
|
||||
# You can also specify which target_features you promise are enabled for a
|
||||
# particular target. target_features are currently not validated against
|
||||
# the actual valid features supported by the target architecture.
|
||||
#{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
|
||||
]
|
||||
# When creating the dependency graph used as the source of truth when checks are
|
||||
# executed, this field can be used to prune crates from the graph, removing them
|
||||
# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate
|
||||
# is pruned from the graph, all of its dependencies will also be pruned unless
|
||||
# they are connected to another crate in the graph that hasn't been pruned,
|
||||
# so it should be used with care. The identifiers are [Package ID Specifications]
|
||||
# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html)
|
||||
#exclude = []
|
||||
# If true, metadata will be collected with `--all-features`. Note that this can't
|
||||
# be toggled off if true, if you want to conditionally enable `--all-features` it
|
||||
# is recommended to pass `--all-features` on the cmd line instead
|
||||
all-features = false
|
||||
# If true, metadata will be collected with `--no-default-features`. The same
|
||||
# caveat with `all-features` applies
|
||||
no-default-features = false
|
||||
# If set, these feature will be enabled when collecting metadata. If `--features`
|
||||
# is specified on the cmd line they will take precedence over this option.
|
||||
#features = []
|
||||
|
||||
# The output table provides options for how/if diagnostics are outputted
|
||||
[output]
|
||||
# When outputting inclusion graphs in diagnostics that include features, this
|
||||
# option can be used to specify the depth at which feature edges will be added.
|
||||
# This option is included since the graphs can be quite large and the addition
|
||||
# of features from the crate(s) to all of the graph roots can be far too verbose.
|
||||
# This option can be overridden via `--feature-depth` on the cmd line
|
||||
feature-depth = 1
|
||||
|
||||
# This section is considered when running `cargo deny check advisories`
|
||||
# More documentation for the advisories section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
||||
[advisories]
|
||||
# The path where the advisory database is cloned/fetched into
|
||||
db-path = "~/.cargo/advisory-db"
|
||||
# The path where the advisory databases are cloned/fetched into
|
||||
#db-path = "$CARGO_HOME/advisory-dbs"
|
||||
# The url(s) of the advisory databases to use
|
||||
db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||
# The lint level for security vulnerabilities
|
||||
vulnerability = "deny"
|
||||
# The lint level for unmaintained crates
|
||||
unmaintained = "warn"
|
||||
# The lint level for crates that have been yanked from their source registry
|
||||
yanked = "warn"
|
||||
# The lint level for crates with security notices. Note that as of
|
||||
# 2019-12-17 there are no security notice advisories in
|
||||
# https://github.com/rustsec/advisory-db
|
||||
notice = "warn"
|
||||
#db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
||||
# output a note when they are encountered.
|
||||
ignore = []
|
||||
# Threshold for security vulnerabilities, any vulnerability with a CVSS score
|
||||
# lower than the range specified will be ignored. Note that ignored advisories
|
||||
# will still output a note when they are encountered.
|
||||
# * None - CVSS Score 0.0
|
||||
# * Low - CVSS Score 0.1 - 3.9
|
||||
# * Medium - CVSS Score 4.0 - 6.9
|
||||
# * High - CVSS Score 7.0 - 8.9
|
||||
# * Critical - CVSS Score 9.0 - 10.0
|
||||
#severity-threshold =
|
||||
ignore = [
|
||||
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
||||
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
||||
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
||||
]
|
||||
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
||||
# If this is false, then it uses a built-in git library.
|
||||
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
||||
# See Git Authentication for more information about setting up git authentication.
|
||||
#git-fetch-with-cli = true
|
||||
|
||||
# This section is considered when running `cargo deny check licenses`
|
||||
# More documentation for the licenses section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
||||
[licenses]
|
||||
# The lint level for crates which do not have a detectable license
|
||||
unlicensed = "deny"
|
||||
# List of explictly allowed licenses
|
||||
# List of explicitly allowed licenses
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||
allow = [
|
||||
@@ -83,28 +103,7 @@ allow = [
|
||||
"OFL-1.1",
|
||||
"LicenseRef-UFL-1.0",
|
||||
"OpenSSL",
|
||||
"GPL-3.0",
|
||||
]
|
||||
# List of explictly disallowed licenses
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||
deny = [
|
||||
#"Nokia",
|
||||
]
|
||||
# Lint level for licenses considered copyleft
|
||||
copyleft = "warn"
|
||||
# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
|
||||
# * both - The license will be approved if it is both OSI-approved *AND* FSF
|
||||
# * either - The license will be approved if it is either OSI-approved *OR* FSF
|
||||
# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
|
||||
# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
|
||||
# * neither - This predicate is ignored and the default lint level is used
|
||||
allow-osi-fsf-free = "neither"
|
||||
# Lint level used when no other predicates are matched
|
||||
# 1. License isn't in the allow or deny lists
|
||||
# 2. License isn't copyleft
|
||||
# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
|
||||
default = "deny"
|
||||
# The confidence threshold for detecting a license from license text.
|
||||
# The higher the value, the more closely the license text must be to the
|
||||
# canonical license text of a valid SPDX license file.
|
||||
@@ -115,17 +114,15 @@ confidence-threshold = 0.8
|
||||
exceptions = [
|
||||
# Each entry is the crate and version constraint, and its specific allow
|
||||
# list
|
||||
#{ allow = ["Zlib"], name = "adler32", version = "*" },
|
||||
#{ allow = ["Zlib"], crate = "adler32" },
|
||||
]
|
||||
|
||||
# Some crates don't have (easily) machine readable licensing information,
|
||||
# adding a clarification entry for it allows you to manually specify the
|
||||
# licensing information
|
||||
[[licenses.clarify]]
|
||||
# The name of the crate the clarification applies to
|
||||
name = "ring"
|
||||
# The optional version constraint for the crate
|
||||
version = "*"
|
||||
# The package spec the clarification applies to
|
||||
crate = "ring"
|
||||
# The SPDX expression for the license requirements of the crate
|
||||
expression = "MIT AND ISC AND OpenSSL"
|
||||
# One or more files in the crate's source used as the "source of truth" for
|
||||
@@ -140,7 +137,9 @@ license-files = [
|
||||
|
||||
[licenses.private]
|
||||
# If true, ignores workspace crates that aren't published, or are only
|
||||
# published to private registries
|
||||
# published to private registries.
|
||||
# To see how to mark a crate as unpublished (to the official registry),
|
||||
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
|
||||
ignore = false
|
||||
# One or more private registries that you might publish crates to, if a crate
|
||||
# is only published to private registries, and ignore is true, the crate will
|
||||
@@ -163,30 +162,63 @@ wildcards = "allow"
|
||||
# * simplest-path - The path to the version with the fewest edges is highlighted
|
||||
# * all - Both lowest-version and simplest-path are used
|
||||
highlight = "all"
|
||||
# The default lint level for `default` features for crates that are members of
|
||||
# the workspace that is being checked. This can be overridden by allowing/denying
|
||||
# `default` on a crate-by-crate basis if desired.
|
||||
workspace-default-features = "allow"
|
||||
# The default lint level for `default` features for external crates that are not
|
||||
# members of the workspace. This can be overridden by allowing/denying `default`
|
||||
# on a crate-by-crate basis if desired.
|
||||
external-default-features = "allow"
|
||||
# List of crates that are allowed. Use with care!
|
||||
allow = [
|
||||
#{ name = "ansi_term", version = "=0.11.0" },
|
||||
#"ansi_term@0.11.0",
|
||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" },
|
||||
]
|
||||
# List of crates to deny
|
||||
deny = [
|
||||
# Each entry the name of a crate and a version range. If version is
|
||||
# not specified, all versions will be matched.
|
||||
#{ name = "ansi_term", version = "=0.11.0" },
|
||||
#
|
||||
#"ansi_term@0.11.0",
|
||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" },
|
||||
# Wrapper crates can optionally be specified to allow the crate when it
|
||||
# is a direct dependency of the otherwise banned crate
|
||||
#{ name = "ansi_term", version = "=0.11.0", wrappers = [] },
|
||||
#{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] },
|
||||
]
|
||||
|
||||
# List of features to allow/deny
|
||||
# Each entry the name of a crate and a version range. If version is
|
||||
# not specified, all versions will be matched.
|
||||
#[[bans.features]]
|
||||
#crate = "reqwest"
|
||||
# Features to not allow
|
||||
#deny = ["json"]
|
||||
# Features to allow
|
||||
#allow = [
|
||||
# "rustls",
|
||||
# "__rustls",
|
||||
# "__tls",
|
||||
# "hyper-rustls",
|
||||
# "rustls",
|
||||
# "rustls-pemfile",
|
||||
# "rustls-tls-webpki-roots",
|
||||
# "tokio-rustls",
|
||||
# "webpki-roots",
|
||||
#]
|
||||
# If true, the allowed features must exactly match the enabled feature set. If
|
||||
# this is set there is no point setting `deny`
|
||||
#exact = true
|
||||
|
||||
# Certain crates/versions that will be skipped when doing duplicate detection.
|
||||
skip = [
|
||||
#{ name = "ansi_term", version = "=0.11.0" },
|
||||
#"ansi_term@0.11.0",
|
||||
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" },
|
||||
]
|
||||
# Similarly to `skip` allows you to skip certain crates during duplicate
|
||||
# detection. Unlike skip, it also includes the entire tree of transitive
|
||||
# dependencies starting at the specified crate, up to a certain depth, which is
|
||||
# by default infinite
|
||||
# by default infinite.
|
||||
skip-tree = [
|
||||
#{ name = "ansi_term", version = "=0.11.0", depth = 20 },
|
||||
#"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies
|
||||
#{ crate = "ansi_term@0.11.0", depth = 20 },
|
||||
]
|
||||
|
||||
# This section is considered when running `cargo deny check sources`.
|
||||
@@ -206,9 +238,9 @@ allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||
allow-git = []
|
||||
|
||||
[sources.allow-org]
|
||||
# 1 or more github.com organizations to allow git sources for
|
||||
github = ["encounter"]
|
||||
# 1 or more gitlab.com organizations to allow git sources for
|
||||
#gitlab = [""]
|
||||
# 1 or more bitbucket.org organizations to allow git sources for
|
||||
#bitbucket = [""]
|
||||
# github.com organizations to allow git sources for
|
||||
github = ["notify-rs"]
|
||||
# gitlab.com organizations to allow git sources for
|
||||
gitlab = []
|
||||
# bitbucket.org organizations to allow git sources for
|
||||
bitbucket = []
|
||||
|
||||
+23
-21
@@ -1,31 +1,33 @@
|
||||
[package]
|
||||
name = "objdiff-cli"
|
||||
version = "2.0.0-beta.6"
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/encounter/objdiff"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
readme = "../README.md"
|
||||
description = """
|
||||
A local diffing tool for decompilation projects.
|
||||
"""
|
||||
publish = false
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.82"
|
||||
argp = "0.3.0"
|
||||
crossterm = "0.27.0"
|
||||
enable-ansi-support = "0.2.1"
|
||||
memmap2 = "0.9.4"
|
||||
anyhow = "1.0"
|
||||
argp = "0.3"
|
||||
crossterm = "0.28"
|
||||
enable-ansi-support = "0.2"
|
||||
memmap2 = "0.9"
|
||||
objdiff-core = { path = "../objdiff-core", features = ["all"] }
|
||||
prost = "0.13.1"
|
||||
ratatui = "0.26.2"
|
||||
rayon = "1.10.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1.0.116"
|
||||
supports-color = "3.0.0"
|
||||
time = { version = "0.3.36", features = ["formatting", "local-offset"] }
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
prost = "0.13"
|
||||
ratatui = "0.28"
|
||||
rayon = "1.10"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
supports-color = "3.0"
|
||||
time = { version = "0.3", features = ["formatting", "local-offset"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
[target.'cfg(target_env = "musl")'.dependencies]
|
||||
mimalloc = "0.1"
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
fn main() {
|
||||
let output = std::process::Command::new("git")
|
||||
.args(["rev-parse", "HEAD"])
|
||||
.output()
|
||||
.expect("Failed to execute git");
|
||||
let rev = String::from_utf8(output.stdout).expect("Failed to parse git output");
|
||||
println!("cargo:rustc-env=GIT_COMMIT_SHA={rev}");
|
||||
println!("cargo:rustc-rerun-if-changed=.git/HEAD");
|
||||
}
|
||||
@@ -31,10 +31,9 @@ where T: FromArgs
|
||||
Ok(v) => {
|
||||
if v.version {
|
||||
println!(
|
||||
"{} {} {}",
|
||||
"{} {}",
|
||||
command_name.first().unwrap_or(&""),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("GIT_COMMIT_SHA"),
|
||||
);
|
||||
std::process::exit(0);
|
||||
} else {
|
||||
|
||||
+62
-34
@@ -102,26 +102,32 @@ pub fn run(args: Args) -> Result<()> {
|
||||
let unit_path =
|
||||
PathBuf::from_str(u).ok().and_then(|p| fs::canonicalize(p).ok());
|
||||
|
||||
let Some(object) = project_config.objects.iter_mut().find_map(|obj| {
|
||||
if obj.name.as_deref() == Some(u) {
|
||||
let Some(object) = project_config
|
||||
.units
|
||||
.as_deref_mut()
|
||||
.unwrap_or_default()
|
||||
.iter_mut()
|
||||
.find_map(|obj| {
|
||||
if obj.name.as_deref() == Some(u) {
|
||||
resolve_paths(obj);
|
||||
return Some(obj);
|
||||
}
|
||||
|
||||
let up = unit_path.as_deref()?;
|
||||
|
||||
resolve_paths(obj);
|
||||
return Some(obj);
|
||||
}
|
||||
|
||||
let up = unit_path.as_deref()?;
|
||||
if [&obj.base_path, &obj.target_path]
|
||||
.into_iter()
|
||||
.filter_map(|p| p.as_ref().and_then(|p| p.canonicalize().ok()))
|
||||
.any(|p| p == up)
|
||||
{
|
||||
return Some(obj);
|
||||
}
|
||||
|
||||
resolve_paths(obj);
|
||||
|
||||
if [&obj.base_path, &obj.target_path]
|
||||
.into_iter()
|
||||
.filter_map(|p| p.as_ref().and_then(|p| p.canonicalize().ok()))
|
||||
.any(|p| p == up)
|
||||
{
|
||||
return Some(obj);
|
||||
}
|
||||
|
||||
None
|
||||
}) else {
|
||||
None
|
||||
})
|
||||
else {
|
||||
bail!("Unit not found: {}", u)
|
||||
};
|
||||
|
||||
@@ -129,7 +135,13 @@ pub fn run(args: Args) -> Result<()> {
|
||||
} else if let Some(symbol_name) = &args.symbol {
|
||||
let mut idx = None;
|
||||
let mut count = 0usize;
|
||||
for (i, obj) in project_config.objects.iter_mut().enumerate() {
|
||||
for (i, obj) in project_config
|
||||
.units
|
||||
.as_deref_mut()
|
||||
.unwrap_or_default()
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
{
|
||||
resolve_paths(obj);
|
||||
|
||||
if obj
|
||||
@@ -148,7 +160,7 @@ pub fn run(args: Args) -> Result<()> {
|
||||
}
|
||||
match (count, idx) {
|
||||
(0, None) => bail!("Symbol not found: {}", symbol_name),
|
||||
(1, Some(i)) => &mut project_config.objects[i],
|
||||
(1, Some(i)) => &mut project_config.units_mut()[i],
|
||||
(2.., Some(_)) => bail!(
|
||||
"Multiple instances of {} were found, try specifying a unit",
|
||||
symbol_name
|
||||
@@ -303,7 +315,7 @@ fn find_function(obj: &ObjInfo, name: &str) -> Option<SymbolRef> {
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[expect(dead_code)]
|
||||
struct FunctionDiffUi {
|
||||
relax_reloc_diffs: bool,
|
||||
left_highlight: HighlightKind,
|
||||
@@ -345,7 +357,7 @@ enum EventControlFlow {
|
||||
|
||||
impl FunctionDiffUi {
|
||||
fn draw(&mut self, f: &mut Frame, result: &mut EventResult) {
|
||||
let chunks = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).split(f.size());
|
||||
let chunks = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).split(f.area());
|
||||
let header_chunks = Layout::horizontal([
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(3),
|
||||
@@ -415,7 +427,7 @@ impl FunctionDiffUi {
|
||||
get_symbol_diff(self.diff_result.left.as_ref(), self.left_sym),
|
||||
) {
|
||||
let mut text = Text::default();
|
||||
let rect = content_chunks[0].inner(&Margin::new(0, 1));
|
||||
let rect = content_chunks[0].inner(Margin::new(0, 1));
|
||||
left_highlight = self.print_sym(
|
||||
&mut text,
|
||||
symbol,
|
||||
@@ -437,7 +449,7 @@ impl FunctionDiffUi {
|
||||
get_symbol_diff(self.diff_result.right.as_ref(), self.right_sym),
|
||||
) {
|
||||
let mut text = Text::default();
|
||||
let rect = content_chunks[2].inner(&Margin::new(0, 1));
|
||||
let rect = content_chunks[2].inner(Margin::new(0, 1));
|
||||
right_highlight = self.print_sym(
|
||||
&mut text,
|
||||
symbol,
|
||||
@@ -452,7 +464,7 @@ impl FunctionDiffUi {
|
||||
|
||||
// Render margin
|
||||
let mut text = Text::default();
|
||||
let rect = content_chunks[1].inner(&Margin::new(1, 1));
|
||||
let rect = content_chunks[1].inner(Margin::new(1, 1));
|
||||
self.print_margin(&mut text, symbol_diff, rect);
|
||||
margin_text = Some(text);
|
||||
}
|
||||
@@ -465,7 +477,7 @@ impl FunctionDiffUi {
|
||||
get_symbol_diff(self.diff_result.prev.as_ref(), self.prev_sym),
|
||||
) {
|
||||
let mut text = Text::default();
|
||||
let rect = content_chunks[4].inner(&Margin::new(0, 1));
|
||||
let rect = content_chunks[4].inner(Margin::new(0, 1));
|
||||
self.print_sym(
|
||||
&mut text,
|
||||
symbol,
|
||||
@@ -480,7 +492,7 @@ impl FunctionDiffUi {
|
||||
|
||||
// Render margin
|
||||
let mut text = Text::default();
|
||||
let rect = content_chunks[3].inner(&Margin::new(1, 1));
|
||||
let rect = content_chunks[3].inner(Margin::new(1, 1));
|
||||
self.print_margin(&mut text, symbol_diff, rect);
|
||||
prev_margin_text = Some(text);
|
||||
}
|
||||
@@ -498,18 +510,30 @@ impl FunctionDiffUi {
|
||||
// Render left column
|
||||
f.render_widget(
|
||||
Paragraph::new(text)
|
||||
.block(Block::new().borders(Borders::TOP).gray().title("TARGET".bold()))
|
||||
.block(
|
||||
Block::new()
|
||||
.borders(Borders::TOP)
|
||||
.border_style(Style::new().fg(Color::Gray))
|
||||
.title_style(Style::new().bold())
|
||||
.title("TARGET"),
|
||||
)
|
||||
.scroll((0, self.scroll_x as u16)),
|
||||
content_chunks[0],
|
||||
);
|
||||
}
|
||||
if let Some(text) = margin_text {
|
||||
f.render_widget(text, content_chunks[1].inner(&Margin::new(1, 1)));
|
||||
f.render_widget(text, content_chunks[1].inner(Margin::new(1, 1)));
|
||||
}
|
||||
if let Some(text) = right_text {
|
||||
f.render_widget(
|
||||
Paragraph::new(text)
|
||||
.block(Block::new().borders(Borders::TOP).gray().title("CURRENT".bold()))
|
||||
.block(
|
||||
Block::new()
|
||||
.borders(Borders::TOP)
|
||||
.border_style(Style::new().fg(Color::Gray))
|
||||
.title_style(Style::new().bold())
|
||||
.title("CURRENT"),
|
||||
)
|
||||
.scroll((0, self.scroll_x as u16)),
|
||||
content_chunks[2],
|
||||
);
|
||||
@@ -517,9 +541,13 @@ impl FunctionDiffUi {
|
||||
|
||||
if self.three_way {
|
||||
if let Some(text) = prev_margin_text {
|
||||
f.render_widget(text, content_chunks[3].inner(&Margin::new(1, 1)));
|
||||
f.render_widget(text, content_chunks[3].inner(Margin::new(1, 1)));
|
||||
}
|
||||
let block = Block::new().borders(Borders::TOP).gray().title("SAVED".bold());
|
||||
let block = Block::new()
|
||||
.borders(Borders::TOP)
|
||||
.border_style(Style::new().fg(Color::Gray))
|
||||
.title_style(Style::new().bold())
|
||||
.title("SAVED");
|
||||
if let Some(text) = prev_text {
|
||||
f.render_widget(
|
||||
Paragraph::new(text).block(block.clone()).scroll((0, self.scroll_x as u16)),
|
||||
@@ -533,7 +561,7 @@ impl FunctionDiffUi {
|
||||
// Render scrollbars
|
||||
f.render_stateful_widget(
|
||||
Scrollbar::new(ScrollbarOrientation::VerticalRight).begin_symbol(None).end_symbol(None),
|
||||
chunks[1].inner(&Margin::new(0, 1)),
|
||||
chunks[1].inner(Margin::new(0, 1)),
|
||||
&mut self.scroll_state_y,
|
||||
);
|
||||
f.render_stateful_widget(
|
||||
@@ -589,7 +617,7 @@ impl FunctionDiffUi {
|
||||
Constraint::Percentage(percent_y),
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
])
|
||||
.split(f.size())[1];
|
||||
.split(f.area())[1];
|
||||
let popup_rect = Layout::horizontal([
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
Constraint::Percentage(percent_x),
|
||||
@@ -742,7 +770,7 @@ impl FunctionDiffUi {
|
||||
self.scroll_y += self.per_page / if half { 2 } else { 1 };
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
fn print_sym(
|
||||
&self,
|
||||
out: &mut Text<'static>,
|
||||
|
||||
@@ -94,7 +94,7 @@ fn generate(args: GenerateArgs) -> Result<()> {
|
||||
};
|
||||
info!(
|
||||
"Generating report for {} units (using {} threads)",
|
||||
project.objects.len(),
|
||||
project.units().len(),
|
||||
if args.deduplicate { 1 } else { rayon::current_num_threads() }
|
||||
);
|
||||
|
||||
@@ -103,7 +103,7 @@ fn generate(args: GenerateArgs) -> Result<()> {
|
||||
let mut existing_functions: HashSet<String> = HashSet::new();
|
||||
if args.deduplicate {
|
||||
// If deduplicating, we need to run single-threaded
|
||||
for object in &mut project.objects {
|
||||
for object in project.units.as_deref_mut().unwrap_or_default() {
|
||||
if let Some(unit) = report_object(
|
||||
object,
|
||||
project_dir,
|
||||
@@ -116,7 +116,9 @@ fn generate(args: GenerateArgs) -> Result<()> {
|
||||
}
|
||||
} else {
|
||||
let vec = project
|
||||
.objects
|
||||
.units
|
||||
.as_deref_mut()
|
||||
.unwrap_or_default()
|
||||
.par_iter_mut()
|
||||
.map(|object| {
|
||||
report_object(
|
||||
@@ -132,7 +134,7 @@ fn generate(args: GenerateArgs) -> Result<()> {
|
||||
}
|
||||
let measures = units.iter().flat_map(|u| u.measures.into_iter()).collect();
|
||||
let mut categories = Vec::new();
|
||||
for category in &project.progress_categories {
|
||||
for category in project.progress_categories() {
|
||||
categories.push(ReportCategory {
|
||||
id: category.id.clone(),
|
||||
name: category.name.clone(),
|
||||
@@ -199,7 +201,7 @@ fn report_object(
|
||||
.unwrap_or_default(),
|
||||
auto_generated: object.metadata.as_ref().and_then(|m| m.auto_generated),
|
||||
};
|
||||
let mut measures = Measures::default();
|
||||
let mut measures = Measures { total_units: 1, ..Default::default() };
|
||||
let mut sections = vec![];
|
||||
let mut functions = vec![];
|
||||
|
||||
@@ -237,7 +239,7 @@ fn report_object(
|
||||
}
|
||||
|
||||
for (symbol, symbol_diff) in section.symbols.iter().zip(§ion_diff.symbols) {
|
||||
if symbol.size == 0 {
|
||||
if symbol.size == 0 || symbol.flags.0.contains(ObjSymbolFlags::Hidden) {
|
||||
continue;
|
||||
}
|
||||
if let Some(existing_functions) = &mut existing_functions {
|
||||
@@ -280,6 +282,7 @@ fn report_object(
|
||||
if metadata.complete.unwrap_or(false) {
|
||||
measures.complete_code = measures.total_code;
|
||||
measures.complete_data = measures.total_data;
|
||||
measures.complete_units = 1;
|
||||
}
|
||||
measures.calc_fuzzy_match_percent();
|
||||
measures.calc_matched_percent();
|
||||
|
||||
@@ -2,6 +2,12 @@ mod argp_version;
|
||||
mod cmd;
|
||||
mod util;
|
||||
|
||||
// musl's allocator is very slow, so use mimalloc when targeting musl.
|
||||
// Otherwise, use the system allocator to avoid extra code size.
|
||||
#[cfg(target_env = "musl")]
|
||||
#[global_allocator]
|
||||
static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
||||
|
||||
use std::{env, ffi::OsStr, fmt::Display, path::PathBuf, str::FromStr};
|
||||
|
||||
use anyhow::{Error, Result};
|
||||
|
||||
+54
-49
@@ -1,76 +1,81 @@
|
||||
[package]
|
||||
name = "objdiff-core"
|
||||
version = "2.0.0-beta.6"
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/encounter/objdiff"
|
||||
readme = "../README.md"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
readme = "README.md"
|
||||
description = """
|
||||
A local diffing tool for decompilation projects.
|
||||
"""
|
||||
documentation = "https://docs.rs/objdiff-core"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
all = ["config", "dwarf", "mips", "ppc", "x86", "arm", "bindings"]
|
||||
any-arch = [] # Implicit, used to check if any arch is enabled
|
||||
config = ["globset", "semver", "serde_json", "serde_yaml"]
|
||||
dwarf = ["gimli"]
|
||||
mips = ["any-arch", "rabbitizer"]
|
||||
ppc = ["any-arch", "cwdemangle", "cwextab", "ppc750cl"]
|
||||
x86 = ["any-arch", "cpp_demangle", "iced-x86", "msvc-demangler"]
|
||||
arm = ["any-arch", "cpp_demangle", "unarm", "arm-attr"]
|
||||
bindings = ["serde_json", "prost", "pbjson"]
|
||||
wasm = ["bindings", "console_error_panic_hook", "console_log"]
|
||||
any-arch = ["config", "dep:bimap", "dep:strum", "dep:similar", "dep:flagset", "dep:log", "dep:memmap2", "dep:byteorder", "dep:num-traits"] # Implicit, used to check if any arch is enabled
|
||||
config = ["dep:bimap", "dep:globset", "dep:semver", "dep:serde_json", "dep:serde_yaml", "dep:serde", "dep:filetime"]
|
||||
dwarf = ["dep:gimli"]
|
||||
mips = ["any-arch", "dep:rabbitizer"]
|
||||
ppc = ["any-arch", "dep:cwdemangle", "dep:cwextab", "dep:ppc750cl"]
|
||||
x86 = ["any-arch", "dep:cpp_demangle", "dep:iced-x86", "dep:msvc-demangler"]
|
||||
arm = ["any-arch", "dep:cpp_demangle", "dep:unarm", "dep:arm-attr"]
|
||||
bindings = ["dep:serde_json", "dep:prost", "dep:pbjson", "dep:serde", "dep:prost-build", "dep:pbjson-build"]
|
||||
wasm = ["bindings", "any-arch", "dep:console_error_panic_hook", "dep:console_log", "dep:wasm-bindgen", "dep:tsify-next", "dep:log"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["all"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.82"
|
||||
byteorder = "1.5.0"
|
||||
filetime = "0.2.23"
|
||||
flagset = "0.4.5"
|
||||
log = "0.4.21"
|
||||
memmap2 = "0.9.4"
|
||||
num-traits = "0.2.18"
|
||||
object = { version = "0.36.0", features = ["read_core", "std", "elf", "pe"], default-features = false }
|
||||
pbjson = { version = "0.7.0", optional = true }
|
||||
prost = { version = "0.13.1", optional = true }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
similar = { version = "2.5.0", default-features = false }
|
||||
strum = { version = "0.26.2", features = ["derive"] }
|
||||
wasm-bindgen = "0.2.93"
|
||||
tsify-next = { version = "0.5.4", default-features = false, features = ["js"] }
|
||||
console_log = { version = "1.0.0", optional = true }
|
||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||
anyhow = "1.0"
|
||||
bimap = { version = "0.6", features = ["serde"], optional = true }
|
||||
byteorder = { version = "1.5", optional = true }
|
||||
filetime = { version = "0.2", optional = true }
|
||||
flagset = { version = "0.4", optional = true }
|
||||
log = { version = "0.4", optional = true }
|
||||
memmap2 = { version = "0.9", optional = true }
|
||||
num-traits = { version = "0.2", optional = true }
|
||||
object = { version = "0.36", features = ["read_core", "std", "elf", "pe"], default-features = false }
|
||||
pbjson = { version = "0.7", optional = true }
|
||||
prost = { version = "0.13", optional = true }
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
similar = { version = "2.6", default-features = false, optional = true }
|
||||
strum = { version = "0.26", features = ["derive"], optional = true }
|
||||
wasm-bindgen = { version = "0.2", optional = true }
|
||||
tsify-next = { version = "0.5", default-features = false, features = ["js"], optional = true }
|
||||
console_log = { version = "1.0", optional = true }
|
||||
console_error_panic_hook = { version = "0.1", optional = true }
|
||||
|
||||
# config
|
||||
globset = { version = "0.4.14", features = ["serde1"], optional = true }
|
||||
semver = { version = "1.0.22", optional = true }
|
||||
serde_json = { version = "1.0.116", optional = true }
|
||||
serde_yaml = { version = "0.9.34", optional = true }
|
||||
globset = { version = "0.4", features = ["serde1"], optional = true }
|
||||
semver = { version = "1.0", optional = true }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
serde_yaml = { version = "0.9", optional = true }
|
||||
|
||||
# dwarf
|
||||
gimli = { version = "0.29.0", default-features = false, features = ["read-all"], optional = true }
|
||||
gimli = { version = "0.31", default-features = false, features = ["read-all"], optional = true }
|
||||
|
||||
# ppc
|
||||
cwdemangle = { version = "1.0.0", optional = true }
|
||||
cwextab = { version = "0.2.3", optional = true }
|
||||
ppc750cl = { git = "https://github.com/encounter/ppc750cl", rev = "6cbd7d888c7082c2c860f66cbb9848d633f753ed", optional = true }
|
||||
cwdemangle = { version = "1.0", optional = true }
|
||||
cwextab = { version = "1.0.2", optional = true }
|
||||
ppc750cl = { version = "0.3", optional = true }
|
||||
|
||||
# mips
|
||||
rabbitizer = { version = "1.11.0", optional = true }
|
||||
rabbitizer = { version = "1.12", optional = true }
|
||||
|
||||
# x86
|
||||
cpp_demangle = { version = "0.4.3", optional = true }
|
||||
iced-x86 = { version = "1.21.0", default-features = false, features = ["std", "decoder", "intel", "gas", "masm", "nasm", "exhaustive_enums"], optional = true }
|
||||
msvc-demangler = { version = "0.10.0", optional = true }
|
||||
cpp_demangle = { version = "0.4", optional = true }
|
||||
iced-x86 = { version = "1.21", default-features = false, features = ["std", "decoder", "intel", "gas", "masm", "nasm", "exhaustive_enums"], optional = true }
|
||||
msvc-demangler = { version = "0.10", optional = true }
|
||||
|
||||
# arm
|
||||
unarm = { version = "1.5.0", optional = true }
|
||||
arm-attr = { version = "0.1.1", optional = true }
|
||||
unarm = { version = "1.6", optional = true }
|
||||
arm-attr = { version = "0.1", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.13.1"
|
||||
pbjson-build = "0.7.0"
|
||||
prost-build = { version = "0.13", optional = true }
|
||||
pbjson-build = { version = "0.7", optional = true }
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# objdiff-core
|
||||
|
||||
objdiff-core contains the core functionality of [objdiff](https://github.com/encounter/objdiff), a tool for comparing object files in decompilation projects. See the main repository for more information.
|
||||
|
||||
## Crate feature flags
|
||||
|
||||
- **`all`**: Enables all main features.
|
||||
- **`config`**: Enables objdiff configuration file support.
|
||||
- **`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).
|
||||
- **`bindings`**: Enables serialization and deserialization of objdiff data structures.
|
||||
@@ -1,6 +1,11 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn main() {
|
||||
#[cfg(feature = "bindings")]
|
||||
compile_protos();
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindings")]
|
||||
fn compile_protos() {
|
||||
use std::path::{Path, PathBuf};
|
||||
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("protos");
|
||||
let descriptor_path = root.join("proto_descriptor.bin");
|
||||
println!("cargo:rerun-if-changed={}", descriptor_path.display());
|
||||
|
||||
Binary file not shown.
@@ -32,6 +32,10 @@ message Measures {
|
||||
uint64 complete_data = 13;
|
||||
// Completed (or "linked") data percent
|
||||
float complete_data_percent = 14;
|
||||
// Total number of units
|
||||
uint32 total_units = 15;
|
||||
// Completed (or "linked") units
|
||||
uint32 complete_units = 16;
|
||||
}
|
||||
|
||||
// Project progress report
|
||||
|
||||
@@ -83,7 +83,7 @@ impl ObjArch for ObjArchMips {
|
||||
&self,
|
||||
address: u64,
|
||||
code: &[u8],
|
||||
_section_index: usize,
|
||||
section_index: usize,
|
||||
relocations: &[ObjReloc],
|
||||
line_info: &BTreeMap<u64, u32>,
|
||||
config: &DiffObjConfig,
|
||||
@@ -140,11 +140,18 @@ impl ObjArch for ObjArchMips {
|
||||
| OperandType::cpu_label
|
||||
| OperandType::cpu_branch_target_label => {
|
||||
if let Some(reloc) = reloc {
|
||||
if matches!(&reloc.target_section, Some(s) if s == ".text")
|
||||
&& reloc.target.address > start_address
|
||||
&& reloc.target.address < end_address
|
||||
// If the relocation target is within the current function, we can
|
||||
// convert it into a relative branch target. Note that we check
|
||||
// target_address > start_address instead of >= so that recursive
|
||||
// tail calls are not considered branch targets.
|
||||
let target_address =
|
||||
reloc.target.address.checked_add_signed(reloc.addend);
|
||||
if reloc.target.orig_section_index == Some(section_index)
|
||||
&& matches!(target_address, Some(addr) if addr > start_address && addr < end_address)
|
||||
{
|
||||
args.push(ObjInsArg::BranchDest(reloc.target.address));
|
||||
let target_address = target_address.unwrap();
|
||||
args.push(ObjInsArg::BranchDest(target_address));
|
||||
branch_dest = Some(target_address);
|
||||
} else {
|
||||
push_reloc(&mut args, reloc)?;
|
||||
branch_dest = None;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user