Compare commits

...

85 Commits

Author SHA1 Message Date
Luke Street 6768df9d80 Version v3.0.0-beta.4 2025-03-18 21:36:37 -06:00
Luke Street eaba2391e0 arm: Fix thumb & data decoding, add tests 2025-03-18 21:26:28 -06:00
Luke Street bd8f5ede23 Add pre-commit hooks 2025-03-18 21:26:28 -06:00
Luke Street acf46c6b54 Fix no_std build 2025-03-14 09:49:31 -06:00
Luke Street 9358d8ec60 mips: Add C++ symbol demangling (CW & modern GCC) 2025-03-14 09:44:15 -06:00
Luke Street 809e2ffddc cargo fmt 2025-03-11 21:43:32 -06:00
Luke Street 87fa29e8b0 objdiff-wasm: Fix symbol filtering
regex crate needed the `unicode-case` feature
2025-03-11 21:42:14 -06:00
Luke Street 42d4c38079 mips: Ignore .NON_MATCHING functions from INLINE_ASM macros 2025-03-11 21:39:17 -06:00
Luke Street fa26200ed7 Silence warning 2025-03-10 22:22:05 -06:00
Luke Street a0e7f9bc37 Fix x86 mov relocations with uint32 2025-03-10 22:09:58 -06:00
Luke Street 5898d7aebf Fix section ordering with many same-named sections
Before, this was comparing, for example, `.text-2`
with `.text-10` with standard string comparison,
yielding `.text-10` before `.text-2`.

