Compare commits

...

8 Commits

Author SHA1 Message Date
Robin Avery fee1804ce4
Merge cf15d3b7e7 into aecb078b2a 2024-03-13 22:30:32 -04:00
Luke Street aecb078b2a ci: Update sccache-action version 2024-03-13 18:34:28 -06:00
Luke Street a5668b484b Update all dependencies 2024-03-13 18:20:46 -06:00
Luke Street ef41e393d4 Resolve dependency advisories 2024-03-04 18:19:08 -07:00
Luke Street 20e42a499a Rework .splitmeta, now .note.split
Uses actual ELF .note format, which is
more standard and handled better by mwld.
2024-03-04 18:06:21 -07:00
Luke Street c39795ae2c Use actual decomp.me host 2024-03-04 18:03:32 -07:00
Luke Street 49ee9b44aa Remove "Algorithm" menu item 2024-03-04 18:03:20 -07:00
Robin Avery cf15d3b7e7
objdiff-cli report: Support data sections 2024-03-01 22:03:44 -05:00
11 changed files with 454 additions and 375 deletions

View File

@ -118,7 +118,7 @@ jobs:
sudo apt-get update
sudo apt-get -y install ${{ matrix.packages }}
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.3
uses: mozilla-actions/sccache-action@v0.0.4
- name: Checkout
uses: actions/checkout@v4
- name: Setup Rust toolchain

258
Cargo.lock generated
View File

