Instruction disassembly in `dol diff`
When a function diff is detected in `dol diff`, objdiff-core is used to print a detailed view highlighting any differences. Resolves #28
This commit is contained in:
parent
d63111466b
commit
255123796e
|
@ -167,6 +167,12 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
@ -255,7 +261,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"strsim",
|
"strsim",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
|
@ -318,6 +324,31 @@ version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"crossterm_winapi",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"signal-hook",
|
||||||
|
"signal-hook-mio",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm_winapi"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
@ -336,13 +367,14 @@ checksum = "c2e06f9bce634a3c898eb1e5cb949ff63133cbb218af93cc9b38b31d6f3ea285"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "decomp-toolkit"
|
name = "decomp-toolkit"
|
||||||
version = "0.8.3"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"ar",
|
"ar",
|
||||||
"argp",
|
"argp",
|
||||||
"base16ct",
|
"base16ct",
|
||||||
"base64",
|
"base64",
|
||||||
|
"crossterm",
|
||||||
"cwdemangle",
|
"cwdemangle",
|
||||||
"enable-ansi-support",
|
"enable-ansi-support",
|
||||||
"filetime",
|
"filetime",
|
||||||
|
@ -455,7 +487,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.4.1",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -542,6 +574,12 @@ version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
|
@ -687,6 +725,16 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.21"
|
version = "0.4.21"
|
||||||
|
@ -736,6 +784,18 @@ dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multimap"
|
name = "multimap"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -855,8 +915,8 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-core"
|
name = "objdiff-core"
|
||||||
version = "1.0.0"
|
version = "2.0.0-alpha.3"
|
||||||
source = "git+https://github.com/encounter/objdiff?rev=8b36fa4fc657d9edf767797af9d394bb32898711#8b36fa4fc657d9edf767797af9d394bb32898711"
|
source = "git+https://github.com/encounter/objdiff?rev=a5a6a3928e392d5af5d92826e73b77e074b8788c#a5a6a3928e392d5af5d92826e73b77e074b8788c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
@ -870,6 +930,7 @@ dependencies = [
|
||||||
"ppc750cl",
|
"ppc750cl",
|
||||||
"serde",
|
"serde",
|
||||||
"similar",
|
"similar",
|
||||||
|
"strum",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -933,6 +994,29 @@ dependencies = [
|
||||||
"supports-color 2.1.0",
|
"supports-color 2.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.5.1",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.52.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "path-slash"
|
name = "path-slash"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -996,7 +1080,7 @@ version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
|
checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"getopts",
|
"getopts",
|
||||||
"memchr",
|
"memchr",
|
||||||
"unicase",
|
"unicase",
|
||||||
|
@ -1047,7 +1131,16 @@ version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1106,6 +1199,12 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.17"
|
version = "1.0.17"
|
||||||
|
@ -1127,6 +1226,12 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19d36299972b96b8ae7e8f04ecbf75fb41a27bf3781af00abcf57609774cb911"
|
checksum = "19d36299972b96b8ae7e8f04ecbf75fb41a27bf3781af00abcf57609774cb911"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.199"
|
version = "1.0.199"
|
||||||
|
@ -1213,6 +1318,36 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"signal-hook-registry",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-mio"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"signal-hook",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "similar"
|
name = "similar"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -1246,7 +1381,7 @@ version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4b19911debfb8c2fb1107bc6cb2d61868aaf53a988449213959bb1b5b1ed95f"
|
checksum = "b4b19911debfb8c2fb1107bc6cb2d61868aaf53a988449213959bb1b5b1ed95f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck 0.4.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.52",
|
||||||
|
@ -1258,6 +1393,28 @@ version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.26.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7993a8e3a9e88a00351486baae9522c91b123a088f76469e5bd5cc17198ea87"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "supports-color"
|
name = "supports-color"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
@ -1306,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
|
checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
"flate2",
|
"flate2",
|
||||||
"fnv",
|
"fnv",
|
||||||
|
@ -1497,6 +1654,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -1543,13 +1706,37 @@ dependencies = [
|
||||||
"windows_x86_64_msvc 0.42.2",
|
"windows_x86_64_msvc 0.42.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets",
|
"windows-targets 0.52.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1573,6 +1760,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
@ -1585,6 +1778,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
@ -1597,6 +1796,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
@ -1609,6 +1814,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
@ -1621,6 +1832,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
@ -1633,6 +1850,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
@ -1645,6 +1868,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
|
|
@ -3,13 +3,13 @@ name = "decomp-toolkit"
|
||||||
description = "Yet another GameCube/Wii decompilation toolkit."
|
description = "Yet another GameCube/Wii decompilation toolkit."
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
version = "0.8.3"
|
version = "0.9.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
repository = "https://github.com/encounter/decomp-toolkit"
|
repository = "https://github.com/encounter/decomp-toolkit"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
categories = ["command-line-utilities"]
|
categories = ["command-line-utilities"]
|
||||||
rust-version = "1.70.0"
|
rust-version = "1.73.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "dtk"
|
name = "dtk"
|
||||||
|
@ -29,6 +29,7 @@ ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "write_symbol_tab
|
||||||
argp = "0.3.0"
|
argp = "0.3.0"
|
||||||
base16ct = "0.2.0"
|
base16ct = "0.2.0"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
|
crossterm = "0.27.0"
|
||||||
cwdemangle = "1.0.0"
|
cwdemangle = "1.0.0"
|
||||||
enable-ansi-support = "0.2.1"
|
enable-ansi-support = "0.2.1"
|
||||||
filetime = "0.2.23"
|
filetime = "0.2.23"
|
||||||
|
@ -47,7 +48,7 @@ nintendo-lz = "0.1.3"
|
||||||
nodtool = { git = "https://github.com/encounter/nod-rs", rev = "03b83484cb17f94408fa0ef8e50d94951464d1b2" }
|
nodtool = { git = "https://github.com/encounter/nod-rs", rev = "03b83484cb17f94408fa0ef8e50d94951464d1b2" }
|
||||||
#nodtool = { path = "../nod-rs/nodtool" }
|
#nodtool = { path = "../nod-rs/nodtool" }
|
||||||
num_enum = "0.7.2"
|
num_enum = "0.7.2"
|
||||||
objdiff-core = { git = "https://github.com/encounter/objdiff", rev = "8b36fa4fc657d9edf767797af9d394bb32898711", features = ["ppc"] }
|
objdiff-core = { git = "https://github.com/encounter/objdiff", rev = "a5a6a3928e392d5af5d92826e73b77e074b8788c", features = ["ppc"] }
|
||||||
#objdiff-core = { path = "../objdiff/objdiff-core", features = ["ppc"] }
|
#objdiff-core = { path = "../objdiff/objdiff-core", features = ["ppc"] }
|
||||||
object = { version = "0.35.0", features = ["read_core", "std", "elf", "write_std"], default-features = false }
|
object = { version = "0.35.0", features = ["read_core", "std", "elf", "write_std"], default-features = false }
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
|
|
|
@ -45,6 +45,7 @@ use crate::{
|
||||||
write_splits_file, write_symbols_file, SectionAddressRef,
|
write_splits_file, write_symbols_file, SectionAddressRef,
|
||||||
},
|
},
|
||||||
dep::DepFile,
|
dep::DepFile,
|
||||||
|
diff::{calc_diff_ranges, print_diff, process_code},
|
||||||
dol::process_dol,
|
dol::process_dol,
|
||||||
elf::{process_elf, write_elf},
|
elf::{process_elf, write_elf},
|
||||||
file::{
|
file::{
|
||||||
|
@ -1503,6 +1504,31 @@ where P: AsRef<Path> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if two symbols' names match, allowing for differences in compiler-generated names,
|
||||||
|
/// like @1234 and @5678, or init$1234 and init$5678.
|
||||||
|
fn symbol_name_fuzzy_eq(a: &ObjSymbol, b: &ObjSymbol) -> bool {
|
||||||
|
if a.name == b.name {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Match e.g. @1234 and @5678
|
||||||
|
if a.name.starts_with('@') && b.name.starts_with('@') {
|
||||||
|
if let (Ok(_), Ok(_)) = (a.name[1..].parse::<u32>(), b.name[1..].parse::<u32>()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Match e.g. init$1234 and init$5678
|
||||||
|
if let (Some(a_dollar), Some(b_dollar)) = (a.name.rfind('$'), b.name.rfind('$')) {
|
||||||
|
if a.name[..a_dollar] == b.name[..b_dollar] {
|
||||||
|
if let (Ok(_), Ok(_)) =
|
||||||
|
(a.name[a_dollar + 1..].parse::<u32>(), b.name[b_dollar + 1..].parse::<u32>())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn diff(args: DiffArgs) -> Result<()> {
|
fn diff(args: DiffArgs) -> Result<()> {
|
||||||
log::info!("Loading {}", args.config.display());
|
log::info!("Loading {}", args.config.display());
|
||||||
let mut config_file = buf_reader(&args.config)?;
|
let mut config_file = buf_reader(&args.config)?;
|
||||||
|
@ -1545,7 +1571,7 @@ fn diff(args: DiffArgs) -> Result<()> {
|
||||||
});
|
});
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
if let Some((_, linked_sym)) = linked_sym {
|
if let Some((_, linked_sym)) = linked_sym {
|
||||||
if linked_sym.name.starts_with(&orig_sym.name) {
|
if symbol_name_fuzzy_eq(linked_sym, orig_sym) {
|
||||||
if linked_sym.size != orig_sym.size &&
|
if linked_sym.size != orig_sym.size &&
|
||||||
// TODO validate common symbol sizes
|
// TODO validate common symbol sizes
|
||||||
// (need to account for inflation bug)
|
// (need to account for inflation bug)
|
||||||
|
@ -1643,8 +1669,37 @@ fn diff(args: DiffArgs) -> Result<()> {
|
||||||
orig_sym.size,
|
orig_sym.size,
|
||||||
orig_sym.address
|
orig_sym.address
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Disassemble and print the diff using objdiff-core if it's a function
|
||||||
|
let mut handled = false;
|
||||||
|
if orig_sym.kind == ObjSymbolKind::Function
|
||||||
|
&& orig_section.kind == ObjSectionKind::Code
|
||||||
|
&& linked_sym.kind == ObjSymbolKind::Function
|
||||||
|
&& linked_section.kind == ObjSectionKind::Code
|
||||||
|
{
|
||||||
|
let config = objdiff_core::diff::DiffObjConfig::default();
|
||||||
|
let orig_code = process_code(&obj, orig_sym, orig_section, &config)?;
|
||||||
|
let linked_code = process_code(&linked_obj, linked_sym, linked_section, &config)?;
|
||||||
|
let (left_diff, right_diff) = objdiff_core::diff::code::diff_code(
|
||||||
|
&orig_code,
|
||||||
|
&linked_code,
|
||||||
|
objdiff_core::obj::SymbolRef::default(),
|
||||||
|
objdiff_core::obj::SymbolRef::default(),
|
||||||
|
&config,
|
||||||
|
)?;
|
||||||
|
let ranges = calc_diff_ranges(&left_diff.instructions, &right_diff.instructions, 3);
|
||||||
|
// objdiff may miss relocation differences, so fall back to printing the data diff
|
||||||
|
// if we don't have any instruction ranges to print
|
||||||
|
if !ranges.is_empty() {
|
||||||
|
print_diff(&left_diff, &right_diff, &ranges)?;
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !handled {
|
||||||
log::error!("Original: {}", hex::encode_upper(orig_data));
|
log::error!("Original: {}", hex::encode_upper(orig_data));
|
||||||
log::error!("Linked: {}", hex::encode_upper(linked_data));
|
log::error!("Linked: {}", hex::encode_upper(linked_data));
|
||||||
|
}
|
||||||
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use object::elf;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::obj::SymbolIndex;
|
use crate::obj::SymbolIndex;
|
||||||
|
@ -64,6 +65,47 @@ pub struct ObjReloc {
|
||||||
pub module: Option<u32>,
|
pub module: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ObjReloc {
|
||||||
|
/// Calculates the ELF r_offset and r_type for a relocation.
|
||||||
|
pub fn to_elf(&self, addr: u32) -> (u64, u32) {
|
||||||
|
let mut r_offset = addr as u64;
|
||||||
|
let r_type = match self.kind {
|
||||||
|
ObjRelocKind::Absolute => {
|
||||||
|
if r_offset & 3 == 0 {
|
||||||
|
elf::R_PPC_ADDR32
|
||||||
|
} else {
|
||||||
|
elf::R_PPC_UADDR32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObjRelocKind::PpcAddr16Hi => {
|
||||||
|
r_offset = (r_offset & !3) + 2;
|
||||||
|
elf::R_PPC_ADDR16_HI
|
||||||
|
}
|
||||||
|
ObjRelocKind::PpcAddr16Ha => {
|
||||||
|
r_offset = (r_offset & !3) + 2;
|
||||||
|
elf::R_PPC_ADDR16_HA
|
||||||
|
}
|
||||||
|
ObjRelocKind::PpcAddr16Lo => {
|
||||||
|
r_offset = (r_offset & !3) + 2;
|
||||||
|
elf::R_PPC_ADDR16_LO
|
||||||
|
}
|
||||||
|
ObjRelocKind::PpcRel24 => {
|
||||||
|
r_offset &= !3;
|
||||||
|
elf::R_PPC_REL24
|
||||||
|
}
|
||||||
|
ObjRelocKind::PpcRel14 => {
|
||||||
|
r_offset &= !3;
|
||||||
|
elf::R_PPC_REL14
|
||||||
|
}
|
||||||
|
ObjRelocKind::PpcEmbSda21 => {
|
||||||
|
r_offset &= !3;
|
||||||
|
elf::R_PPC_EMB_SDA21
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(r_offset, r_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ObjRelocations {
|
pub struct ObjRelocations {
|
||||||
relocations: BTreeMap<u32, ObjReloc>,
|
relocations: BTreeMap<u32, ObjReloc>,
|
||||||
|
|
|
@ -0,0 +1,384 @@
|
||||||
|
//! This includes helpers to convert between decomp-toolkit types and objdiff-core types.
|
||||||
|
//! Eventually it'd be nice to share [ObjInfo] and related types between decomp-toolkit and
|
||||||
|
//! objdiff-core to avoid this conversion.
|
||||||
|
use std::{
|
||||||
|
io::{stdout, Write},
|
||||||
|
ops::Range,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use crossterm::style::Color;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use objdiff_core::{
|
||||||
|
arch::{ObjArch, ProcessCodeResult},
|
||||||
|
diff::{
|
||||||
|
display::{display_diff, DiffText},
|
||||||
|
DiffObjConfig, ObjInsDiff, ObjInsDiffKind, ObjSymbolDiff,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use object::RelocationFlags;
|
||||||
|
|
||||||
|
use crate::obj::{ObjInfo, ObjReloc, ObjSection, ObjSymbol};
|
||||||
|
|
||||||
|
/// Processes code for a PPC function using objdiff-core.
|
||||||
|
/// Returns [ProcessCodeResult] for other objdiff-core functions to accept.
|
||||||
|
pub fn process_code(
|
||||||
|
obj: &ObjInfo,
|
||||||
|
symbol: &ObjSymbol,
|
||||||
|
section: &ObjSection,
|
||||||
|
config: &DiffObjConfig,
|
||||||
|
) -> Result<ProcessCodeResult> {
|
||||||
|
let arch = objdiff_core::arch::ppc::ObjArchPpc {};
|
||||||
|
let orig_relocs = section
|
||||||
|
.relocations
|
||||||
|
.range(symbol.address as u32..symbol.address as u32 + symbol.size as u32)
|
||||||
|
.map(|(a, r)| to_objdiff_reloc(obj, a, r))
|
||||||
|
.collect_vec();
|
||||||
|
let orig_data =
|
||||||
|
section.data_range(symbol.address as u32, symbol.address as u32 + symbol.size as u32)?;
|
||||||
|
arch.process_code(
|
||||||
|
symbol.address,
|
||||||
|
orig_data,
|
||||||
|
section.elf_index,
|
||||||
|
&orig_relocs,
|
||||||
|
&Default::default(),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates ranges of instructions to print, collapsing ranges of unchanged instructions.
|
||||||
|
/// (e.g. `grep -C`)
|
||||||
|
pub fn calc_diff_ranges(
|
||||||
|
left: &[ObjInsDiff],
|
||||||
|
right: &[ObjInsDiff],
|
||||||
|
collapse_lines: usize,
|
||||||
|
) -> Vec<Range<usize>> {
|
||||||
|
enum State {
|
||||||
|
None,
|
||||||
|
DiffStart(usize),
|
||||||
|
DiffRange(Range<usize>),
|
||||||
|
}
|
||||||
|
let mut state = State::None;
|
||||||
|
let mut idx = 0usize;
|
||||||
|
let mut left_iter = left.iter();
|
||||||
|
let mut right_iter = right.iter();
|
||||||
|
let mut ranges = Vec::new();
|
||||||
|
|
||||||
|
// Left and right should always have the same number of instructions
|
||||||
|
while let (Some(left_ins), Some(right_ins)) = (left_iter.next(), right_iter.next()) {
|
||||||
|
match &state {
|
||||||
|
State::None => {
|
||||||
|
if left_ins.kind != ObjInsDiffKind::None || right_ins.kind != ObjInsDiffKind::None {
|
||||||
|
state = State::DiffStart(idx.saturating_sub(collapse_lines));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
State::DiffStart(start) => {
|
||||||
|
if left_ins.kind == ObjInsDiffKind::None && right_ins.kind == ObjInsDiffKind::None {
|
||||||
|
state = State::DiffRange(*start..idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
State::DiffRange(range) => {
|
||||||
|
if left_ins.kind != ObjInsDiffKind::None || right_ins.kind != ObjInsDiffKind::None {
|
||||||
|
// Restart the range if we find a another diff
|
||||||
|
state = State::DiffStart(range.start);
|
||||||
|
} else if idx > range.end + collapse_lines * 2 {
|
||||||
|
// If we've gone collapse_lines * 2 instructions without a diff, add the range
|
||||||
|
ranges.push(range.start..range.end + collapse_lines);
|
||||||
|
state = State::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the last range
|
||||||
|
match state {
|
||||||
|
State::None => {}
|
||||||
|
State::DiffStart(start) => {
|
||||||
|
ranges.push(start..idx);
|
||||||
|
}
|
||||||
|
State::DiffRange(range) => {
|
||||||
|
ranges.push(range.start..idx.min(range.end + collapse_lines));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ranges
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_diff(
|
||||||
|
left: &ObjSymbolDiff,
|
||||||
|
right: &ObjSymbolDiff,
|
||||||
|
ranges: &[Range<usize>],
|
||||||
|
) -> Result<()> {
|
||||||
|
let (w, _) = crossterm::terminal::size()?;
|
||||||
|
let mut stdout = stdout();
|
||||||
|
for range in ranges {
|
||||||
|
if range.start > 0 {
|
||||||
|
crossterm::queue!(stdout, crossterm::style::Print("...\n"))?;
|
||||||
|
}
|
||||||
|
let left_ins = left.instructions[range.clone()].iter();
|
||||||
|
let right_ins = right.instructions[range.clone()].iter();
|
||||||
|
for (left_diff, right_diff) in left_ins.zip(right_ins) {
|
||||||
|
let left_line = print_line(left_diff, 0);
|
||||||
|
let right_line = print_line(right_diff, 0);
|
||||||
|
let mut x = 0;
|
||||||
|
let hw = (w as usize - 3) / 2;
|
||||||
|
for span in left_line {
|
||||||
|
if span.color != Color::Reset {
|
||||||
|
crossterm::queue!(stdout, crossterm::style::SetForegroundColor(span.color))?;
|
||||||
|
}
|
||||||
|
let len = (hw - x).min(span.text.len());
|
||||||
|
crossterm::queue!(stdout, crossterm::style::Print(&span.text[..len]))?;
|
||||||
|
x += len;
|
||||||
|
}
|
||||||
|
if x < hw {
|
||||||
|
crossterm::queue!(stdout, crossterm::style::Print(" ".repeat(hw - x)))?;
|
||||||
|
}
|
||||||
|
if left_diff.kind != ObjInsDiffKind::None || right_diff.kind != ObjInsDiffKind::None {
|
||||||
|
crossterm::queue!(
|
||||||
|
stdout,
|
||||||
|
crossterm::style::ResetColor,
|
||||||
|
crossterm::style::Print(" | ")
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
crossterm::queue!(
|
||||||
|
stdout,
|
||||||
|
crossterm::style::ResetColor,
|
||||||
|
crossterm::style::Print(" ")
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
x = hw + 3;
|
||||||
|
for span in right_line {
|
||||||
|
if span.color != Color::Reset {
|
||||||
|
crossterm::queue!(stdout, crossterm::style::SetForegroundColor(span.color))?;
|
||||||
|
}
|
||||||
|
let len = (w as usize - x).min(span.text.len());
|
||||||
|
crossterm::queue!(stdout, crossterm::style::Print(&span.text[..len]))?;
|
||||||
|
x += len;
|
||||||
|
}
|
||||||
|
crossterm::queue!(stdout, crossterm::style::ResetColor, crossterm::style::Print("\n"))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matches!(ranges.last().map(|r| r.end), Some(n) if n != left.instructions.len()) {
|
||||||
|
crossterm::queue!(stdout, crossterm::style::Print("...\n"))?;
|
||||||
|
}
|
||||||
|
stdout.flush()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const COLOR_ROTATION: [Color; 7] = [
|
||||||
|
Color::Magenta,
|
||||||
|
Color::Cyan,
|
||||||
|
Color::Green,
|
||||||
|
Color::Red,
|
||||||
|
Color::Yellow,
|
||||||
|
Color::Blue,
|
||||||
|
Color::Green,
|
||||||
|
];
|
||||||
|
|
||||||
|
struct Span {
|
||||||
|
text: String,
|
||||||
|
color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_line(ins_diff: &ObjInsDiff, base_addr: u64) -> Vec<Span> {
|
||||||
|
let mut line = Vec::new();
|
||||||
|
display_diff(ins_diff, base_addr, |text| -> Result<()> {
|
||||||
|
let label_text;
|
||||||
|
let mut base_color = match ins_diff.kind {
|
||||||
|
ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => {
|
||||||
|
Color::Grey
|
||||||
|
}
|
||||||
|
ObjInsDiffKind::Replace => Color::Cyan,
|
||||||
|
ObjInsDiffKind::Delete => Color::Red,
|
||||||
|
ObjInsDiffKind::Insert => Color::Green,
|
||||||
|
};
|
||||||
|
let mut pad_to = 0;
|
||||||
|
match text {
|
||||||
|
DiffText::Basic(text) => {
|
||||||
|
label_text = text.to_string();
|
||||||
|
}
|
||||||
|
DiffText::BasicColor(s, idx) => {
|
||||||
|
label_text = s.to_string();
|
||||||
|
base_color = COLOR_ROTATION[idx % COLOR_ROTATION.len()];
|
||||||
|
}
|
||||||
|
DiffText::Line(num) => {
|
||||||
|
label_text = format!("{num} ");
|
||||||
|
base_color = Color::DarkGrey;
|
||||||
|
pad_to = 5;
|
||||||
|
}
|
||||||
|
DiffText::Address(addr) => {
|
||||||
|
label_text = format!("{:x}:", addr);
|
||||||
|
pad_to = 5;
|
||||||
|
}
|
||||||
|
DiffText::Opcode(mnemonic, _op) => {
|
||||||
|
label_text = mnemonic.to_string();
|
||||||
|
if ins_diff.kind == ObjInsDiffKind::OpMismatch {
|
||||||
|
base_color = Color::Blue;
|
||||||
|
}
|
||||||
|
pad_to = 8;
|
||||||
|
}
|
||||||
|
DiffText::Argument(arg, diff) => {
|
||||||
|
label_text = arg.to_string();
|
||||||
|
if let Some(diff) = diff {
|
||||||
|
base_color = COLOR_ROTATION[diff.idx % COLOR_ROTATION.len()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DiffText::BranchDest(addr) => {
|
||||||
|
label_text = format!("{addr:x}");
|
||||||
|
}
|
||||||
|
DiffText::Symbol(sym) => {
|
||||||
|
let name = sym.demangled_name.as_ref().unwrap_or(&sym.name);
|
||||||
|
label_text = name.clone();
|
||||||
|
base_color = Color::White;
|
||||||
|
}
|
||||||
|
DiffText::Spacing(n) => {
|
||||||
|
line.push(Span { text: " ".repeat(n), color: Color::Reset });
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
DiffText::Eol => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let len = label_text.len();
|
||||||
|
line.push(Span { text: label_text, color: base_color });
|
||||||
|
if pad_to > len {
|
||||||
|
let pad = (pad_to - len) as u16;
|
||||||
|
line.push(Span { text: " ".repeat(pad as usize), color: Color::Reset });
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
line
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts an [ObjReloc] to an [objdiff_core::obj::ObjReloc].
|
||||||
|
fn to_objdiff_reloc(obj: &ObjInfo, address: u32, reloc: &ObjReloc) -> objdiff_core::obj::ObjReloc {
|
||||||
|
let target_symbol = &obj.symbols[reloc.target_symbol];
|
||||||
|
let target_section = target_symbol.section.map(|i| &obj.sections[i]);
|
||||||
|
let (r_offset, r_type) = reloc.to_elf(address);
|
||||||
|
objdiff_core::obj::ObjReloc {
|
||||||
|
flags: RelocationFlags::Elf { r_type },
|
||||||
|
address: r_offset,
|
||||||
|
target: to_objdiff_symbol(target_symbol, target_section, reloc.addend),
|
||||||
|
target_section: target_section.map(|s| s.name.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts an [ObjSymbol] to an [objdiff_core::obj::ObjSymbol].
|
||||||
|
fn to_objdiff_symbol(
|
||||||
|
symbol: &ObjSymbol,
|
||||||
|
section: Option<&ObjSection>,
|
||||||
|
addend: i64,
|
||||||
|
) -> objdiff_core::obj::ObjSymbol {
|
||||||
|
let mut flags = objdiff_core::obj::ObjSymbolFlagSet::default();
|
||||||
|
if symbol.flags.is_global() {
|
||||||
|
flags.0 |= objdiff_core::obj::ObjSymbolFlags::Global;
|
||||||
|
}
|
||||||
|
if symbol.flags.is_local() {
|
||||||
|
flags.0 |= objdiff_core::obj::ObjSymbolFlags::Local;
|
||||||
|
}
|
||||||
|
if symbol.flags.is_weak() {
|
||||||
|
flags.0 |= objdiff_core::obj::ObjSymbolFlags::Weak;
|
||||||
|
}
|
||||||
|
if symbol.flags.is_common() {
|
||||||
|
flags.0 |= objdiff_core::obj::ObjSymbolFlags::Common;
|
||||||
|
}
|
||||||
|
if symbol.flags.is_hidden() {
|
||||||
|
flags.0 |= objdiff_core::obj::ObjSymbolFlags::Hidden;
|
||||||
|
}
|
||||||
|
objdiff_core::obj::ObjSymbol {
|
||||||
|
name: symbol.name.clone(),
|
||||||
|
demangled_name: symbol.demangled_name.clone(),
|
||||||
|
address: symbol.address,
|
||||||
|
section_address: symbol.address - section.map(|s| s.address).unwrap_or(0),
|
||||||
|
size: symbol.size,
|
||||||
|
size_known: symbol.size_known,
|
||||||
|
flags,
|
||||||
|
addend,
|
||||||
|
virtual_address: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
macro_rules! ins_diff {
|
||||||
|
($kind:expr) => {
|
||||||
|
ObjInsDiff {
|
||||||
|
ins: None,
|
||||||
|
kind: $kind,
|
||||||
|
branch_from: None,
|
||||||
|
branch_to: None,
|
||||||
|
arg_diff: vec![],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_diff_ranges() {
|
||||||
|
// Test single range
|
||||||
|
let diff = vec![
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
];
|
||||||
|
assert_eq!(calc_diff_ranges(&diff, &diff, 3), vec![0..10]);
|
||||||
|
|
||||||
|
// Test combining ranges
|
||||||
|
let diff = vec![
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
// This should be combined with the previous range,
|
||||||
|
// since it's within collapse_lines * 2 + 1 instructions
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
];
|
||||||
|
assert_eq!(calc_diff_ranges(&diff, &diff, 3), vec![0..15]);
|
||||||
|
|
||||||
|
// Test separating ranges
|
||||||
|
let diff = vec![
|
||||||
|
// start range 1
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
// end range 1
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
// start range 2
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::Replace),
|
||||||
|
ins_diff!(ObjInsDiffKind::None),
|
||||||
|
// end range 2
|
||||||
|
];
|
||||||
|
assert_eq!(calc_diff_ranges(&diff, &diff, 3), vec![0..7, 9..15]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -727,41 +727,8 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||||
}
|
}
|
||||||
writer.write_align_relocation();
|
writer.write_align_relocation();
|
||||||
ensure!(writer.len() == out_section.rela_offset);
|
ensure!(writer.len() == out_section.rela_offset);
|
||||||
for (reloc_address, reloc) in section.relocations.iter() {
|
for (addr, reloc) in section.relocations.iter() {
|
||||||
let mut r_offset = reloc_address as u64;
|
let (r_offset, r_type) = reloc.to_elf(addr);
|
||||||
let r_type = match reloc.kind {
|
|
||||||
ObjRelocKind::Absolute => {
|
|
||||||
if r_offset & 3 == 0 {
|
|
||||||
elf::R_PPC_ADDR32
|
|
||||||
} else {
|
|
||||||
elf::R_PPC_UADDR32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ObjRelocKind::PpcAddr16Hi => {
|
|
||||||
r_offset = (r_offset & !3) + 2;
|
|
||||||
elf::R_PPC_ADDR16_HI
|
|
||||||
}
|
|
||||||
ObjRelocKind::PpcAddr16Ha => {
|
|
||||||
r_offset = (r_offset & !3) + 2;
|
|
||||||
elf::R_PPC_ADDR16_HA
|
|
||||||
}
|
|
||||||
ObjRelocKind::PpcAddr16Lo => {
|
|
||||||
r_offset = (r_offset & !3) + 2;
|
|
||||||
elf::R_PPC_ADDR16_LO
|
|
||||||
}
|
|
||||||
ObjRelocKind::PpcRel24 => {
|
|
||||||
r_offset &= !3;
|
|
||||||
elf::R_PPC_REL24
|
|
||||||
}
|
|
||||||
ObjRelocKind::PpcRel14 => {
|
|
||||||
r_offset &= !3;
|
|
||||||
elf::R_PPC_REL14
|
|
||||||
}
|
|
||||||
ObjRelocKind::PpcEmbSda21 => {
|
|
||||||
r_offset &= !3;
|
|
||||||
elf::R_PPC_EMB_SDA21
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let r_sym = symbol_map[reloc.target_symbol]
|
let r_sym = symbol_map[reloc.target_symbol]
|
||||||
.ok_or_else(|| anyhow!("Relocation against stripped symbol"))?;
|
.ok_or_else(|| anyhow!("Relocation against stripped symbol"))?;
|
||||||
writer.write_relocation(true, &Rel { r_offset, r_sym, r_type, r_addend: reloc.addend });
|
writer.write_relocation(true, &Rel { r_offset, r_sym, r_type, r_addend: reloc.addend });
|
||||||
|
|
|
@ -6,6 +6,7 @@ pub mod bin2c;
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod dep;
|
pub mod dep;
|
||||||
|
pub mod diff;
|
||||||
pub mod dol;
|
pub mod dol;
|
||||||
pub mod dwarf;
|
pub mod dwarf;
|
||||||
pub mod elf;
|
pub mod elf;
|
||||||
|
|
Loading…
Reference in New Issue