Compare commits

...

81 Commits

Author SHA1 Message Date
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
Luke Street 676488433f Fix resolving symbols for section-relative relocations
Also fixes MIPS `j` handling when jumping within the function.

Reworks `ObjReloc` struct to be a little more sensible.
2024-10-11 18:09:18 -06:00
Luke Street 83de98b5ee Version v2.3.1 2024-10-10 22:58:33 -06:00
Luke Street c1ba4e91d1 ci: Setup python venv for cargo-zigbuild 2024-10-10 22:39:31 -06:00
Luke Street 575900024d Avoid resetting diff state on unit config reload 2024-10-10 22:31:04 -06:00
Luke Street cbe299e859 Fix logic issue with 0-sized symbols
Fixes #119
2024-10-10 22:20:48 -06:00
Luke Street 741d93e211 Add symbol mapping feature (#118)
This allows users to "map" (or "link") symbols with different names so that they can be compared without having to update either the target or base objects. Symbol mappings are persisted in objdiff.json, so generators will need to ensure that they're preserved when updating. (Example: https://github.com/encounter/dtk-template/commit/d1334bb79e71af1a7b3b090bffda4adc483f722c)

Resolves #117
2024-10-09 21:44:18 -06:00
Luke Street 603dbd6882 Round match percent down before display
Ensures that 100% isn't displayed until it's a
perfect match.
2024-10-07 20:17:56 -06:00
Luke Street 6fb0a63de2 Click on empty space in row to clear highlight
Resolves #116
2024-10-07 19:53:16 -06:00
Luke Street ab2e84a2c6 Deprioritize generated GCC symbols in find_section_symbol
Resolves #115
2024-10-07 19:49:52 -06:00
Luke Street 9596051cb4 Allow collapsing sidebar in symbols view 2024-10-07 19:46:16 -06:00
Luke Street a5d9d8282e Update all dependencies 2024-10-03 22:00:43 -06:00
Amber Brault 3287a0f65c Bump cwextab again to 1.0.2 (#114)
* Bump cwextab

* Updated cwextab to not error on null actions

* Bump cwextab again
2024-10-03 01:12:37 -06:00
Amber Brault fab9c62dfb Bump cwextab (#113)
* Bump cwextab

* Updated cwextab to not error on null actions
2024-10-01 23:20:09 -06:00
Luke Street 08cd768260 Add total_units, complete_units to progress report 2024-09-30 21:41:57 -06:00
Luke Street 8acaaf528c Version v2.2.0 2024-09-29 12:26:41 -06:00
Luke Street 6e881a74e1 Remove armv7-unknown-linux-musleabi build 2024-09-29 11:57:13 -06:00
Luke Street cc1bc44e69 Use mimalloc when targeting musl 2024-09-29 11:52:04 -06:00
Luke Street c7b85518ab Rework jobs view & error handling improvements
Job status is now shown in the top menu bar,
with a new Jobs window that can be toggled.

Build and diff errors are now handled more
gracefully.

Fixes #40
2024-09-28 12:14:20 -06:00
Luke Street bb039a1445 Add "Open source file" option
Available when right-clicking an object in
the object list or when viewing an object

Resolves #99
2024-09-28 11:50:56 -06:00
Luke Street 8fc142d316 Debounce loaded object modification check
Before, this was running 2 fs::metadata
calls every frame. We don't need to do it
nearly that often, so now it only checks
once every 500ms.

This required refactoring AppConfig into
a separate AppState that holds transient
runtime state along with the loaded
AppConfig.
2024-09-28 10:55:22 -06:00
Luke Street b0123b3f83 Improve build log message when command doesn't exist
Before, it didn't include the actual command
that was attempted to run.
2024-09-28 10:55:09 -06:00
Luke Street 2ec17aee9b Improve config read/write performance
We were accidentally using unbuffered readers
and writers before, leading to long pauses on
the main thread on slow filesystems. (e.g.
FUSE or WSL)
2024-09-28 10:54:54 -06:00
Luke Street ec9731e1e5 Set app_id in eframe NativeOptions
Fixes missing WM_CLASS on Wayland
2024-09-28 10:53:58 -06:00
OndrikB a06382c27e Disambiguate dummy symbols (#107)
* Disambiguate dummy symbols

* Small formatting improvement

* Put HashMap logic into symbol creation
2024-09-27 00:33:36 -06:00
Luke Street e013638c5a clippy fixes 2024-09-27 00:30:30 -06:00
Luke Street 70ab82f1f7 gui: Highlight registers in columns separately
This matches the behavior of decomp.me and the
CLI.

Resolves #71
2024-09-27 00:27:36 -06:00
Luke Street c5896689cf Use ppc750cl Opcode::from 2024-09-27 00:12:21 -06:00
Luke Street 67719dd93e report: Exclude "hidden" functions
Fixes #111
2024-09-27 00:12:21 -06:00
Luke Street 258e141017 Upgrade all dependencies 2024-09-27 00:12:16 -06:00
Luke Street dbdda55065 Add Report::split
A hack for supporting games that build
all versions at once.
2024-09-26 23:47:03 -06:00
Steven Casper a43320af1f PPC: Guess reloc data type based on the instruction. (#108)
* Guess reloc data type based on the instruction.

Adds an entry to the reloc tooltip to show the inferred data type
and value.

* Fix clippy warning

* Match on Opcode rather than mnemonic string
2024-09-25 23:45:37 -06:00
Amber Brault 35bbd40f5d Actually update extab stuff (#110)
* Update cwextab

* Update

* Update ppc.rs

* Make fmt shut up
2024-09-24 09:16:14 -06:00
Amber Brault c1cb4b0b19 Update cwextab (#109) 2024-09-23 21:24:33 -06:00
Luke Street 2379853faa Remove unused imports 2024-09-10 23:29:22 -06:00
Luke Street 5e1aff180f Remove vergen / GIT_COMMIT_SHA handling 2024-09-10 23:22:40 -06:00
Luke Street 3846a7d315 Version v2.0.0 2024-09-09 20:18:56 -06:00
Luke Street dcf209aac5 Cleanup & move extab code into ppc arch 2024-09-09 19:43:10 -06:00
Luke Street c7e6394628 Try to resolve deleting autoupdate tmp dir 2024-09-09 19:42:01 -06:00
Luke Street 235dc7f517 Use released ppc750cl & update README.md 2024-09-09 19:41:29 -06:00
Robin Avery 199c07e975 Add cargo install instructions to README (#105) 2024-09-09 19:38:06 -06:00
Luke Street 56a5a61825 Updates to CI workflow & README.md 2024-09-09 19:34:50 -06:00
Luke Street 3d2236de82 Use workspace keys in Cargo.toml 2024-09-09 19:32:22 -06:00
Luke Street bcc5871cd8 Update all dependencies 2024-09-09 19:26:46 -06:00
Robin Lambertz 7d0d7df54c Add 32-bit windows objdiff-cli build (#102)
* Revert "Add 32-bit windows builds (#101)"

This reverts commit bc687173c0.

* Add 32-bit objdiff-cli build
2024-09-06 19:25:18 -06:00
Luke Street 0221a2d54d clippy fix 2024-09-05 17:52:43 -06:00
Robin Lambertz bc687173c0 Add 32-bit windows builds (#101) 2024-09-05 17:50:37 -06:00
75 changed files with 12664 additions and 4848 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"
+44 -44
View File
@@ -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
@@ -85,7 +65,7 @@ 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 }}
@@ -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
+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/
Generated
+1854 -1360
View File
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -8,5 +8,14 @@ resolver = "2"
[profile.release-lto]
inherits = "release"
lto = "thin"
lto = "fat"
strip = "debuginfo"
codegen-units = 1
[workspace.package]
version = "2.7.0"
authors = ["Luke Street <luke@street.dev>"]
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/encounter/objdiff"
rust-version = "1.81"
+32 -4
View File
@@ -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,13 +15,34 @@ 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)
- ARM (GBA, DS, 3DS)
- ARM64 (Switch, experimental)
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
![Symbol Screenshot](assets/screen-symbols.png)
![Diff Screenshot](assets/screen-diff.png)
@@ -141,16 +163,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.
+7
View File
@@ -133,6 +133,13 @@
},
"metadata": {
"ref": "#/$defs/metadata"
},
"symbol_mappings": {
"type": "object",
"description": "Manual symbol mappings from target to base.",
"additionalProperties": {
"type": "string"
}
}
}
},
+102 -70
View File
@@ -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 = [
@@ -77,34 +97,13 @@ 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",
"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 = []
# gitlab.com organizations to allow git sources for
gitlab = []
# bitbucket.org organizations to allow git sources for
bitbucket = []
+23 -21
View File
@@ -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.4"
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.29"
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"
-9
View File
@@ -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");
}
+1 -2
View File
@@ -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 {
File diff suppressed because it is too large Load Diff
+20 -10
View File
@@ -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(),
@@ -167,22 +169,29 @@ fn report_object(
}
_ => {}
}
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, &diff_config)
.with_context(|| format!("Failed to open {}", p.display()))
})
.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, &diff_config)
.with_context(|| format!("Failed to open {}", p.display()))
})
.transpose()?;
let result = diff::diff_objs(&config, target.as_ref(), base.as_ref(), None)?;
let result =
diff::diff_objs(&diff_config, &mapping_config, target.as_ref(), base.as_ref(), None)?;
let metadata = ReportUnitMetadata {
complete: object.complete(),
@@ -199,7 +208,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 +246,7 @@ fn report_object(
}
for (symbol, symbol_diff) in section.symbols.iter().zip(&section_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 +289,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();
+7
View File
@@ -1,6 +1,13 @@
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.
#[cfg(target_env = "musl")]
#[global_allocator]
static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
use std::{env, ffi::OsStr, fmt::Display, path::PathBuf, str::FromStr};
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<()>;
}
+175 -50
View File
@@ -1,76 +1,201 @@
[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"]
all = [
# Features
"bindings",
"build",
"config",
"dwarf",
# Architectures
"mips",
"ppc",
"x86",
"arm",
"arm64",
]
# Implicit, used to check if any arch is enabled
any-arch = [
"config",
"dep:bimap",
"dep:byteorder",
"dep:flagset",
"dep:heck",
"dep:log",
"dep:memmap2",
"dep:num-traits",
"dep:prettyplease",
"dep:proc-macro2",
"dep:quote",
"dep:serde",
"dep:serde_json",
"dep:similar",
"dep:strum",
"dep:syn",
]
bindings = [
"dep:pbjson",
"dep:pbjson-build",
"dep:prost",
"dep:prost-build",
"dep:serde",
"dep:serde_json",
]
build = [
"dep:notify",
"dep:notify-debouncer-full",
"dep:path-slash",
"dep:reqwest",
"dep:self_update",
"dep:shell-escape",
"dep:tempfile",
"dep:time",
"dep:winapi",
]
config = [
"dep:bimap",
"dep:filetime",
"dep:globset",
"dep:semver",
"dep:serde",
"dep:serde_json",
"dep:serde_yaml",
]
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:arm-attr",
"dep:cpp_demangle",
"dep:unarm",
]
arm64 = [
"any-arch",
"dep:cpp_demangle",
"dep:yaxpeax-arch",
"dep:yaxpeax-arm",
]
wasm = [
"any-arch",
"bindings",
"dep:console_error_panic_hook",
"dep:console_log",
"dep:log",
"dep:tsify-next",
"dep:wasm-bindgen",
]
[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", 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 }
# arm64
yaxpeax-arch = { version = "0.3", default-features = false, features = ["std"], optional = true }
yaxpeax-arm = { version = "0.3", default-features = false, features = ["std"], 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.15", optional = true }
time = { version = "0.3", optional = true }
[target.'cfg(windows)'.dependencies]
path-slash = { version = "0.2", optional = true }
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.1"
pbjson-build = "0.7.0"
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"], optional = true }
serde_json = { version = "1.0", optional = true }
syn = { version = "2.0", optional = true }
+15
View File
@@ -0,0 +1,15 @@
# 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).
- **`arm64`**: Enables the ARM64 backend powered by [yaxpeax-arm](https://github.com/iximeow/yaxpeax-arm).
- **`bindings`**: Enables serialization and deserialization of objdiff data structures.
+11 -1
View File
@@ -1,6 +1,16 @@
use std::path::{Path, PathBuf};
#[cfg(feature = "any-arch")]
mod config_gen;
fn main() {
#[cfg(feature = "bindings")]
compile_protos();
#[cfg(feature = "any-arch")]
config_gen::generate_diff_config();
}
#[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());
+248
View File
@@ -0,0 +1,248 @@
{
"properties": [
{
"id": "functionRelocDiffs",
"type": "choice",
"default": "name_address",
"name": "Function relocation diffs",
"description": "How relocation targets will be diffed in the function view.",
"items": [
{
"value": "none",
"name": "None"
},
{
"value": "name_address",
"name": "Name or address"
},
{
"value": "data_value",
"name": "Data value"
},
{
"value": "all",
"name": "Name or address, data value"
}
]
},
{
"id": "spaceBetweenArgs",
"type": "boolean",
"default": true,
"name": "Space between args",
"description": "Adds a space between arguments in the diff output."
},
{
"id": "combineDataSections",
"type": "boolean",
"default": false,
"name": "Combine data sections",
"description": "Combines data sections with equal names."
},
{
"id": "arm.archVersion",
"type": "choice",
"default": "auto",
"name": "Architecture version",
"description": "ARM architecture version to use for disassembly.",
"items": [
{
"value": "auto",
"name": "Auto"
},
{
"value": "v4t",
"name": "ARMv4T (GBA)"
},
{
"value": "v5te",
"name": "ARMv5TE (DS)"
},
{
"value": "v6k",
"name": "ARMv6K (3DS)"
}
]
},
{
"id": "arm.unifiedSyntax",
"type": "boolean",
"default": false,
"name": "Unified syntax",
"description": "Disassemble as unified assembly language (UAL)."
},
{
"id": "arm.avRegisters",
"type": "boolean",
"default": false,
"name": "Use A/V registers",
"description": "Display R0-R3 as A1-A4 and R4-R11 as V1-V8."
},
{
"id": "arm.r9Usage",
"type": "choice",
"default": "generalPurpose",
"name": "Display R9 as",
"items": [
{
"value": "generalPurpose",
"name": "R9 or V6",
"description": "Use R9 as a general-purpose register."
},
{
"value": "sb",
"name": "SB (static base)",
"description": "Used for position-independent data (PID)."
},
{
"value": "tr",
"name": "TR (TLS register)",
"description": "Used for thread-local storage."
}
]
},
{
"id": "arm.slUsage",
"type": "boolean",
"default": false,
"name": "Display R10 as SL",
"description": "Used for explicit stack limits."
},
{
"id": "arm.fpUsage",
"type": "boolean",
"default": false,
"name": "Display R11 as FP",
"description": "Used for frame pointers."
},
{
"id": "arm.ipUsage",
"type": "boolean",
"default": false,
"name": "Display R12 as IP",
"description": "Used for interworking and long branches."
},
{
"id": "mips.abi",
"type": "choice",
"default": "auto",
"name": "ABI",
"description": "MIPS ABI to use for disassembly.",
"items": [
{
"value": "auto",
"name": "Auto"
},
{
"value": "o32",
"name": "O32"
},
{
"value": "n32",
"name": "N32"
},
{
"value": "n64",
"name": "N64"
}
]
},
{
"id": "mips.instrCategory",
"type": "choice",
"default": "auto",
"name": "Instruction category",
"description": "MIPS instruction category to use for disassembly.",
"items": [
{
"value": "auto",
"name": "Auto"
},
{
"value": "cpu",
"name": "CPU"
},
{
"value": "rsp",
"name": "RSP (N64)"
},
{
"value": "r3000gte",
"name": "R3000 GTE (PS1)"
},
{
"value": "r4000allegrex",
"name": "R4000 ALLEGREX (PSP)"
},
{
"value": "r5900",
"name": "R5900 EE (PS2)"
}
]
},
{
"id": "x86.formatter",
"type": "choice",
"default": "intel",
"name": "Format",
"description": "x86 disassembly syntax.",
"items": [
{
"value": "intel",
"name": "Intel"
},
{
"value": "gas",
"name": "AT&T"
},
{
"value": "nasm",
"name": "NASM"
},
{
"value": "masm",
"name": "MASM"
}
]
}
],
"groups": [
{
"id": "general",
"name": "General",
"properties": [
"functionRelocDiffs",
"spaceBetweenArgs",
"combineDataSections"
]
},
{
"id": "arm",
"name": "ARM",
"properties": [
"arm.archVersion",
"arm.unifiedSyntax",
"arm.avRegisters",
"arm.r9Usage",
"arm.slUsage",
"arm.fpUsage",
"arm.ipUsage"
]
},
{
"id": "mips",
"name": "MIPS",
"properties": [
"mips.abi",
"mips.instrCategory"
]
},
{
"id": "x86",
"name": "x86",
"properties": [
"x86.formatter"
]
}
]
}

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