@ -175,9 +175,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.80"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
[[package]]
name = "arboard"
@ -195,37 +195,6 @@ dependencies = [
"x11rb",
]
[[package]]
name = "argh"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
dependencies = [
"argh_derive",
"argh_shared",
]
[[package]]
name = "argh_derive"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
dependencies = [
"argh_shared",
"proc-macro2",
"quote",
"syn 2.0.51",
]
[[package]]
name = "argh_shared"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
dependencies = [
"serde",
]
[[package]]
name = "argp"
version = "0.3.0"
@ -483,7 +452,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -518,7 +487,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -592,7 +561,7 @@ dependencies = [
"cfg-if",
"libc",
"miniz_oxide",
"object",
"object 0.32.2",
"rustc-demangle",
]
@ -713,9 +682,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.15.3"
version = "3.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
[[package]]
name = "bytemuck"
@ -734,7 +703,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -824,10 +793,11 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.88"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
dependencies = [
"jobserver",
"libc",
]
@ -1189,12 +1159,9 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
[[package]]
name = "cwdemangle"
version = "0.1.6"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c251bc5553377b3dc85c7b9b3955cfc2eb5a7b5544cf65adc2d53c2a4c2f4162"
dependencies = [
"argh",
]
checksum = "c2e06f9bce634a3c898eb1e5cb949ff63133cbb218af93cc9b38b31d6f3ea285"
[[package]]
name = "deranged"
@ -1513,7 +1480,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -1534,7 +1501,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -1545,7 +1512,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -1721,9 +1688,9 @@ dependencies = [
[[package]]
name = "flagset"
version = "0.4.4"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a7e408202050813e6f1d9addadcaafef3dca7530c7ddfb005d4081cce6779"
checksum = "cdeb3aa5e95cf9aabc17f060cfa0ced7b83f042390760ca53bf09df9968acaa1"
[[package]]
name = "flate2"
@ -1799,7 +1766,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -1910,7 +1877,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -2350,9 +2317,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.2.3"
version = "2.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
dependencies = [
"equivalent",
"hashbrown",
@ -2467,10 +2434,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
version = "0.3.68"
name = "jobserver"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
@ -2596,9 +2572,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.20"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "lru"
@ -2713,9 +2689,9 @@ dependencies = [
[[package]]
name = "mio"
version = "0.8.10"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
@ -2867,16 +2843,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "num_enum"
version = "0.5.11"
@ -2916,7 +2882,7 @@ dependencies = [
"proc-macro-crate 3.1.0",
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -3056,7 +3022,7 @@ dependencies = [
"log",
"memmap2",
"num-traits",
"object",
"object 0.34.0",
"ppc750cl",
"rabbitizer",
"semver",
@ -3103,7 +3069,7 @@ dependencies = [
"tempfile",
"thiserror",
"time",
"toml 0.8.10",
"toml 0.8.11",
"tracing-subscriber",
"tracing-wasm",
"vergen",
@ -3120,6 +3086,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "object"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7090bae93f8585aad99e595b7073c5de9ba89fbd6b4e9f0cdd7a10177273ac8"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
@ -3149,7 +3124,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -3408,9 +3383,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.78"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-ident",
]
@ -3462,9 +3437,9 @@ dependencies = [
[[package]]
name = "rabbitizer"
version = "1.9.1"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51f468c45304a333c45ceeb1fca08f63ad37a21a918ad16982beebfcde9529fa"
checksum = "4f3097d22d421d6fe2ca7266eb625f3859a41c1bfebcf19d7ace140aada47551"
dependencies = [
"cc",
"glob",
@ -3634,9 +3609,9 @@ checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
[[package]]
name = "reqwest"
version = "0.11.24"
version = "0.11.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2"
dependencies = [
"base64",
"bytes",
@ -3950,7 +3925,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -3972,7 +3947,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -4228,7 +4203,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -4253,9 +4228,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.51"
version = "2.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c"
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
dependencies = [
"proc-macro2",
"quote",
@ -4312,22 +4287,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.57"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.57"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -4423,7 +4398,6 @@ dependencies = [
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
"socket2 0.5.6",
"windows-sys 0.48.0",
@ -4474,14 +4448,14 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.10"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290"
checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.22.6",
"toml_edit 0.22.7",
]
[[package]]
@ -4517,9 +4491,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.6"
version = "0.22.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6"
checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992"
dependencies = [
"indexmap",
"serde",
@ -4553,7 +4527,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]
@ -4787,9 +4761,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -4797,16 +4771,16 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
"wasm-bindgen-shared",
]
@ -4824,9 +4798,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -4834,22 +4808,22 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "wayland-backend"
@ -4962,9 +4936,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.68"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -5161,7 +5135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core",
"windows-targets 0.52.3",
"windows-targets 0.52.4",
]
[[package]]
@ -5170,7 +5144,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.3",
"windows-targets 0.52.4",
]
[[package]]
@ -5234,7 +5208,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.3",
"windows-targets 0.52.4",
]
[[package]]
@ -5269,17 +5243,17 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm 0.52.3",
"windows_aarch64_msvc 0.52.3",
"windows_i686_gnu 0.52.3",
"windows_i686_msvc 0.52.3",
"windows_x86_64_gnu 0.52.3",
"windows_x86_64_gnullvm 0.52.3",
"windows_x86_64_msvc 0.52.3",
"windows_aarch64_gnullvm 0.52.4",
"windows_aarch64_msvc 0.52.4",
"windows_i686_gnu 0.52.4",
"windows_i686_msvc 0.52.4",
"windows_x86_64_gnu 0.52.4",
"windows_x86_64_gnullvm 0.52.4",
"windows_x86_64_msvc 0.52.4",
]
[[package]]
@ -5296,9 +5270,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
@ -5314,9 +5288,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
@ -5332,9 +5306,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
@ -5350,9 +5324,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
@ -5368,9 +5342,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
@ -5386,9 +5360,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
@ -5404,15 +5378,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.3"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
name = "winit"
version = "0.29.11"
version = "0.29.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "272be407f804517512fdf408f0fe6c067bf24659a913c61af97af176bfd5aa92"
checksum = "2b9d7047a2a569d5a81e3be098dcd8153759909b127477f4397e03cf1006d90a"
dependencies = [
"ahash",
"android-activity",
@ -5735,7 +5709,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
"syn 2.0.52",
]
[[package]]

View File

@ -14,18 +14,18 @@ publish = false
build = "build.rs"
[dependencies]
anyhow = "1.0.80"
anyhow = "1.0.81"
argp = "0.3.0"
crossterm = "0.27.0"
enable-ansi-support = "0.2.1"
log = "0.4.20"
log = "0.4.21"
objdiff-core = { path = "../objdiff-core", features = ["all"] }
ratatui = "0.26.1"
rayon = "1.8.1"
rayon = "1.9.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.111"
serde_json = "1.0.114"
supports-color = "3.0.0"
time = { version = "0.3.31", features = ["formatting", "local-offset"] }
time = { version = "0.3.34", features = ["formatting", "local-offset"] }
tracing = "0.1.40"
tracing-attributes = "0.1.27"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }

View File

@ -41,7 +41,7 @@ pub struct GenerateArgs {
/// Output JSON file
output: Option<PathBuf>,
#[argp(switch, short = 'd')]
/// Deduplicate global and weak symbols
/// Deduplicate global and weak symbols (runs single-threaded)
deduplicate: bool,
}
@ -63,9 +63,12 @@ pub struct ChangesArgs {
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
struct Report {
fuzzy_match_percent: f32,
total_size: u64,
matched_size: u64,
matched_size_percent: f32,
total_code: u64,
matched_code: u64,
matched_code_percent: f32,
total_data: u64,
matched_data: u64,
matched_data_percent: f32,
total_functions: u32,
matched_functions: u32,
matched_functions_percent: f32,
@ -76,8 +79,10 @@ struct Report {
struct ReportUnit {
name: String,
fuzzy_match_percent: f32,
total_size: u64,
matched_size: u64,
total_code: u64,
matched_code: u64,
total_data: u64,
matched_data: u64,
total_functions: u32,
matched_functions: u32,
#[serde(skip_serializing_if = "Option::is_none")]
@ -86,11 +91,12 @@ struct ReportUnit {
module_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
module_id: Option<u32>,
functions: Vec<ReportFunction>,
sections: Vec<ReportItem>,
functions: Vec<ReportItem>,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
struct ReportFunction {
struct ReportItem {
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
demangled_name: Option<String>,
@ -159,21 +165,29 @@ fn generate(args: GenerateArgs) -> Result<()> {
report.units = units.into_iter().flatten().collect();
}
for unit in &report.units {
report.fuzzy_match_percent += unit.fuzzy_match_percent * unit.total_size as f32;
report.total_size += unit.total_size;
report.matched_size += unit.matched_size;
report.fuzzy_match_percent += unit.fuzzy_match_percent * unit.total_code as f32;
report.total_code += unit.total_code;
report.matched_code += unit.matched_code;
report.total_data += unit.total_data;
report.matched_data += unit.matched_data;
report.total_functions += unit.total_functions;
report.matched_functions += unit.matched_functions;
}
if report.total_size == 0 {
if report.total_code == 0 {
report.fuzzy_match_percent = 100.0;
} else {
report.fuzzy_match_percent /= report.total_size as f32;
report.fuzzy_match_percent /= report.total_code as f32;
}
report.matched_size_percent = if report.total_size == 0 {
report.matched_code_percent = if report.total_code == 0 {
100.0
} else {
report.matched_size as f32 / report.total_size as f32 * 100.0
report.matched_code as f32 / report.total_code as f32 * 100.0
};
report.matched_data_percent = if report.total_data == 0 {
100.0
} else {
report.matched_data as f32 / report.total_data as f32 * 100.0
};
report.matched_functions_percent = if report.total_functions == 0 {
100.0
@ -215,7 +229,6 @@ fn report_object(
}
_ => {}
}
// println!("Checking {}", object.name());
let mut target = object
.target_path
.as_ref()
@ -239,10 +252,39 @@ fn report_object(
..Default::default()
};
let obj = target.as_ref().or(base.as_ref()).unwrap();
for section in target
.as_ref()
.map_or(&vec![], |o| &o.sections)
.iter()
.chain(base.as_ref().map_or(&vec![], |o| &o.sections))
.filter(|o| o.match_percent != 0.0)
{
// TODO
println!("{}: {}", section.name, section.match_percent);
}
for section in &obj.sections {
if section.kind != ObjSectionKind::Code {
continue;
unit.sections.push(ReportItem {
name: section.name.clone(),
demangled_name: None,
fuzzy_match_percent: section.match_percent,
size: section.size,
address: section.virtual_address,
});
match section.kind {
ObjSectionKind::Data | ObjSectionKind::Bss => {
unit.total_data += section.size;
// section.data_diff
if section.match_percent == 100.0 {
unit.matched_data += section.size;
}
continue;
}
ObjSectionKind::Code => (),
}
for symbol in &section.symbols {
if symbol.size == 0 {
continue;
@ -265,11 +307,11 @@ fn report_object(
}
});
unit.fuzzy_match_percent += match_percent * symbol.size as f32;
unit.total_size += symbol.size;
unit.total_code += symbol.size;
if match_percent == 100.0 {
unit.matched_size += symbol.size;
unit.matched_code += symbol.size;
}
unit.functions.push(ReportFunction {
unit.functions.push(ReportItem {
name: symbol.name.clone(),
demangled_name: symbol.demangled_name.clone(),
size: symbol.size,
@ -282,10 +324,10 @@ fn report_object(
unit.total_functions += 1;
}
}
if unit.total_size == 0 {
if unit.total_code == 0 {
unit.fuzzy_match_percent = 100.0;
} else {
unit.fuzzy_match_percent /= unit.total_size as f32;
unit.fuzzy_match_percent /= unit.total_code as f32;
}
Ok(Some(unit))
}
@ -300,9 +342,12 @@ struct Changes {
#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
struct ChangeInfo {
fuzzy_match_percent: f32,
total_size: u64,
matched_size: u64,
matched_size_percent: f32,
total_code: u64,
matched_code: u64,
matched_code_percent: f32,
total_data: u64,
matched_data: u64,
matched_data_percent: f32,
total_functions: u32,
matched_functions: u32,
matched_functions_percent: f32,
@ -312,9 +357,12 @@ impl From<&Report> for ChangeInfo {
fn from(report: &Report) -> Self {
Self {
fuzzy_match_percent: report.fuzzy_match_percent,
total_size: report.total_size,
matched_size: report.matched_size,
matched_size_percent: report.matched_size_percent,
total_code: report.total_code,
matched_code: report.matched_code,
matched_code_percent: report.matched_code_percent,
total_data: report.total_data,
matched_data: report.matched_data,
matched_data_percent: report.matched_data_percent,
total_functions: report.total_functions,
matched_functions: report.matched_functions,
matched_functions_percent: report.matched_functions_percent,
@ -326,12 +374,19 @@ impl From<&ReportUnit> for ChangeInfo {
fn from(value: &ReportUnit) -> Self {
Self {
fuzzy_match_percent: value.fuzzy_match_percent,
total_size: value.total_size,
matched_size: value.matched_size,
matched_size_percent: if value.total_size == 0 {
total_code: value.total_code,
matched_code: value.matched_code,
matched_code_percent: if value.total_code == 0 {
100.0
} else {
value.matched_size as f32 / value.total_size as f32 * 100.0
value.matched_code as f32 / value.total_code as f32 * 100.0
},
total_data: value.total_data,
matched_data: value.matched_data,
matched_data_percent: if value.total_data == 0 {
100.0
} else {
value.matched_data as f32 / value.total_data as f32 * 100.0
},
total_functions: value.total_functions,
matched_functions: value.matched_functions,
@ -349,24 +404,25 @@ struct ChangeUnit {
name: String,
from: Option<ChangeInfo>,
to: Option<ChangeInfo>,
functions: Vec<ChangeFunction>,
sections: Vec<ChangeItem>,
functions: Vec<ChangeItem>,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
struct ChangeFunction {
struct ChangeItem {
name: String,
from: Option<ChangeFunctionInfo>,
to: Option<ChangeFunctionInfo>,
from: Option<ChangeItemInfo>,
to: Option<ChangeItemInfo>,
}
#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
struct ChangeFunctionInfo {
struct ChangeItemInfo {
fuzzy_match_percent: f32,
size: u64,
}
impl From<&ReportFunction> for ChangeFunctionInfo {
fn from(value: &ReportFunction) -> Self {
impl From<&ReportItem> for ChangeItemInfo {
fn from(value: &ReportItem) -> Self {
Self { fuzzy_match_percent: value.fuzzy_match_percent, size: value.size }
}
}
@ -380,54 +436,18 @@ fn changes(args: ChangesArgs) -> Result<()> {
units: vec![],
};
for prev_unit in &previous.units {
let prev_unit_info = ChangeInfo::from(prev_unit);
let curr_unit = current.units.iter().find(|u| u.name == prev_unit.name);
let sections = process_items(prev_unit, curr_unit, |u| &u.sections);
let functions = process_items(prev_unit, curr_unit, |u| &u.functions);
let prev_unit_info = ChangeInfo::from(prev_unit);
let curr_unit_info = curr_unit.map(ChangeInfo::from);
let mut functions = vec![];
if let Some(curr_unit) = curr_unit {
for prev_func in &prev_unit.functions {
let prev_func_info = ChangeFunctionInfo::from(prev_func);
let curr_func = curr_unit.functions.iter().find(|f| f.name == prev_func.name);
let curr_func_info = curr_func.map(ChangeFunctionInfo::from);
if let Some(curr_func_info) = curr_func_info {
if prev_func_info != curr_func_info {
functions.push(ChangeFunction {
name: prev_func.name.clone(),
from: Some(prev_func_info),
to: Some(curr_func_info),
});
}
} else {
functions.push(ChangeFunction {
name: prev_func.name.clone(),
from: Some(prev_func_info),
to: None,
});
}
}
for curr_func in &curr_unit.functions {
if !prev_unit.functions.iter().any(|f| f.name == curr_func.name) {
functions.push(ChangeFunction {
name: curr_func.name.clone(),
from: None,
to: Some(ChangeFunctionInfo::from(curr_func)),
});
}
}
} else {
for prev_func in &prev_unit.functions {
functions.push(ChangeFunction {
name: prev_func.name.clone(),
from: Some(ChangeFunctionInfo::from(prev_func)),
to: None,
});
}
}
if !functions.is_empty() || !matches!(&curr_unit_info, Some(v) if v == &prev_unit_info) {
changes.units.push(ChangeUnit {
name: prev_unit.name.clone(),
from: Some(prev_unit_info),
to: curr_unit_info,
sections,
functions,
});
}
@ -438,15 +458,8 @@ fn changes(args: ChangesArgs) -> Result<()> {
name: curr_unit.name.clone(),
from: None,
to: Some(ChangeInfo::from(curr_unit)),
functions: curr_unit
.functions
.iter()
.map(|f| ChangeFunction {
name: f.name.clone(),
from: None,
to: Some(ChangeFunctionInfo::from(f)),
})
.collect(),
sections: process_new_items(&curr_unit.sections),
functions: process_new_items(&curr_unit.functions),
});
}
}
@ -464,6 +477,63 @@ fn changes(args: ChangesArgs) -> Result<()> {
Ok(())
}
fn process_items<F: Fn(&ReportUnit) -> &Vec<ReportItem>>(
prev_unit: &ReportUnit,
curr_unit: Option<&ReportUnit>,
getter: F,
) -> Vec<ChangeItem> {
let prev_items = getter(prev_unit);
let mut items = vec![];
if let Some(curr_unit) = curr_unit {
let curr_items = getter(curr_unit);
for prev_func in prev_items {
let prev_func_info = ChangeItemInfo::from(prev_func);
let curr_func = curr_items.iter().find(|f| f.name == prev_func.name);
let curr_func_info = curr_func.map(ChangeItemInfo::from);
if let Some(curr_func_info) = curr_func_info {
if prev_func_info != curr_func_info {
items.push(ChangeItem {
name: prev_func.name.clone(),
from: Some(prev_func_info),
to: Some(curr_func_info),
});
}
} else {
items.push(ChangeItem {
name: prev_func.name.clone(),
from: Some(prev_func_info),
to: None,
});
}
}
for curr_func in curr_items {
if !prev_items.iter().any(|f| f.name == curr_func.name) {
items.push(ChangeItem {
name: curr_func.name.clone(),
from: None,
to: Some(ChangeItemInfo::from(curr_func)),
});
}
}
} else {
for prev_func in prev_items {
items.push(ChangeItem {
name: prev_func.name.clone(),
from: Some(ChangeItemInfo::from(prev_func)),
to: None,
});
}
}
items
}
fn process_new_items(items: &[ReportItem]) -> Vec<ChangeItem> {
items
.iter()
.map(|f| ChangeItem { name: f.name.clone(), from: None, to: Some(ChangeItemInfo::from(f)) })
.collect()
}
fn read_report(path: &Path) -> Result<Report> {
serde_json::from_reader(BufReader::new(
File::open(path).with_context(|| format!("Failed to open {}", path.display()))?,

View File

@ -20,23 +20,23 @@ mips = ["any-arch", "rabbitizer"]
ppc = ["any-arch", "cwdemangle", "ppc750cl"]
[dependencies]
anyhow = "1.0.80"
anyhow = "1.0.81"
byteorder = "1.5.0"
cwdemangle = { version = "0.1.6", optional = true }
cwdemangle = { version = "1.0.0", optional = true }
filetime = "0.2.23"
flagset = "0.4.4"
flagset = "0.4.5"
gimli = { version = "0.28.1", default-features = false, features = ["read-all"], optional = true }
log = "0.4.20"
memmap2 = "0.9.3"
log = "0.4.21"
memmap2 = "0.9.4"
num-traits = "0.2.18"
object = { version = "0.32.2", features = ["read_core", "std", "elf"], default-features = false }
object = { version = "0.34.0", features = ["read_core", "std", "elf"], default-features = false }
ppc750cl = { git = "https://github.com/encounter/ppc750cl", rev = "4a2bbbc6f84dcb76255ab6f3595a8d4a0ce96618", optional = true }
rabbitizer = { version = "1.8.1", optional = true }
rabbitizer = { version = "1.9.2", optional = true }
serde = { version = "1", features = ["derive"] }
similar = { version = "2.4.0", default-features = false }
# config
globset = { version = "0.4.14", features = ["serde1"] }
semver = "1.0.21"
serde_json = "1.0.111"
serde_yaml = "0.9.30"
semver = "1.0.22"
serde_json = "1.0.114"
serde_yaml = "0.9.32"

View File

@ -5,8 +5,8 @@ use byteorder::{BigEndian, ReadBytesExt};
use filetime::FileTime;
use flagset::Flags;
use object::{
elf, Architecture, File, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget,
SectionIndex, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
elf, Architecture, File, Object, ObjectSection, ObjectSymbol, RelocationFlags,
RelocationTarget, SectionIndex, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
};
use crate::obj::{
@ -230,21 +230,22 @@ fn relocations_by_section(
.context("Failed to locate relocation target symbol")?,
_ => bail!("Unhandled relocation target: {:?}", reloc.target()),
};
let kind = match reloc.kind() {
RelocationKind::Absolute => ObjRelocKind::Absolute,
RelocationKind::Elf(kind) => match arch {
let kind = match reloc.flags() {
RelocationFlags::Elf { r_type } => match arch {
#[cfg(feature = "ppc")]
ObjArchitecture::PowerPc => match kind {
ObjArchitecture::PowerPc => match r_type {
elf::R_PPC_ADDR32 | elf::R_PPC_UADDR32 => ObjRelocKind::Absolute,
elf::R_PPC_ADDR16_LO => ObjRelocKind::PpcAddr16Lo,
elf::R_PPC_ADDR16_HI => ObjRelocKind::PpcAddr16Hi,
elf::R_PPC_ADDR16_HA => ObjRelocKind::PpcAddr16Ha,
elf::R_PPC_REL24 => ObjRelocKind::PpcRel24,
elf::R_PPC_REL14 => ObjRelocKind::PpcRel14,
elf::R_PPC_EMB_SDA21 => ObjRelocKind::PpcEmbSda21,
_ => bail!("Unhandled PPC relocation type: {kind}"),
_ => bail!("Unhandled PPC relocation type: {r_type}"),
},
#[cfg(feature = "mips")]
ObjArchitecture::Mips => match kind {
ObjArchitecture::Mips => match r_type {
elf::R_MIPS_32 => ObjRelocKind::Absolute,
elf::R_MIPS_26 => ObjRelocKind::Mips26,
elf::R_MIPS_HI16 => ObjRelocKind::MipsHi16,
elf::R_MIPS_LO16 => ObjRelocKind::MipsLo16,
@ -252,10 +253,10 @@ fn relocations_by_section(
elf::R_MIPS_CALL16 => ObjRelocKind::MipsCall16,
elf::R_MIPS_GPREL16 => ObjRelocKind::MipsGpRel16,
elf::R_MIPS_GPREL32 => ObjRelocKind::MipsGpRel32,
_ => bail!("Unhandled MIPS relocation type: {kind}"),
_ => bail!("Unhandled MIPS relocation type: {r_type}"),
},
},
_ => bail!("Unhandled relocation type: {:?}", reloc.kind()),
flags => bail!("Unhandled relocation flags: {:?}", flags),
};
let target_section = match symbol.section() {
SymbolSection::Common => Some(".comm".to_string()),
@ -328,13 +329,12 @@ fn line_info(obj_file: &File<'_>) -> Result<Option<BTreeMap<u64, u64>>> {
// DWARF 2+
#[cfg(feature = "dwarf")]
{
use std::borrow::Cow;
let dwarf_cow = gimli::Dwarf::load(|id| {
Ok::<_, gimli::Error>(
obj_file
.section_by_name(id.name())
.and_then(|section| section.uncompressed_data().ok())
.unwrap_or(Cow::Borrowed(&[][..])),
.unwrap_or(std::borrow::Cow::Borrowed(&[][..])),
)
})?;
let endian = match obj_file.endianness() {
@ -407,13 +407,7 @@ pub fn has_function(obj_path: &Path, symbol_name: &str) -> Result<bool> {
fn split_meta(obj_file: &File<'_>) -> Result<Option<SplitMeta>> {
Ok(if let Some(section) = obj_file.section_by_name(SPLITMETA_SECTION) {
if section.size() != 0 {
let data = section.uncompressed_data()?;
let mut reader = data.as_ref();
Some(SplitMeta::from_reader(&mut reader, obj_file.endianness(), obj_file.is_64())?)
} else {
None
}
Some(SplitMeta::from_section(section, obj_file.endianness(), obj_file.is_64())?)
} else {
None
})

View File

@ -188,7 +188,7 @@ pub struct ObjSymbol {
pub size_known: bool,
pub flags: ObjSymbolFlagSet,
pub addend: i64,
/// Original virtual address (from .splitmeta section)
/// Original virtual address (from .note.split section)
pub virtual_address: Option<u64>,
// Diff
@ -215,7 +215,7 @@ pub struct ObjInfo {
pub common: Vec<ObjSymbol>,
/// Line number info (.line or .debug_line section)
pub line_info: Option<BTreeMap<u64, u64>>,
/// Split object metadata (.splitmeta section)
/// Split object metadata (.note.split section)
pub split_meta: Option<SplitMeta>,
}

View File

@ -1,13 +1,10 @@
use std::{
io,
io::{Read, Write},
};
use std::{io, io::Write};
use object::{elf::SHT_LOUSER, Endian};
use object::{elf::SHT_NOTE, Endian, ObjectSection};
pub const SPLITMETA_SECTION: &str = ".splitmeta";
// Use the same section type as .mwcats.* so the linker ignores it
pub const SHT_SPLITMETA: u32 = SHT_LOUSER + 0x4A2A82C2;
pub const SPLITMETA_SECTION: &str = ".note.split";
pub const SHT_SPLITMETA: u32 = SHT_NOTE;
pub const ELF_NOTE_SPLIT: &[u8] = b"Split";
/// This is used to store metadata about the source of an object file,
/// such as the original virtual addresses and the tool that wrote it.
@ -24,79 +21,50 @@ pub struct SplitMeta {
pub virtual_addresses: Option<Vec<u64>>,
}
/**
* .splitmeta section format:
* - Magic: "SPMD"
* - Section: Magic: 4 bytes, Data size: 4 bytes, Data: variable
* Section size can be used to skip unknown sections
* - Repeat section until EOF
* Endianness matches the object file
*
* Sections:
* - Generator: Magic: "GENR", Data size: 4 bytes, Data: UTF-8 string (no null terminator)
* - Virtual addresses: Magic: "VIRT", Data size: 4 bytes, Data: array
* Data is u32 array for 32-bit objects, u64 array for 64-bit objects
* Count is size / 4 (32-bit) or size / 8 (64-bit)
*/
const SPLIT_META_MAGIC: [u8; 4] = *b"SPMD";
const GENERATOR_MAGIC: [u8; 4] = *b"GENR";
const MODULE_NAME_MAGIC: [u8; 4] = *b"MODN";
const MODULE_ID_MAGIC: [u8; 4] = *b"MODI";
const VIRTUAL_ADDRESS_MAGIC: [u8; 4] = *b"VIRT";
const NT_SPLIT_GENERATOR: u32 = u32::from_be_bytes(*b"GENR");
const NT_SPLIT_MODULE_NAME: u32 = u32::from_be_bytes(*b"MODN");
const NT_SPLIT_MODULE_ID: u32 = u32::from_be_bytes(*b"MODI");
const NT_SPLIT_VIRTUAL_ADDRESSES: u32 = u32::from_be_bytes(*b"VIRT");
impl SplitMeta {
pub fn from_reader<E, R>(reader: &mut R, e: E, is_64: bool) -> io::Result<Self>
where
E: Endian,
R: Read + ?Sized,
{
let mut magic = [0; 4];
reader.read_exact(&mut magic)?;
if magic != SPLIT_META_MAGIC {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid split metadata magic"));
}
pub fn from_section<E>(section: object::Section, e: E, is_64: bool) -> io::Result<Self>
where E: Endian {
let mut result = SplitMeta::default();
loop {
let mut magic = [0; 4];
match reader.read_exact(&mut magic) {
Ok(()) => {}
Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => break,
Err(e) => return Err(e),
};
let mut size_bytes = [0; 4];
reader.read_exact(&mut size_bytes)?;
let size = e.read_u32_bytes(size_bytes);
let mut data = vec![0; size as usize];
reader.read_exact(&mut data)?;
match magic {
GENERATOR_MAGIC => {
let string = String::from_utf8(data)
let data = section.uncompressed_data().map_err(object_io_error)?;
let mut iter = NoteIterator::new(data.as_ref(), section.align(), e, is_64)?;
while let Some(note) = iter.next(e)? {
if note.name != ELF_NOTE_SPLIT {
continue;
}
match note.n_type {
NT_SPLIT_GENERATOR => {
let string = String::from_utf8(note.desc.to_vec())
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
result.generator = Some(string);
}
MODULE_NAME_MAGIC => {
let string = String::from_utf8(data)
NT_SPLIT_MODULE_NAME => {
let string = String::from_utf8(note.desc.to_vec())
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
result.module_name = Some(string);
}
MODULE_ID_MAGIC => {
let id = e.read_u32_bytes(data.as_slice().try_into().map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "Invalid module ID size")
})?);
result.module_id = Some(id);
NT_SPLIT_MODULE_ID => {
result.module_id =
Some(e.read_u32_bytes(note.desc.try_into().map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "Invalid module ID size")
})?));
}
VIRTUAL_ADDRESS_MAGIC => {
NT_SPLIT_VIRTUAL_ADDRESSES => {
let vec = if is_64 {
let mut vec = vec![0u64; data.len() / 8];
for i in 0..vec.len() {
vec[i] = e.read_u64_bytes(data[i * 8..(i + 1) * 8].try_into().unwrap());
let mut vec = vec![0u64; note.desc.len() / 8];
for (i, v) in vec.iter_mut().enumerate() {
*v =
e.read_u64_bytes(note.desc[i * 8..(i + 1) * 8].try_into().unwrap());
}
vec
} else {
let mut vec = vec![0u64; data.len() / 4];
for i in 0..vec.len() {
vec[i] = e.read_u32_bytes(data[i * 4..(i + 1) * 4].try_into().unwrap())
let mut vec = vec![0u64; note.desc.len() / 4];
for (i, v) in vec.iter_mut().enumerate() {
*v = e.read_u32_bytes(note.desc[i * 4..(i + 1) * 4].try_into().unwrap())
as u64;
}
vec
@ -116,32 +84,29 @@ impl SplitMeta {
E: Endian,
W: Write + ?Sized,
{
writer.write_all(&SPLIT_META_MAGIC)?;
if let Some(generator) = &self.generator {
writer.write_all(&GENERATOR_MAGIC)?;
writer.write_all(&e.write_u32_bytes(generator.len() as u32))?;
write_note_header(writer, e, NT_SPLIT_GENERATOR, generator.len())?;
writer.write_all(generator.as_bytes())?;
align_to_4(writer, generator.len())?;
}
if let Some(module_name) = &self.module_name {
writer.write_all(&MODULE_NAME_MAGIC)?;
writer.write_all(&e.write_u32_bytes(module_name.len() as u32))?;
write_note_header(writer, e, NT_SPLIT_MODULE_NAME, module_name.len())?;
writer.write_all(module_name.as_bytes())?;
align_to_4(writer, module_name.len())?;
}
if let Some(module_id) = self.module_id {
writer.write_all(&MODULE_ID_MAGIC)?;
writer.write_all(&e.write_u32_bytes(4))?;
write_note_header(writer, e, NT_SPLIT_MODULE_ID, 4)?;
writer.write_all(&e.write_u32_bytes(module_id))?;
}
if let Some(virtual_addresses) = &self.virtual_addresses {
writer.write_all(&VIRTUAL_ADDRESS_MAGIC)?;
let count = virtual_addresses.len() as u32;
let count = virtual_addresses.len();
let size = if is_64 { count * 8 } else { count * 4 };
write_note_header(writer, e, NT_SPLIT_VIRTUAL_ADDRESSES, size)?;
if is_64 {
writer.write_all(&e.write_u32_bytes(count * 8))?;
for &addr in virtual_addresses {
writer.write_all(&e.write_u64_bytes(addr))?;
}
} else {
writer.write_all(&e.write_u32_bytes(count * 4))?;
for &addr in virtual_addresses {
writer.write_all(&e.write_u32_bytes(addr as u32))?;
}
@ -151,19 +116,102 @@ impl SplitMeta {
}
pub fn write_size(&self, is_64: bool) -> usize {
let mut size = 4;
let mut size = 0;
if let Some(generator) = self.generator.as_deref() {
size += 8 + generator.len();
size += NOTE_HEADER_SIZE + generator.len();
}
if let Some(module_name) = self.module_name.as_deref() {
size += 8 + module_name.len();
size += NOTE_HEADER_SIZE + module_name.len();
}
if self.module_id.is_some() {
size += 12;
size += NOTE_HEADER_SIZE + 4;
}
if let Some(virtual_addresses) = self.virtual_addresses.as_deref() {
size += 8 + if is_64 { 8 } else { 4 } * virtual_addresses.len();
size += NOTE_HEADER_SIZE + if is_64 { 8 } else { 4 } * virtual_addresses.len();
}
size
}
}
/// Convert an object::read::Error to an io::Error.
fn object_io_error(err: object::read::Error) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, err)
}
/// An ELF note entry.
struct Note<'data> {
n_type: u32,
name: &'data [u8],
desc: &'data [u8],
}
/// object::read::elf::NoteIterator is awkward to use generically,
/// so wrap it in our own iterator.
enum NoteIterator<'data, E>
where E: Endian
{
B32(object::read::elf::NoteIterator<'data, object::elf::FileHeader32<E>>),
B64(object::read::elf::NoteIterator<'data, object::elf::FileHeader64<E>>),
}
impl<'data, E> NoteIterator<'data, E>
where E: Endian
{
fn new(data: &'data [u8], align: u64, e: E, is_64: bool) -> io::Result<Self> {
Ok(if is_64 {
NoteIterator::B64(
object::read::elf::NoteIterator::new(e, align, data).map_err(object_io_error)?,
)
} else {
NoteIterator::B32(
object::read::elf::NoteIterator::new(e, align as u32, data)
.map_err(object_io_error)?,
)
})
}
fn next(&mut self, e: E) -> io::Result<Option<Note<'data>>> {
match self {
NoteIterator::B32(iter) => Ok(iter.next().map_err(object_io_error)?.map(|note| Note {
n_type: note.n_type(e),
name: note.name(),
desc: note.desc(),
})),
NoteIterator::B64(iter) => Ok(iter.next().map_err(object_io_error)?.map(|note| Note {
n_type: note.n_type(e),
name: note.name(),
desc: note.desc(),
})),
}
}
}
fn align_to_4<W: Write + ?Sized>(writer: &mut W, len: usize) -> io::Result<()> {
const ALIGN_BYTES: &[u8] = &[0; 4];
if len % 4 != 0 {
writer.write_all(&ALIGN_BYTES[..4 - len % 4])?;
}
Ok(())
}
// ELF note format:
// Name Size | 4 bytes (integer)
// Desc Size | 4 bytes (integer)
// Type | 4 bytes (usually interpreted as an integer)
// Name | variable size, padded to a 4 byte boundary
// Desc | variable size, padded to a 4 byte boundary
const NOTE_HEADER_SIZE: usize = 12 + ((ELF_NOTE_SPLIT.len() + 4) & !3);
fn write_note_header<E, W>(writer: &mut W, e: E, kind: u32, desc_len: usize) -> io::Result<()>
where
E: Endian,
W: Write + ?Sized,
{
writer.write_all(&e.write_u32_bytes(ELF_NOTE_SPLIT.len() as u32 + 1))?; // Name Size
writer.write_all(&e.write_u32_bytes(desc_len as u32))?; // Desc Size
writer.write_all(&e.write_u32_bytes(kind))?; // Type
writer.write_all(ELF_NOTE_SPLIT)?; // Name
writer.write_all(&[0; 1])?; // Null terminator
align_to_4(writer, ELF_NOTE_SPLIT.len() + 1)?;
Ok(())
}

View File

@ -23,11 +23,11 @@ wgpu = ["eframe/wgpu"]
wsl = []
[dependencies]
anyhow = "1.0.80"
anyhow = "1.0.81"
bytes = "1.5.0"
cfg-if = "1.0.0"
const_format = "0.2.32"
cwdemangle = "0.1.6"
cwdemangle = "1.0.0"
dirs = "5.0.1"
eframe = { version = "0.26.2", features = ["persistence"] }
egui = "0.26.2"
@ -36,31 +36,31 @@ filetime = "0.2.23"
float-ord = "0.3.2"
font-kit = "0.12.0"
globset = { version = "0.4.14", features = ["serde1"] }
log = "0.4.20"
log = "0.4.21"
notify = "6.1.1"
objdiff-core = { path = "../objdiff-core", features = ["all"] }
png = "0.17.11"
png = "0.17.13"
pollster = "0.3.0"
rfd = { version = "0.14.0" } #, default-features = false, features = ['xdg-portal']
ron = "0.8.1"
semver = "1.0.21"
semver = "1.0.22"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.111"
serde_yaml = "0.9.30"
serde_json = "1.0.114"
serde_yaml = "0.9.32"
shell-escape = "0.1.5"
tempfile = "3.9.0"
thiserror = "1.0.56"
time = { version = "0.3.31", features = ["formatting", "local-offset"] }
toml = "0.8.8"
tempfile = "3.10.1"
thiserror = "1.0.58"
time = { version = "0.3.34", features = ["formatting", "local-offset"] }
toml = "0.8.11"
# For Linux static binaries, use rustls
[target.'cfg(target_os = "linux")'.dependencies]
reqwest = { version = "0.11.23", default-features = false, features = ["blocking", "json", "multipart", "rustls"] }
reqwest = { version = "0.11.26", default-features = false, features = ["blocking", "json", "multipart", "rustls"] }
self_update = { version = "0.39.0", default-features = false, features = ["rustls"] }
# For all other platforms, use native TLS
[target.'cfg(not(target_os = "linux"))'.dependencies]
reqwest = { version = "0.11.23", default-features = false, features = ["blocking", "json", "multipart", "default-tls"] }
reqwest = { version = "0.11.26", default-features = false, features = ["blocking", "json", "multipart", "default-tls"] }
self_update = "0.39.0"
[target.'cfg(windows)'.dependencies]
@ -83,5 +83,5 @@ console_error_panic_hook = "0.1.7"
tracing-wasm = "0.2"
[build-dependencies]
anyhow = "1.0.79"
anyhow = "1.0.81"
vergen = { version = "8.3.1", features = ["build", "cargo", "git", "gitcl"] }

View File

@ -47,7 +47,6 @@ pub struct ViewState {
pub show_appearance_config: bool,
pub show_demangle: bool,
pub show_project_config: bool,
pub show_diff_options: bool,
pub show_debug: bool,
}
@ -409,7 +408,6 @@ impl eframe::App for App {
show_appearance_config,
show_demangle,
show_project_config,
show_diff_options,
show_debug,
} = view_state;
@ -463,10 +461,6 @@ impl eframe::App for App {
}
});
ui.menu_button("Diff Options", |ui| {
if ui.button("Algorithm…").clicked() {
*show_diff_options = !*show_diff_options;
ui.close_menu();
}
let mut config = config.write().unwrap();
let response = ui
.checkbox(&mut config.rebuild_on_changes, "Rebuild on changes")

View File

@ -67,8 +67,7 @@ struct CreateScratchResponse {
pub claim_token: String,
}
const API_HOST: &str = "http://127.0.0.1:8000";
const WEB_HOST: &str = "http://localhost:8080";
const API_HOST: &str = "https://decomp.me";
fn run_create_scratch(
status: &JobContext,
@ -121,7 +120,7 @@ fn run_create_scratch(
return Err(anyhow!("Failed to create scratch: {}", response.text()?));
}
let body: CreateScratchResponse = response.json().context("Failed to parse response")?;
let scratch_url = format!("{WEB_HOST}/scratch/{}/claim?token={}", body.slug, body.claim_token);
let scratch_url = format!("{API_HOST}/scratch/{}/claim?token={}", body.slug, body.claim_token);
update_status(status, "Complete".to_string(), 2, 2, &cancel)?;
Ok(Box::from(CreateScratchResult { scratch_url }))