elfx86exts-0.6.2/.cargo_vcs_info.json0000644000000001360000000000100130610ustar { "git": { "sha1": "1c92372ebcd18662169698e5361c96270f752f7e" }, "path_in_vcs": "" }elfx86exts-0.6.2/.gitattributes000064400000000000000000000000141046102023000145370ustar 00000000000000* text=auto elfx86exts-0.6.2/.github/dependabot.yml000064400000000000000000000001771046102023000160460ustar 00000000000000version: 2 updates: - package-ecosystem: cargo directory: "/" schedule: interval: daily open-pull-requests-limit: 10 elfx86exts-0.6.2/.gitignore000064400000000000000000000000121046102023000136320ustar 00000000000000/target/ elfx86exts-0.6.2/CHANGELOG.md000064400000000000000000000070021046102023000134610ustar 00000000000000# elfx86exts 0.6.2 (2023-10-22) - Fix excessive memory consumption (@HanabishiRecca, #2, #90, #173). For a long time, we have known that this program can consume surprisingly large amounts of memory when processing large programs (well, and small ones too). It turns out that if we simply disassemble one instruction at a time instead of in bulk, not only do the memory requirements go way down, but the program is much faster too! Thanks again to @HanabishiRecca for finally solving this longstanding issue. # elfx86exts 0.6.1 (2023-10-21) - Ignore invalid instructions when parsing the executable (@HanabishiRecca, #171, #172). This allows `elfx86exts` to handle some executables which have regions of "junk" data between functions, such as ones created by [mold]. Thank you to @HanabishiRecca for reporting, investigating, and solving this issue! [mold]: https://github.com/rui314/mold # elfx86exts 0.6.0 (2023-10-12) In the ongoing effort to make the name of this tool ever more inaccurate, @jasonmccampbell has added preliminary support for ARM64 (aarch64) binaries in #166! The program will now automatically detect the CPU architecture of the binary under analysis, and choose the X86 or ARM64 analysis path depending on what it sees. (Or if the binary is for some other architecture, it will bail out.) Since the last release, @dargor also added some names for AMD CPU generations and tidied up some of the related information (#88). There are also some general updates to the dependencies from @pkgw. # elfx86exts 0.5.0 (2021-10-18) This release updates this tool to do its disassembly using [capstone 0.10][cs] and [object 0.27][obj]. In at least some cases, the previous release based on capstone 0.7 was giving seriously incorrect output (see [#66], filed by [@rowanworth]). [cs]: https://github.com/capstone-rust/capstone-rs [obj]: https://github.com/gimli-rs/object [#66]: https://github.com/pkgw/elfx86exts/issues/66 [@rowanworth]: https://github.com/rowanworth # elfx86exts 0.4.3 (2020-09-01) - Bump to Rust 2018 edition - ci: use cranko's new binary-packaging helper and publish Rust packages to crates.io upon deployment - Numerous dependency updates since last release on crates.io # elfx86exts 0.4.2 (2020-08-28) - Add a Windows build ... mainly to demonstrate Cranko's usage in a build pipeline that includes Windows builds. # elfx86exts 0.4.1 (2020-08-28) - Migrate to Cranko for versioning and release workflow. # 0.4.0 (2020 May 11) - Update dependencies, including to [capstone](https://crates.io/crates/capstone) 0.7.0. - Fix a missing space in the `--help` output (@bjmoran, [#29](https://github.com/pkgw/elfx86exts/pull/29)) # 0.3.0 (2018 Oct 16) - The tool will now print out its best guess as to the minimum Intel CPU generation needed to run the analyzed binary, based on an internal table of which extensions were introduced in which model. This is a bit approximate because the evolution is not strictly linear. Thanks to [@apjanke](https://github.com/apjanke) for [the contribution](https://github.com/pkgw/elfx86exts/pull/10)! Bumping the minor version because this alters the output format. - Update dependencies, including to [capstone](https://crates.io/crates/capstone) 0.5.0. # 0.2.0 (2018 Jan 23) - Support MachO/PE binaries as well! Now the name of this tool is super misleading! Oh well, it was worth it. Thanks to [@reuben](https://github.com/reuben) for [the contribution](https://github.com/pkgw/elfx86exts/pull/1)! # 0.1.0 (2017 Sep 29) - Initial release. elfx86exts-0.6.2/Cargo.lock0000644000000362630000000000100110460ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "anstream" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys", ] [[package]] name = "assert_cmd" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" dependencies = [ "anstyle", "bstr", "doc-comment", "predicates", "predicates-core", "predicates-tree", "wait-timeout", ] [[package]] name = "bstr" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" dependencies = [ "memchr", "regex-automata", "serde", ] [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "capstone" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1097e608594dad3bad608295567f757742b883606fe150faf7a9740b849730d8" dependencies = [ "capstone-sys", "libc", ] [[package]] name = "capstone-sys" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7f651d5ec4c2a2e6c508f2c8032655003cd728ec85663e9796616990e25b5a" dependencies = [ "cc", "libc", ] [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.38", ] [[package]] name = "clap_lex" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "doc-comment" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elfx86exts" version = "0.6.2" dependencies = [ "assert_cmd", "capstone", "clap", "escargot", "memmap", "object", ] [[package]] name = "escargot" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "768064bd3a0e2bedcba91dc87ace90beea91acc41b6a01a3ca8e9aa8827461bf" dependencies = [ "log", "once_cell", "serde", "serde_json", ] [[package]] name = "flate2" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "itertools" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "libc" version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" dependencies = [ "libc", "winapi", ] [[package]] name = "miniz_oxide" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] name = "object" version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "flate2", "memchr", "ruzstd", ] [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "predicates" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dfc28575c2e3f19cb3c73b93af36460ae898d426eba6fc15b9bd2a5220758a0" dependencies = [ "anstyle", "difflib", "itertools", "predicates-core", ] [[package]] name = "predicates-core" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" [[package]] name = "predicates-tree" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" dependencies = [ "predicates-core", "termtree", ] [[package]] name = "proc-macro2" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "regex-automata" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "465c6fc0621e4abc4187a2bda0937bfd4f722c2730b29562e19689ea796c9a4b" [[package]] name = "ruzstd" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" dependencies = [ "byteorder", "thiserror-core", "twox-hash", ] [[package]] name = "ryu" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "serde" version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", "syn 2.0.38", ] [[package]] name = "serde_json" version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "termtree" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror-core" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" dependencies = [ "thiserror-core-impl", ] [[package]] name = "thiserror-core-impl" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "twox-hash" version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "static_assertions", ] [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "wait-timeout" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ "libc", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" elfx86exts-0.6.2/Cargo.toml0000644000000024440000000000100110630ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "elfx86exts" version = "0.6.2" authors = ["Peter Williams "] description = "Decode x86 binaries (ELF or MachO) and print out which instruction set extensions they use." homepage = "https://github.com/pkgw/elfx86exts" documentation = "https://docs.rs/crate/elfx86exts" readme = "README.md" keywords = [ "disassembly", "ELF", "MachO", "x86", ] categories = [ "command-line-utilities", "development-tools::debugging", "parsing", ] license = "MIT" repository = "https://github.com/pkgw/elfx86exts" [dependencies.capstone] version = "^0.11" [dependencies.clap] version = "^4" features = ["derive"] [dependencies.memmap] version = "^0.7.0" [dependencies.object] version = "^0.32" [dev-dependencies.assert_cmd] version = "2.0" [dev-dependencies.escargot] version = "0.5" elfx86exts-0.6.2/Cargo.toml.orig000064400000000000000000000014221046102023000145370ustar 00000000000000# Copyright 2017-2022 Peter Williams # Licensed under the MIT License. [package] name = "elfx86exts" version = "0.6.2" authors = ["Peter Williams "] description = "Decode x86 binaries (ELF or MachO) and print out which instruction set extensions they use." homepage = "https://github.com/pkgw/elfx86exts" repository = "https://github.com/pkgw/elfx86exts" documentation = "https://docs.rs/crate/elfx86exts" readme = "README.md" keywords = ["disassembly", "ELF", "MachO", "x86"] categories = ["command-line-utilities", "development-tools::debugging", "parsing"] license = "MIT" edition = "2018" [dependencies] capstone = "^0.11" clap = { version = "^4", features = ["derive"] } object = "^0.32" memmap = "^0.7.0" [dev-dependencies] assert_cmd = "2.0" escargot = "0.5" elfx86exts-0.6.2/LICENSE000064400000000000000000000020661046102023000126620ustar 00000000000000The MIT License (MIT) Copyright (c) 2013 Thomas Park Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. elfx86exts-0.6.2/README.md000064400000000000000000000047121046102023000131340ustar 00000000000000# elfx86exts Disassemble a binary and print out which instruction set extensions it uses. Despite the utterly misleading name, this tool supports ELF and MachO binaries, and perhaps other formats as well, and has preliminary support for ARM64 as well as X86/64. It used to be a lot more limited! I have no idea what I'm doing here, but it seems to work. There are several Rust crates that make this pretty easy to do. ## Change Log See [the CHANGELOG on the release branch](https://github.com/pkgw/elfx86exts/blob/release/CHANGELOG.md) for news about what has changed between releases. ## Installation ### Prepackaged This tool is installable through a few package managers: - [Arch Linux AUR](https://aur.archlinux.org/packages/elfx86exts/) - [conda-forge](https://anaconda.org/conda-forge/elfx86exts) (Linux only right now) If you are interested in packaging `elfx86exts` in a new packaging system, or have already done so, please submit a PR to add it to this list. ### Compiling the Latest Release If a package is not available, in most cases it will be straightforward to build `elfx86exts` yourself. Dependencies are: - A [Rust](https://www.rust-lang.org/) toolchain - The [Capstone](http://www.capstone-engine.org/) disassembly engine Both of these dependencies are available through a wide variety of package managers. Once they’re set up, you don’t even need to check out this repository to install the latest release. Simply run: ``` cargo install elfx86exts ``` … and the tool will be installed in your Cargo binary directory, usually `~/.cargo/bin/`. When using this method, you need to add the `--force` flag to upgrade from one version to the next. ### Compiling the Code From Git This is hardly any more difficult than the above. Check out this repository, then run: ``` cargo install --path . ``` To develop the program, use the `cargo build` and `cargo run` commands. For more information, see [The Cargo Book](https://doc.rust-lang.org/cargo/index.html). ## Contributions Contributions are welcome! Please submit PRs against this repository, or file issues for discussion. The only important rule is that all participants are expected to abide by the spirit of a standard [Contributor Covenant code of conduct](https://www.contributor-covenant.org/). All contributions will be assumed to be licensed under the terms described below unless you explicitly state otherwise. ## Licensing Licensed under the [MIT License](https://opensource.org/licenses/MIT). elfx86exts-0.6.2/ci/azure-build-and-test.yml000064400000000000000000000054221046102023000167320ustar 00000000000000parameters: - name: canaryBuild type: boolean default: false - name: primaryBuild type: boolean default: false steps: - checkout: self - bash: | set -ex rustup set profile minimal rustup component remove --toolchain=$TOOLCHAIN rust-docs || echo "already removed" rustup update --no-self-update $TOOLCHAIN rustup default $TOOLCHAIN # Helpful versions rustup -V rustc -Vv cargo -V displayName: Setup Rust - bash: | d="$(mktemp -d /tmp/cranko.XXXXXX)" cd "$d" curl --proto '=https' --tlsv1.2 -sSf https://pkgw.github.io/cranko/fetch-latest.sh | sh echo "##vso[task.prependpath]$d" displayName: Install latest Cranko (not Windows) condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) - pwsh: | $d = Join-Path $Env:Temp cranko-$(New-Guid) [void][System.IO.Directory]::CreateDirectory($d) cd $d [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 iex ((New-Object System.Net.WebClient).DownloadString('https://pkgw.github.io/cranko/fetch-latest.ps1')) echo "##vso[task.prependpath]$d" displayName: Install latest Cranko (Windows) condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - bash: | cranko release-workflow apply-versions displayName: "cranko release-workflow apply-versions" - bash: cargo build --all --release displayName: "cargo build" - bash: cargo test --all --release displayName: "cargo test" # For non-canary builds, export artifacts. - ${{ if eq(parameters.canaryBuild, false) }}: - bash: | git add . cranko release-workflow commit git show HEAD displayName: Make release commit - bash: | artifact_dir="$(Build.ArtifactStagingDirectory)/binary-$TARGET" mkdir -p "$artifact_dir" cranko cargo package-released-binaries -t $TARGET $artifact_dir -- build --release displayName: Package binaries - task: PublishPipelineArtifact@1 displayName: Publish packaged binary artifact(s) inputs: targetPath: '$(Build.ArtifactStagingDirectory)/binary-$(TARGET)' artifactName: binary-$(TARGET) # If, further, we're the primary build on the `rc` branch, export ours as the # canonical release commit. - ${{ if and(eq(parameters.primaryBuild, true), eq(variables['Build.SourceBranchName'], 'rc')) }}: - bash: | artifact_dir="$(Build.ArtifactStagingDirectory)/git-release" mkdir -p "$artifact_dir" git bundle create "$artifact_dir/release.bundle" origin/master..HEAD displayName: "Generate and Bundle release commit" - task: PublishPipelineArtifact@1 displayName: Publish git bundle artifact inputs: targetPath: '$(Build.ArtifactStagingDirectory)/git-release' artifactName: git-release elfx86exts-0.6.2/ci/azure-ci-cd.yml000064400000000000000000000054511046102023000150770ustar 00000000000000# Main pipeline spec for CI/CD on Azure Pipelines. trigger: branches: include: - master - rc # We cannot use Pipeline's matrixing framework because only it works with # *runtime variables*, while we want to use templates with *parameters* which # are evaluated at *compile time* only. By coding our matrixing data as # top-level parameters, we can use them in compile-time template evaluation # (`${{ }}` expressions) to achieve a matrixing effect. Only a few *variables* # can be used at compile time: see "Available in templates?" in the table at: # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml # This is why some platform-specific steps use `condition:` terms rather than # compile-time `${{ if }}:` statements. parameters: - name: builds type: object default: - name: linux_stable vmImage: ubuntu-20.04 params: primaryBuild: true vars: TARGET: x86_64-unknown-linux-gnu TOOLCHAIN: stable - name: linux_beta vmImage: ubuntu-20.04 params: canaryBuild: true vars: TARGET: x86_64-unknown-linux-gnu TOOLCHAIN: beta - name: linux_nightly vmImage: ubuntu-20.04 params: canaryBuild: true vars: TARGET: x86_64-unknown-linux-gnu TOOLCHAIN: nightly - name: windows_msvc vmImage: windows-2019 params: {} vars: TARGET: x86_64-pc-windows-msvc TOOLCHAIN: stable-x86_64-pc-windows-msvc - name: windows_gnu vmImage: windows-2019 params: {} vars: TARGET: x86_64-pc-windows-gnu TOOLCHAIN: stable-x86_64-pc-windows-gnu - name: macos vmImage: macos-11 params: {} vars: TARGET: x86_64-apple-darwin TOOLCHAIN: stable stages: - stage: BuildAndTest jobs: - ${{ each build in parameters.builds }}: - job: ${{ format('build_{0}', build.name) }} pool: vmImage: ${{ build.vmImage }} steps: - template: azure-build-and-test.yml parameters: ${{ insert }}: ${{ build.params }} variables: ${{ insert }}: ${{ build.vars }} # If all of those succeed and we're not in a pull request, run the deployment # pipeline. If we're specifically on the `rc` branch, this will finalize any # releases. - stage: Deploy condition: and(succeeded('BuildAndTest'), not(eq(variables['build.reason'], 'PullRequest'))) jobs: - deployment: Deploy environment: Deploy displayName: Deploy pool: vmImage: ubuntu-20.04 variables: - group: Deployment Credentials strategy: runOnce: deploy: steps: - template: azure-deployment.yml parameters: rcBuild: ${{ eq(variables['Build.SourceBranchName'], 'rc') }} elfx86exts-0.6.2/ci/azure-deployment.yml000064400000000000000000000032421046102023000162740ustar 00000000000000# Deployment pipeline, run when all CI tests pass on `master` or `rc`. parameters: - name: rcBuild type: boolean default: false steps: - bash: | cd $(Pipeline.Workspace) mkdir binary-collection cp binary-*/* binary-collection/ displayName: Collect release artifacts - publish: $(Pipeline.Workspace)/binary-collection displayName: Publish release artifacts artifact: binary-collection # if we're on the `rc` branch, the release has been fully vetted and the # internal artifacts have been gathered -- time to lock in a new `release` # commit and invoke the full release processes. - ${{ if eq(parameters.rcBuild, true) }}: - checkout: self - bash: | d="$(mktemp -d /tmp/cranko.XXXXXX)" cd "$d" curl --proto '=https' --tlsv1.2 -sSf https://pkgw.github.io/cranko/fetch-latest.sh | sh echo "##vso[task.prependpath]$d" displayName: Install latest Cranko - bash: | git switch -c release git pull --ff-only $(Pipeline.Workspace)/git-release/release.bundle git show cranko release-workflow tag displayName: Prepare release commit and tags - bash: | cranko github install-credential-helper git push --tags origin release:release displayName: Update release branch env: GITHUB_TOKEN: $(GITHUB_TOKEN) - bash: | cranko cargo foreach-released publish displayName: Publish updated Cargo crates env: CARGO_REGISTRY_TOKEN: $(CARGO_REGISTRY_TOKEN) - bash: | cranko github create-releases cranko github upload-artifacts elfx86exts $(Pipeline.Workspace)/binary-collection/* displayName: Create GitHub releases env: GITHUB_TOKEN: $(GITHUB_TOKEN) elfx86exts-0.6.2/src/main.rs000064400000000000000000000317431046102023000137420ustar 00000000000000// Copyright 2017-2023 elfx86exts contributors // Licensed under the MIT License. //! elfx86exts helps you understand which instruction set extensions are used //! by a binary. Despite the misleading name, this crate supports both //! ELF and MachO binary formats and x86 as well as Arm processor architectures via the //! [capstone](https://crates.io/crates/capstone) crate. use capstone::{Arch as CapArch, Capstone, Mode, NO_EXTRA_MODE}; use clap::Parser; use object::{Architecture as ObjArch, Object, ObjectSection, SectionKind}; use std::{ cmp, collections::{HashMap, HashSet}, fs::File, path::PathBuf, }; /// These are from capstone/include/x86.h, which is super sketchy since the /// enum values are not specificied explicitly. fn describe_group_x86(g: &u8) -> Option<&'static str> { Some(match *g { 128 => "VT-x/AMD-V", // https://github.com/aquynh/capstone/blob/master/include/x86.h#L1583 129 => "3DNow", 130 => "AES", 131 => "ADX", 132 => "AVX", 133 => "AVX2", 134 => "AVX512", 135 => "BMI", 136 => "BMI2", 137 => "CMOV", 138 => "F16C", // line 1593 139 => "FMA", 140 => "FMA4", 141 => "FSGSBASE", 142 => "HLE", 143 => "MMX", 144 => "MODE32", 145 => "MODE64", 146 => "RTM", 147 => "SHA", 148 => "SSE1", // line 1603 149 => "SSE2", 150 => "SSE3", 151 => "SSE41", 152 => "SSE42", 153 => "SSE4A", 154 => "SSSE3", 155 => "PCLMUL", 156 => "XOP", 157 => "CDI", 158 => "ERI", // line 1613 159 => "TBM", 160 => "16BITMODE", 161 => "NOT64BITMODE", 162 => "SGX", 163 => "DQI", 164 => "BWI", 165 => "PFI", 166 => "VLX", 167 => "SMAP", 168 => "NOVLX", // line 1623 _ => { return None; } }) } /// These are from capstone/include/arm64.h fn describe_group_aarch64(g: &u8) -> Option<&'static str> { Some(match *g { 128 => "CRYPTO", // https://github.com/aquynh/capstone/blob/master/include/aarch64.h 129 => "FPARMV8", // Appears to map to both fp and fp16 instruction sets 130 => "NEON", 131 => "CRC", 132 => "AES", 133 => "DOTPROD", 134 => "FULLFP16", 135 => "LSE", 136 => "RCPC", 137 => "RDM", 138 => "SHA2", 139 => "SHA3", 140 => "SM4", 141 => "SVE", 142 => "SVE2", 143 => "SVE2AES", 144 => "SVE2BitPerm", 145 => "SVE2SHA3", 146 => "SV#2SM4", 147 => "SME", 148 => "SMEF64", 149 => "SMEI64", 150 => "MatMulFP32", 151 => "MatMulFP64", 152 => "MatMulInt8", 153 => "V8_1A", 154 => "V8_3A", 155 => "V8_4A", _ => { return None; } }) } #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { /// The path of the file to analyze path: PathBuf, } fn main() { // This list is taken from https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures // The ID numbers here are internal elfx86exts identifiers; they have no meaning except // for their relative ordering. let cpu_generations: HashMap<&str, u16> = [ // Intel: 1xx ("Pentium", 100), ("Pentium Pro", 101), ("Pentium III", 102), ("Pentium 4", 103), ("Pentium M", 104), ("Prescott", 105), ("Intel Core", 106), ("Penryn", 107), ("Nehalem", 108), ("Bonnell", 109), ("Westmere", 110), ("Saltwell", 111), ("Sandy Bridge", 112), ("Ivy Bridge", 113), ("Silvermont", 114), ("Haswell", 115), ("Broadwell", 116), ("Airmont", 117), ("Skylake", 118), ("Goldmont", 119), ("Kaby Lake", 120), ("Coffee Lake", 121), ("Cannon Lake", 122), ("Whiskey Lake", 123), ("Amber Lake", 124), ("Cascade Lake", 125), ("Cooper Lake", 126), ("Ice Lake", 127), // AMD: 2xx ("K6-2", 200), ("Bulldozer", 201), ("K10", 202), ("Piledriver", 203), // Unknown ("Unknown", 999), ] .iter() .cloned() .collect(); let mut cpu_generations_reverse: HashMap = HashMap::new(); for (key, val) in &cpu_generations { cpu_generations_reverse.insert(*val, key); } // The Intel generation that introduced each instruction set // This list is based on Googling and Wikipedia reading // Many of these are approximations, since CPU development isn't strictly linear, and not // all models of a generation support a given instruction set. let instrset_to_cpu: HashMap<&str, &str> = [ ("VT-x/AMD-V", "Intel Core"), // guess; https://en.wikipedia.org/wiki/X86_virtualization ("3DNow", "K6-2"), // Not supported by Intel CPUs, nor AMD since 2010; https://en.wikipedia.org/wiki/3DNow! ("AES", "Westmere"), // https://en.wikipedia.org/wiki/AES_instruction_set ("ADX", "Broadwell"), // https://en.wikipedia.org/wiki/Intel_ADX ("AVX", "Sandy Bridge"), // https://en.wikipedia.org/wiki/Advanced_Vector_Extensions ("AVX2", "Haswell"), // https://en.wikipedia.org/wiki/Advanced_Vector_Extensions ("AVX512", "Unknown"), // It's complicated. https://en.wikipedia.org/wiki/Advanced_Vector_Extensions ("BMI", "Haswell"), // https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets ("BMI2", "Haswell"), // https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets ("CMOV", "Pentium Pro"), // https://en.wikipedia.org/wiki/X86_instruction_listings ("F16C", "Ivy Bridge"), // https://en.wikipedia.org/wiki/F16C ("FMA", "Haswell"), // https://en.wikipedia.org/wiki/FMA_instruction_set ("FMA4", "Bulldozer"), // Not supported by Intel? https://en.wikipedia.org/wiki/FMA_instruction_set ("FSGSBASE", "Ivy Bridge"), // https://lwn.net/Articles/821723/ ("HLE", "Haswell"), // Part of TSX - https://en.wikipedia.org/wiki/Transactional_Synchronization_Extensions ("MMX", "Pentium"), // https://en.wikipedia.org/wiki/MMX_(instruction_set) ("MODE32", "Pentium"), // Assuming all x86 CPUs support 32-bit mode ("MODE64", "Intel Core"), // I'm assuming this just means x86-64 support ("RTM", "Haswell"), // Part of TSX - https://en.wikipedia.org/wiki/Transactional_Synchronization_Extensions ("SHA", "Goldmont"), // https://en.wikipedia.org/wiki/Intel_SHA_extensions ("SSE1", "Pentium III"), // https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions ("SSE2", "Pentium 4"), // https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions ("SSE3", "Prescott"), // https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions ("SSE41", "Penryn"), // https://en.wikipedia.org/wiki/SSE4 ("SSE42", "Nehalem"), // https://en.wikipedia.org/wiki/SSE4 ("SSE4A", "K10"), // AMD-only - https://en.wikipedia.org/wiki/SSE4 ("SSSE3", "Intel Core"), // https://en.wikipedia.org/wiki/Intel_Core_(microarchitecture) ("PCLMUL", "Intel Core"), // https://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ ("XOP", "Bulldozer"), // AMD-only - https://en.wikipedia.org/wiki/XOP_instruction_set ("CDI", "Unknown"), // Knights Landing - https://software.intel.com/en-us/blogs/2013/avx-512-instructions ("ERI", "Unknown"), // Knights Landing - https://software.intel.com/en-us/blogs/2013/avx-512-instructions ("TBM", "Piledriver"), // AMD-only - https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets#TBM_(Trailing_Bit_Manipulation) ("16BITMODE", "Unknown"), ("NOT64BITMODE", "Unknown"), ("SGX", "Skylake"), // https://en.wikipedia.org/wiki/Software_Guard_Extensions ("DQI", "Cannon Lake"), // AVX-512 Doubleword and Quadword Instructions ("BWI", "Cannon Lake"), // AVX-512 Byte and Word Instructions ("PFI", "Unknown"), // AVX-512 Prefetch Instructions, implemented by Knights Landing - https://software.intel.com/en-us/blogs/2013/avx-512-instructions ("VLX", "Cannon Lake"), // AVX-512 Vector Length Extensions ("SMAP", "Broadwell"), // https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention ("NOVLX", "Unknown"), // References in LLVM sources, associated mostly with AVX and AVX2 when VLX are not available ] .iter() .cloned() .collect(); let args = Args::parse(); // Read the file let f = File::open(&args.path).expect("can't open object file"); let buf = unsafe { memmap::Mmap::map(&f).expect("can't memmap object file") }; let obj = object::File::parse(&*buf).expect("can't parse object file"); let obj_arch = obj.architecture(); println!( "File format and CPU architecture: {:?}, {obj_arch:?}", obj.format() ); // Figure out the capstone / analysis settings. // // Capstone apparently doesn't do any validation, so if we initialize it // with the wrong architecture, it will just plunge on ahead and parse // everything as best it can. So in principle instead of exiting early with // unrecognized arches, we could print a warning and YOLO it. Right now we // don't do that, but we do try to be generous about accepting any `object` // architecture that might be consistent with a supported `capstone` // architecture. let (cap_arch, mode, describe_group): (CapArch, Mode, fn(&u8) -> Option<&str>) = match obj_arch { ObjArch::X86_64 | ObjArch::X86_64_X32 => { if obj.is_64() { (CapArch::X86, Mode::Mode64, describe_group_x86) } else { (CapArch::X86, Mode::Mode32, describe_group_x86) } } ObjArch::Aarch64 | ObjArch::Aarch64_Ilp32 => { (CapArch::ARM64, Mode::Arm, describe_group_aarch64) } _ => { // This could plausibly be an error exit, but it doesn't seem // unreasonable to exit with success either. println!( "CPU architecture `{obj_arch:?}` of input file `{}` is not currently supported for analysis", args.path.display() ); return; } }; // Disassemble the file let mut cs = Capstone::new_raw(cap_arch, mode, NO_EXTRA_MODE, None).expect("can't initialize capstone"); cs.set_detail(true) .expect("can't enable Capstone detail mode"); cs.set_skipdata(true) .expect("can't enable Capstone skip data mode"); let mut seen_groups = HashSet::new(); for sect in obj.sections() { if sect.kind() != SectionKind::Text { continue; } let data = sect.data().expect("couldn't get section data"); let mut offset = 0; loop { let rest = &data[offset..]; if rest.is_empty() { break; } let insns = cs .disasm_count(rest, 0, 1) .expect("couldn't disassemble section"); for insn in insns.iter() { offset += insn.bytes().len(); let Ok(detail) = cs.insn_detail(insn) else { continue; }; for group_code in detail.groups() { if seen_groups.insert(group_code.0) { if let Some(mnemonic) = insn.mnemonic() { if let Some(desc) = describe_group(&group_code.0) { println!("{} ({})", desc, mnemonic); } } } } } } } let mut proc_features = seen_groups .iter() .filter_map(describe_group) .collect::>(); proc_features.sort(); println!( "Instruction set extensions used: {}", proc_features.join(", ") ); // For x86 processors, we can map the instruction set features to specific CPU generations if cap_arch == CapArch::X86 { let mut max_gen_code = 100; for group_code in seen_groups.iter() { if let Some(desc) = describe_group(group_code) { match instrset_to_cpu.get(desc) { Some(generation) => match cpu_generations.get(generation) { Some(gen_code) => { max_gen_code = cmp::max(max_gen_code, *gen_code); } None => unimplemented!(), }, None => unimplemented!(), } } } match cpu_generations_reverse.get(&max_gen_code) { Some(generation) => { println!("CPU Generation: {}", generation); } None => unimplemented!(), } } } elfx86exts-0.6.2/tests/command.rs000064400000000000000000000015261046102023000150030ustar 00000000000000// Copyright 2019 Peter Williams // Licensed under the MIT License. //! Test the CLI command. extern crate assert_cmd; extern crate escargot; use assert_cmd::prelude::*; use std::process::Command; /// Test that the command runs successfully on itself. In principle I think /// this might be somewhat limiting: there's no reason you couldn't compile /// this tool on a platform whose executable format is not ELF or Mach-O, and /// in that case this test would fail. Somehow I'm not very worried about that /// possibility, though. #[test] fn run_on_self() { let cmd_run = escargot::CargoBuild::new() .bin("elfx86exts") .current_release() .current_target() .run() .unwrap(); let cmd_path = cmd_run.path(); let mut cmd = Command::new(cmd_path); cmd.arg(cmd_path); cmd.assert().success(); }