Instead, this simply uses a stable sort by name,
which preserves the relative ordering of sections.
2025-03-10 21:51:54 -06:00
Luke Street ffb38d1bb0 Fix cargo deny advisories 2025-03-09 22:59:42 -06:00
Luke Street d56dda72f0 Version v3.0.0-beta.2 2025-03-09 22:56:28 -06:00
Luke Street c6971f3f2d Add initial support for x86-64 relocations 2025-03-09 22:51:43 -06:00
Luke Street 3965a035fa objdiff-cli diff: Show build errors/log 2025-03-09 22:51:43 -06:00
Luke Street f1fc29f77e Split report changes into separate proto 2025-03-08 14:39:15 -07:00
Luke Street 7c4f1c5d13 Fix left/right arch mismatches in diff code 2025-03-08 10:44:44 -07:00
Luke Street fa4a6cadbb Downgrade objdiff-wasm Rust edition temporarily 2025-03-04 23:27:17 -07:00
Luke Street 799971d54e Migrate to Rust edition 2024 2025-03-04 22:31:38 -07:00
Luke Street 8eef37e8df Version v3.0.0-beta.1 2025-03-04 22:24:55 -07:00
Luke Street 5f36916087 Fix unintended unwrap in load_font_if_needed 2025-03-04 22:24:20 -07:00
Luke Street ee667a2dde Update config-schema.json: PPC -> PowerPC 2025-03-04 22:23:45 -07:00
LagoLunatic cf5fc54cfa PPC: Reimplement pooled data reference calculation (#167)
* PPC: Calculate pooled relocations

Reimplements #140

The relocations are now generated when the object is first read in `parse`, right after the real relocations are read.

`resolve_relocation` was changed to take `obj.symbols` instead of `obj` as an argument, because `obj` itself doesn't exist yet at the time the relocations are being read.

* Improve readability of PPC pool relocs code

* Fix regression causing extern pool relocs to be ignored

* Fix showing incorrect diff when diffing weak stripped symbol with an addend

This is a regression that was introduced by #158 diffing addends in addition to symbol names. But it's not really a bug in that PR, rather it seems like I simply never added the offset into the addend when creating a fake pool relocation for an extern symbol. So this commit fixes that root issue instead.

* Add PPC "Calculate pooled data references" option

* Fix objdiff-wasm compilation errors

* Update PPC test snapshots
2025-03-04 20:40:34 -07:00
Luke Street 1cdfa1e857 Update rabbitizer & utilize use_dollar option 2025-03-04 09:38:59 -07:00
Luke Street 3f157f33a5 Reorder tooltip/context items slightly 2025-03-04 09:10:54 -07:00
LagoLunatic a1ea2919f8 Reimplement function data value tooltips, function data value diffing, and data relocation diffing (#166)
* Show data literal values on instruction hover

Reimplements #108

* Show reloc diffs in func view when data's content differs

Reimplements #153

* Data diff view: Show relocs on hover and in context menu

This reimplements #154

Note that colorizing the text depending on the kind of diff has still not been reimplemented yet

* Fix up some comments
2025-03-04 08:56:46 -07:00
Luke Street 9c31c82a37 cargo fmt 2025-03-03 21:08:36 -07:00
Luke Street 4f34dfa194 Don't infer sizes for labels within another symbol 2025-03-03 21:01:22 -07:00
Luke Street ae6d37a10b Version v3.0.0-alpha.2 2025-03-03 18:25:38 -07:00
Luke Street 06e54f3456 cargo fmt 2025-03-03 17:16:35 -07:00
Luke Street 6ed07bfaf1 MIPS relocation pairing, '$' prefix option & fixes
Implements MIPS relocation pairing logic.
New option for "Register '$' prefix", off by default.
Fixes various regressions introduced by refactoring.

Resolves #122
Resolves #156
2025-03-03 17:14:32 -07:00
Luke Street 80e939653a Build objdiff-gui against older glibc
Resolves #165
2025-03-03 13:34:05 -07:00
Luke Street 48305e0380 Add hover/context APIs to wasm component 2025-03-02 21:51:47 -07:00
Luke Street 2eafbb218b Update all dependencies 2025-03-02 16:13:12 -07:00
Luke Street a1f2a535e5 Unify context menu / hover tooltip code + UI improvements 2025-03-02 16:13:12 -07:00
Luke Street 8461b35cd7 Fix WASM CI build 2025-03-02 16:13:12 -07:00
Luke Street 95868f1d19 Reimplement x86 arch, MSVC section group combining
Plus display_row/DiffText refactoring
2025-03-02 16:13:12 -07:00
Luke Street 506c251d68 Various fixes 2025-02-26 22:47:42 -07:00
Luke Street f3c157ff06 WIP objdiff 3.0 refactor 2025-02-26 22:09:39 -07:00
angie 6d3c63ccd8 Use rabbitizer 2
Co-Authored-By: Luke Street <luke@street.dev>
2025-02-09 22:28:04 -07:00
Luke Street bbd8d9714f Adjust CI build features 2025-02-09 22:28:04 -07:00
Luke Street 3c66ac3d54 Fix run_make on Windows 2025-02-09 22:28:04 -07:00
Luke Street 561a9107e2 clippy & deny fixes 2025-02-09 22:28:04 -07:00
Luke Street e8de35b78e Make objdiff-core no_std + huge WASM rework 2025-02-09 22:28:02 -07:00
Luke Street d938988d43 Diff view refactor 2025-02-09 22:27:42 -07:00
LagoLunatic 3e6efb7736 Check relocation addends when diffing functions (#158)
* Check relocation addends when diffing functions

* Also highlight addend when reloc differs
2025-02-09 22:26:49 -07:00
Steven Casper 674c942d7d Implement context menu copy functionality for data values (#163)
* Implement context menu copy functionality for data values

* Clippy fixes
2025-02-09 22:24:52 -07:00
LagoLunatic 6b7dcabbed Fix added/removed bytes being visually misaligned in data diff view (#159) 2025-01-24 17:12:44 -07:00
Luke Street e202c3ef95 Version v2.7.1 2025-01-21 22:59:20 -07:00
LagoLunatic b7730b3d00 Refactor data relocation diffing to improve accuracy and fix bugs (#157)
* Data reloc hover tooltip: Show relocation source address

* Refactor data relocation diffing to improve accuracy and fix bugs
2025-01-21 22:54:31 -07:00
LagoLunatic a4fdb61f04 Implement diffing relocations within data sections (#154)
* Data view: Show data bytes with differing relocations as a diff

* Data view: Show differing relocations on hover

* Symbol list view: Adjust symbol/section match %s when relocations differ

* Improve data reloc diffing logic

* Don't make reloc diffs cause bytes to show as red or green

* Properly detect byte size of each relocation

* Data view: Add context menu for copying relocation target symbols

* Also show already-matching relocations on hover/right click

* Change font color for nonmatching relocs on hover
2025-01-18 16:20:07 -07:00
LagoLunatic 2876be37a3 Show relocation diffs in function view when the data's content differs (#153)
* Show reloc diff in func view when data content differs

* Add "Relax shifted data diffs" option

* Display fake pool relocations at end of line

* Diff reloc data by display string instead of raw bytes

This is to handle data symbols that contain multiple values in them at once, such as stringBase. If you compare the target symbol's bytes directly, then any part of the symbol having different bytes will cause *all* relocations to that symbol to show as a diff, even if the specific string being accessed is the same.

* Fix weak stripped symbols showing as a false diff

Fixed this by showing extern symbols correctly instead of skipping them.

* Add "Relax shifted data diffs" option to objdiff-cli

Includes both a command line argument and a keyboard shortcut (S).

* Remove addi string data hack and ... pool name hack

* Clippy fix

* PPC: Clear relocs from GPRs when overwritten

* PPC: Follow branches to improve pool detection accuracy

* PPC: Handle following bctr jump table control flow

* Clippy fixes

* PPC: Fix extern relocations not having their addend copied

* Add option to disable func data value diffing

* PPC: Handle lmw when clearing GPRs

* PPC: Handle moving reloc address with `add` inst

* Combine "relax reloc diffs" with other reloc diff options

* Add v3 config and migrate from v2

---------

Co-authored-by: Luke Street <luke@street.dev>
2025-01-18 16:18:05 -07:00
Luke Street 11171763eb Use cargo-deny-action@v2 2025-01-18 16:16:12 -07:00
Luke Street 6037a79ba2 Update all dependencies 2025-01-18 15:58:38 -07:00
Luke Street f7efe5fdff cargo update 2025-01-04 21:29:29 -07:00
Luke Street 0692deac59 Use ObjInsArgValue::loose_eq in arg_eq 2025-01-04 21:02:54 -07:00
Luke Street c3e3d175c5 Create schema for diff config properties 2025-01-04 21:02:54 -07:00
Luke Street c45f4bbc99 Diff schema updates & WASM updates 2025-01-04 21:02:54 -07:00
Luke Street b0c5431ac5 Add version to notify deps 2025-01-04 21:02:54 -07:00
LagoLunatic 9ab246367b Add buttons to collapse or expand all sections in the symbol list view for an object simultaneously (#149)
* Add buttons to expand/collapse all sections to symbol list view

* Add buttons to expand/collapse all sections to the split view
2025-01-01 20:48:25 -07:00
NWPlayer123 dcafe51eda Update Dependencies (#150)
* Update Dependencies

* Fix non-WGPU builds

---------

Co-authored-by: NWPlayer123 <NWPlayer123@users.noreply.github.com>
2025-01-01 20:45:48 -07:00
Luke Street c65e87c382 Version 2.5.0 2024-12-08 21:48:21 -07:00
Luke Street 1756b9f6c5 Repaint after view action 2024-12-08 21:42:33 -07:00
Luke Street 303f2938a2 Update dependencies 2024-12-08 21:40:13 -07:00
Luke Street 526e031251 Experimental objdiff-cli diff auto-rebuild 2024-12-08 21:40:13 -07:00
LagoLunatic 10b2a9c129 PPC: Display data values on hover for pools as well (#140)
* Fix missing dependency feature for objdiff-gui

* Update .gitignore

* PPC: Display data values on hover for pools as well

* Tooltip data display: Format floats and doubles better

Floats and doubles will now always be displayed with a decimal point and one digit after it, even if they are whole numbers. Floats will also have the f suffix. This is so you can tell the data type just by glancing at the value.

* Move big functions to bottom ppc.rs

* Clear pool relocs in volatile registers on function call

This fixes some false positives.

* Revert ObjArch API changes, add fake target symbol hack

Because we no longer have access to the actual symbol name via sections, guess_data_type can no longer detect the String data type for pooled references.

* Add hack to detect strings via the addi opcode

* Move hack to resolve placeholder symbol into process_code_symbol

* Merge reloc and fake_pool_reloc fields of ObjIns
2024-12-03 22:50:05 -07:00
LagoLunatic abe68ef2f2 objdiff-gui: Implement keyboard shortcuts (#139)
* Fix missing dependency feature for objdiff-gui

* Update .gitignore

* Add enter and back hotkeys

* Add scroll hotkeys

* Add hotkeys to select the next symbol above/below the current one in the listing

* Do not clear highlighted symbol when backing out of diff view

* Do not clear highlighted symbol when hovering mouse over an unpaired symbol

* Auto-scroll the keyboard-selected symbols into view if offscreen

* Fix some hotkeys stealing input from focused widgets

e.g. The symbol list was stealing the W/S key presses when typing into the symbol filter text edit.

If the user actually wants to use these shortcuts while a widget is focused, they can simply press the escape key to unfocus all widgets and then press the shortcut.

* Add Ctrl+F/S shortcuts for focusing the object and symbol filter text edits

* Add space as alternative to enter hotkey

This is for consistency with egui's builtint enter/space hotkey for interacting with the focused widget.

* Add hotkeys to change target and base functions

* Split function diff view: Enable PageUp/PageDown/Home/End for scrolling

* Add escape as an alternative to back hotkey

* Fix auto-scrolling to highlighted symbol only working for the left side

The flag is cleared after one scroll to avoid doing it continuously, but this breaks when we need to scroll to both the left and the right symbol at the same time. So now each side has its own flag to keep track of this state independently.

* Simplify clearing of the autoscroll flag, remove &mut State

* Found a better place to clear the autoscroll flag

DiffViewState::post_update is where the flag gets set, so clearing it right before that at the start of the function seems to make the most sense, instead of doing it in App::update.
2024-12-02 21:51:37 -07:00
LagoLunatic 304df96411 Display decoded rlwinm info to hover tooltip (#141)
* Fix missing dependency feature for objdiff-gui

* Update .gitignore

* Display decoded rlwinm info to hover tooltip

* Remove trailing newline when displaying decoded rlwinm info

* Change variable name

* Also update variable name in rlwinm.rs
2024-12-02 21:40:05 -07:00
Luke Street 7aa878b48e Update all dependencies & clippy fixes 2024-12-01 22:22:35 -07:00
Luke Street a119d9a6dd Add scratch preset_id field for decomp.me
Resolves #133
2024-11-07 09:27:13 -07:00
robojumper ebf653816a Combine nested otherwise empty directories in objects view (#137) 2024-11-07 08:21:39 -07:00
Luke Street 424434edd6 Experimental ARM64 support
Based on yaxpeax-arm, but with a heavy dose of
custom code to work around its limitations.

Please report any issues or unhandled relocations.
2024-10-31 17:39:12 -06:00
Luke Street 7f14b684bf Ignore PlainText segments when diffing 2024-10-31 17:27:27 -06:00
Luke Street c5da7f7dd5 Show diff color when symbols differ 2024-10-31 17:26:59 -06:00
Luke Street 2fd655850a Ignore Absolute relocations and log warning 2024-10-31 17:24:49 -06:00
Luke Street 79bd7317c1 Match BranchDest->Reloc with relaxed relocation diffs 2024-10-31 17:24:33 -06:00
Luke Street 21f8f2407c Relax symbol comparison logic
The Ghidra delinker plugin emits functions with type STT_OBJECT,
rather than STT_FUNC. The current logic was preventing these from
being compared based on their symbol type. Relax this condition
for now.
2024-10-29 22:46:02 -06:00
Luke Street d2b7a9ef25 Fix missing common BSS symbols
Resolves #128
2024-10-28 17:54:49 -06:00
Luke Street 2cf9cf24d6 Version v2.3.3 2024-10-20 20:01:35 -07:00
Anghelo Carvajal 5ef3416457 Improve dependency gating on objdiff-core (#126)
* Reduce dependencies for no features

* Add missing deps to every feature

* Add missing `dep:`s

* Gate even more deps behind features

Removes dependency on tsify-next / wasm-bindgen unless
compiling with the wasm feature by using `#[cfg_attr]`

* Fix wasm

---------

Co-authored-by: Luke Street <luke@street.dev>
2024-10-20 19:04:29 -07:00
Aetias 6ff8d002f7 Fix panic when parsing DWARF 2 line info for empty section (#125)
* Fix panic when parsing DWARF 2 line info for empty section

* Fix panic when parsing DWARF 2 line info for empty section
May as well remove both unwraps :p
2024-10-19 09:39:18 -06:00
Luke Street 9ca157d717 Lighten default blue diff color
The old default was very dark and blended in with
the dark theme's background.
2024-10-18 17:51:29 -06:00
Steven Casper 67b63311fc Fix data tooltip panic (#123)
* Fix data tooltip panic

Prevents panicing when attempting to display the data tooltip for a symbol that is too large by just using as many bytes as needed from the begging of the symbol.

* Don't attempt to interpret wrongly sized data

* Reference data display improvment issue

* Log failure to display a symbol's value
2024-10-14 22:03:30 -06:00
Luke Street 72ea1c8911 ci: Use rust-lld on Windows 2024-10-12 18:57:49 -06:00
Luke Street d4a540857d ci: Add Rust workspace cache 2024-10-12 18:41:42 -06:00
146 changed files with 41254 additions and 10754 deletions
+5
View File
@@ -0,0 +1,5 @@
[target.x86_64-pc-windows-msvc]
linker = "rust-lld"
[target.aarch64-pc-windows-msvc]
linker = "rust-lld"
+2
View File
@@ -0,0 +1,2 @@
[*.md]
trim_trailing_whitespace = false
+58 -19
View File
@@ -4,13 +4,12 @@ on:
pull_request:
push:
paths-ignore:
- '*.md'
- 'LICENSE*'
- "*.md"
- "LICENSE*"
workflow_dispatch:
env:
BUILD_PROFILE: release-lto
CARGO_TARGET_DIR: target
CARGO_INCREMENTAL: 0
jobs:
@@ -30,10 +29,12 @@ jobs:
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Cache Rust workspace
uses: Swatinem/rust-cache@v2
- name: Cargo check
run: cargo check --all-features --all-targets
run: cargo check --all-targets --all-features
- name: Cargo clippy
run: cargo clippy --all-features --all-targets
run: cargo clippy --all-targets --all-features
fmt:
name: Format
@@ -63,16 +64,15 @@ jobs:
continue-on-error: ${{ matrix.checks == 'advisories' }}
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v1
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check ${{ matrix.checks }}
test:
name: Test
if: 'false' # No tests yet
strategy:
matrix:
platform: [ ubuntu-latest, windows-latest, macos-latest ]
platform: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: false
runs-on: ${{ matrix.platform }}
steps:
@@ -85,8 +85,10 @@ jobs:
uses: actions/checkout@v4
- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache Rust workspace
uses: Swatinem/rust-cache@v2
- name: Cargo test
run: cargo test --release --all-features
run: cargo test --release --features all
build-cli:
name: Build objdiff-cli
@@ -146,22 +148,26 @@ jobs:
python3 -m venv .venv
. .venv/bin/activate
echo PATH=$PATH >> $GITHUB_ENV
pip install ziglang==0.13.0 cargo-zigbuild==0.19.1
pip install ziglang==0.13.0.post1 cargo-zigbuild==0.19.8
- 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 }}
cargo ${{ matrix.build }} --profile ${{ env.BUILD_PROFILE }} --target ${{ matrix.target }}
--bin ${{ env.CARGO_BIN_NAME }} --features ${{ matrix.features }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ env.CARGO_BIN_NAME }}-${{ matrix.name }}
path: |
${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}
${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}.exe
target/${{ matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}
target/${{ matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}.exe
if-no-files-found: error
build-gui:
@@ -172,21 +178,26 @@ jobs:
matrix:
include:
- platform: ubuntu-latest
target: x86_64-unknown-linux-gnu
target: x86_64-unknown-linux-gnu.2.31
target_base: x86_64-unknown-linux-gnu
name: linux-x86_64
packages: libgtk-3-dev
build: zigbuild
features: default
- platform: windows-latest
target: x86_64-pc-windows-msvc
name: windows-x86_64
build: build
features: default
- platform: macos-latest
target: x86_64-apple-darwin
name: macos-x86_64
build: build
features: default
- platform: macos-latest
target: aarch64-apple-darwin
name: macos-arm64
build: build
features: default
fail-fast: false
runs-on: ${{ matrix.platform }}
@@ -198,28 +209,56 @@ jobs:
sudo apt-get -y install ${{ matrix.packages }}
- name: Checkout
uses: actions/checkout@v4
- name: Install cargo-zigbuild
if: matrix.build == 'zigbuild'
run: |
python3 -m venv .venv
. .venv/bin/activate
echo PATH=$PATH >> $GITHUB_ENV
pip install ziglang==0.13.0.post1 cargo-zigbuild==0.19.8
- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
targets: ${{ matrix.target_base || matrix.target }}
- name: Cache Rust workspace
uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Cargo build
run: >
cargo build --profile ${{ env.BUILD_PROFILE }} --target ${{ matrix.target }}
cargo ${{ matrix.build }} --profile ${{ env.BUILD_PROFILE }} --target ${{ matrix.target }}
--bin ${{ env.CARGO_BIN_NAME }} --features ${{ matrix.features }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ env.CARGO_BIN_NAME }}-${{ matrix.name }}
path: |
${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}
${{ env.CARGO_TARGET_DIR }}/${{ matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}.exe
target/${{ matrix.target_base || matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}
target/${{ matrix.target_base || matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}.exe
if-no-files-found: error
build-wasm:
name: Build objdiff-wasm
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@nightly
with:
components: rust-src
- name: Cache Rust workspace
uses: Swatinem/rust-cache@v2
- name: Install dependencies
run: npm -C objdiff-wasm install
- name: Build
run: npm -C objdiff-wasm run build
release:
name: Release
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
needs: [ build-cli, build-gui ]
needs: [build-cli, build-gui]
permissions:
contents: write
steps:
+1 -5
View File
@@ -3,10 +3,6 @@ target/
**/*.rs.bk
generated/
# cargo-mobile
.cargo/
/gen
# macOS
.DS_Store
@@ -22,4 +18,4 @@ android.keystore
*.frag
*.vert
*.metal
.vscode/launch.json
.vscode/
+36
View File
@@ -0,0 +1,36 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: check-yaml
- id: check-added-large-files
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
description: Run cargo fmt on all project files.
language: system
entry: cargo
args: ["+nightly", "fmt", "--all"]
pass_filenames: false
- id: cargo clippy
name: cargo clippy
description: Run cargo clippy on all project files.
language: system
entry: cargo
args: ["+nightly", "clippy", "--all-targets", "--all-features"]
pass_filenames: false
- id: cargo-deny
name: cargo deny
description: Run cargo deny on all project files.
language: system
entry: cargo
args: ["deny", "check"]
pass_filenames: false
always_run: true
Generated
+2035 -994
View File
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -3,8 +3,9 @@ members = [
"objdiff-cli",
"objdiff-core",
"objdiff-gui",
"objdiff-wasm",
]
resolver = "2"
resolver = "3"
[profile.release-lto]
inherits = "release"
@@ -13,9 +14,9 @@ strip = "debuginfo"
codegen-units = 1
[workspace.package]
version = "2.3.2"
version = "3.0.0-beta.4"
authors = ["Luke Street <luke@street.dev>"]
edition = "2021"
edition = "2024"
license = "MIT OR Apache-2.0"
repository = "https://github.com/encounter/objdiff"
rust-version = "1.74"
rust-version = "1.85"
+20 -4
View File
@@ -20,6 +20,7 @@ Supports:
- MIPS (N64, PS1, PS2, PSP)
- x86 (COFF only at the moment)
- ARM (GBA, DS, 3DS)
- ARM64 (Switch, experimental)
See [Usage](#usage) for more information.
@@ -142,15 +143,15 @@ If not specified, objdiff will use the default patterns listed above.
`units` _(optional)_: If specified, objdiff will display a list of objects in the sidebar for easy navigation.
> `name` _(optional)_: The name of the object in the UI. If not specified, the object's `path` will be used.
>
>
> `target_path`: Path to the "target" or "expected" object from the project root.
> This object is the **intended result** of the match.
>
>
> `base_path`: Path to the "base" or "actual" object from the project root.
> This object is built from the **current source code**.
>
>
> `metadata.auto_generated` _(optional)_: Hides the object from the object list, but still includes it in reports.
>
>
> `metadata.complete` _(optional)_: Marks the object as "complete" (or "linked") in the object list.
> This is useful for marking objects that are fully decompiled. A value of `false` will mark the object as "incomplete".
@@ -172,6 +173,21 @@ $ cargo install --locked --git https://github.com/encounter/objdiff.git objdiff-
The binaries will be installed to `~/.cargo/bin` as `objdiff` and `objdiff-cli`.
## Installing `pre-commit`
When contributing, it's recommended to install `pre-commit` to automatically run the linter and formatter before a commit.
[`uv`](https://github.com/astral-sh/uv#installation) is recommended to manage Python version and tools.
Rust nightly is required for `cargo +nightly fmt` and `cargo +nightly clippy`.
```shell
$ cargo install --locked cargo-deny
$ rustup toolchain install nightly
$ uv tool install pre-commit
$ pre-commit install
```
## License
Licensed under either of
+9 -4
View File
@@ -73,6 +73,7 @@ ignore = [
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
{ id = "RUSTSEC-2024-0436", reason = "Unmaintained paste crate is an indirect dependency" },
]
# If this is true, then cargo deny will use the git executable to fetch advisory database.
# If this is false, then it uses a built-in git library.
@@ -97,12 +98,11 @@ allow = [
"BSL-1.0",
"CC0-1.0",
"MPL-2.0",
"Unicode-DFS-2016",
"Unicode-3.0",
"Zlib",
"0BSD",
"OFL-1.1",
"LicenseRef-UFL-1.0",
"OpenSSL",
"Ubuntu-font-1.0",
]
# The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the
@@ -239,7 +239,12 @@ allow-git = []
[sources.allow-org]
# github.com organizations to allow git sources for
github = ["notify-rs"]
github = [
"CelestialAmber", # cwextab, rlwinmdec
"Decompollaborate", # rabbitizer
"enarx", # flagset
"encounter",
]
# gitlab.com organizations to allow git sources for
gitlab = []
# bitbucket.org organizations to allow git sources for
+3 -2
View File
@@ -14,13 +14,13 @@ publish = false
[dependencies]
anyhow = "1.0"
argp = "0.3"
argp = "0.4"
crossterm = "0.28"
enable-ansi-support = "0.2"
memmap2 = "0.9"
objdiff-core = { path = "../objdiff-core", features = ["all"] }
prost = "0.13"
ratatui = "0.28"
ratatui = "0.29"
rayon = "1.10"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
@@ -28,6 +28,7 @@ supports-color = "3.0"
time = { version = "0.3", features = ["formatting", "local-offset"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
typed-path = "0.10"
[target.'cfg(target_env = "musl")'.dependencies]
mimalloc = "0.1"
+1 -1
View File
@@ -4,7 +4,7 @@
//! For now, this only adds a --version/-V option which causes early-exit.
use std::ffi::OsStr;
use argp::{parser::ParseGlobalOptions, EarlyExit, FromArgs, TopLevelCommand};
use argp::{EarlyExit, FromArgs, TopLevelCommand, parser::ParseGlobalOptions};
struct ArgsOrVersion<T>(T)
where T: FromArgs;
File diff suppressed because it is too large Load Diff
+85 -96
View File
@@ -1,28 +1,25 @@
use std::{
collections::HashSet,
fs::File,
io::Read,
path::{Path, PathBuf},
time::Instant,
};
use std::{collections::HashSet, fs::File, io::Read, time::Instant};
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use argp::FromArgs;
use objdiff_core::{
bindings::report::{
ChangeItem, ChangeItemInfo, ChangeUnit, Changes, ChangesInput, Measures, Report,
ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata,
REPORT_VERSION,
ChangeItem, ChangeItemInfo, ChangeUnit, Changes, ChangesInput, Measures, REPORT_VERSION,
Report, ReportCategory, ReportItem, ReportItemMetadata, ReportUnit, ReportUnitMetadata,
},
config::ProjectObject,
config::path::platform_path,
diff, obj,
obj::{ObjSectionKind, ObjSymbolFlags},
obj::{SectionKind, SymbolFlag},
};
use prost::Message;
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use tracing::{info, warn};
use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
use crate::util::output::{write_output, OutputFormat};
use crate::{
cmd::diff::ObjectConfig,
util::output::{OutputFormat, write_output},
};
#[derive(FromArgs, PartialEq, Debug)]
/// Generate a progress report for a project.
@@ -43,12 +40,12 @@ pub enum SubCommand {
/// Generate a progress report for a project.
#[argp(subcommand, name = "generate")]
pub struct GenerateArgs {
#[argp(option, short = 'p')]
#[argp(option, short = 'p', from_str_fn(platform_path))]
/// Project directory
project: Option<PathBuf>,
#[argp(option, short = 'o')]
project: Option<Utf8PlatformPathBuf>,
#[argp(option, short = 'o', from_str_fn(platform_path))]
/// Output file
output: Option<PathBuf>,
output: Option<Utf8PlatformPathBuf>,
#[argp(switch, short = 'd')]
/// Deduplicate global and weak symbols (runs single-threaded)
deduplicate: bool,
@@ -61,15 +58,15 @@ pub struct GenerateArgs {
/// List any changes from a previous report.
#[argp(subcommand, name = "changes")]
pub struct ChangesArgs {
#[argp(positional)]
#[argp(positional, from_str_fn(platform_path))]
/// Previous report file
previous: PathBuf,
#[argp(positional)]
previous: Utf8PlatformPathBuf,
#[argp(positional, from_str_fn(platform_path))]
/// Current report file
current: PathBuf,
#[argp(option, short = 'o')]
current: Utf8PlatformPathBuf,
#[argp(option, short = 'o', from_str_fn(platform_path))]
/// Output file
output: Option<PathBuf>,
output: Option<Utf8PlatformPathBuf>,
#[argp(option, short = 'f')]
/// Output format (json, json-pretty, proto) (default: json)
format: Option<String>,
@@ -84,10 +81,10 @@ pub fn run(args: Args) -> Result<()> {
fn generate(args: GenerateArgs) -> Result<()> {
let output_format = OutputFormat::from_option(args.format.as_deref())?;
let project_dir = args.project.as_deref().unwrap_or_else(|| Path::new("."));
info!("Loading project {}", project_dir.display());
let project_dir = args.project.as_deref().unwrap_or_else(|| Utf8PlatformPath::new("."));
info!("Loading project {}", project_dir);
let mut project = match objdiff_core::config::try_project_config(project_dir) {
let project = match objdiff_core::config::try_project_config(project_dir.as_ref()) {
Some((Ok(config), _)) => config,
Some((Err(err), _)) => bail!("Failed to load project configuration: {}", err),
None => bail!("No project configuration found"),
@@ -98,37 +95,33 @@ fn generate(args: GenerateArgs) -> Result<()> {
if args.deduplicate { 1 } else { rayon::current_num_threads() }
);
let target_obj_dir =
project.target_dir.as_ref().map(|p| project_dir.join(p.with_platform_encoding()));
let base_obj_dir =
project.base_dir.as_ref().map(|p| project_dir.join(p.with_platform_encoding()));
let objects = project
.units
.iter()
.flatten()
.map(|o| {
ObjectConfig::new(o, project_dir, target_obj_dir.as_deref(), base_obj_dir.as_deref())
})
.collect::<Vec<_>>();
let start = Instant::now();
let mut units = vec![];
let mut existing_functions: HashSet<String> = HashSet::new();
if args.deduplicate {
// If deduplicating, we need to run single-threaded
for object in project.units.as_deref_mut().unwrap_or_default() {
if let Some(unit) = report_object(
object,
project_dir,
project.target_dir.as_deref(),
project.base_dir.as_deref(),
Some(&mut existing_functions),
)? {
for object in &objects {
if let Some(unit) = report_object(object, Some(&mut existing_functions))? {
units.push(unit);
}
}
} else {
let vec = project
.units
.as_deref_mut()
.unwrap_or_default()
.par_iter_mut()
.map(|object| {
report_object(
object,
project_dir,
project.target_dir.as_deref(),
project.base_dir.as_deref(),
None,
)
})
let vec = objects
.par_iter()
.map(|object| report_object(object, None))
.collect::<Result<Vec<Option<ReportUnit>>>>()?;
units = vec.into_iter().flatten().collect();
}
@@ -151,55 +144,54 @@ fn generate(args: GenerateArgs) -> Result<()> {
}
fn report_object(
object: &mut ProjectObject,
project_dir: &Path,
target_dir: Option<&Path>,
base_dir: Option<&Path>,
object: &ObjectConfig,
mut existing_functions: Option<&mut HashSet<String>>,
) -> Result<Option<ReportUnit>> {
object.resolve_paths(project_dir, target_dir, base_dir);
match (&object.target_path, &object.base_path) {
(None, Some(_)) if !object.complete().unwrap_or(false) => {
warn!("Skipping object without target: {}", object.name());
(None, Some(_)) if !object.complete.unwrap_or(false) => {
warn!("Skipping object without target: {}", object.name);
return Ok(None);
}
(None, None) => {
warn!("Skipping object without target or base: {}", object.name());
warn!("Skipping object without target or base: {}", object.name);
return Ok(None);
}
_ => {}
}
let config = diff::DiffObjConfig { relax_reloc_diffs: true, ..Default::default() };
let diff_config = diff::DiffObjConfig {
function_reloc_diffs: diff::FunctionRelocDiffs::None,
..Default::default()
};
let mapping_config = diff::MappingConfig::default();
let target = object
.target_path
.as_ref()
.map(|p| {
obj::read::read(p, &config).with_context(|| format!("Failed to open {}", p.display()))
obj::read::read(p.as_ref(), &diff_config)
.with_context(|| format!("Failed to open {}", p))
})
.transpose()?;
let base = object
.base_path
.as_ref()
.map(|p| {
obj::read::read(p, &config).with_context(|| format!("Failed to open {}", p.display()))
obj::read::read(p.as_ref(), &diff_config)
.with_context(|| format!("Failed to open {}", p))
})
.transpose()?;
let result = diff::diff_objs(&config, target.as_ref(), base.as_ref(), None)?;
let result =
diff::diff_objs(target.as_ref(), base.as_ref(), None, &diff_config, &mapping_config)?;
let metadata = ReportUnitMetadata {
complete: object.complete(),
complete: object.metadata.complete,
module_name: target
.as_ref()
.and_then(|o| o.split_meta.as_ref())
.and_then(|m| m.module_name.clone()),
module_id: target.as_ref().and_then(|o| o.split_meta.as_ref()).and_then(|m| m.module_id),
source_path: object.metadata.as_ref().and_then(|m| m.source_path.clone()),
progress_categories: object
.metadata
.as_ref()
.and_then(|m| m.progress_categories.clone())
.unwrap_or_default(),
auto_generated: object.metadata.as_ref().and_then(|m| m.auto_generated),
source_path: object.metadata.source_path.as_ref().map(|p| p.to_string()),
progress_categories: object.metadata.progress_categories.clone().unwrap_or_default(),
auto_generated: object.metadata.auto_generated,
};
let mut measures = Measures { total_units: 1, ..Default::default() };
let mut sections = vec![];
@@ -207,15 +199,13 @@ fn report_object(
let obj = target.as_ref().or(base.as_ref()).unwrap();
let obj_diff = result.left.as_ref().or(result.right.as_ref()).unwrap();
for (section, section_diff) in obj.sections.iter().zip(&obj_diff.sections) {
for ((section_idx, section), section_diff) in
obj.sections.iter().enumerate().zip(&obj_diff.sections)
{
let section_match_percent = section_diff.match_percent.unwrap_or_else(|| {
// Support cases where we don't have a target object,
// assume complete means 100% match
if object.complete().unwrap_or(false) {
100.0
} else {
0.0
}
if object.complete.unwrap_or(false) { 100.0 } else { 0.0 }
});
sections.push(ReportItem {
name: section.name.clone(),
@@ -228,23 +218,27 @@ fn report_object(
});
match section.kind {
ObjSectionKind::Data | ObjSectionKind::Bss => {
SectionKind::Data | SectionKind::Bss => {
measures.total_data += section.size;
if section_match_percent == 100.0 {
measures.matched_data += section.size;
}
continue;
}
ObjSectionKind::Code => (),
_ => {}
}
for (symbol, symbol_diff) in section.symbols.iter().zip(&section_diff.symbols) {
if symbol.size == 0 || symbol.flags.0.contains(ObjSymbolFlags::Hidden) {
for (symbol, symbol_diff) in obj.symbols.iter().zip(&obj_diff.symbols) {
if symbol.section != Some(section_idx)
|| symbol.size == 0
|| symbol.flags.contains(SymbolFlag::Hidden)
|| symbol.flags.contains(SymbolFlag::Ignored)
{
continue;
}
if let Some(existing_functions) = &mut existing_functions {
if (symbol.flags.0.contains(ObjSymbolFlags::Global)
|| symbol.flags.0.contains(ObjSymbolFlags::Weak))
if (symbol.flags.contains(SymbolFlag::Global)
|| symbol.flags.contains(SymbolFlag::Weak))
&& !existing_functions.insert(symbol.name.clone())
{
continue;
@@ -253,11 +247,7 @@ fn report_object(
let match_percent = symbol_diff.match_percent.unwrap_or_else(|| {
// Support cases where we don't have a target object,
// assume complete means 100% match
if object.complete().unwrap_or(false) {
100.0
} else {
0.0
}
if object.complete.unwrap_or(false) { 100.0 } else { 0.0 }
});
measures.fuzzy_match_percent += match_percent * symbol.size as f32;
measures.total_code += symbol.size;
@@ -287,7 +277,7 @@ fn report_object(
measures.calc_fuzzy_match_percent();
measures.calc_matched_percent();
Ok(Some(ReportUnit {
name: object.name().to_string(),
name: object.name.clone(),
measures: Some(measures),
sections,
functions,
@@ -297,7 +287,7 @@ fn report_object(
fn changes(args: ChangesArgs) -> Result<()> {
let output_format = OutputFormat::from_option(args.format.as_deref())?;
let (previous, current) = if args.previous == Path::new("-") && args.current == Path::new("-") {
let (previous, current) = if args.previous == "-" && args.current == "-" {
// Special case for comparing two reports from stdin
let mut data = vec![];
std::io::stdin().read_to_end(&mut data)?;
@@ -412,15 +402,14 @@ fn process_new_items(items: &[ReportItem]) -> Vec<ChangeItem> {
.collect()
}
fn read_report(path: &Path) -> Result<Report> {
if path == Path::new("-") {
fn read_report(path: &Utf8PlatformPath) -> Result<Report> {
if path == Utf8PlatformPath::new("-") {
let mut data = vec![];
std::io::stdin().read_to_end(&mut data)?;
return Report::parse(&data).with_context(|| "Failed to load report from stdin");
}
let file = File::open(path).with_context(|| format!("Failed to open {}", path.display()))?;
let mmap = unsafe { memmap2::Mmap::map(&file) }
.with_context(|| format!("Failed to map {}", path.display()))?;
Report::parse(mmap.as_ref())
.with_context(|| format!("Failed to load report {}", path.display()))
let file = File::open(path).with_context(|| format!("Failed to open {}", path))?;
let mmap =
unsafe { memmap2::Mmap::map(&file) }.with_context(|| format!("Failed to map {}", path))?;
Report::parse(mmap.as_ref()).with_context(|| format!("Failed to load report {}", path))
}
+4 -1
View File
@@ -1,6 +1,9 @@
#![allow(clippy::too_many_arguments)]
mod argp_version;
mod cmd;
mod util;
mod views;
// musl's allocator is very slow, so use mimalloc when targeting musl.
// Otherwise, use the system allocator to avoid extra code size.
@@ -14,7 +17,7 @@ use anyhow::{Error, Result};
use argp::{FromArgValue, FromArgs};
use enable_ansi_support::enable_ansi_support;
use supports_color::Stream;
use tracing_subscriber::{filter::LevelFilter, EnvFilter};
use tracing_subscriber::{EnvFilter, filter::LevelFilter};
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
enum LogLevel {
+7 -4
View File
@@ -5,7 +5,7 @@ use std::{
path::Path,
};
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use tracing::info;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
@@ -34,9 +34,12 @@ impl OutputFormat {
}
}
pub fn write_output<T>(input: &T, output: Option<&Path>, format: OutputFormat) -> Result<()>
where T: serde::Serialize + prost::Message {
match output {
pub fn write_output<T, P>(input: &T, output: Option<P>, format: OutputFormat) -> Result<()>
where
T: serde::Serialize + prost::Message,
P: AsRef<Path>,
{
match output.as_ref().map(|p| p.as_ref()) {
Some(output) if output != Path::new("-") => {
info!("Writing to {}", output.display());
let file = File::options()
+1 -1
View File
@@ -3,7 +3,7 @@ use std::{io::stdout, panic};
use crossterm::{
cursor::Show,
event::DisableMouseCapture,
terminal::{disable_raw_mode, LeaveAlternateScreen},
terminal::{LeaveAlternateScreen, disable_raw_mode},
};
pub fn crossterm_panic_handler() {
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
use anyhow::Result;
use crossterm::event::Event;
use ratatui::Frame;
use crate::cmd::diff::AppState;
pub mod function_diff;
#[derive(Default)]
pub struct EventResult {
pub redraw: bool,
pub click_xy: Option<(u16, u16)>,
}
pub enum EventControlFlow {
Break,
Continue(EventResult),
Reload,
}
pub trait UiView {
fn draw(&mut self, state: &AppState, f: &mut Frame, result: &mut EventResult);
fn handle_event(&mut self, state: &mut AppState, event: Event) -> EventControlFlow;
fn reload(&mut self, state: &AppState) -> Result<()>;
}
+161 -45
View File
@@ -12,70 +12,186 @@ 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 = ["bimap"] # Implicit, used to check if any arch is enabled
config = ["bimap", "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"]
default = ["std"]
all = [
# Features
"bindings",
"build",
"config",
"dwarf",
"serde",
# Architectures
"arm",
"arm64",
"mips",
"ppc",
"x86",
]
# Implicit, used to check if any arch is enabled
any-arch = [
"dep:flagset",
"dep:heck",
"dep:log",
"dep:num-traits",
"dep:prettyplease",
"dep:proc-macro2",
"dep:quote",
"dep:regex",
"dep:similar",
"dep:syn",
]
bindings = [
"dep:prost",
"dep:prost-build",
]
build = [
"dep:notify",
"dep:notify-debouncer-full",
"dep:reqwest",
"dep:self_update",
"dep:shell-escape",
"dep:tempfile",
"dep:time",
"dep:winapi",
]
config = [
"dep:globset",
"dep:semver",
"dep:typed-path",
]
dwarf = ["dep:gimli"]
serde = [
"dep:pbjson",
"dep:pbjson-build",
"dep:serde",
"dep:serde_json",
]
std = [
"anyhow/std",
"flagset?/std",
"log?/std",
"num-traits?/std",
"object/std",
"prost?/std",
"serde?/std",
"typed-path?/std",
"dep:filetime",
"dep:memmap2",
]
mips = [
"any-arch",
"dep:cpp_demangle",
"dep:cwdemangle",
"dep:rabbitizer",
]
ppc = [
"any-arch",
"dep:cwdemangle",
"dep:cwextab",
"dep:ppc750cl",
"dep:rlwinmdec",
]
x86 = [
"any-arch",
"dep:cpp_demangle",
"dep:iced-x86",
"dep:msvc-demangler",
]
arm = [
"any-arch",
"dep:arm-attr",
"dep:cpp_demangle",
"dep:unarm",
]
arm64 = [
"any-arch",
"dep:cpp_demangle",
"dep:yaxpeax-arch",
"dep:yaxpeax-arm",
]
[package.metadata.docs.rs]
features = ["all"]
[dependencies]
anyhow = "1.0"
bimap = { version = "0.6", features = ["serde"], optional = true }
byteorder = "1.5"
filetime = "0.2"
flagset = "0.4"
log = "0.4"
memmap2 = "0.9"
num-traits = "0.2"
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"] }
similar = { version = "2.6", default-features = false }
strum = { version = "0.26", features = ["derive"] }
wasm-bindgen = "0.2"
tsify-next = { version = "0.5", default-features = false, features = ["js"] }
console_log = { version = "1.0", optional = true }
console_error_panic_hook = { version = "0.1", optional = true }
anyhow = { version = "1.0", default-features = false }
filetime = { version = "0.2", optional = true }
flagset = { version = "0.4", default-features = false, optional = true, git = "https://github.com/enarx/flagset.git", rev = "a1fe9369b3741e43fec45da1998e83b9d78966a2" }
itertools = { version = "0.14", default-features = false, features = ["use_alloc"] }
log = { version = "0.4", default-features = false, optional = true }
memmap2 = { version = "0.9", optional = true }
num-traits = { version = "0.2", default-features = false, optional = true }
object = { version = "0.36", default-features = false, features = ["read_core", "elf", "pe"] }
pbjson = { version = "0.7", default-features = false, optional = true }
prost = { version = "0.13", default-features = false, features = ["prost-derive"], optional = true }
regex = { version = "1.11", default-features = false, features = [], optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
similar = { version = "2.7", default-features = false, optional = true, git = "https://github.com/encounter/similar.git", branch = "no_std" }
typed-path = { version = "0.10", default-features = false, optional = true }
# config
globset = { version = "0.4", features = ["serde1"], optional = true }
semver = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true }
serde_yaml = { version = "0.9", optional = true }
globset = { version = "0.4", default-features = false, optional = true }
semver = { version = "1.0", default-features = false, optional = true }
serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true }
# dwarf
gimli = { version = "0.31", default-features = false, features = ["read-all"], optional = true }
gimli = { version = "0.31", default-features = false, features = ["read"], optional = true }
# ppc
cwdemangle = { version = "1.0", optional = true }
cwextab = { version = "1.0.2", optional = true }
cwextab = { version = "1.0", optional = true, git = "https://github.com/CelestialAmber/cwextab.git" }
ppc750cl = { version = "0.3", optional = true }
rlwinmdec = { version = "1.1", optional = true, git = "https://github.com/CelestialAmber/rlwinmdec.git" }
# mips
rabbitizer = { version = "1.12", optional = true }
rabbitizer = { git = "https://github.com/Decompollaborate/rabbitizer.git", branch = "🦀", default-features = false, features = ["all_extensions"], optional = true }
# x86
cpp_demangle = { version = "0.4", 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 }
cpp_demangle = { version = "0.4", default-features = false, features = ["alloc"], optional = true }
iced-x86 = { version = "1.21", default-features = false, features = ["decoder", "intel", "gas", "masm", "nasm", "exhaustive_enums", "no_std"], optional = true }
msvc-demangler = { version = "0.11", optional = true }
# arm
unarm = { version = "1.6", optional = true }
arm-attr = { version = "0.1", optional = true }
unarm = { version = "1.7", optional = true }
arm-attr = { version = "0.2", optional = true }
# arm64
yaxpeax-arch = { version = "0.3", default-features = false, optional = true }
yaxpeax-arm = { version = "0.3", default-features = false, optional = true }
# build
notify = { version = "8.0.0", optional = true }
notify-debouncer-full = { version = "0.5.0", optional = true }
shell-escape = { version = "0.1", optional = true }
tempfile = { version = "3.17", optional = true }
time = { version = "0.3", optional = true }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", optional = true }
# For Linux static binaries, use rustls
[target.'cfg(target_os = "linux")'.dependencies]
reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "multipart", "rustls-tls"], optional = true }
self_update = { version = "0.42", default-features = false, features = ["rustls"], optional = true }
# For all other platforms, use native TLS
[target.'cfg(not(target_os = "linux"))'.dependencies]
reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "multipart", "default-tls"], optional = true }
self_update = { version = "0.42", optional = true }
[build-dependencies]
prost-build = "0.13"
pbjson-build = "0.7"
heck = { version = "0.5", optional = true }
pbjson-build = { version = "0.7", optional = true }
prettyplease = { version = "0.2", optional = true }
proc-macro2 = { version = "1.0", optional = true }
prost-build = { version = "0.13", optional = true }
quote = { version = "1.0", optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
syn = { version = "2.0", optional = true }
[dev-dependencies]
# Enable all features for tests
objdiff-core = { path = ".", features = ["all"] }
insta = "1.42"
+1
View File
@@ -11,4 +11,5 @@ objdiff-core contains the core functionality of [objdiff](https://github.com/enc
- **`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).
- **`bindings`**: Enables serialization and deserialization of objdiff data structures.

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