diff options
Diffstat (limited to 'vendor/gimli')
42 files changed, 411 insertions, 5034 deletions
diff --git a/vendor/gimli/.cargo-checksum.json b/vendor/gimli/.cargo-checksum.json index 5ffb76b27..92605591d 100644 --- a/vendor/gimli/.cargo-checksum.json +++ b/vendor/gimli/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"71187c6f7d8c6d8b265cad8dab182e9a79b77f47c696f67cb01dacf697cebb1d","CONTRIBUTING.md":"5f513ec06013e4f6f097e9c9492da5a47b9f25c94c6ecadfb655a77405fe912c","Cargo.lock":"c62e5cea9b318657dd2cbe0281765bae6ad3e6aed4dd845c74be6b5fbf7e6dcd","Cargo.toml":"00ec44ce045b53f6d5de383d6813f911a3f29cfa496b7a9bf1dfdd1ff4573ce7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"2ef8998059f83f88a4702932a8ce0cf374006b7946b0e6557ba0c714d2413823","benches/bench.rs":"e0045b989683794951563aa91b37069b2f6ae55f95e288d23f5c984b46e3a7eb","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/dwarf-validate.rs":"4aac1045e3c08bf00878eeff75c0cfc30c06171c5eab2e71d757505786729687","examples/dwarfdump.rs":"d67c9a94ef894fed33899b317ec8551e0ed3d06bd8aaf52ec43dea12e0d4598e","examples/simple.rs":"4c3425e8bd1880d9522f5ed2581fb5ccd452d4be678eebc0e147c48722a7be1d","examples/simple_line.rs":"ac795f859a17650dde466b5b23b8c161b2e3b8eb57e32f5b6718a3072f6bfad0","fixtures/self/README.md":"7cfd76031ec5a4b38cc4eb56ccbfe1bb590fb54c333d037550bdeaaeacfc20cb","fixtures/self/debug_abbrev":"7c0faa940d9c68d196d03ad55a20e5c746040fa428ff323277fa381deff82bba","fixtures/self/debug_aranges":"8c2aeb2335f61d04ecb7b747070d24f83a6517cbee79dc5c96d97fb6c53d6b6d","fixtures/self/debug_info":"42028a5983006e0703f9ca9515cd27d891ae4af70279fae5011d547f581e2661","fixtures/self/debug_inlined":"89d9516f06ff835621936037f5884fc56712bf304c1dcde52251ddd510fe8710","fixtures/self/debug_line":"b29aebcca3b38bb2bb8aa708cbe74a0dce5a3b0c18916b63d6d17282c017bec7","fixtures/self/debug_loc":"8906ccb9c204f233eb74c1d069dee97a19d18c2051f9147795d7b5364a9266aa","fixtures/self/debug_pubnames":"cf58e237f89c68afba724597fa7e260448636b45f2e69dc6f1bfe34006e27c48","fixtures/self/debug_pubtypes":"d43c1bed71c9d14d1683294cdc1833f069cf131d6e95ee808547919b4f352d81","fixtures/self/debug_ranges":"6d765ac18d33accd89186d077eeb505cbdf97d990c9201d63d9463cd7787ce7a","fixtures/self/debug_str":"9ed904b68eee77b8558b80b3b7ca03e8527f6c64483e9d6d845f40270eb21183","fixtures/self/eh_frame":"6dc3d84351cac42cf73d03452fbb532470dd94d08715154c48417e3f62095f17","fixtures/self/eh_frame_hdr":"afba7a0aa233c9a8c81c986495bd2505164844adb93272d6bc0c9e592e684716","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/arch.rs":"3a9b44d51a770b83e19c5420c7a6c090cf895fe668cbecea4e3c20acdfef871c","src/common.rs":"227d13db91b65d49b1b2d22033eb8374521731a50a7210ceb0ef49194a5d545c","src/constants.rs":"358cf7924c79bc72de59d23d1fa02b2047d6c763c8fbd8be263ab8cd3e3ba7ec","src/endianity.rs":"1f7e62ae34f540c06bedf1e7948739211556eea7dd83731a5ca52c7d687ed0fc","src/leb128.rs":"996d5c79d027f97c010ca487bc4ff5f8265f4b9e63d62b4e4fa291383c259ee9","src/lib.rs":"9a307a6d1fbebeae581df014b4f2b8bd16399fa883209fbdcc4d85eb9ec1dfd5","src/read/abbrev.rs":"31f7e9544a30e35f49dca355981730c2eb145e55ddbf281161d842a566d0a88d","src/read/addr.rs":"f63f289edf889e87107bb2090fb1c50b48af7015f31b7c39c3d6ea09630a38e9","src/read/aranges.rs":"ba3302f87cffb7ee15f48b0530ebd707f45ad056934223078d25ae2a1b034f1c","src/read/cfi.rs":"85cb294cf6a932d31769a747c58d1767b83e64831d8c633ab0b517014fe1cdec","src/read/dwarf.rs":"bac3f10a4f813833cf337361dd13d7e9bcb177355488ec785e901c5369e12daf","src/read/endian_reader.rs":"320983a859c2bb0dd44a3e6fae55ff0a84dba3fa80c2edbc64aa8135c44eddf0","src/read/endian_slice.rs":"476055ef571d53fbb890545fe5893b9083b10b90ec9e538bd82216bbe8bc45fd","src/read/index.rs":"e79b8d591b8e2007a37f5ea85a6d71b69d56ca3739a85cf7bf361724c5b829fa","src/read/lazy.rs":"85642e886ab3a94cea53534d1e133d1c4c17d2deaf291facdc316507e499ce22","src/read/line.rs":"f15196fa61955c40dfdd50f9034667143ab8d58efd8a51469ff7100c8c61f0be","src/read/lists.rs":"67ca9e1a36a91feb4996d035211de845205212bfda02163685d217818567ff93","src/read/loclists.rs":"857701a9e86aee809bfca3fd661e283b4f05038764dfc9c3cb1a349acc00bc47","src/read/lookup.rs":"0cf89ba12b9d48b1fe035dd3a497730323acb9427a9457abbc2f7c58c4c71165","src/read/mod.rs":"2d537e3c8dedc9b2096d27641d86edd598b51b4c26f476f8bc65e6eba5303acb","src/read/op.rs":"57aba989cc3d49772a51de7d487cbd10458f688487d3ae4e5efae4c84adb4e39","src/read/pubnames.rs":"ed752ee1a7017e6d3be42d81e4ddaaac960ef08081463a19106c9f041526d4a3","src/read/pubtypes.rs":"5e75b32c0923e827aff0bb2db456797a0e8d38ba46be992558a7990b3196bcf5","src/read/reader.rs":"b10ff3e77b54347e96b1f3cff30da104dfdd0c4d7a55b672950788f1f1ae3478","src/read/rnglists.rs":"4ec166e73fdfc85efa97b3b005b514bb64d454edb1ba0f201c45df4f2127e745","src/read/str.rs":"4c2f50014451621fea45969cd313f6840fcd3a99d7a2d081bfa1f8e0e434133a","src/read/unit.rs":"4e8af3c654faf8dc42b8bc62edf2f2402c6b42b31889662b0b48753c08b9893a","src/read/util.rs":"40f07a7b6623f29d03e15e41cda625a613ab1973969a4ddbb42365a8550b7e79","src/read/value.rs":"5a91e03ad3d41f679b264753498434b91948c6b89955e4beb4522498386d9b1d","src/test_util.rs":"291eefa6b51c6d934ba2f4a4c9bc7c403046fc1cccf4d43487820f0154bb89e2","src/write/abbrev.rs":"fa02163389e92e804d139cf84f833ab6af932083f0eb2d74464b4a70bd3237ff","src/write/cfi.rs":"3b04b0ebd82363738199cc673f64e0ceb60506a67c4f18b435a109caa62840f3","src/write/dwarf.rs":"8a1a0893e31134ad68993994594f3024ad0c8af7c1188b29e0ffc26b42edef21","src/write/endian_vec.rs":"1d5811986648816a677580b22630f5059757a381487d73e9adbb3008c9ae0c58","src/write/line.rs":"73bf3bab57433fe1dc891c48303cbc4e482306a1b9425f3483ad2985a9676ee9","src/write/loc.rs":"5c1f8d97d8e871a6663ad704f5e15694bddd54b85f2d801b52a520522f1258fd","src/write/mod.rs":"d8aa1da854cdee629d470d00d87e00dc6998e4bec1ca951f8d2f277730ab9d69","src/write/op.rs":"08fec7613aaa9061aae6e31d8b49933c812a6b7609f69e611a2a953af09aa18a","src/write/range.rs":"259e21e32bebbf7cdd8027d401862dee95cb5111e45bc4ff30bf54e3306d0262","src/write/section.rs":"effefef0d5e4557cb099431a20a7304392e6bf4ce04941d72b8bd2df9100e297","src/write/str.rs":"4850cc2fee55980f9cbb6b4169f9861ab9d05c2b28a85c2b790480b83a66f514","src/write/unit.rs":"8876c88dc3529d32e9894acc3194ed99fe437bb7520821c18f9f9f638db08d81","src/write/writer.rs":"7d5dd07b82ec3becebb060c106d4ea697cbd8b9b64a5de78403511a5244e08b1","tests/convert_self.rs":"180909b562969e1691b64628ded8654e6e0b10b3357f39917bd8ac288c5826dd","tests/parse_self.rs":"f2da1c7daef7139545c9367c2f26199e8b4623b31d4ec6480ddd851e6980f2dc"},"package":"ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"}
\ No newline at end of file +{"files":{"CHANGELOG.md":"c4ed38f2fcbc511dfe7631a79d7fb154c782eac0dd8f1d390846ba257bcf66c7","Cargo.toml":"b5b1c07a6bd1b719ab1d79742fb6e5c83e23e41ea44c269a86cf47b368b7743c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"ca364ea6f4977f61d45064f656a3ed08a2dda69056a0f573c8e7b9d5bf45a510","src/arch.rs":"8c97cee9a199e0b3b9453e69517a6302ca582481406bdbc36dfc8a7d8506071f","src/common.rs":"301ec88e624ea0ab28a0b4c6819712feacc2886a3640b159f1a8b7eb007ac634","src/constants.rs":"cf37acb6703a3f7cbb5b26467721560a074a03f2a8dfd1a6104d916cb5255117","src/endianity.rs":"1f7e62ae34f540c06bedf1e7948739211556eea7dd83731a5ca52c7d687ed0fc","src/leb128.rs":"996d5c79d027f97c010ca487bc4ff5f8265f4b9e63d62b4e4fa291383c259ee9","src/lib.rs":"0dd6cff2e1fa56a79188b3b83c738b747af3288ef37f5e867e2a53971190818c","src/read/abbrev.rs":"31f7e9544a30e35f49dca355981730c2eb145e55ddbf281161d842a566d0a88d","src/read/addr.rs":"f63f289edf889e87107bb2090fb1c50b48af7015f31b7c39c3d6ea09630a38e9","src/read/aranges.rs":"ba3302f87cffb7ee15f48b0530ebd707f45ad056934223078d25ae2a1b034f1c","src/read/cfi.rs":"6eccbb361753bf2a68a647c100c1f5e29d8b3e5171a2cf1e4c6cdc3ba1ca4586","src/read/dwarf.rs":"bac3f10a4f813833cf337361dd13d7e9bcb177355488ec785e901c5369e12daf","src/read/endian_reader.rs":"320983a859c2bb0dd44a3e6fae55ff0a84dba3fa80c2edbc64aa8135c44eddf0","src/read/endian_slice.rs":"9163375a1d6403cd91b7b665ed42306252500c15d104c75a824c0b7a635ac7be","src/read/index.rs":"e79b8d591b8e2007a37f5ea85a6d71b69d56ca3739a85cf7bf361724c5b829fa","src/read/lazy.rs":"85642e886ab3a94cea53534d1e133d1c4c17d2deaf291facdc316507e499ce22","src/read/line.rs":"19d38cbd27645885c59c41f7b8e7a509e0be1d701e4b30be13780744384c674b","src/read/lists.rs":"67ca9e1a36a91feb4996d035211de845205212bfda02163685d217818567ff93","src/read/loclists.rs":"857701a9e86aee809bfca3fd661e283b4f05038764dfc9c3cb1a349acc00bc47","src/read/lookup.rs":"0cf89ba12b9d48b1fe035dd3a497730323acb9427a9457abbc2f7c58c4c71165","src/read/mod.rs":"45b203294b007cd5184a5b0d65facf8549461dacc0cf928f05b3fe3c479046e0","src/read/op.rs":"a7502462986453d773c28cd4a34d344738e58348290445792c60a8a29cb0857c","src/read/pubnames.rs":"ed752ee1a7017e6d3be42d81e4ddaaac960ef08081463a19106c9f041526d4a3","src/read/pubtypes.rs":"5e75b32c0923e827aff0bb2db456797a0e8d38ba46be992558a7990b3196bcf5","src/read/reader.rs":"3e8ce504b651e14b839ef63c080c705ba7aef956ac2c7a74e298c015b791e2d2","src/read/rnglists.rs":"4ec166e73fdfc85efa97b3b005b514bb64d454edb1ba0f201c45df4f2127e745","src/read/str.rs":"4c2f50014451621fea45969cd313f6840fcd3a99d7a2d081bfa1f8e0e434133a","src/read/unit.rs":"60ecb8099d9386d85119b45ab92d628f3d3409b04669489b76e732d338b27f65","src/read/util.rs":"40f07a7b6623f29d03e15e41cda625a613ab1973969a4ddbb42365a8550b7e79","src/read/value.rs":"5ce8ef633f5af47bd367a5e4cde2c71bcef297c91a8d567192e460c890aef6de","src/test_util.rs":"291eefa6b51c6d934ba2f4a4c9bc7c403046fc1cccf4d43487820f0154bb89e2","src/write/abbrev.rs":"fa02163389e92e804d139cf84f833ab6af932083f0eb2d74464b4a70bd3237ff","src/write/cfi.rs":"e274b8b28f4e58c49ce530a5c630a26c6074be12f0faffed09709b700748afd7","src/write/dwarf.rs":"8a1a0893e31134ad68993994594f3024ad0c8af7c1188b29e0ffc26b42edef21","src/write/endian_vec.rs":"1d5811986648816a677580b22630f5059757a381487d73e9adbb3008c9ae0c58","src/write/line.rs":"73bf3bab57433fe1dc891c48303cbc4e482306a1b9425f3483ad2985a9676ee9","src/write/loc.rs":"5c1f8d97d8e871a6663ad704f5e15694bddd54b85f2d801b52a520522f1258fd","src/write/mod.rs":"d8aa1da854cdee629d470d00d87e00dc6998e4bec1ca951f8d2f277730ab9d69","src/write/op.rs":"08fec7613aaa9061aae6e31d8b49933c812a6b7609f69e611a2a953af09aa18a","src/write/range.rs":"259e21e32bebbf7cdd8027d401862dee95cb5111e45bc4ff30bf54e3306d0262","src/write/section.rs":"effefef0d5e4557cb099431a20a7304392e6bf4ce04941d72b8bd2df9100e297","src/write/str.rs":"4850cc2fee55980f9cbb6b4169f9861ab9d05c2b28a85c2b790480b83a66f514","src/write/unit.rs":"4a96a5f302b3bdf03faf3ff404bbcbed60d295080853ab8dabff5efa53f9ba37","src/write/writer.rs":"7d5dd07b82ec3becebb060c106d4ea697cbd8b9b64a5de78403511a5244e08b1"},"package":"6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"}
\ No newline at end of file diff --git a/vendor/gimli/CHANGELOG.md b/vendor/gimli/CHANGELOG.md index e90718c5a..8c5456b25 100644 --- a/vendor/gimli/CHANGELOG.md +++ b/vendor/gimli/CHANGELOG.md @@ -2,6 +2,69 @@ -------------------------------------------------------------------------------- +## 0.28.0 + +Released 2023/08/12. + +### Breaking changes + +* Deleted `impl From<EndianSlice> for &[u8]`. Use `EndianSlice::slice` instead. + [#669](https://github.com/gimli-rs/gimli/pull/669) + +* Deleted `impl Index<usize> for EndianSlice` and + `impl Index<RangeFrom<usize>> for EndianSlice`. + [#669](https://github.com/gimli-rs/gimli/pull/669) + +* Replaced `impl From<Pointer> for u64` with `Pointer::pointer`. + [#670](https://github.com/gimli-rs/gimli/pull/670) + +* Updated `fallible-iterator` to 0.3.0. + [#672](https://github.com/gimli-rs/gimli/pull/672) + +* Changed some optional dependencies to use the `dep:` feature syntax. + [#672](https://github.com/gimli-rs/gimli/pull/672) + +* Added `non_exhaustive` attribute to `read::RegisterRule`, + `read::CallFrameInstruction`, and `write::CallFrameInstruction`. + [#673](https://github.com/gimli-rs/gimli/pull/673) + +### Changed + +* The minimum supported rust version for the `read` feature and its dependencies + increased to 1.60.0. + +* The minimum supported rust version for other features increased to 1.65.0. + +### Added + +* Added `Vendor`, `read::DebugFrame::set_vendor`, and `read::EhFrame::set_vendor`. + [#673](https://github.com/gimli-rs/gimli/pull/673) + +* Added more ARM and AArch64 register definitions, and + `DW_CFA_AARCH64_negate_ra_state` support. + [#673](https://github.com/gimli-rs/gimli/pull/673) + +-------------------------------------------------------------------------------- + +## 0.27.3 + +Released 2023/06/14. + +### Changed + +* Excluded test fixtures from published package. + [#661](https://github.com/gimli-rs/gimli/pull/661) + +### Added + +* Added `FallibleIterator` implementation for `read::OperationIter`. + [#649](https://github.com/gimli-rs/gimli/pull/649) + +* Added `DW_AT_GNU_deleted` constant. + [#658](https://github.com/gimli-rs/gimli/pull/658) + +-------------------------------------------------------------------------------- + ## 0.27.2 Released 2023/02/15. @@ -546,7 +609,7 @@ and adding support for writing CFI. ### Fixed -* The `code_alignment_factor` is now used when evaluting CFI instructions +* The `code_alignment_factor` is now used when evaluating CFI instructions that advance the location. [#401](https://github.com/gimli-rs/gimli/pull/401) diff --git a/vendor/gimli/CONTRIBUTING.md b/vendor/gimli/CONTRIBUTING.md deleted file mode 100644 index 4f9e574ce..000000000 --- a/vendor/gimli/CONTRIBUTING.md +++ /dev/null @@ -1,137 +0,0 @@ -# Contributing to `gimli` - -Hi! We'd love to have your contributions! If you want help or mentorship, reach -out to us in a GitHub issue, or ping `fitzgen` in `#rust` on `irc.mozilla.org`. - -* [Code of Conduct](#coc) -* [Filing an Issue](#issues) -* [Building `gimli`](#building) -* [Testing `gimli`](#testing) - * [Test Coverage](#coverage) - * [Using `test-assembler`](#test-assembler) - * [Fuzzing](#fuzzing) -* [Benchmarking](#benchmarking) -* [Style](#style) - -## <a id="coc"></a> Code of Conduct - -We abide by the -[Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html) and ask -that you do as well. - -## <a id="issues"></a> Filing an Issue - -Think you've found a bug? File an issue! To help us understand and reproduce the -issue, provide us with: - -* The (preferably minimal) test case -* Steps to reproduce the issue using the test case -* The expected result of following those steps -* The actual result of following those steps - -Definitely file an issue if you see an unexpected panic originating from within -`gimli`! `gimli` should never panic unless it is explicitly documented to panic -in the specific circumstances provided. - -## <a id="building"></a> Building `gimli` - -`gimli` should always build on stable `rustc`, but we recommend using -[`rustup`](https://www.rustup.rs/) so you can switch to nightly `rustc` and run -benchmarks. - -To build `gimli`: - -``` -$ cargo build -``` - -## <a id="testing"></a> Testing `gimli` - -Run the tests with `cargo`: - -``` -$ cargo test -``` - -### <a id="coverage"></a> Test Coverage - -If you have `kcov` installed under linux, then you can generate code coverage -results using the `coverage` script in the root of the repository, and view them -at `target/kcov/index.html`. Otherwise you can create a pull request and view -the coverage results on coveralls.io. - -``` -$ ./coverage -``` - -The ideal we aim to reach is having our unit tests exercise every branch in -`gimli`. We allow an exception for branches which propagate errors inside a -`try!(..)` invocation, but we *do* want to exercise the original error paths. - -Pull requests adding new code should ensure that this ideal is met. - -At the time of writing we have 94% test coverage according to our coveralls.io -continuous integration. That number should generally stay the same or go up ;) -This is a bit subjective, because -.001% is just noise and doesn't matter. - -### <a id="test-assembler"></a> Using `test-assembler` - -We use the awesome -[`test-assembler`](https://github.com/luser/rust-test-assembler) crate to -construct binary test data. It makes building complex test cases readable. - -[Here is an example usage in `gimli`](https://github.com/gimli-rs/gimli/blob/156451f3fe6eeb2fa62b84b362c33fcb176e1171/src/loc.rs#L263) - -### <a id="fuzzing"></a> Fuzzing - -First, install `cargo fuzz`: - -``` -$ cargo install cargo-fuzz -``` - -Optionally, [set up the corpora for our fuzz targets by following these -instructions](https://github.com/gimli-rs/gimli-libfuzzer-corpora/blob/master/README.md#using-these-corpora). - -Finally, run a fuzz target! In this case, we are running the `eh_frame` fuzz -target: - -``` -$ cargo fuzz run eh_frame -``` - -The fuzz target definitions live in `fuzz/fuzz_targets/*`. You can add new ones -via `cargo fuzz add <my_new_target>`. - -## <a id="benchmarking"></a> Benchmarking - -The benchmarks require nightly `rustc`, so use `rustup`: - -``` -$ rustup run nightly cargo bench -``` - -We aim to be the fastest DWARF library. Period. - -Please provide before and after benchmark results with your pull requests. You -may also find [`cargo benchcmp`](https://github.com/BurntSushi/cargo-benchcmp) -handy for comparing results. - -Pull requests adding `#[bench]` micro-benchmarks that exercise a new edge case -are very welcome! - -## <a id="style"></a> Style - -We use `rustfmt` to automatically format and style all of our code. - -To install `rustfmt`: - -``` -$ rustup component add rustfmt-preview -``` - -To run `rustfmt` on `gimli`: - -``` -$ cargo fmt -``` diff --git a/vendor/gimli/Cargo.lock b/vendor/gimli/Cargo.lock deleted file mode 100644 index 566f1dd6c..000000000 --- a/vendor/gimli/Cargo.lock +++ /dev/null @@ -1,345 +0,0 @@ -# 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 = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "compiler_builtins" -version = "0.1.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dae98c88e576098d7ab13ebcb40cc43e5114b2beafe61a87cda9200649ff205" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" -dependencies = [ - "cfg-if", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "flate2" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "gimli" -version = "0.27.2" -dependencies = [ - "compiler_builtins", - "crossbeam", - "fallible-iterator", - "getopts", - "indexmap", - "memmap2", - "num_cpus", - "object", - "rayon", - "regex", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", - "stable_deref_trait", - "test-assembler", - "typed-arena", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "libc" -version = "0.2.139" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memmap2" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.30.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" -dependencies = [ - "flate2", - "memchr", - "wasmparser", -] - -[[package]] -name = "rayon" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "regex" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" - -[[package]] -name = "rustc-std-workspace-alloc" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff66d57013a5686e1917ed6a025d54dd591fcda71a41fe07edf4d16726aefa86" - -[[package]] -name = "rustc-std-workspace-core" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "test-assembler" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a6da51de149453f5c43fa67d5e73cccd75b3c5727a38a2f18c5f3c47f2db582" -dependencies = [ - "byteorder", -] - -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "wasmparser" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6" diff --git a/vendor/gimli/Cargo.toml b/vendor/gimli/Cargo.toml index f49444711..f7d9c9dc1 100644 --- a/vendor/gimli/Cargo.toml +++ b/vendor/gimli/Cargo.toml @@ -11,11 +11,16 @@ [package] edition = "2018" +rust-version = "1.60" name = "gimli" -version = "0.27.2" -exclude = [ - "/releases/*", - "/.github", +version = "0.28.0" +include = [ + "/CHANGELOG.md", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src", ] description = "A library for reading and writing the DWARF debugging format." documentation = "https://docs.rs/gimli" @@ -33,6 +38,7 @@ categories = [ ] license = "MIT OR Apache-2.0" repository = "https://github.com/gimli-rs/gimli" +resolver = "2" [profile.bench] codegen-units = 1 @@ -42,28 +48,6 @@ split-debuginfo = "packed" [profile.test] split-debuginfo = "packed" -[[example]] -name = "simple" -required-features = ["read"] - -[[example]] -name = "simple_line" -required-features = ["read"] - -[[example]] -name = "dwarfdump" -required-features = [ - "read", - "std", -] - -[[example]] -name = "dwarf-validate" -required-features = [ - "read", - "std", -] - [dependencies.alloc] version = "1.0.0" optional = true @@ -79,12 +63,12 @@ optional = true package = "rustc-std-workspace-core" [dependencies.fallible-iterator] -version = "0.2.0" +version = "0.3.0" optional = true default-features = false [dependencies.indexmap] -version = "1.0.2" +version = "2.0.0" optional = true [dependencies.stable_deref_trait] @@ -92,55 +76,34 @@ version = "1.1.0" optional = true default-features = false -[dev-dependencies.crossbeam] -version = "0.8" - -[dev-dependencies.getopts] -version = "0.2" - -[dev-dependencies.memmap2] -version = "0.5.5" - -[dev-dependencies.num_cpus] -version = "1" - -[dev-dependencies.object] -version = "0.30.0" -features = ["wasm"] - -[dev-dependencies.rayon] -version = "1.0" - -[dev-dependencies.regex] -version = "1" - [dev-dependencies.test-assembler] version = "0.1.3" -[dev-dependencies.typed-arena] -version = "2" - [features] default = [ - "read", + "read-all", "write", - "std", - "fallible-iterator", - "endian-reader", ] endian-reader = [ "read", - "stable_deref_trait", + "dep:stable_deref_trait", ] +fallible-iterator = ["dep:fallible-iterator"] read = ["read-core"] +read-all = [ + "read", + "std", + "fallible-iterator", + "endian-reader", +] read-core = [] rustc-dep-of-std = [ - "core", - "alloc", - "compiler_builtins", + "dep:core", + "dep:alloc", + "dep:compiler_builtins", ] std = [ - "fallible-iterator/std", - "stable_deref_trait/std", + "fallible-iterator?/std", + "stable_deref_trait?/std", ] -write = ["indexmap"] +write = ["dep:indexmap"] diff --git a/vendor/gimli/README.md b/vendor/gimli/README.md index cc73daf4d..fa6467cbc 100644 --- a/vendor/gimli/README.md +++ b/vendor/gimli/README.md @@ -22,7 +22,7 @@ * Unsure which object file parser to use? Try the cross-platform [`object`](https://github.com/gimli-rs/object) crate. See the - [`examples/`](./examples) directory for usage with `gimli`. + [`gimli-examples`](./crates/examples/src/bin) crate for usage with `gimli`. ## Install @@ -30,10 +30,13 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -gimli = "0.27.2" +gimli = "0.28.0" ``` -The minimum supported Rust version is 1.42.0. +The minimum supported Rust version is: + +* 1.60.0 for the `read` feature and its dependencies. +* 1.65.0 for other features. ## Documentation @@ -41,11 +44,11 @@ The minimum supported Rust version is 1.42.0. * Example programs: - * [A simple `.debug_info` parser](./examples/simple.rs) + * [A simple `.debug_info` parser](./crates/examples/src/bin/simple.rs) - * [A simple `.debug_line` parser](./examples/simple_line.rs) + * [A simple `.debug_line` parser](./crates/examples/src/bin/simple_line.rs) - * [A `dwarfdump` clone](./examples/dwarfdump.rs) + * [A `dwarfdump` clone](./crates/examples/src/bin/dwarfdump.rs) * [An `addr2line` clone](https://github.com/gimli-rs/addr2line) @@ -56,7 +59,7 @@ The minimum supported Rust version is 1.42.0. compilers used to create each compilation unit within a shared library or executable (via `DW_AT_producer`). - * [`dwarf-validate`](./examples/dwarf-validate.rs), a program to validate the + * [`dwarf-validate`](./crates/examples/src/bin/dwarf-validate.rs), a program to validate the integrity of some DWARF and its references between sections and compilation units. diff --git a/vendor/gimli/benches/bench.rs b/vendor/gimli/benches/bench.rs deleted file mode 100644 index fb29df77c..000000000 --- a/vendor/gimli/benches/bench.rs +++ /dev/null @@ -1,807 +0,0 @@ -#![feature(test)] - -extern crate test; - -use gimli::{ - AttributeValue, DebugAbbrev, DebugAddr, DebugAddrBase, DebugAranges, DebugInfo, DebugLine, - DebugLineOffset, DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges, - DebugRngLists, Encoding, EndianSlice, EntriesTreeNode, Expression, LittleEndian, LocationLists, - Operation, RangeLists, RangeListsOffset, Reader, ReaderOffset, -}; -use std::env; -use std::fs::File; -use std::io::Read; -use std::path::PathBuf; -use std::rc::Rc; - -pub fn read_section(section: &str) -> Vec<u8> { - let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into())); - path.push("./fixtures/self/"); - path.push(section); - - assert!(path.is_file()); - let mut file = File::open(path).unwrap(); - - let mut buf = Vec::new(); - file.read_to_end(&mut buf).unwrap(); - buf -} - -#[bench] -fn bench_parsing_debug_abbrev(b: &mut test::Bencher) { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - let unit = debug_info - .units() - .next() - .expect("Should have at least one compilation unit") - .expect("And it should parse OK"); - - let debug_abbrev = read_section("debug_abbrev"); - - b.iter(|| { - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - test::black_box( - unit.abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"), - ); - }); -} - -#[inline] -fn impl_bench_parsing_debug_info<R: Reader>( - debug_info: DebugInfo<R>, - debug_abbrev: DebugAbbrev<R>, -) { - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") { - let mut attrs = entry.attrs(); - loop { - match attrs.next() { - Ok(Some(ref attr)) => { - test::black_box(attr); - } - Ok(None) => break, - e @ Err(_) => { - e.expect("Should parse entry's attribute"); - } - } - } - } - } -} - -#[bench] -fn bench_parsing_debug_info(b: &mut test::Bencher) { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - b.iter(|| impl_bench_parsing_debug_info(debug_info, debug_abbrev)); -} - -#[bench] -fn bench_parsing_debug_info_with_endian_rc_slice(b: &mut test::Bencher) { - let debug_info = read_section("debug_info"); - let debug_info = Rc::from(&debug_info[..]); - let debug_info = gimli::EndianRcSlice::new(debug_info, LittleEndian); - let debug_info = DebugInfo::from(debug_info); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = Rc::from(&debug_abbrev[..]); - let debug_abbrev = gimli::EndianRcSlice::new(debug_abbrev, LittleEndian); - let debug_abbrev = DebugAbbrev::from(debug_abbrev); - - b.iter(|| impl_bench_parsing_debug_info(debug_info.clone(), debug_abbrev.clone())); -} - -#[bench] -fn bench_parsing_debug_info_tree(b: &mut test::Bencher) { - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_info = read_section("debug_info"); - - b.iter(|| { - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut tree = unit - .entries_tree(&abbrevs, None) - .expect("Should have entries tree"); - let root = tree.root().expect("Should parse root entry"); - parse_debug_info_tree(root); - } - }); -} - -fn parse_debug_info_tree<R: Reader>(node: EntriesTreeNode<R>) { - { - let mut attrs = node.entry().attrs(); - loop { - match attrs.next() { - Ok(Some(ref attr)) => { - test::black_box(attr); - } - Ok(None) => break, - e @ Err(_) => { - e.expect("Should parse entry's attribute"); - } - } - } - } - let mut children = node.children(); - while let Some(child) = children.next().expect("Should parse child entry") { - parse_debug_info_tree(child); - } -} - -#[bench] -fn bench_parsing_debug_info_raw(b: &mut test::Bencher) { - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_info = read_section("debug_info"); - - b.iter(|| { - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut raw = unit - .entries_raw(&abbrevs, None) - .expect("Should have entries"); - while !raw.is_empty() { - if let Some(abbrev) = raw - .read_abbreviation() - .expect("Should parse abbreviation code") - { - for spec in abbrev.attributes().iter().cloned() { - match raw.read_attribute(spec) { - Ok(ref attr) => { - test::black_box(attr); - } - e @ Err(_) => { - e.expect("Should parse attribute"); - } - } - } - } - } - } - }); -} - -#[bench] -fn bench_parsing_debug_aranges(b: &mut test::Bencher) { - let debug_aranges = read_section("debug_aranges"); - let debug_aranges = DebugAranges::new(&debug_aranges, LittleEndian); - - b.iter(|| { - let mut headers = debug_aranges.headers(); - while let Some(header) = headers.next().expect("Should parse arange header OK") { - let mut entries = header.entries(); - while let Some(arange) = entries.next().expect("Should parse arange entry OK") { - test::black_box(arange); - } - } - }); -} - -#[bench] -fn bench_parsing_debug_pubnames(b: &mut test::Bencher) { - let debug_pubnames = read_section("debug_pubnames"); - let debug_pubnames = DebugPubNames::new(&debug_pubnames, LittleEndian); - - b.iter(|| { - let mut pubnames = debug_pubnames.items(); - while let Some(pubname) = pubnames.next().expect("Should parse pubname OK") { - test::black_box(pubname); - } - }); -} - -#[bench] -fn bench_parsing_debug_pubtypes(b: &mut test::Bencher) { - let debug_pubtypes = read_section("debug_pubtypes"); - let debug_pubtypes = DebugPubTypes::new(&debug_pubtypes, LittleEndian); - - b.iter(|| { - let mut pubtypes = debug_pubtypes.items(); - while let Some(pubtype) = pubtypes.next().expect("Should parse pubtype OK") { - test::black_box(pubtype); - } - }); -} - -// We happen to know that there is a line number program and header at -// offset 0 and that address size is 8 bytes. No need to parse DIEs to grab -// this info off of the compilation units. -const OFFSET: DebugLineOffset = DebugLineOffset(0); -const ADDRESS_SIZE: u8 = 8; - -#[bench] -fn bench_parsing_line_number_program_opcodes(b: &mut test::Bencher) { - let debug_line = read_section("debug_line"); - let debug_line = DebugLine::new(&debug_line, LittleEndian); - - b.iter(|| { - let program = debug_line - .program(OFFSET, ADDRESS_SIZE, None, None) - .expect("Should parse line number program header"); - let header = program.header(); - - let mut instructions = header.instructions(); - while let Some(instruction) = instructions - .next_instruction(header) - .expect("Should parse instruction") - { - test::black_box(instruction); - } - }); -} - -#[bench] -fn bench_executing_line_number_programs(b: &mut test::Bencher) { - let debug_line = read_section("debug_line"); - let debug_line = DebugLine::new(&debug_line, LittleEndian); - - b.iter(|| { - let program = debug_line - .program(OFFSET, ADDRESS_SIZE, None, None) - .expect("Should parse line number program header"); - - let mut rows = program.rows(); - while let Some(row) = rows - .next_row() - .expect("Should parse and execute all rows in the line number program") - { - test::black_box(row); - } - }); -} - -#[bench] -fn bench_parsing_debug_loc(b: &mut test::Bencher) { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); - let debug_addr_base = DebugAddrBase(0); - - let debug_loc = read_section("debug_loc"); - let debug_loc = DebugLoc::new(&debug_loc, LittleEndian); - let debug_loclists = DebugLocLists::new(&[], LittleEndian); - let loclists = LocationLists::new(debug_loc, debug_loclists); - - let mut offsets = Vec::new(); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - cursor.next_dfs().expect("Should parse next dfs"); - - let mut low_pc = 0; - - { - let unit_entry = cursor.current().expect("Should have a root entry"); - let low_pc_attr = unit_entry - .attr_value(gimli::DW_AT_low_pc) - .expect("Should parse low_pc"); - if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr { - low_pc = address; - } - } - - while cursor.next_dfs().expect("Should parse next dfs").is_some() { - let entry = cursor.current().expect("Should have a current entry"); - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { - if let gimli::AttributeValue::LocationListsRef(offset) = attr.value() { - offsets.push((offset, unit.encoding(), low_pc)); - } - } - } - } - - b.iter(|| { - for &(offset, encoding, base_address) in &*offsets { - let mut locs = loclists - .locations(offset, encoding, base_address, &debug_addr, debug_addr_base) - .expect("Should parse locations OK"); - while let Some(loc) = locs.next().expect("Should parse next location") { - test::black_box(loc); - } - } - }); -} - -#[bench] -fn bench_parsing_debug_ranges(b: &mut test::Bencher) { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); - let debug_addr_base = DebugAddrBase(0); - - let debug_ranges = read_section("debug_ranges"); - let debug_ranges = DebugRanges::new(&debug_ranges, LittleEndian); - let debug_rnglists = DebugRngLists::new(&[], LittleEndian); - let rnglists = RangeLists::new(debug_ranges, debug_rnglists); - - let mut offsets = Vec::new(); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - cursor.next_dfs().expect("Should parse next dfs"); - - let mut low_pc = 0; - - { - let unit_entry = cursor.current().expect("Should have a root entry"); - let low_pc_attr = unit_entry - .attr_value(gimli::DW_AT_low_pc) - .expect("Should parse low_pc"); - if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr { - low_pc = address; - } - } - - while cursor.next_dfs().expect("Should parse next dfs").is_some() { - let entry = cursor.current().expect("Should have a current entry"); - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { - if let gimli::AttributeValue::RangeListsRef(offset) = attr.value() { - offsets.push((RangeListsOffset(offset.0), unit.encoding(), low_pc)); - } - } - } - } - - b.iter(|| { - for &(offset, encoding, base_address) in &*offsets { - let mut ranges = rnglists - .ranges(offset, encoding, base_address, &debug_addr, debug_addr_base) - .expect("Should parse ranges OK"); - while let Some(range) = ranges.next().expect("Should parse next range") { - test::black_box(range); - } - } - }); -} - -fn debug_info_expressions<R: Reader>( - debug_info: &DebugInfo<R>, - debug_abbrev: &DebugAbbrev<R>, -) -> Vec<(Expression<R>, Encoding)> { - let mut expressions = Vec::new(); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") { - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { - if let AttributeValue::Exprloc(expression) = attr.value() { - expressions.push((expression, unit.encoding())); - } - } - } - } - - expressions -} - -#[bench] -fn bench_parsing_debug_info_expressions(b: &mut test::Bencher) { - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let expressions = debug_info_expressions(&debug_info, &debug_abbrev); - - b.iter(|| { - for &(expression, encoding) in &*expressions { - let mut pc = expression.0; - while !pc.is_empty() { - Operation::parse(&mut pc, encoding).expect("Should parse operation"); - } - } - }); -} - -#[bench] -fn bench_evaluating_debug_info_expressions(b: &mut test::Bencher) { - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let expressions = debug_info_expressions(&debug_info, &debug_abbrev); - - b.iter(|| { - for &(expression, encoding) in &*expressions { - let mut eval = expression.evaluation(encoding); - eval.set_initial_value(0); - let result = eval.evaluate().expect("Should evaluate expression"); - test::black_box(result); - } - }); -} - -fn debug_loc_expressions<R: Reader>( - debug_info: &DebugInfo<R>, - debug_abbrev: &DebugAbbrev<R>, - debug_addr: &DebugAddr<R>, - loclists: &LocationLists<R>, -) -> Vec<(Expression<R>, Encoding)> { - let debug_addr_base = DebugAddrBase(R::Offset::from_u8(0)); - - let mut expressions = Vec::new(); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - cursor.next_dfs().expect("Should parse next dfs"); - - let mut low_pc = 0; - - { - let unit_entry = cursor.current().expect("Should have a root entry"); - let low_pc_attr = unit_entry - .attr_value(gimli::DW_AT_low_pc) - .expect("Should parse low_pc"); - if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr { - low_pc = address; - } - } - - while cursor.next_dfs().expect("Should parse next dfs").is_some() { - let entry = cursor.current().expect("Should have a current entry"); - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { - if let gimli::AttributeValue::LocationListsRef(offset) = attr.value() { - let mut locs = loclists - .locations(offset, unit.encoding(), low_pc, debug_addr, debug_addr_base) - .expect("Should parse locations OK"); - while let Some(loc) = locs.next().expect("Should parse next location") { - expressions.push((loc.data, unit.encoding())); - } - } - } - } - } - - expressions -} - -#[bench] -fn bench_parsing_debug_loc_expressions(b: &mut test::Bencher) { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); - - let debug_loc = read_section("debug_loc"); - let debug_loc = DebugLoc::new(&debug_loc, LittleEndian); - let debug_loclists = DebugLocLists::new(&[], LittleEndian); - let loclists = LocationLists::new(debug_loc, debug_loclists); - - let expressions = debug_loc_expressions(&debug_info, &debug_abbrev, &debug_addr, &loclists); - - b.iter(|| { - for &(expression, encoding) in &*expressions { - let mut pc = expression.0; - while !pc.is_empty() { - Operation::parse(&mut pc, encoding).expect("Should parse operation"); - } - } - }); -} - -#[bench] -fn bench_evaluating_debug_loc_expressions(b: &mut test::Bencher) { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); - - let debug_loc = read_section("debug_loc"); - let debug_loc = DebugLoc::new(&debug_loc, LittleEndian); - let debug_loclists = DebugLocLists::new(&[], LittleEndian); - let loclists = LocationLists::new(debug_loc, debug_loclists); - - let expressions = debug_loc_expressions(&debug_info, &debug_abbrev, &debug_addr, &loclists); - - b.iter(|| { - for &(expression, encoding) in &*expressions { - let mut eval = expression.evaluation(encoding); - eval.set_initial_value(0); - let result = eval.evaluate().expect("Should evaluate expression"); - test::black_box(result); - } - }); -} - -// See comment above `test_parse_self_eh_frame`. -#[cfg(target_pointer_width = "64")] -mod cfi { - use super::*; - use fallible_iterator::FallibleIterator; - - use gimli::{ - BaseAddresses, CieOrFde, EhFrame, FrameDescriptionEntry, LittleEndian, UnwindContext, - UnwindSection, - }; - - #[bench] - fn iterate_entries_and_do_not_parse_any_fde(b: &mut test::Bencher) { - let eh_frame = read_section("eh_frame"); - let eh_frame = EhFrame::new(&eh_frame, LittleEndian); - - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_got(0) - .set_text(0); - - b.iter(|| { - let mut entries = eh_frame.entries(&bases); - while let Some(entry) = entries.next().expect("Should parse CFI entry OK") { - test::black_box(entry); - } - }); - } - - #[bench] - fn iterate_entries_and_parse_every_fde(b: &mut test::Bencher) { - let eh_frame = read_section("eh_frame"); - let eh_frame = EhFrame::new(&eh_frame, LittleEndian); - - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_got(0) - .set_text(0); - - b.iter(|| { - let mut entries = eh_frame.entries(&bases); - while let Some(entry) = entries.next().expect("Should parse CFI entry OK") { - match entry { - CieOrFde::Cie(cie) => { - test::black_box(cie); - } - CieOrFde::Fde(partial) => { - let fde = partial - .parse(EhFrame::cie_from_offset) - .expect("Should be able to get CIE for FED"); - test::black_box(fde); - } - }; - } - }); - } - - #[bench] - fn iterate_entries_and_parse_every_fde_and_instructions(b: &mut test::Bencher) { - let eh_frame = read_section("eh_frame"); - let eh_frame = EhFrame::new(&eh_frame, LittleEndian); - - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_got(0) - .set_text(0); - - b.iter(|| { - let mut entries = eh_frame.entries(&bases); - while let Some(entry) = entries.next().expect("Should parse CFI entry OK") { - match entry { - CieOrFde::Cie(cie) => { - let mut instrs = cie.instructions(&eh_frame, &bases); - while let Some(i) = - instrs.next().expect("Can parse next CFI instruction OK") - { - test::black_box(i); - } - } - CieOrFde::Fde(partial) => { - let fde = partial - .parse(EhFrame::cie_from_offset) - .expect("Should be able to get CIE for FED"); - let mut instrs = fde.instructions(&eh_frame, &bases); - while let Some(i) = - instrs.next().expect("Can parse next CFI instruction OK") - { - test::black_box(i); - } - } - }; - } - }); - } - - #[bench] - fn iterate_entries_evaluate_every_fde(b: &mut test::Bencher) { - let eh_frame = read_section("eh_frame"); - let eh_frame = EhFrame::new(&eh_frame, LittleEndian); - - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_got(0) - .set_text(0); - - let mut ctx = Box::new(UnwindContext::new()); - - b.iter(|| { - let mut entries = eh_frame.entries(&bases); - while let Some(entry) = entries.next().expect("Should parse CFI entry OK") { - match entry { - CieOrFde::Cie(_) => {} - CieOrFde::Fde(partial) => { - let fde = partial - .parse(EhFrame::cie_from_offset) - .expect("Should be able to get CIE for FED"); - let mut table = fde - .rows(&eh_frame, &bases, &mut ctx) - .expect("Should be able to initialize ctx"); - while let Some(row) = - table.next_row().expect("Should get next unwind table row") - { - test::black_box(row); - } - } - }; - } - }); - } - - fn instrs_len<R: Reader>( - eh_frame: &EhFrame<R>, - bases: &BaseAddresses, - fde: &FrameDescriptionEntry<R>, - ) -> usize { - fde.instructions(eh_frame, bases) - .fold(0, |count, _| Ok(count + 1)) - .expect("fold over instructions OK") - } - - fn get_fde_with_longest_cfi_instructions<R: Reader>( - eh_frame: &EhFrame<R>, - bases: &BaseAddresses, - ) -> FrameDescriptionEntry<R> { - let mut longest: Option<(usize, FrameDescriptionEntry<_>)> = None; - - let mut entries = eh_frame.entries(bases); - while let Some(entry) = entries.next().expect("Should parse CFI entry OK") { - match entry { - CieOrFde::Cie(_) => {} - CieOrFde::Fde(partial) => { - let fde = partial - .parse(EhFrame::cie_from_offset) - .expect("Should be able to get CIE for FED"); - - let this_len = instrs_len(eh_frame, bases, &fde); - - let found_new_longest = match longest { - None => true, - Some((longest_len, ref _fde)) => this_len > longest_len, - }; - - if found_new_longest { - longest = Some((this_len, fde)); - } - } - }; - } - - longest.expect("At least one FDE in .eh_frame").1 - } - - #[bench] - fn parse_longest_fde_instructions(b: &mut test::Bencher) { - let eh_frame = read_section("eh_frame"); - let eh_frame = EhFrame::new(&eh_frame, LittleEndian); - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_got(0) - .set_text(0); - let fde = get_fde_with_longest_cfi_instructions(&eh_frame, &bases); - - b.iter(|| { - let mut instrs = fde.instructions(&eh_frame, &bases); - while let Some(i) = instrs.next().expect("Should parse instruction OK") { - test::black_box(i); - } - }); - } - - #[bench] - fn eval_longest_fde_instructions_new_ctx_everytime(b: &mut test::Bencher) { - let eh_frame = read_section("eh_frame"); - let eh_frame = EhFrame::new(&eh_frame, LittleEndian); - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_got(0) - .set_text(0); - let fde = get_fde_with_longest_cfi_instructions(&eh_frame, &bases); - - b.iter(|| { - let mut ctx = Box::new(UnwindContext::new()); - let mut table = fde - .rows(&eh_frame, &bases, &mut ctx) - .expect("Should initialize the ctx OK"); - while let Some(row) = table.next_row().expect("Should get next unwind table row") { - test::black_box(row); - } - }); - } - - #[bench] - fn eval_longest_fde_instructions_same_ctx(b: &mut test::Bencher) { - let eh_frame = read_section("eh_frame"); - let eh_frame = EhFrame::new(&eh_frame, LittleEndian); - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_got(0) - .set_text(0); - let fde = get_fde_with_longest_cfi_instructions(&eh_frame, &bases); - - let mut ctx = Box::new(UnwindContext::new()); - - b.iter(|| { - let mut table = fde - .rows(&eh_frame, &bases, &mut ctx) - .expect("Should initialize the ctx OK"); - while let Some(row) = table.next_row().expect("Should get next unwind table row") { - test::black_box(row); - } - }); - } -} diff --git a/vendor/gimli/clippy.toml b/vendor/gimli/clippy.toml deleted file mode 100644 index f97e544b6..000000000 --- a/vendor/gimli/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -msrv = "1.42.0" diff --git a/vendor/gimli/examples/dwarf-validate.rs b/vendor/gimli/examples/dwarf-validate.rs deleted file mode 100644 index 54d8f3a1d..000000000 --- a/vendor/gimli/examples/dwarf-validate.rs +++ /dev/null @@ -1,267 +0,0 @@ -// Allow clippy lints when building without clippy. -#![allow(unknown_lints)] - -use gimli::{AttributeValue, UnitHeader}; -use object::{Object, ObjectSection}; -use rayon::prelude::*; -use std::borrow::{Borrow, Cow}; -use std::env; -use std::fs; -use std::io::{self, BufWriter, Write}; -use std::iter::Iterator; -use std::path::{Path, PathBuf}; -use std::process; -use std::sync::Mutex; -use typed_arena::Arena; - -trait Reader: gimli::Reader<Offset = usize> + Send + Sync { - type SyncSendEndian: gimli::Endianity + Send + Sync; -} - -impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian> -where - Endian: gimli::Endianity + Send + Sync, -{ - type SyncSendEndian = Endian; -} - -struct ErrorWriter<W: Write + Send> { - inner: Mutex<(W, usize)>, - path: PathBuf, -} - -impl<W: Write + Send> ErrorWriter<W> { - #[allow(clippy::needless_pass_by_value)] - fn error(&self, s: String) { - let mut lock = self.inner.lock().unwrap(); - writeln!(&mut lock.0, "DWARF error in {}: {}", self.path.display(), s).unwrap(); - lock.1 += 1; - } -} - -fn main() { - let mut w = BufWriter::new(io::stdout()); - let mut errors = 0; - for arg in env::args_os().skip(1) { - let path = Path::new(&arg); - let file = match fs::File::open(&path) { - Ok(file) => file, - Err(err) => { - eprintln!("Failed to open file '{}': {}", path.display(), err); - errors += 1; - continue; - } - }; - let file = match unsafe { memmap2::Mmap::map(&file) } { - Ok(mmap) => mmap, - Err(err) => { - eprintln!("Failed to map file '{}': {}", path.display(), &err); - errors += 1; - continue; - } - }; - let file = match object::File::parse(&*file) { - Ok(file) => file, - Err(err) => { - eprintln!("Failed to parse file '{}': {}", path.display(), err); - errors += 1; - continue; - } - }; - - let endian = if file.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - let mut error_writer = ErrorWriter { - inner: Mutex::new((&mut w, 0)), - path: path.to_owned(), - }; - validate_file(&mut error_writer, &file, endian); - errors += error_writer.inner.into_inner().unwrap().1; - } - // Flush any errors. - drop(w); - if errors > 0 { - process::exit(1); - } -} - -fn validate_file<W, Endian>(w: &mut ErrorWriter<W>, file: &object::File, endian: Endian) -where - W: Write + Send, - Endian: gimli::Endianity + Send + Sync, -{ - let arena = Arena::new(); - - fn load_section<'a, 'file, 'input, S, Endian>( - arena: &'a Arena<Cow<'file, [u8]>>, - file: &'file object::File<'input>, - endian: Endian, - ) -> S - where - S: gimli::Section<gimli::EndianSlice<'a, Endian>>, - Endian: gimli::Endianity + Send + Sync, - 'file: 'input, - 'a: 'file, - { - let data = match file.section_by_name(S::section_name()) { - Some(ref section) => section - .uncompressed_data() - .unwrap_or(Cow::Borrowed(&[][..])), - None => Cow::Borrowed(&[][..]), - }; - let data_ref = (*arena.alloc(data)).borrow(); - S::from(gimli::EndianSlice::new(data_ref, endian)) - } - - // Variables representing sections of the file. The type of each is inferred from its use in the - // validate_info function below. - let debug_abbrev = &load_section(&arena, file, endian); - let debug_info = &load_section(&arena, file, endian); - - validate_info(w, debug_info, debug_abbrev); -} - -struct UnitSummary { - // True if we successfully parsed all the DIEs and attributes in the compilation unit - internally_valid: bool, - offset: gimli::DebugInfoOffset, - die_offsets: Vec<gimli::UnitOffset>, - global_die_references: Vec<(gimli::UnitOffset, gimli::DebugInfoOffset)>, -} - -fn validate_info<W, R>( - w: &mut ErrorWriter<W>, - debug_info: &gimli::DebugInfo<R>, - debug_abbrev: &gimli::DebugAbbrev<R>, -) where - W: Write + Send, - R: Reader, -{ - let mut units = Vec::new(); - let mut units_iter = debug_info.units(); - let mut last_offset = 0; - loop { - let u = match units_iter.next() { - Err(err) => { - w.error(format!( - "Can't read unit header at offset {:#x}, stopping reading units: {}", - last_offset, err - )); - break; - } - Ok(None) => break, - Ok(Some(u)) => u, - }; - last_offset = u.offset().as_debug_info_offset().unwrap().0 + u.length_including_self(); - units.push(u); - } - let process_unit = |unit: UnitHeader<R>| -> UnitSummary { - let unit_offset = unit.offset().as_debug_info_offset().unwrap(); - let mut ret = UnitSummary { - internally_valid: false, - offset: unit_offset, - die_offsets: Vec::new(), - global_die_references: Vec::new(), - }; - let abbrevs = match unit.abbreviations(debug_abbrev) { - Ok(abbrevs) => abbrevs, - Err(err) => { - w.error(format!( - "Invalid abbrevs for unit {:#x}: {}", - unit_offset.0, &err - )); - return ret; - } - }; - let mut entries = unit.entries(&abbrevs); - let mut unit_refs = Vec::new(); - loop { - let (_, entry) = match entries.next_dfs() { - Err(err) => { - w.error(format!( - "Invalid DIE for unit {:#x}: {}", - unit_offset.0, &err - )); - return ret; - } - Ok(None) => break, - Ok(Some(entry)) => entry, - }; - ret.die_offsets.push(entry.offset()); - - let mut attrs = entry.attrs(); - loop { - let attr = match attrs.next() { - Err(err) => { - w.error(format!( - "Invalid attribute for unit {:#x} at DIE {:#x}: {}", - unit_offset.0, - entry.offset().0, - &err - )); - return ret; - } - Ok(None) => break, - Ok(Some(attr)) => attr, - }; - match attr.value() { - AttributeValue::UnitRef(offset) => { - unit_refs.push((entry.offset(), offset)); - } - AttributeValue::DebugInfoRef(offset) => { - ret.global_die_references.push((entry.offset(), offset)); - } - _ => (), - } - } - } - ret.internally_valid = true; - ret.die_offsets.shrink_to_fit(); - ret.global_die_references.shrink_to_fit(); - - // Check intra-unit references - for (from, to) in unit_refs { - if ret.die_offsets.binary_search(&to).is_err() { - w.error(format!( - "Invalid intra-unit reference in unit {:#x} from DIE {:#x} to {:#x}", - unit_offset.0, from.0, to.0 - )); - } - } - - ret - }; - let processed_units = units.into_par_iter().map(process_unit).collect::<Vec<_>>(); - - let check_unit = |summary: &UnitSummary| { - if !summary.internally_valid { - return; - } - for &(from, to) in summary.global_die_references.iter() { - let u = match processed_units.binary_search_by_key(&to, |v| v.offset) { - Ok(i) => &processed_units[i], - Err(i) => { - if i > 0 { - &processed_units[i - 1] - } else { - w.error(format!("Invalid cross-unit reference in unit {:#x} from DIE {:#x} to global DIE {:#x}: no unit found", - summary.offset.0, from.0, to.0)); - continue; - } - } - }; - if !u.internally_valid { - continue; - } - let to_offset = gimli::UnitOffset(to.0 - u.offset.0); - if u.die_offsets.binary_search(&to_offset).is_err() { - w.error(format!("Invalid cross-unit reference in unit {:#x} from DIE {:#x} to global DIE {:#x}: unit at {:#x} contains no DIE {:#x}", - summary.offset.0, from.0, to.0, u.offset.0, to_offset.0)); - } - } - }; - processed_units.par_iter().for_each(check_unit); -} diff --git a/vendor/gimli/examples/dwarfdump.rs b/vendor/gimli/examples/dwarfdump.rs deleted file mode 100644 index a11f298f8..000000000 --- a/vendor/gimli/examples/dwarfdump.rs +++ /dev/null @@ -1,2369 +0,0 @@ -// Allow clippy lints when building without clippy. -#![allow(unknown_lints)] - -use fallible_iterator::FallibleIterator; -use gimli::{Section, UnitHeader, UnitOffset, UnitSectionOffset, UnitType, UnwindSection}; -use object::{Object, ObjectSection, ObjectSymbol}; -use regex::bytes::Regex; -use std::borrow::{Borrow, Cow}; -use std::cmp::min; -use std::collections::HashMap; -use std::env; -use std::fmt::{self, Debug}; -use std::fs; -use std::io; -use std::io::{BufWriter, Write}; -use std::iter::Iterator; -use std::mem; -use std::process; -use std::result; -use std::sync::{Condvar, Mutex}; -use typed_arena::Arena; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Error { - GimliError(gimli::Error), - ObjectError(object::read::Error), - IoError, -} - -impl fmt::Display for Error { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> { - Debug::fmt(self, f) - } -} - -fn writeln_error<W: Write, R: Reader>( - w: &mut W, - dwarf: &gimli::Dwarf<R>, - err: Error, - msg: &str, -) -> io::Result<()> { - writeln!( - w, - "{}: {}", - msg, - match err { - Error::GimliError(err) => dwarf.format_error(err), - Error::ObjectError(err) => - format!("{}:{:?}", "An object error occurred while reading", err), - Error::IoError => "An I/O error occurred while writing.".to_string(), - } - ) -} - -impl From<gimli::Error> for Error { - fn from(err: gimli::Error) -> Self { - Error::GimliError(err) - } -} - -impl From<io::Error> for Error { - fn from(_: io::Error) -> Self { - Error::IoError - } -} - -impl From<object::read::Error> for Error { - fn from(err: object::read::Error) -> Self { - Error::ObjectError(err) - } -} - -pub type Result<T> = result::Result<T, Error>; - -fn parallel_output<W, II, F>(w: &mut W, max_workers: usize, iter: II, f: F) -> Result<()> -where - W: Write + Send, - F: Sync + Fn(II::Item, &mut Vec<u8>) -> Result<()>, - II: IntoIterator, - II::IntoIter: Send, -{ - struct ParallelOutputState<I, W> { - iterator: I, - current_worker: usize, - result: Result<()>, - w: W, - } - - let state = Mutex::new(ParallelOutputState { - iterator: iter.into_iter().fuse(), - current_worker: 0, - result: Ok(()), - w, - }); - let workers = min(max_workers, num_cpus::get()); - let mut condvars = Vec::new(); - for _ in 0..workers { - condvars.push(Condvar::new()); - } - { - let state_ref = &state; - let f_ref = &f; - let condvars_ref = &condvars; - crossbeam::scope(|scope| { - for i in 0..workers { - scope.spawn(move |_| { - let mut v = Vec::new(); - let mut lock = state_ref.lock().unwrap(); - while lock.current_worker != i { - lock = condvars_ref[i].wait(lock).unwrap(); - } - loop { - let item = if lock.result.is_ok() { - lock.iterator.next() - } else { - None - }; - lock.current_worker = (i + 1) % workers; - condvars_ref[lock.current_worker].notify_one(); - mem::drop(lock); - - let ret = if let Some(item) = item { - v.clear(); - f_ref(item, &mut v) - } else { - return; - }; - - lock = state_ref.lock().unwrap(); - while lock.current_worker != i { - lock = condvars_ref[i].wait(lock).unwrap(); - } - if lock.result.is_ok() { - let ret2 = lock.w.write_all(&v); - if ret.is_err() { - lock.result = ret; - } else { - lock.result = ret2.map_err(Error::from); - } - } - } - }); - } - }) - .unwrap(); - } - state.into_inner().unwrap().result -} - -trait Reader: gimli::Reader<Offset = usize> + Send + Sync {} - -impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian> where - Endian: gimli::Endianity + Send + Sync -{ -} - -type RelocationMap = HashMap<usize, object::Relocation>; - -fn add_relocations( - relocations: &mut RelocationMap, - file: &object::File, - section: &object::Section, -) { - for (offset64, mut relocation) in section.relocations() { - let offset = offset64 as usize; - if offset as u64 != offset64 { - continue; - } - let offset = offset as usize; - match relocation.kind() { - object::RelocationKind::Absolute => { - match relocation.target() { - object::RelocationTarget::Symbol(symbol_idx) => { - match file.symbol_by_index(symbol_idx) { - Ok(symbol) => { - let addend = - symbol.address().wrapping_add(relocation.addend() as u64); - relocation.set_addend(addend as i64); - } - Err(_) => { - eprintln!( - "Relocation with invalid symbol for section {} at offset 0x{:08x}", - section.name().unwrap(), - offset - ); - } - } - } - _ => {} - } - if relocations.insert(offset, relocation).is_some() { - eprintln!( - "Multiple relocations for section {} at offset 0x{:08x}", - section.name().unwrap(), - offset - ); - } - } - _ => { - eprintln!( - "Unsupported relocation for section {} at offset 0x{:08x}", - section.name().unwrap(), - offset - ); - } - } - } -} - -/// Apply relocations to addresses and offsets during parsing, -/// instead of requiring the data to be fully relocated prior -/// to parsing. -/// -/// Pros -/// - allows readonly buffers, we don't need to implement writing of values back to buffers -/// - potentially allows us to handle addresses and offsets differently -/// - potentially allows us to add metadata from the relocation (eg symbol names) -/// Cons -/// - maybe incomplete -#[derive(Debug, Clone)] -struct Relocate<'a, R: gimli::Reader<Offset = usize>> { - relocations: &'a RelocationMap, - section: R, - reader: R, -} - -impl<'a, R: gimli::Reader<Offset = usize>> Relocate<'a, R> { - fn relocate(&self, offset: usize, value: u64) -> u64 { - if let Some(relocation) = self.relocations.get(&offset) { - match relocation.kind() { - object::RelocationKind::Absolute => { - if relocation.has_implicit_addend() { - // Use the explicit addend too, because it may have the symbol value. - return value.wrapping_add(relocation.addend() as u64); - } else { - return relocation.addend() as u64; - } - } - _ => {} - } - }; - value - } -} - -impl<'a, R: gimli::Reader<Offset = usize>> gimli::Reader for Relocate<'a, R> { - type Endian = R::Endian; - type Offset = R::Offset; - - fn read_address(&mut self, address_size: u8) -> gimli::Result<u64> { - let offset = self.reader.offset_from(&self.section); - let value = self.reader.read_address(address_size)?; - Ok(self.relocate(offset, value)) - } - - fn read_length(&mut self, format: gimli::Format) -> gimli::Result<usize> { - let offset = self.reader.offset_from(&self.section); - let value = self.reader.read_length(format)?; - <usize as gimli::ReaderOffset>::from_u64(self.relocate(offset, value as u64)) - } - - fn read_offset(&mut self, format: gimli::Format) -> gimli::Result<usize> { - let offset = self.reader.offset_from(&self.section); - let value = self.reader.read_offset(format)?; - <usize as gimli::ReaderOffset>::from_u64(self.relocate(offset, value as u64)) - } - - fn read_sized_offset(&mut self, size: u8) -> gimli::Result<usize> { - let offset = self.reader.offset_from(&self.section); - let value = self.reader.read_sized_offset(size)?; - <usize as gimli::ReaderOffset>::from_u64(self.relocate(offset, value as u64)) - } - - #[inline] - fn split(&mut self, len: Self::Offset) -> gimli::Result<Self> { - let mut other = self.clone(); - other.reader.truncate(len)?; - self.reader.skip(len)?; - Ok(other) - } - - // All remaining methods simply delegate to `self.reader`. - - #[inline] - fn endian(&self) -> Self::Endian { - self.reader.endian() - } - - #[inline] - fn len(&self) -> Self::Offset { - self.reader.len() - } - - #[inline] - fn empty(&mut self) { - self.reader.empty() - } - - #[inline] - fn truncate(&mut self, len: Self::Offset) -> gimli::Result<()> { - self.reader.truncate(len) - } - - #[inline] - fn offset_from(&self, base: &Self) -> Self::Offset { - self.reader.offset_from(&base.reader) - } - - #[inline] - fn offset_id(&self) -> gimli::ReaderOffsetId { - self.reader.offset_id() - } - - #[inline] - fn lookup_offset_id(&self, id: gimli::ReaderOffsetId) -> Option<Self::Offset> { - self.reader.lookup_offset_id(id) - } - - #[inline] - fn find(&self, byte: u8) -> gimli::Result<Self::Offset> { - self.reader.find(byte) - } - - #[inline] - fn skip(&mut self, len: Self::Offset) -> gimli::Result<()> { - self.reader.skip(len) - } - - #[inline] - fn to_slice(&self) -> gimli::Result<Cow<[u8]>> { - self.reader.to_slice() - } - - #[inline] - fn to_string(&self) -> gimli::Result<Cow<str>> { - self.reader.to_string() - } - - #[inline] - fn to_string_lossy(&self) -> gimli::Result<Cow<str>> { - self.reader.to_string_lossy() - } - - #[inline] - fn read_slice(&mut self, buf: &mut [u8]) -> gimli::Result<()> { - self.reader.read_slice(buf) - } -} - -impl<'a, R: Reader> Reader for Relocate<'a, R> {} - -#[derive(Default)] -struct Flags<'a> { - eh_frame: bool, - goff: bool, - info: bool, - line: bool, - pubnames: bool, - pubtypes: bool, - aranges: bool, - dwo: bool, - dwp: bool, - dwo_parent: Option<object::File<'a>>, - sup: Option<object::File<'a>>, - raw: bool, - match_units: Option<Regex>, -} - -fn print_usage(opts: &getopts::Options) -> ! { - let brief = format!("Usage: {} <options> <file>", env::args().next().unwrap()); - write!(&mut io::stderr(), "{}", opts.usage(&brief)).ok(); - process::exit(1); -} - -fn main() { - let mut opts = getopts::Options::new(); - opts.optflag( - "", - "eh-frame", - "print .eh-frame exception handling frame information", - ); - opts.optflag("G", "", "show global die offsets"); - opts.optflag("i", "", "print .debug_info and .debug_types sections"); - opts.optflag("l", "", "print .debug_line section"); - opts.optflag("p", "", "print .debug_pubnames section"); - opts.optflag("r", "", "print .debug_aranges section"); - opts.optflag("y", "", "print .debug_pubtypes section"); - opts.optflag( - "", - "dwo", - "print the .dwo versions of the selected sections", - ); - opts.optflag( - "", - "dwp", - "print the .dwp versions of the selected sections", - ); - opts.optopt( - "", - "dwo-parent", - "use the specified file as the parent of the dwo or dwp (e.g. for .debug_addr)", - "library path", - ); - opts.optflag("", "raw", "print raw data values"); - opts.optopt( - "u", - "match-units", - "print compilation units whose output matches a regex", - "REGEX", - ); - opts.optopt("", "sup", "path to supplementary object file", "PATH"); - - let matches = match opts.parse(env::args().skip(1)) { - Ok(m) => m, - Err(e) => { - writeln!(&mut io::stderr(), "{:?}\n", e).ok(); - print_usage(&opts); - } - }; - if matches.free.is_empty() { - print_usage(&opts); - } - - let mut all = true; - let mut flags = Flags::default(); - if matches.opt_present("eh-frame") { - flags.eh_frame = true; - all = false; - } - if matches.opt_present("G") { - flags.goff = true; - } - if matches.opt_present("i") { - flags.info = true; - all = false; - } - if matches.opt_present("l") { - flags.line = true; - all = false; - } - if matches.opt_present("p") { - flags.pubnames = true; - all = false; - } - if matches.opt_present("y") { - flags.pubtypes = true; - all = false; - } - if matches.opt_present("r") { - flags.aranges = true; - all = false; - } - if matches.opt_present("dwo") { - flags.dwo = true; - } - if matches.opt_present("dwp") { - flags.dwp = true; - } - if matches.opt_present("raw") { - flags.raw = true; - } - if all { - // .eh_frame is excluded even when printing all information. - // cosmetic flags like -G must be set explicitly too. - flags.info = true; - flags.line = true; - flags.pubnames = true; - flags.pubtypes = true; - flags.aranges = true; - } - flags.match_units = if let Some(r) = matches.opt_str("u") { - match Regex::new(&r) { - Ok(r) => Some(r), - Err(e) => { - eprintln!("Invalid regular expression {}: {}", r, e); - process::exit(1); - } - } - } else { - None - }; - - let arena_mmap = Arena::new(); - let load_file = |path| { - let file = match fs::File::open(&path) { - Ok(file) => file, - Err(err) => { - eprintln!("Failed to open file '{}': {}", path, err); - process::exit(1); - } - }; - let mmap = match unsafe { memmap2::Mmap::map(&file) } { - Ok(mmap) => mmap, - Err(err) => { - eprintln!("Failed to map file '{}': {}", path, err); - process::exit(1); - } - }; - let mmap_ref = (*arena_mmap.alloc(mmap)).borrow(); - match object::File::parse(&**mmap_ref) { - Ok(file) => Some(file), - Err(err) => { - eprintln!("Failed to parse file '{}': {}", path, err); - process::exit(1); - } - } - }; - - flags.sup = matches.opt_str("sup").and_then(load_file); - flags.dwo_parent = matches.opt_str("dwo-parent").and_then(load_file); - if flags.dwo_parent.is_some() && !flags.dwo && !flags.dwp { - eprintln!("--dwo-parent also requires --dwo or --dwp"); - process::exit(1); - } - if flags.dwo_parent.is_none() && flags.dwp { - eprintln!("--dwp also requires --dwo-parent"); - process::exit(1); - } - - for file_path in &matches.free { - if matches.free.len() != 1 { - println!("{}", file_path); - println!(); - } - - let file = match fs::File::open(&file_path) { - Ok(file) => file, - Err(err) => { - eprintln!("Failed to open file '{}': {}", file_path, err); - continue; - } - }; - let file = match unsafe { memmap2::Mmap::map(&file) } { - Ok(mmap) => mmap, - Err(err) => { - eprintln!("Failed to map file '{}': {}", file_path, err); - continue; - } - }; - let file = match object::File::parse(&*file) { - Ok(file) => file, - Err(err) => { - eprintln!("Failed to parse file '{}': {}", file_path, err); - continue; - } - }; - - let endian = if file.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - let ret = dump_file(&file, endian, &flags); - match ret { - Ok(_) => (), - Err(err) => eprintln!("Failed to dump '{}': {}", file_path, err,), - } - } -} - -fn empty_file_section<'input, 'arena, Endian: gimli::Endianity>( - endian: Endian, - arena_relocations: &'arena Arena<RelocationMap>, -) -> Relocate<'arena, gimli::EndianSlice<'arena, Endian>> { - let reader = gimli::EndianSlice::new(&[], endian); - let section = reader; - let relocations = RelocationMap::default(); - let relocations = (*arena_relocations.alloc(relocations)).borrow(); - Relocate { - relocations, - section, - reader, - } -} - -fn load_file_section<'input, 'arena, Endian: gimli::Endianity>( - id: gimli::SectionId, - file: &object::File<'input>, - endian: Endian, - is_dwo: bool, - arena_data: &'arena Arena<Cow<'input, [u8]>>, - arena_relocations: &'arena Arena<RelocationMap>, -) -> Result<Relocate<'arena, gimli::EndianSlice<'arena, Endian>>> { - let mut relocations = RelocationMap::default(); - let name = if is_dwo { - id.dwo_name() - } else if file.format() == object::BinaryFormat::Xcoff { - id.xcoff_name() - } else { - Some(id.name()) - }; - - let data = match name.and_then(|name| file.section_by_name(&name)) { - Some(ref section) => { - // DWO sections never have relocations, so don't bother. - if !is_dwo { - add_relocations(&mut relocations, file, section); - } - section.uncompressed_data()? - } - // Use a non-zero capacity so that `ReaderOffsetId`s are unique. - None => Cow::Owned(Vec::with_capacity(1)), - }; - let data_ref = (*arena_data.alloc(data)).borrow(); - let reader = gimli::EndianSlice::new(data_ref, endian); - let section = reader; - let relocations = (*arena_relocations.alloc(relocations)).borrow(); - Ok(Relocate { - relocations, - section, - reader, - }) -} - -fn dump_file<Endian>(file: &object::File, endian: Endian, flags: &Flags) -> Result<()> -where - Endian: gimli::Endianity + Send + Sync, -{ - let arena_data = Arena::new(); - let arena_relocations = Arena::new(); - - let dwo_parent = if let Some(dwo_parent_file) = flags.dwo_parent.as_ref() { - let mut load_dwo_parent_section = |id: gimli::SectionId| -> Result<_> { - load_file_section( - id, - dwo_parent_file, - endian, - false, - &arena_data, - &arena_relocations, - ) - }; - Some(gimli::Dwarf::load(&mut load_dwo_parent_section)?) - } else { - None - }; - let dwo_parent = dwo_parent.as_ref(); - - let dwo_parent_units = if let Some(dwo_parent) = dwo_parent { - Some( - match dwo_parent - .units() - .map(|unit_header| dwo_parent.unit(unit_header)) - .filter_map(|unit| Ok(unit.dwo_id.map(|dwo_id| (dwo_id, unit)))) - .collect() - { - Ok(units) => units, - Err(err) => { - eprintln!("Failed to process --dwo-parent units: {}", err); - return Ok(()); - } - }, - ) - } else { - None - }; - let dwo_parent_units = dwo_parent_units.as_ref(); - - let mut load_section = |id: gimli::SectionId| -> Result<_> { - load_file_section( - id, - file, - endian, - flags.dwo || flags.dwp, - &arena_data, - &arena_relocations, - ) - }; - - let w = &mut BufWriter::new(io::stdout()); - if flags.dwp { - let empty = empty_file_section(endian, &arena_relocations); - let dwp = gimli::DwarfPackage::load(&mut load_section, empty)?; - dump_dwp(w, &dwp, dwo_parent.unwrap(), dwo_parent_units, flags)?; - w.flush()?; - return Ok(()); - } - - let mut dwarf = gimli::Dwarf::load(&mut load_section)?; - if flags.dwo { - if let Some(dwo_parent) = dwo_parent { - dwarf.make_dwo(&dwo_parent); - } else { - dwarf.file_type = gimli::DwarfFileType::Dwo; - } - } - - if let Some(sup_file) = flags.sup.as_ref() { - let mut load_sup_section = |id: gimli::SectionId| -> Result<_> { - // Note: we really only need the `.debug_str` section, - // but for now we load them all. - load_file_section(id, sup_file, endian, false, &arena_data, &arena_relocations) - }; - dwarf.load_sup(&mut load_sup_section)?; - } - - if flags.eh_frame { - let eh_frame = gimli::EhFrame::load(&mut load_section).unwrap(); - dump_eh_frame(w, file, eh_frame)?; - } - if flags.info { - dump_info(w, &dwarf, dwo_parent_units, flags)?; - dump_types(w, &dwarf, dwo_parent_units, flags)?; - } - if flags.line { - dump_line(w, &dwarf)?; - } - if flags.pubnames { - let debug_pubnames = &gimli::Section::load(&mut load_section).unwrap(); - dump_pubnames(w, debug_pubnames, &dwarf.debug_info)?; - } - if flags.aranges { - let debug_aranges = &gimli::Section::load(&mut load_section).unwrap(); - dump_aranges(w, debug_aranges)?; - } - if flags.pubtypes { - let debug_pubtypes = &gimli::Section::load(&mut load_section).unwrap(); - dump_pubtypes(w, debug_pubtypes, &dwarf.debug_info)?; - } - w.flush()?; - Ok(()) -} - -fn dump_eh_frame<R: Reader, W: Write>( - w: &mut W, - file: &object::File, - mut eh_frame: gimli::EhFrame<R>, -) -> Result<()> { - // TODO: this might be better based on the file format. - let address_size = file - .architecture() - .address_size() - .map(|w| w.bytes()) - .unwrap_or(mem::size_of::<usize>() as u8); - eh_frame.set_address_size(address_size); - - fn register_name_none(_: gimli::Register) -> Option<&'static str> { - None - } - let arch_register_name = match file.architecture() { - object::Architecture::Arm | object::Architecture::Aarch64 => gimli::Arm::register_name, - object::Architecture::I386 => gimli::X86::register_name, - object::Architecture::X86_64 => gimli::X86_64::register_name, - _ => register_name_none, - }; - let register_name = &|register| match arch_register_name(register) { - Some(name) => Cow::Borrowed(name), - None => Cow::Owned(format!("{}", register.0)), - }; - - let mut bases = gimli::BaseAddresses::default(); - if let Some(section) = file.section_by_name(".eh_frame_hdr") { - bases = bases.set_eh_frame_hdr(section.address()); - } - if let Some(section) = file.section_by_name(".eh_frame") { - bases = bases.set_eh_frame(section.address()); - } - if let Some(section) = file.section_by_name(".text") { - bases = bases.set_text(section.address()); - } - if let Some(section) = file.section_by_name(".got") { - bases = bases.set_got(section.address()); - } - - // TODO: Print "__eh_frame" here on macOS, and more generally use the - // section that we're actually looking at, which is what the canonical - // dwarfdump does. - writeln!( - w, - "Exception handling frame information for section .eh_frame" - )?; - - let mut cies = HashMap::new(); - - let mut entries = eh_frame.entries(&bases); - loop { - match entries.next()? { - None => return Ok(()), - Some(gimli::CieOrFde::Cie(cie)) => { - writeln!(w)?; - writeln!(w, "{:#010x}: CIE", cie.offset())?; - writeln!(w, " length: {:#010x}", cie.entry_len())?; - // TODO: CIE_id - writeln!(w, " version: {:#04x}", cie.version())?; - // TODO: augmentation - writeln!(w, " code_align: {}", cie.code_alignment_factor())?; - writeln!(w, " data_align: {}", cie.data_alignment_factor())?; - writeln!( - w, - " ra_register: {}", - register_name(cie.return_address_register()) - )?; - if let Some(encoding) = cie.lsda_encoding() { - writeln!( - w, - " lsda_encoding: {}/{}", - encoding.application(), - encoding.format() - )?; - } - if let Some((encoding, personality)) = cie.personality_with_encoding() { - write!( - w, - " personality: {}/{} ", - encoding.application(), - encoding.format() - )?; - dump_pointer(w, personality)?; - writeln!(w)?; - } - if let Some(encoding) = cie.fde_address_encoding() { - writeln!( - w, - " fde_encoding: {}/{}", - encoding.application(), - encoding.format() - )?; - } - let instructions = cie.instructions(&eh_frame, &bases); - dump_cfi_instructions(w, instructions, true, register_name)?; - writeln!(w)?; - } - Some(gimli::CieOrFde::Fde(partial)) => { - let mut offset = None; - let fde = partial.parse(|_, bases, o| { - offset = Some(o); - cies.entry(o) - .or_insert_with(|| eh_frame.cie_from_offset(bases, o)) - .clone() - })?; - - writeln!(w)?; - writeln!(w, "{:#010x}: FDE", fde.offset())?; - writeln!(w, " length: {:#010x}", fde.entry_len())?; - writeln!(w, " CIE_pointer: {:#010x}", offset.unwrap().0)?; - // TODO: symbolicate the start address like the canonical dwarfdump does. - writeln!(w, " start_addr: {:#018x}", fde.initial_address())?; - writeln!( - w, - " range_size: {:#018x} (end_addr = {:#018x})", - fde.len(), - fde.initial_address() + fde.len() - )?; - if let Some(lsda) = fde.lsda() { - write!(w, " lsda: ")?; - dump_pointer(w, lsda)?; - writeln!(w)?; - } - let instructions = fde.instructions(&eh_frame, &bases); - dump_cfi_instructions(w, instructions, false, register_name)?; - writeln!(w)?; - } - } - } -} - -fn dump_pointer<W: Write>(w: &mut W, p: gimli::Pointer) -> Result<()> { - match p { - gimli::Pointer::Direct(p) => { - write!(w, "{:#018x}", p)?; - } - gimli::Pointer::Indirect(p) => { - write!(w, "({:#018x})", p)?; - } - } - Ok(()) -} - -#[allow(clippy::unneeded_field_pattern)] -fn dump_cfi_instructions<R: Reader, W: Write>( - w: &mut W, - mut insns: gimli::CallFrameInstructionIter<R>, - is_initial: bool, - register_name: &dyn Fn(gimli::Register) -> Cow<'static, str>, -) -> Result<()> { - use gimli::CallFrameInstruction::*; - - // TODO: we need to actually evaluate these instructions as we iterate them - // so we can print the initialized state for CIEs, and each unwind row's - // registers for FDEs. - // - // TODO: We should print DWARF expressions for the CFI instructions that - // embed DWARF expressions within themselves. - - if !is_initial { - writeln!(w, " Instructions:")?; - } - - loop { - match insns.next() { - Err(e) => { - writeln!(w, "Failed to decode CFI instruction: {}", e)?; - return Ok(()); - } - Ok(None) => { - if is_initial { - writeln!(w, " Instructions: Init State:")?; - } - return Ok(()); - } - Ok(Some(op)) => match op { - SetLoc { address } => { - writeln!(w, " DW_CFA_set_loc ({:#x})", address)?; - } - AdvanceLoc { delta } => { - writeln!(w, " DW_CFA_advance_loc ({})", delta)?; - } - DefCfa { register, offset } => { - writeln!( - w, - " DW_CFA_def_cfa ({}, {})", - register_name(register), - offset - )?; - } - DefCfaSf { - register, - factored_offset, - } => { - writeln!( - w, - " DW_CFA_def_cfa_sf ({}, {})", - register_name(register), - factored_offset - )?; - } - DefCfaRegister { register } => { - writeln!( - w, - " DW_CFA_def_cfa_register ({})", - register_name(register) - )?; - } - DefCfaOffset { offset } => { - writeln!(w, " DW_CFA_def_cfa_offset ({})", offset)?; - } - DefCfaOffsetSf { factored_offset } => { - writeln!( - w, - " DW_CFA_def_cfa_offset_sf ({})", - factored_offset - )?; - } - DefCfaExpression { expression: _ } => { - writeln!(w, " DW_CFA_def_cfa_expression (...)")?; - } - Undefined { register } => { - writeln!( - w, - " DW_CFA_undefined ({})", - register_name(register) - )?; - } - SameValue { register } => { - writeln!( - w, - " DW_CFA_same_value ({})", - register_name(register) - )?; - } - Offset { - register, - factored_offset, - } => { - writeln!( - w, - " DW_CFA_offset ({}, {})", - register_name(register), - factored_offset - )?; - } - OffsetExtendedSf { - register, - factored_offset, - } => { - writeln!( - w, - " DW_CFA_offset_extended_sf ({}, {})", - register_name(register), - factored_offset - )?; - } - ValOffset { - register, - factored_offset, - } => { - writeln!( - w, - " DW_CFA_val_offset ({}, {})", - register_name(register), - factored_offset - )?; - } - ValOffsetSf { - register, - factored_offset, - } => { - writeln!( - w, - " DW_CFA_val_offset_sf ({}, {})", - register_name(register), - factored_offset - )?; - } - Register { - dest_register, - src_register, - } => { - writeln!( - w, - " DW_CFA_register ({}, {})", - register_name(dest_register), - register_name(src_register) - )?; - } - Expression { - register, - expression: _, - } => { - writeln!( - w, - " DW_CFA_expression ({}, ...)", - register_name(register) - )?; - } - ValExpression { - register, - expression: _, - } => { - writeln!( - w, - " DW_CFA_val_expression ({}, ...)", - register_name(register) - )?; - } - Restore { register } => { - writeln!( - w, - " DW_CFA_restore ({})", - register_name(register) - )?; - } - RememberState => { - writeln!(w, " DW_CFA_remember_state")?; - } - RestoreState => { - writeln!(w, " DW_CFA_restore_state")?; - } - ArgsSize { size } => { - writeln!(w, " DW_CFA_GNU_args_size ({})", size)?; - } - Nop => { - writeln!(w, " DW_CFA_nop")?; - } - }, - } - } -} - -fn dump_dwp<R: Reader, W: Write + Send>( - w: &mut W, - dwp: &gimli::DwarfPackage<R>, - dwo_parent: &gimli::Dwarf<R>, - dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>, - flags: &Flags, -) -> Result<()> -where - R::Endian: Send + Sync, -{ - if dwp.cu_index.unit_count() != 0 { - writeln!( - w, - "\n.debug_cu_index: version = {}, sections = {}, units = {}, slots = {}", - dwp.cu_index.version(), - dwp.cu_index.section_count(), - dwp.cu_index.unit_count(), - dwp.cu_index.slot_count(), - )?; - for i in 1..=dwp.cu_index.unit_count() { - writeln!(w, "\nCU index {}", i)?; - dump_dwp_sections( - w, - &dwp, - dwo_parent, - dwo_parent_units, - flags, - dwp.cu_index.sections(i)?, - )?; - } - } - - if dwp.tu_index.unit_count() != 0 { - writeln!( - w, - "\n.debug_tu_index: version = {}, sections = {}, units = {}, slots = {}", - dwp.tu_index.version(), - dwp.tu_index.section_count(), - dwp.tu_index.unit_count(), - dwp.tu_index.slot_count(), - )?; - for i in 1..=dwp.tu_index.unit_count() { - writeln!(w, "\nTU index {}", i)?; - dump_dwp_sections( - w, - &dwp, - dwo_parent, - dwo_parent_units, - flags, - dwp.tu_index.sections(i)?, - )?; - } - } - - Ok(()) -} - -fn dump_dwp_sections<R: Reader, W: Write + Send>( - w: &mut W, - dwp: &gimli::DwarfPackage<R>, - dwo_parent: &gimli::Dwarf<R>, - dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>, - flags: &Flags, - sections: gimli::UnitIndexSectionIterator<R>, -) -> Result<()> -where - R::Endian: Send + Sync, -{ - for section in sections.clone() { - writeln!( - w, - " {}: offset = 0x{:x}, size = 0x{:x}", - section.section.dwo_name().unwrap(), - section.offset, - section.size - )?; - } - let dwarf = dwp.sections(sections, dwo_parent)?; - if flags.info { - dump_info(w, &dwarf, dwo_parent_units, flags)?; - dump_types(w, &dwarf, dwo_parent_units, flags)?; - } - if flags.line { - dump_line(w, &dwarf)?; - } - Ok(()) -} - -fn dump_info<R: Reader, W: Write + Send>( - w: &mut W, - dwarf: &gimli::Dwarf<R>, - dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>, - flags: &Flags, -) -> Result<()> -where - R::Endian: Send + Sync, -{ - writeln!(w, "\n.debug_info")?; - - let units = match dwarf.units().collect::<Vec<_>>() { - Ok(units) => units, - Err(err) => { - writeln_error( - w, - dwarf, - Error::GimliError(err), - "Failed to read unit headers", - )?; - return Ok(()); - } - }; - let process_unit = |header: UnitHeader<R>, buf: &mut Vec<u8>| -> Result<()> { - dump_unit(buf, header, dwarf, dwo_parent_units, flags)?; - if !flags - .match_units - .as_ref() - .map(|r| r.is_match(&buf)) - .unwrap_or(true) - { - buf.clear(); - } - Ok(()) - }; - // Don't use more than 16 cores even if available. No point in soaking hundreds - // of cores if you happen to have them. - parallel_output(w, 16, units, process_unit) -} - -fn dump_types<R: Reader, W: Write>( - w: &mut W, - dwarf: &gimli::Dwarf<R>, - dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>, - flags: &Flags, -) -> Result<()> { - writeln!(w, "\n.debug_types")?; - - let mut iter = dwarf.type_units(); - while let Some(header) = iter.next()? { - dump_unit(w, header, dwarf, dwo_parent_units, flags)?; - } - Ok(()) -} - -fn dump_unit<R: Reader, W: Write>( - w: &mut W, - header: UnitHeader<R>, - dwarf: &gimli::Dwarf<R>, - dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>, - flags: &Flags, -) -> Result<()> { - write!(w, "\nUNIT<")?; - match header.offset() { - UnitSectionOffset::DebugInfoOffset(o) => { - write!(w, ".debug_info+0x{:08x}", o.0)?; - } - UnitSectionOffset::DebugTypesOffset(o) => { - write!(w, ".debug_types+0x{:08x}", o.0)?; - } - } - writeln!(w, ">: length = 0x{:x}, format = {:?}, version = {}, address_size = {}, abbrev_offset = 0x{:x}", - header.unit_length(), - header.format(), - header.version(), - header.address_size(), - header.debug_abbrev_offset().0, - )?; - - match header.type_() { - UnitType::Compilation | UnitType::Partial => (), - UnitType::Type { - type_signature, - type_offset, - } - | UnitType::SplitType { - type_signature, - type_offset, - } => { - write!(w, " signature = ")?; - dump_type_signature(w, type_signature)?; - writeln!(w)?; - writeln!(w, " type_offset = 0x{:x}", type_offset.0,)?; - } - UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => { - write!(w, " dwo_id = ")?; - writeln!(w, "0x{:016x}", dwo_id.0)?; - } - } - - let mut unit = match dwarf.unit(header) { - Ok(unit) => unit, - Err(err) => { - writeln_error(w, dwarf, err.into(), "Failed to parse unit root entry")?; - return Ok(()); - } - }; - - if let Some(dwo_parent_units) = dwo_parent_units { - if let Some(dwo_id) = unit.dwo_id { - if let Some(parent_unit) = dwo_parent_units.get(&dwo_id) { - unit.copy_relocated_attributes(parent_unit); - } - } - } - - let entries_result = dump_entries(w, unit, dwarf, flags); - if let Err(err) = entries_result { - writeln_error(w, dwarf, err, "Failed to dump entries")?; - } - Ok(()) -} - -fn spaces(buf: &mut String, len: usize) -> &str { - while buf.len() < len { - buf.push(' '); - } - &buf[..len] -} - -// " GOFF=0x{:08x}" adds exactly 16 spaces. -const GOFF_SPACES: usize = 16; - -fn write_offset<R: Reader, W: Write>( - w: &mut W, - unit: &gimli::Unit<R>, - offset: gimli::UnitOffset<R::Offset>, - flags: &Flags, -) -> Result<()> { - write!(w, "<0x{:08x}", offset.0)?; - if flags.goff { - let goff = match offset.to_unit_section_offset(unit) { - UnitSectionOffset::DebugInfoOffset(o) => o.0, - UnitSectionOffset::DebugTypesOffset(o) => o.0, - }; - write!(w, " GOFF=0x{:08x}", goff)?; - } - write!(w, ">")?; - Ok(()) -} - -fn dump_entries<R: Reader, W: Write>( - w: &mut W, - unit: gimli::Unit<R>, - dwarf: &gimli::Dwarf<R>, - flags: &Flags, -) -> Result<()> { - let mut spaces_buf = String::new(); - - let mut entries = unit.entries_raw(None)?; - while !entries.is_empty() { - let offset = entries.next_offset(); - let depth = entries.next_depth(); - let abbrev = entries.read_abbreviation()?; - - let mut indent = if depth >= 0 { - depth as usize * 2 + 2 - } else { - 2 - }; - write!(w, "<{}{}>", if depth < 10 { " " } else { "" }, depth)?; - write_offset(w, &unit, offset, flags)?; - writeln!( - w, - "{}{}", - spaces(&mut spaces_buf, indent), - abbrev.map(|x| x.tag()).unwrap_or(gimli::DW_TAG_null) - )?; - - indent += 18; - if flags.goff { - indent += GOFF_SPACES; - } - - for spec in abbrev.map(|x| x.attributes()).unwrap_or(&[]) { - let attr = entries.read_attribute(*spec)?; - w.write_all(spaces(&mut spaces_buf, indent).as_bytes())?; - if let Some(n) = attr.name().static_string() { - let right_padding = 27 - std::cmp::min(27, n.len()); - write!(w, "{}{} ", n, spaces(&mut spaces_buf, right_padding))?; - } else { - write!(w, "{:27} ", attr.name())?; - } - if flags.raw { - writeln!(w, "{:?}", attr.raw_value())?; - } else { - match dump_attr_value(w, &attr, &unit, dwarf) { - Ok(_) => (), - Err(err) => writeln_error(w, dwarf, err, "Failed to dump attribute value")?, - }; - } - } - } - Ok(()) -} - -fn dump_attr_value<R: Reader, W: Write>( - w: &mut W, - attr: &gimli::Attribute<R>, - unit: &gimli::Unit<R>, - dwarf: &gimli::Dwarf<R>, -) -> Result<()> { - let value = attr.value(); - match value { - gimli::AttributeValue::Addr(address) => { - writeln!(w, "0x{:08x}", address)?; - } - gimli::AttributeValue::Block(data) => { - for byte in data.to_slice()?.iter() { - write!(w, "{:02x}", byte)?; - } - writeln!(w)?; - } - gimli::AttributeValue::Data1(_) - | gimli::AttributeValue::Data2(_) - | gimli::AttributeValue::Data4(_) - | gimli::AttributeValue::Data8(_) => { - if let (Some(udata), Some(sdata)) = (attr.udata_value(), attr.sdata_value()) { - if sdata >= 0 { - writeln!(w, "{}", udata)?; - } else { - writeln!(w, "{} ({})", udata, sdata)?; - } - } else { - writeln!(w, "{:?}", value)?; - } - } - gimli::AttributeValue::Sdata(data) => { - match attr.name() { - gimli::DW_AT_data_member_location => { - writeln!(w, "{}", data)?; - } - _ => { - if data >= 0 { - writeln!(w, "0x{:08x}", data)?; - } else { - writeln!(w, "0x{:08x} ({})", data, data)?; - } - } - }; - } - gimli::AttributeValue::Udata(data) => { - match attr.name() { - gimli::DW_AT_high_pc => { - writeln!(w, "<offset-from-lowpc>{}", data)?; - } - gimli::DW_AT_data_member_location => { - if let Some(sdata) = attr.sdata_value() { - // This is a DW_FORM_data* value. - // libdwarf-dwarfdump displays this as signed too. - if sdata >= 0 { - writeln!(w, "{}", data)?; - } else { - writeln!(w, "{} ({})", data, sdata)?; - } - } else { - writeln!(w, "{}", data)?; - } - } - gimli::DW_AT_lower_bound | gimli::DW_AT_upper_bound => { - writeln!(w, "{}", data)?; - } - _ => { - writeln!(w, "0x{:08x}", data)?; - } - }; - } - gimli::AttributeValue::Exprloc(ref data) => { - if let gimli::AttributeValue::Exprloc(_) = attr.raw_value() { - write!(w, "len 0x{:04x}: ", data.0.len())?; - for byte in data.0.to_slice()?.iter() { - write!(w, "{:02x}", byte)?; - } - write!(w, ": ")?; - } - dump_exprloc(w, unit.encoding(), data)?; - writeln!(w)?; - } - gimli::AttributeValue::Flag(true) => { - writeln!(w, "yes")?; - } - gimli::AttributeValue::Flag(false) => { - writeln!(w, "no")?; - } - gimli::AttributeValue::SecOffset(offset) => { - writeln!(w, "0x{:08x}", offset)?; - } - gimli::AttributeValue::DebugAddrBase(base) => { - writeln!(w, "<.debug_addr+0x{:08x}>", base.0)?; - } - gimli::AttributeValue::DebugAddrIndex(index) => { - write!(w, "(indirect address, index {:#x}): ", index.0)?; - let address = dwarf.address(unit, index)?; - writeln!(w, "0x{:08x}", address)?; - } - gimli::AttributeValue::UnitRef(offset) => { - write!(w, "0x{:08x}", offset.0)?; - match offset.to_unit_section_offset(unit) { - UnitSectionOffset::DebugInfoOffset(goff) => { - write!(w, "<.debug_info+0x{:08x}>", goff.0)?; - } - UnitSectionOffset::DebugTypesOffset(goff) => { - write!(w, "<.debug_types+0x{:08x}>", goff.0)?; - } - } - writeln!(w)?; - } - gimli::AttributeValue::DebugInfoRef(offset) => { - writeln!(w, "<.debug_info+0x{:08x}>", offset.0)?; - } - gimli::AttributeValue::DebugInfoRefSup(offset) => { - writeln!(w, "<.debug_info(sup)+0x{:08x}>", offset.0)?; - } - gimli::AttributeValue::DebugLineRef(offset) => { - writeln!(w, "<.debug_line+0x{:08x}>", offset.0)?; - } - gimli::AttributeValue::LocationListsRef(offset) => { - dump_loc_list(w, offset, unit, dwarf)?; - } - gimli::AttributeValue::DebugLocListsBase(base) => { - writeln!(w, "<.debug_loclists+0x{:08x}>", base.0)?; - } - gimli::AttributeValue::DebugLocListsIndex(index) => { - write!(w, "(indirect location list, index {:#x}): ", index.0)?; - let offset = dwarf.locations_offset(unit, index)?; - dump_loc_list(w, offset, unit, dwarf)?; - } - gimli::AttributeValue::DebugMacinfoRef(offset) => { - writeln!(w, "<.debug_macinfo+0x{:08x}>", offset.0)?; - } - gimli::AttributeValue::DebugMacroRef(offset) => { - writeln!(w, "<.debug_macro+0x{:08x}>", offset.0)?; - } - gimli::AttributeValue::RangeListsRef(offset) => { - let offset = dwarf.ranges_offset_from_raw(unit, offset); - dump_range_list(w, offset, unit, dwarf)?; - } - gimli::AttributeValue::DebugRngListsBase(base) => { - writeln!(w, "<.debug_rnglists+0x{:08x}>", base.0)?; - } - gimli::AttributeValue::DebugRngListsIndex(index) => { - write!(w, "(indirect range list, index {:#x}): ", index.0)?; - let offset = dwarf.ranges_offset(unit, index)?; - dump_range_list(w, offset, unit, dwarf)?; - } - gimli::AttributeValue::DebugTypesRef(signature) => { - dump_type_signature(w, signature)?; - writeln!(w, " <type signature>")?; - } - gimli::AttributeValue::DebugStrRef(offset) => { - if let Ok(s) = dwarf.debug_str.get_str(offset) { - writeln!(w, "{}", s.to_string_lossy()?)?; - } else { - writeln!(w, "<.debug_str+0x{:08x}>", offset.0)?; - } - } - gimli::AttributeValue::DebugStrRefSup(offset) => { - if let Some(s) = dwarf - .sup() - .and_then(|sup| sup.debug_str.get_str(offset).ok()) - { - writeln!(w, "{}", s.to_string_lossy()?)?; - } else { - writeln!(w, "<.debug_str(sup)+0x{:08x}>", offset.0)?; - } - } - gimli::AttributeValue::DebugStrOffsetsBase(base) => { - writeln!(w, "<.debug_str_offsets+0x{:08x}>", base.0)?; - } - gimli::AttributeValue::DebugStrOffsetsIndex(index) => { - write!(w, "(indirect string, index {:#x}): ", index.0)?; - let offset = dwarf.debug_str_offsets.get_str_offset( - unit.encoding().format, - unit.str_offsets_base, - index, - )?; - if let Ok(s) = dwarf.debug_str.get_str(offset) { - writeln!(w, "{}", s.to_string_lossy()?)?; - } else { - writeln!(w, "<.debug_str+0x{:08x}>", offset.0)?; - } - } - gimli::AttributeValue::DebugLineStrRef(offset) => { - if let Ok(s) = dwarf.debug_line_str.get_str(offset) { - writeln!(w, "{}", s.to_string_lossy()?)?; - } else { - writeln!(w, "<.debug_line_str=0x{:08x}>", offset.0)?; - } - } - gimli::AttributeValue::String(s) => { - writeln!(w, "{}", s.to_string_lossy()?)?; - } - gimli::AttributeValue::Encoding(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::DecimalSign(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::Endianity(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::Accessibility(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::Visibility(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::Virtuality(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::Language(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::AddressClass(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::IdentifierCase(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::CallingConvention(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::Inline(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::Ordering(value) => { - writeln!(w, "{}", value)?; - } - gimli::AttributeValue::FileIndex(value) => { - write!(w, "0x{:08x}", value)?; - dump_file_index(w, value, unit, dwarf)?; - writeln!(w)?; - } - gimli::AttributeValue::DwoId(value) => { - writeln!(w, "0x{:016x}", value.0)?; - } - } - - Ok(()) -} - -fn dump_type_signature<W: Write>(w: &mut W, signature: gimli::DebugTypeSignature) -> Result<()> { - write!(w, "0x{:016x}", signature.0)?; - Ok(()) -} - -fn dump_file_index<R: Reader, W: Write>( - w: &mut W, - file_index: u64, - unit: &gimli::Unit<R>, - dwarf: &gimli::Dwarf<R>, -) -> Result<()> { - if file_index == 0 && unit.header.version() <= 4 { - return Ok(()); - } - let header = match unit.line_program { - Some(ref program) => program.header(), - None => return Ok(()), - }; - let file = match header.file(file_index) { - Some(file) => file, - None => { - writeln!(w, "Unable to get header for file {}", file_index)?; - return Ok(()); - } - }; - write!(w, " ")?; - if let Some(directory) = file.directory(header) { - let directory = dwarf.attr_string(unit, directory)?; - let directory = directory.to_string_lossy()?; - if file.directory_index() != 0 && !directory.starts_with('/') { - if let Some(ref comp_dir) = unit.comp_dir { - write!(w, "{}/", comp_dir.to_string_lossy()?,)?; - } - } - write!(w, "{}/", directory)?; - } - write!( - w, - "{}", - dwarf - .attr_string(unit, file.path_name())? - .to_string_lossy()? - )?; - Ok(()) -} - -fn dump_exprloc<R: Reader, W: Write>( - w: &mut W, - encoding: gimli::Encoding, - data: &gimli::Expression<R>, -) -> Result<()> { - let mut pc = data.0.clone(); - let mut space = false; - while pc.len() != 0 { - let pc_clone = pc.clone(); - match gimli::Operation::parse(&mut pc, encoding) { - Ok(op) => { - if space { - write!(w, " ")?; - } else { - space = true; - } - dump_op(w, encoding, pc_clone, op)?; - } - Err(gimli::Error::InvalidExpression(op)) => { - writeln!(w, "WARNING: unsupported operation 0x{:02x}", op.0)?; - return Ok(()); - } - Err(gimli::Error::UnsupportedRegister(register)) => { - writeln!(w, "WARNING: unsupported register {}", register)?; - return Ok(()); - } - Err(gimli::Error::UnexpectedEof(_)) => { - writeln!(w, "WARNING: truncated or malformed expression")?; - return Ok(()); - } - Err(e) => { - writeln!(w, "WARNING: unexpected operation parse error: {}", e)?; - return Ok(()); - } - } - } - Ok(()) -} - -fn dump_op<R: Reader, W: Write>( - w: &mut W, - encoding: gimli::Encoding, - mut pc: R, - op: gimli::Operation<R>, -) -> Result<()> { - let dwop = gimli::DwOp(pc.read_u8()?); - write!(w, "{}", dwop)?; - match op { - gimli::Operation::Deref { - base_type, size, .. - } => { - if dwop == gimli::DW_OP_deref_size || dwop == gimli::DW_OP_xderef_size { - write!(w, " {}", size)?; - } - if base_type != UnitOffset(0) { - write!(w, " type 0x{:08x}", base_type.0)?; - } - } - gimli::Operation::Pick { index } => { - if dwop == gimli::DW_OP_pick { - write!(w, " {}", index)?; - } - } - gimli::Operation::PlusConstant { value } => { - write!(w, " {}", value as i64)?; - } - gimli::Operation::Bra { target } => { - write!(w, " {}", target)?; - } - gimli::Operation::Skip { target } => { - write!(w, " {}", target)?; - } - gimli::Operation::SignedConstant { value } => match dwop { - gimli::DW_OP_const1s - | gimli::DW_OP_const2s - | gimli::DW_OP_const4s - | gimli::DW_OP_const8s - | gimli::DW_OP_consts => { - write!(w, " {}", value)?; - } - _ => {} - }, - gimli::Operation::UnsignedConstant { value } => match dwop { - gimli::DW_OP_const1u - | gimli::DW_OP_const2u - | gimli::DW_OP_const4u - | gimli::DW_OP_const8u - | gimli::DW_OP_constu => { - write!(w, " {}", value)?; - } - _ => { - // These have the value encoded in the operation, eg DW_OP_lit0. - } - }, - gimli::Operation::Register { register } => { - if dwop == gimli::DW_OP_regx { - write!(w, " {}", register.0)?; - } - } - gimli::Operation::RegisterOffset { - register, - offset, - base_type, - } => { - if dwop >= gimli::DW_OP_breg0 && dwop <= gimli::DW_OP_breg31 { - write!(w, "{:+}", offset)?; - } else { - write!(w, " {}", register.0)?; - if offset != 0 { - write!(w, "{:+}", offset)?; - } - if base_type != UnitOffset(0) { - write!(w, " type 0x{:08x}", base_type.0)?; - } - } - } - gimli::Operation::FrameOffset { offset } => { - write!(w, " {}", offset)?; - } - gimli::Operation::Call { offset } => match offset { - gimli::DieReference::UnitRef(gimli::UnitOffset(offset)) => { - write!(w, " 0x{:08x}", offset)?; - } - gimli::DieReference::DebugInfoRef(gimli::DebugInfoOffset(offset)) => { - write!(w, " 0x{:08x}", offset)?; - } - }, - gimli::Operation::Piece { - size_in_bits, - bit_offset: None, - } => { - write!(w, " {}", size_in_bits / 8)?; - } - gimli::Operation::Piece { - size_in_bits, - bit_offset: Some(bit_offset), - } => { - write!(w, " 0x{:08x} offset 0x{:08x}", size_in_bits, bit_offset)?; - } - gimli::Operation::ImplicitValue { data } => { - let data = data.to_slice()?; - write!(w, " 0x{:08x} contents 0x", data.len())?; - for byte in data.iter() { - write!(w, "{:02x}", byte)?; - } - } - gimli::Operation::ImplicitPointer { value, byte_offset } => { - write!(w, " 0x{:08x} {}", value.0, byte_offset)?; - } - gimli::Operation::EntryValue { expression } => { - write!(w, "(")?; - dump_exprloc(w, encoding, &gimli::Expression(expression))?; - write!(w, ")")?; - } - gimli::Operation::ParameterRef { offset } => { - write!(w, " 0x{:08x}", offset.0)?; - } - gimli::Operation::Address { address } => { - write!(w, " 0x{:08x}", address)?; - } - gimli::Operation::AddressIndex { index } => { - write!(w, " 0x{:08x}", index.0)?; - } - gimli::Operation::ConstantIndex { index } => { - write!(w, " 0x{:08x}", index.0)?; - } - gimli::Operation::TypedLiteral { base_type, value } => { - write!(w, " type 0x{:08x} contents 0x", base_type.0)?; - for byte in value.to_slice()?.iter() { - write!(w, "{:02x}", byte)?; - } - } - gimli::Operation::Convert { base_type } => { - write!(w, " type 0x{:08x}", base_type.0)?; - } - gimli::Operation::Reinterpret { base_type } => { - write!(w, " type 0x{:08x}", base_type.0)?; - } - gimli::Operation::WasmLocal { index } - | gimli::Operation::WasmGlobal { index } - | gimli::Operation::WasmStack { index } => { - let wasmop = pc.read_u8()?; - write!(w, " 0x{:x} 0x{:x}", wasmop, index)?; - } - gimli::Operation::Drop - | gimli::Operation::Swap - | gimli::Operation::Rot - | gimli::Operation::Abs - | gimli::Operation::And - | gimli::Operation::Div - | gimli::Operation::Minus - | gimli::Operation::Mod - | gimli::Operation::Mul - | gimli::Operation::Neg - | gimli::Operation::Not - | gimli::Operation::Or - | gimli::Operation::Plus - | gimli::Operation::Shl - | gimli::Operation::Shr - | gimli::Operation::Shra - | gimli::Operation::Xor - | gimli::Operation::Eq - | gimli::Operation::Ge - | gimli::Operation::Gt - | gimli::Operation::Le - | gimli::Operation::Lt - | gimli::Operation::Ne - | gimli::Operation::Nop - | gimli::Operation::PushObjectAddress - | gimli::Operation::TLS - | gimli::Operation::CallFrameCFA - | gimli::Operation::StackValue => {} - }; - Ok(()) -} - -fn dump_range<W: Write>(w: &mut W, range: Option<gimli::Range>) -> Result<()> { - if let Some(range) = range { - write!(w, " [0x{:08x}, 0x{:08x}]", range.begin, range.end)?; - } else { - write!(w, " [ignored]")?; - } - Ok(()) -} - -fn dump_loc_list<R: Reader, W: Write>( - w: &mut W, - offset: gimli::LocationListsOffset<R::Offset>, - unit: &gimli::Unit<R>, - dwarf: &gimli::Dwarf<R>, -) -> Result<()> { - let mut locations = dwarf.locations(unit, offset)?; - writeln!( - w, - "<loclist at {}+0x{:08x}>", - if unit.encoding().version < 5 { - ".debug_loc" - } else { - ".debug_loclists" - }, - offset.0, - )?; - let mut i = 0; - while let Some(raw) = locations.next_raw()? { - write!(w, "\t\t\t[{:2}]", i)?; - i += 1; - let range = locations - .convert_raw(raw.clone())? - .map(|location| location.range); - match raw { - gimli::RawLocListEntry::BaseAddress { addr } => { - writeln!(w, "<base-address 0x{:08x}>", addr)?; - } - gimli::RawLocListEntry::BaseAddressx { addr } => { - let addr_val = dwarf.address(unit, addr)?; - writeln!(w, "<base-addressx [{}]0x{:08x}>", addr.0, addr_val)?; - } - gimli::RawLocListEntry::StartxEndx { - begin, - end, - ref data, - } => { - let begin_val = dwarf.address(unit, begin)?; - let end_val = dwarf.address(unit, end)?; - write!( - w, - "<startx-endx [{}]0x{:08x}, [{}]0x{:08x}>", - begin.0, begin_val, end.0, end_val, - )?; - dump_range(w, range)?; - dump_exprloc(w, unit.encoding(), data)?; - writeln!(w)?; - } - gimli::RawLocListEntry::StartxLength { - begin, - length, - ref data, - } => { - let begin_val = dwarf.address(unit, begin)?; - write!( - w, - "<startx-length [{}]0x{:08x}, 0x{:08x}>", - begin.0, begin_val, length, - )?; - dump_range(w, range)?; - dump_exprloc(w, unit.encoding(), data)?; - writeln!(w)?; - } - gimli::RawLocListEntry::AddressOrOffsetPair { - begin, - end, - ref data, - } - | gimli::RawLocListEntry::OffsetPair { - begin, - end, - ref data, - } => { - write!(w, "<offset-pair 0x{:08x}, 0x{:08x}>", begin, end)?; - dump_range(w, range)?; - dump_exprloc(w, unit.encoding(), data)?; - writeln!(w)?; - } - gimli::RawLocListEntry::DefaultLocation { ref data } => { - write!(w, "<default location>")?; - dump_exprloc(w, unit.encoding(), data)?; - writeln!(w)?; - } - gimli::RawLocListEntry::StartEnd { - begin, - end, - ref data, - } => { - write!(w, "<start-end 0x{:08x}, 0x{:08x}>", begin, end)?; - dump_range(w, range)?; - dump_exprloc(w, unit.encoding(), data)?; - writeln!(w)?; - } - gimli::RawLocListEntry::StartLength { - begin, - length, - ref data, - } => { - write!(w, "<start-length 0x{:08x}, 0x{:08x}>", begin, length)?; - dump_range(w, range)?; - dump_exprloc(w, unit.encoding(), data)?; - writeln!(w)?; - } - }; - } - Ok(()) -} - -fn dump_range_list<R: Reader, W: Write>( - w: &mut W, - offset: gimli::RangeListsOffset<R::Offset>, - unit: &gimli::Unit<R>, - dwarf: &gimli::Dwarf<R>, -) -> Result<()> { - let mut ranges = dwarf.ranges(unit, offset)?; - writeln!( - w, - "<rnglist at {}+0x{:08x}>", - if unit.encoding().version < 5 { - ".debug_ranges" - } else { - ".debug_rnglists" - }, - offset.0, - )?; - let mut i = 0; - while let Some(raw) = ranges.next_raw()? { - write!(w, "\t\t\t[{:2}] ", i)?; - i += 1; - let range = ranges.convert_raw(raw.clone())?; - match raw { - gimli::RawRngListEntry::BaseAddress { addr } => { - writeln!(w, "<new base address 0x{:08x}>", addr)?; - } - gimli::RawRngListEntry::BaseAddressx { addr } => { - let addr_val = dwarf.address(unit, addr)?; - writeln!(w, "<new base addressx [{}]0x{:08x}>", addr.0, addr_val)?; - } - gimli::RawRngListEntry::StartxEndx { begin, end } => { - let begin_val = dwarf.address(unit, begin)?; - let end_val = dwarf.address(unit, end)?; - write!( - w, - "<startx-endx [{}]0x{:08x}, [{}]0x{:08x}>", - begin.0, begin_val, end.0, end_val, - )?; - dump_range(w, range)?; - writeln!(w)?; - } - gimli::RawRngListEntry::StartxLength { begin, length } => { - let begin_val = dwarf.address(unit, begin)?; - write!( - w, - "<startx-length [{}]0x{:08x}, 0x{:08x}>", - begin.0, begin_val, length, - )?; - dump_range(w, range)?; - writeln!(w)?; - } - gimli::RawRngListEntry::AddressOrOffsetPair { begin, end } - | gimli::RawRngListEntry::OffsetPair { begin, end } => { - write!(w, "<offset-pair 0x{:08x}, 0x{:08x}>", begin, end)?; - dump_range(w, range)?; - writeln!(w)?; - } - gimli::RawRngListEntry::StartEnd { begin, end } => { - write!(w, "<start-end 0x{:08x}, 0x{:08x}>", begin, end)?; - dump_range(w, range)?; - writeln!(w)?; - } - gimli::RawRngListEntry::StartLength { begin, length } => { - write!(w, "<start-length 0x{:08x}, 0x{:08x}>", begin, length)?; - dump_range(w, range)?; - writeln!(w)?; - } - }; - } - Ok(()) -} - -fn dump_line<R: Reader, W: Write>(w: &mut W, dwarf: &gimli::Dwarf<R>) -> Result<()> { - let mut iter = dwarf.units(); - while let Some(header) = iter.next()? { - writeln!( - w, - "\n.debug_line: line number info for unit at .debug_info offset 0x{:08x}", - header.offset().as_debug_info_offset().unwrap().0 - )?; - let unit = match dwarf.unit(header) { - Ok(unit) => unit, - Err(err) => { - writeln_error( - w, - dwarf, - err.into(), - "Failed to parse unit root entry for dump_line", - )?; - continue; - } - }; - match dump_line_program(w, &unit, dwarf) { - Ok(_) => (), - Err(Error::IoError) => return Err(Error::IoError), - Err(err) => writeln_error(w, dwarf, err, "Failed to dump line program")?, - } - } - Ok(()) -} - -fn dump_line_program<R: Reader, W: Write>( - w: &mut W, - unit: &gimli::Unit<R>, - dwarf: &gimli::Dwarf<R>, -) -> Result<()> { - if let Some(program) = unit.line_program.clone() { - { - let header = program.header(); - writeln!(w)?; - writeln!( - w, - "Offset: 0x{:x}", - header.offset().0 - )?; - writeln!( - w, - "Length: {}", - header.unit_length() - )?; - writeln!( - w, - "DWARF version: {}", - header.version() - )?; - writeln!( - w, - "Address size: {}", - header.address_size() - )?; - writeln!( - w, - "Prologue length: {}", - header.header_length() - )?; - writeln!( - w, - "Minimum instruction length: {}", - header.minimum_instruction_length() - )?; - writeln!( - w, - "Maximum operations per instruction: {}", - header.maximum_operations_per_instruction() - )?; - writeln!( - w, - "Default is_stmt: {}", - header.default_is_stmt() - )?; - writeln!( - w, - "Line base: {}", - header.line_base() - )?; - writeln!( - w, - "Line range: {}", - header.line_range() - )?; - writeln!( - w, - "Opcode base: {}", - header.opcode_base() - )?; - - writeln!(w)?; - writeln!(w, "Opcodes:")?; - for (i, length) in header - .standard_opcode_lengths() - .to_slice()? - .iter() - .enumerate() - { - writeln!(w, " Opcode {} has {} args", i + 1, length)?; - } - - let base = if header.version() >= 5 { 0 } else { 1 }; - writeln!(w)?; - writeln!(w, "The Directory Table:")?; - for (i, dir) in header.include_directories().iter().enumerate() { - writeln!( - w, - " {} {}", - base + i, - dwarf.attr_string(unit, dir.clone())?.to_string_lossy()? - )?; - } - - writeln!(w)?; - writeln!(w, "The File Name Table")?; - write!(w, " Entry\tDir\tTime\tSize")?; - if header.file_has_md5() { - write!(w, "\tMD5\t\t\t\t")?; - } - writeln!(w, "\tName")?; - for (i, file) in header.file_names().iter().enumerate() { - write!( - w, - " {}\t{}\t{}\t{}", - base + i, - file.directory_index(), - file.timestamp(), - file.size(), - )?; - if header.file_has_md5() { - let md5 = file.md5(); - write!(w, "\t")?; - for i in 0..16 { - write!(w, "{:02X}", md5[i])?; - } - } - writeln!( - w, - "\t{}", - dwarf - .attr_string(unit, file.path_name())? - .to_string_lossy()? - )?; - } - - writeln!(w)?; - writeln!(w, "Line Number Instructions:")?; - let mut instructions = header.instructions(); - while let Some(instruction) = instructions.next_instruction(header)? { - writeln!(w, " {}", instruction)?; - } - - writeln!(w)?; - writeln!(w, "Line Number Rows:")?; - writeln!(w, "<pc> [lno,col]")?; - } - let mut rows = program.rows(); - let mut file_index = std::u64::MAX; - while let Some((header, row)) = rows.next_row()? { - let line = match row.line() { - Some(line) => line.get(), - None => 0, - }; - let column = match row.column() { - gimli::ColumnType::Column(column) => column.get(), - gimli::ColumnType::LeftEdge => 0, - }; - write!(w, "0x{:08x} [{:4},{:2}]", row.address(), line, column)?; - if row.is_stmt() { - write!(w, " NS")?; - } - if row.basic_block() { - write!(w, " BB")?; - } - if row.end_sequence() { - write!(w, " ET")?; - } - if row.prologue_end() { - write!(w, " PE")?; - } - if row.epilogue_begin() { - write!(w, " EB")?; - } - if row.isa() != 0 { - write!(w, " IS={}", row.isa())?; - } - if row.discriminator() != 0 { - write!(w, " DI={}", row.discriminator())?; - } - if file_index != row.file_index() { - file_index = row.file_index(); - if let Some(file) = row.file(header) { - if let Some(directory) = file.directory(header) { - write!( - w, - " uri: \"{}/{}\"", - dwarf.attr_string(unit, directory)?.to_string_lossy()?, - dwarf - .attr_string(unit, file.path_name())? - .to_string_lossy()? - )?; - } else { - write!( - w, - " uri: \"{}\"", - dwarf - .attr_string(unit, file.path_name())? - .to_string_lossy()? - )?; - } - } - } - writeln!(w)?; - } - } - Ok(()) -} - -fn dump_pubnames<R: Reader, W: Write>( - w: &mut W, - debug_pubnames: &gimli::DebugPubNames<R>, - debug_info: &gimli::DebugInfo<R>, -) -> Result<()> { - writeln!(w, "\n.debug_pubnames")?; - - let mut cu_offset; - let mut cu_die_offset = gimli::DebugInfoOffset(0); - let mut prev_cu_offset = None; - let mut pubnames = debug_pubnames.items(); - while let Some(pubname) = pubnames.next()? { - cu_offset = pubname.unit_header_offset(); - if Some(cu_offset) != prev_cu_offset { - let cu = debug_info.header_from_offset(cu_offset)?; - cu_die_offset = gimli::DebugInfoOffset(cu_offset.0 + cu.header_size()); - prev_cu_offset = Some(cu_offset); - } - let die_in_cu = pubname.die_offset(); - let die_in_sect = cu_offset.0 + die_in_cu.0; - writeln!(w, - "global die-in-sect 0x{:08x}, cu-in-sect 0x{:08x}, die-in-cu 0x{:08x}, cu-header-in-sect 0x{:08x} '{}'", - die_in_sect, - cu_die_offset.0, - die_in_cu.0, - cu_offset.0, - pubname.name().to_string_lossy()? - )?; - } - Ok(()) -} - -fn dump_pubtypes<R: Reader, W: Write>( - w: &mut W, - debug_pubtypes: &gimli::DebugPubTypes<R>, - debug_info: &gimli::DebugInfo<R>, -) -> Result<()> { - writeln!(w, "\n.debug_pubtypes")?; - - let mut cu_offset; - let mut cu_die_offset = gimli::DebugInfoOffset(0); - let mut prev_cu_offset = None; - let mut pubtypes = debug_pubtypes.items(); - while let Some(pubtype) = pubtypes.next()? { - cu_offset = pubtype.unit_header_offset(); - if Some(cu_offset) != prev_cu_offset { - let cu = debug_info.header_from_offset(cu_offset)?; - cu_die_offset = gimli::DebugInfoOffset(cu_offset.0 + cu.header_size()); - prev_cu_offset = Some(cu_offset); - } - let die_in_cu = pubtype.die_offset(); - let die_in_sect = cu_offset.0 + die_in_cu.0; - writeln!(w, - "pubtype die-in-sect 0x{:08x}, cu-in-sect 0x{:08x}, die-in-cu 0x{:08x}, cu-header-in-sect 0x{:08x} '{}'", - die_in_sect, - cu_die_offset.0, - die_in_cu.0, - cu_offset.0, - pubtype.name().to_string_lossy()? - )?; - } - Ok(()) -} - -fn dump_aranges<R: Reader, W: Write>( - w: &mut W, - debug_aranges: &gimli::DebugAranges<R>, -) -> Result<()> { - writeln!(w, "\n.debug_aranges")?; - - let mut headers = debug_aranges.headers(); - while let Some(header) = headers.next()? { - writeln!( - w, - "Address Range Header: length = 0x{:08x}, version = 0x{:04x}, cu_offset = 0x{:08x}, addr_size = 0x{:02x}, seg_size = 0x{:02x}", - header.length(), - header.encoding().version, - header.debug_info_offset().0, - header.encoding().address_size, - header.segment_size(), - )?; - let mut aranges = header.entries(); - while let Some(arange) = aranges.next()? { - let range = arange.range(); - if let Some(segment) = arange.segment() { - writeln!( - w, - "[0x{:016x}, 0x{:016x}) segment 0x{:x}", - range.begin, range.end, segment - )?; - } else { - writeln!(w, "[0x{:016x}, 0x{:016x})", range.begin, range.end)?; - } - } - } - Ok(()) -} diff --git a/vendor/gimli/examples/simple.rs b/vendor/gimli/examples/simple.rs deleted file mode 100644 index 7c958d45c..000000000 --- a/vendor/gimli/examples/simple.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! A simple example of parsing `.debug_info`. - -use object::{Object, ObjectSection}; -use std::{borrow, env, fs}; - -fn main() { - for path in env::args().skip(1) { - let file = fs::File::open(&path).unwrap(); - let mmap = unsafe { memmap2::Mmap::map(&file).unwrap() }; - let object = object::File::parse(&*mmap).unwrap(); - let endian = if object.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - dump_file(&object, endian).unwrap(); - } -} - -fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), gimli::Error> { - // Load a section and return as `Cow<[u8]>`. - let load_section = |id: gimli::SectionId| -> Result<borrow::Cow<[u8]>, gimli::Error> { - match object.section_by_name(id.name()) { - Some(ref section) => Ok(section - .uncompressed_data() - .unwrap_or(borrow::Cow::Borrowed(&[][..]))), - None => Ok(borrow::Cow::Borrowed(&[][..])), - } - }; - - // Load all of the sections. - let dwarf_cow = gimli::Dwarf::load(&load_section)?; - - // Borrow a `Cow<[u8]>` to create an `EndianSlice`. - let borrow_section: &dyn for<'a> Fn( - &'a borrow::Cow<[u8]>, - ) -> gimli::EndianSlice<'a, gimli::RunTimeEndian> = - &|section| gimli::EndianSlice::new(&*section, endian); - - // Create `EndianSlice`s for all of the sections. - let dwarf = dwarf_cow.borrow(&borrow_section); - - // Iterate over the compilation units. - let mut iter = dwarf.units(); - while let Some(header) = iter.next()? { - println!( - "Unit at <.debug_info+0x{:x}>", - header.offset().as_debug_info_offset().unwrap().0 - ); - let unit = dwarf.unit(header)?; - - // Iterate over the Debugging Information Entries (DIEs) in the unit. - let mut depth = 0; - let mut entries = unit.entries(); - while let Some((delta_depth, entry)) = entries.next_dfs()? { - depth += delta_depth; - println!("<{}><{:x}> {}", depth, entry.offset().0, entry.tag()); - - // Iterate over the attributes in the DIE. - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next()? { - println!(" {}: {:?}", attr.name(), attr.value()); - } - } - } - Ok(()) -} diff --git a/vendor/gimli/examples/simple_line.rs b/vendor/gimli/examples/simple_line.rs deleted file mode 100644 index 87b224cda..000000000 --- a/vendor/gimli/examples/simple_line.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! A simple example of parsing `.debug_line`. - -use object::{Object, ObjectSection}; -use std::{borrow, env, fs, path}; - -fn main() { - for path in env::args().skip(1) { - let file = fs::File::open(&path).unwrap(); - let mmap = unsafe { memmap2::Mmap::map(&file).unwrap() }; - let object = object::File::parse(&*mmap).unwrap(); - let endian = if object.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - dump_file(&object, endian).unwrap(); - } -} - -fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), gimli::Error> { - // Load a section and return as `Cow<[u8]>`. - let load_section = |id: gimli::SectionId| -> Result<borrow::Cow<[u8]>, gimli::Error> { - match object.section_by_name(id.name()) { - Some(ref section) => Ok(section - .uncompressed_data() - .unwrap_or(borrow::Cow::Borrowed(&[][..]))), - None => Ok(borrow::Cow::Borrowed(&[][..])), - } - }; - - // Load all of the sections. - let dwarf_cow = gimli::Dwarf::load(&load_section)?; - - // Borrow a `Cow<[u8]>` to create an `EndianSlice`. - let borrow_section: &dyn for<'a> Fn( - &'a borrow::Cow<[u8]>, - ) -> gimli::EndianSlice<'a, gimli::RunTimeEndian> = - &|section| gimli::EndianSlice::new(&*section, endian); - - // Create `EndianSlice`s for all of the sections. - let dwarf = dwarf_cow.borrow(&borrow_section); - - // Iterate over the compilation units. - let mut iter = dwarf.units(); - while let Some(header) = iter.next()? { - println!( - "Line number info for unit at <.debug_info+0x{:x}>", - header.offset().as_debug_info_offset().unwrap().0 - ); - let unit = dwarf.unit(header)?; - - // Get the line program for the compilation unit. - if let Some(program) = unit.line_program.clone() { - let comp_dir = if let Some(ref dir) = unit.comp_dir { - path::PathBuf::from(dir.to_string_lossy().into_owned()) - } else { - path::PathBuf::new() - }; - - // Iterate over the line program rows. - let mut rows = program.rows(); - while let Some((header, row)) = rows.next_row()? { - if row.end_sequence() { - // End of sequence indicates a possible gap in addresses. - println!("{:x} end-sequence", row.address()); - } else { - // Determine the path. Real applications should cache this for performance. - let mut path = path::PathBuf::new(); - if let Some(file) = row.file(header) { - path = comp_dir.clone(); - - // The directory index 0 is defined to correspond to the compilation unit directory. - if file.directory_index() != 0 { - if let Some(dir) = file.directory(header) { - path.push( - dwarf.attr_string(&unit, dir)?.to_string_lossy().as_ref(), - ); - } - } - - path.push( - dwarf - .attr_string(&unit, file.path_name())? - .to_string_lossy() - .as_ref(), - ); - } - - // Determine line/column. DWARF line/column is never 0, so we use that - // but other applications may want to display this differently. - let line = match row.line() { - Some(line) => line.get(), - None => 0, - }; - let column = match row.column() { - gimli::ColumnType::LeftEdge => 0, - gimli::ColumnType::Column(column) => column.get(), - }; - - println!("{:x} {}:{}:{}", row.address(), path.display(), line, column); - } - } - } - } - Ok(()) -} diff --git a/vendor/gimli/fixtures/self/README.md b/vendor/gimli/fixtures/self/README.md deleted file mode 100644 index 91053d9b4..000000000 --- a/vendor/gimli/fixtures/self/README.md +++ /dev/null @@ -1,147 +0,0 @@ -# What are these files? - -These files are the DWARF data generated for (an early version of) this -library. Each file corresponds is a section from the built library's object -file. By splitting the sections out to their own files, we don't need to worry -about cross platform and cross object file format issues when running examples. - -# Updating and adding new sections - -## macOS - -Use `otool` to list the sections of a binary: - -``` -$ otool -l path/to/binary -``` - -You should see output similar to this: - -``` -Load command 0 - cmd LC_SEGMENT_64 - cmdsize 72 - segname __PAGEZERO - vmaddr 0x0000000000000000 - vmsize 0x0000000100000000 - fileoff 0 - filesize 0 - maxprot 0x00000000 - initprot 0x00000000 - nsects 0 - flags 0x0 -Load command 1 - cmd LC_SEGMENT_64 - cmdsize 712 - segname __TEXT - vmaddr 0x0000000100000000 - vmsize 0x00000000001b7000 - fileoff 0 - filesize 1798144 - maxprot 0x00000007 - initprot 0x00000005 - nsects 8 - flags 0x0 -Section - sectname __text - segname __TEXT - addr 0x0000000100000a50 - size 0x0000000000170716 - offset 2640 - align 2^4 (16) - reloff 0 - nreloc 0 - flags 0x80000400 - reserved1 0 - reserved2 0 -``` - -Etc. - -Find the `Section` entry of the section you'd like to isolate. For example, if -you're looking for `eh_frame`, find an entry like this: - -``` -Section - sectname __eh_frame - segname __TEXT - addr 0x0000000100192f38 - size 0x00000000000240c8 - offset 1650488 - align 2^3 (8) - reloff 0 - nreloc 0 - flags 0x00000000 - reserved1 0 - reserved2 0 -``` - -Then use `dd` to copy `size` bytes starting from `offset`: - -``` -$ dd bs=1 skip=1650488 count=$(printf "%d" 0x00000000000240c8) if=path/to/binary of=fixtures/self/eh_frame -``` - -Finally, use `otool` and `hexdump` to verify that the isolated section has the -same data as the section within the binary: - -``` -$ otool -s __TEXT __eh_frame path/to/binary | head -path/to/binary: -Contents of (__TEXT,__eh_frame) section -0000000100192f38 14 00 00 00 00 00 00 00 01 7a 52 00 01 78 10 01 -0000000100192f48 10 0c 07 08 90 01 00 00 24 00 00 00 1c 00 00 00 -0000000100192f58 f8 da e6 ff ff ff ff ff 66 00 00 00 00 00 00 00 -0000000100192f68 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00 -0000000100192f78 1c 00 00 00 00 00 00 00 01 7a 50 4c 52 00 01 78 -0000000100192f88 10 07 9b 9d 40 02 00 10 10 0c 07 08 90 01 00 00 -0000000100192f98 2c 00 00 00 24 00 00 00 20 db e6 ff ff ff ff ff -0000000100192fa8 8d 00 00 00 00 00 00 00 08 37 e7 fd ff ff ff ff - -$ otool -s __TEXT __eh_frame path/to/binary | tail -00000001001b6f68 9a 0a 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d -00000001001b6f78 06 50 83 07 8c 06 8d 05 8e 04 8f 03 00 00 00 00 -00000001001b6f88 24 00 00 00 7c 0e 00 00 30 a0 fb ff ff ff ff ff -00000001001b6f98 15 00 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d -00000001001b6fa8 06 00 00 00 00 00 00 00 24 00 00 00 a4 0e 00 00 -00000001001b6fb8 28 a0 fb ff ff ff ff ff 1c 00 00 00 00 00 00 00 -00000001001b6fc8 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00 -00000001001b6fd8 24 00 00 00 cc 0e 00 00 20 a0 fb ff ff ff ff ff -00000001001b6fe8 66 01 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d -00000001001b6ff8 06 00 00 00 00 00 00 00 -``` - -This should be the same, ignoring the leading offsets: - -``` -$ hexdump fixtures/self/eh_frame | head -0000000 14 00 00 00 00 00 00 00 01 7a 52 00 01 78 10 01 -0000010 10 0c 07 08 90 01 00 00 24 00 00 00 1c 00 00 00 -0000020 f8 da e6 ff ff ff ff ff 66 00 00 00 00 00 00 00 -0000030 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00 -0000040 1c 00 00 00 00 00 00 00 01 7a 50 4c 52 00 01 78 -0000050 10 07 9b 9d 40 02 00 10 10 0c 07 08 90 01 00 00 -0000060 2c 00 00 00 24 00 00 00 20 db e6 ff ff ff ff ff -0000070 8d 00 00 00 00 00 00 00 08 37 e7 fd ff ff ff ff -0000080 ff 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00 -0000090 24 00 00 00 94 00 00 00 80 db e6 ff ff ff ff ff - -$ hexdump fixtures/self/eh_frame | tail -0024040 06 50 83 07 8c 06 8d 05 8e 04 8f 03 00 00 00 00 -0024050 24 00 00 00 7c 0e 00 00 30 a0 fb ff ff ff ff ff -0024060 15 00 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d -0024070 06 00 00 00 00 00 00 00 24 00 00 00 a4 0e 00 00 -0024080 28 a0 fb ff ff ff ff ff 1c 00 00 00 00 00 00 00 -0024090 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00 -00240a0 24 00 00 00 cc 0e 00 00 20 a0 fb ff ff ff ff ff -00240b0 66 01 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d -00240c0 06 00 00 00 00 00 00 00 -``` - -## Linux - -Something like this: - -``` -objcopy --dump-section .eh_frame=fixtures/self/eh_frame path/to/binary -``` diff --git a/vendor/gimli/fixtures/self/debug_abbrev b/vendor/gimli/fixtures/self/debug_abbrev Binary files differdeleted file mode 100644 index 809e61152..000000000 --- a/vendor/gimli/fixtures/self/debug_abbrev +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_aranges b/vendor/gimli/fixtures/self/debug_aranges Binary files differdeleted file mode 100644 index b2d983d78..000000000 --- a/vendor/gimli/fixtures/self/debug_aranges +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_info b/vendor/gimli/fixtures/self/debug_info Binary files differdeleted file mode 100644 index aa430a5ce..000000000 --- a/vendor/gimli/fixtures/self/debug_info +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_inlined b/vendor/gimli/fixtures/self/debug_inlined Binary files differdeleted file mode 100644 index 949d18c93..000000000 --- a/vendor/gimli/fixtures/self/debug_inlined +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_line b/vendor/gimli/fixtures/self/debug_line Binary files differdeleted file mode 100644 index 896a07364..000000000 --- a/vendor/gimli/fixtures/self/debug_line +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_loc b/vendor/gimli/fixtures/self/debug_loc Binary files differdeleted file mode 100644 index 3fcdb32ba..000000000 --- a/vendor/gimli/fixtures/self/debug_loc +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_pubnames b/vendor/gimli/fixtures/self/debug_pubnames Binary files differdeleted file mode 100644 index bbcd62e24..000000000 --- a/vendor/gimli/fixtures/self/debug_pubnames +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_pubtypes b/vendor/gimli/fixtures/self/debug_pubtypes Binary files differdeleted file mode 100644 index 68b4e0405..000000000 --- a/vendor/gimli/fixtures/self/debug_pubtypes +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_ranges b/vendor/gimli/fixtures/self/debug_ranges Binary files differdeleted file mode 100644 index a5f52ed4a..000000000 --- a/vendor/gimli/fixtures/self/debug_ranges +++ /dev/null diff --git a/vendor/gimli/fixtures/self/debug_str b/vendor/gimli/fixtures/self/debug_str Binary files differdeleted file mode 100644 index da35ee574..000000000 --- a/vendor/gimli/fixtures/self/debug_str +++ /dev/null diff --git a/vendor/gimli/fixtures/self/eh_frame b/vendor/gimli/fixtures/self/eh_frame Binary files differdeleted file mode 100644 index 1d4df1a61..000000000 --- a/vendor/gimli/fixtures/self/eh_frame +++ /dev/null diff --git a/vendor/gimli/fixtures/self/eh_frame_hdr b/vendor/gimli/fixtures/self/eh_frame_hdr Binary files differdeleted file mode 100644 index a590ba213..000000000 --- a/vendor/gimli/fixtures/self/eh_frame_hdr +++ /dev/null diff --git a/vendor/gimli/rustfmt.toml b/vendor/gimli/rustfmt.toml deleted file mode 100644 index e69de29bb..000000000 --- a/vendor/gimli/rustfmt.toml +++ /dev/null diff --git a/vendor/gimli/src/arch.rs b/vendor/gimli/src/arch.rs index abc872d83..adb405280 100644 --- a/vendor/gimli/src/arch.rs +++ b/vendor/gimli/src/arch.rs @@ -44,7 +44,8 @@ macro_rules! registers { /// ARM architecture specific definitions. /// -/// See [DWARF for the ARM Architecture](https://developer.arm.com/documentation/ihi0040/c/). +/// See [DWARF for the ARM Architecture]( +/// https://github.com/ARM-software/abi-aa/blob/main/aadwarf32/aadwarf32.rst). #[derive(Debug, Clone, Copy)] pub struct Arm; @@ -99,6 +100,8 @@ registers!(Arm, { SPSR_UND = (132, "SPSR_UND"), SPSR_SVC = (133, "SPSR_SVC"), + RA_AUTH_CODE = (143, "RA_AUTH_CODE"), + R8_USR = (144, "R8_USR"), R9_USR = (145, "R9_USR"), R10_USR = (146, "R10_USR"), @@ -168,6 +171,11 @@ registers!(Arm, { D29 = (285, "D29"), D30 = (286, "D30"), D31 = (287, "D31"), + + TPIDRURO = (320, "TPIDRURO"), + TPIDRURW = (321, "TPIDRURW"), + TPIDPR = (322, "TPIDPR"), + HTPIDPR = (323, "HTPIDPR"), }, aliases { SP = (13, "SP"), @@ -219,7 +227,8 @@ aliases { /// ARM 64-bit (AArch64) architecture specific definitions. /// -/// See [DWARF for the ARM 64-bit Architecture](https://developer.arm.com/documentation/ihi0057/b/). +/// See [DWARF for the ARM 64-bit Architecture]( +/// https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst). #[derive(Debug, Clone, Copy)] pub struct AArch64; @@ -256,6 +265,14 @@ registers!(AArch64, { X29 = (29, "X29"), X30 = (30, "X30"), SP = (31, "SP"), + PC = (32, "PC"), + ELR_MODE = (33, "ELR_mode"), + RA_SIGN_STATE = (34, "RA_SIGN_STATE"), + TPIDRRO_EL0 = (35, "TPIDRRO_EL0"), + TPIDR_EL0 = (36, "TPIDR_EL0"), + TPIDR_EL1 = (37, "TPIDR_EL1"), + TPIDR_EL2 = (38, "TPIDR_EL2"), + TPIDR_EL3 = (39, "TPIDR_EL3"), V0 = (64, "V0"), V1 = (65, "V1"), diff --git a/vendor/gimli/src/common.rs b/vendor/gimli/src/common.rs index 3c8073622..fc6693d1c 100644 --- a/vendor/gimli/src/common.rs +++ b/vendor/gimli/src/common.rs @@ -27,6 +27,16 @@ impl Format { } } +/// Which vendor extensions to support. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum Vendor { + /// A default set of extensions, including some common GNU extensions. + Default, + /// AAarch64 extensions. + AArch64, +} + /// Encoding parameters that are commonly used for multiple DWARF sections. /// /// This is intended to be small enough to pass by value. diff --git a/vendor/gimli/src/constants.rs b/vendor/gimli/src/constants.rs index c617f4e2e..e58050ba0 100644 --- a/vendor/gimli/src/constants.rs +++ b/vendor/gimli/src/constants.rs @@ -56,7 +56,10 @@ use core::fmt; // } // } macro_rules! dw { - ($(#[$meta:meta])* $struct_name:ident($struct_type:ty) { $($name:ident = $val:expr),+ $(,)? }) => { + ($(#[$meta:meta])* $struct_name:ident($struct_type:ty) + { $($name:ident = $val:expr),+ $(,)? } + $(, aliases { $($alias_name:ident = $alias_val:expr),+ $(,)? })? + ) => { $(#[$meta])* #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct $struct_name(pub $struct_type); @@ -64,6 +67,9 @@ macro_rules! dw { $( pub const $name: $struct_name = $struct_name($val); )+ + $($( + pub const $alias_name: $struct_name = $struct_name($alias_val); + )+)* impl $struct_name { pub fn static_string(&self) -> Option<&'static str> { @@ -182,6 +188,9 @@ DwCfa(u8) { DW_CFA_GNU_window_save = 0x2d, DW_CFA_GNU_args_size = 0x2e, DW_CFA_GNU_negative_offset_extended = 0x2f, +}, +aliases { + DW_CFA_AARCH64_negate_ra_state = 0x2d, }); dw!( @@ -529,6 +538,7 @@ DwAt(u16) { DW_AT_GNU_all_call_sites = 0x2117, DW_AT_GNU_all_source_call_sites = 0x2118, DW_AT_GNU_macros = 0x2119, + DW_AT_GNU_deleted = 0x211a, // Extensions for Fission proposal. DW_AT_GNU_dwo_name = 0x2130, @@ -1276,7 +1286,7 @@ dw!( /// format of the pointer, the upper four bits describe how the encoding should /// be applied. /// -/// Defined in https://refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html +/// Defined in `<https://refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html>` DwEhPe(u8) { // Format of pointer encoding. diff --git a/vendor/gimli/src/lib.rs b/vendor/gimli/src/lib.rs index db30375aa..5dea34439 100644 --- a/vendor/gimli/src/lib.rs +++ b/vendor/gimli/src/lib.rs @@ -48,7 +48,7 @@ extern crate alloc; #[macro_use] extern crate std; -#[cfg(feature = "stable_deref_trait")] +#[cfg(feature = "endian-reader")] pub use stable_deref_trait::{CloneStableDeref, StableDeref}; mod common; @@ -62,7 +62,7 @@ pub mod constants; pub use crate::constants::*; mod endianity; -pub use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian, RunTimeEndian}; +pub use crate::endianity::*; pub mod leb128; diff --git a/vendor/gimli/src/read/cfi.rs b/vendor/gimli/src/read/cfi.rs index 5e9befac1..6ac019f10 100644 --- a/vendor/gimli/src/read/cfi.rs +++ b/vendor/gimli/src/read/cfi.rs @@ -8,7 +8,9 @@ use core::mem; use core::num::Wrapping; use super::util::{ArrayLike, ArrayVec}; -use crate::common::{DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId}; +use crate::common::{ + DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId, Vendor, +}; use crate::constants::{self, DwEhPe}; use crate::endianity::Endianity; use crate::read::{ @@ -34,6 +36,7 @@ pub struct DebugFrame<R: Reader> { section: R, address_size: u8, segment_size: u8, + vendor: Vendor, } impl<R: Reader> DebugFrame<R> { @@ -52,6 +55,13 @@ impl<R: Reader> DebugFrame<R> { pub fn set_segment_size(&mut self, segment_size: u8) { self.segment_size = segment_size } + + /// Set the vendor extensions to use. + /// + /// This defaults to `Vendor::Default`. + pub fn set_vendor(&mut self, vendor: Vendor) { + self.vendor = vendor; + } } impl<'input, Endian> DebugFrame<EndianSlice<'input, Endian>> @@ -95,6 +105,7 @@ impl<R: Reader> From<R> for DebugFrame<R> { section, address_size: mem::size_of::<usize>() as u8, segment_size: 0, + vendor: Vendor::Default, } } } @@ -158,11 +169,7 @@ impl<R: Reader> EhFrameHdr<R> { if fde_count_enc == constants::DW_EH_PE_omit || table_enc == constants::DW_EH_PE_omit { fde_count = 0 } else { - let ptr = parse_encoded_pointer(fde_count_enc, ¶meters, &mut reader)?; - fde_count = match ptr { - Pointer::Direct(c) => c, - Pointer::Indirect(_) => return Err(Error::UnsupportedPointerEncoding), - } + fde_count = parse_encoded_pointer(fde_count_enc, ¶meters, &mut reader)?.direct()?; } Ok(ParsedEhFrameHdr { @@ -348,11 +355,8 @@ impl<'a, R: Reader + 'a> EhHdrTable<'a, R> { let head = reader.split(R::Offset::from_u64((len / 2) * row_size)?)?; let tail = reader.clone(); - let pivot = parse_encoded_pointer(self.hdr.table_enc, ¶meters, &mut reader)?; - let pivot = match pivot { - Pointer::Direct(x) => x, - Pointer::Indirect(_) => return Err(Error::UnsupportedPointerEncoding), - }; + let pivot = + parse_encoded_pointer(self.hdr.table_enc, ¶meters, &mut reader)?.direct()?; match pivot.cmp(&address) { Ordering::Equal => { @@ -379,15 +383,8 @@ impl<'a, R: Reader + 'a> EhHdrTable<'a, R> { /// /// This does not support indirect pointers. pub fn pointer_to_offset(&self, ptr: Pointer) -> Result<EhFrameOffset<R::Offset>> { - let ptr = match ptr { - Pointer::Direct(x) => x, - _ => return Err(Error::UnsupportedPointerEncoding), - }; - - let eh_frame_ptr = match self.hdr.eh_frame_ptr() { - Pointer::Direct(x) => x, - _ => return Err(Error::UnsupportedPointerEncoding), - }; + let ptr = ptr.direct()?; + let eh_frame_ptr = self.hdr.eh_frame_ptr().direct()?; // Calculate the offset in the EhFrame section R::Offset::from_u64(ptr - eh_frame_ptr).map(EhFrameOffset) @@ -496,6 +493,7 @@ impl<'a, R: Reader + 'a> EhHdrTable<'a, R> { pub struct EhFrame<R: Reader> { section: R, address_size: u8, + vendor: Vendor, } impl<R: Reader> EhFrame<R> { @@ -505,6 +503,13 @@ impl<R: Reader> EhFrame<R> { pub fn set_address_size(&mut self, address_size: u8) { self.address_size = address_size } + + /// Set the vendor extensions to use. + /// + /// This defaults to `Vendor::Default`. + pub fn set_vendor(&mut self, vendor: Vendor) { + self.vendor = vendor; + } } impl<'input, Endian> EhFrame<EndianSlice<'input, Endian>> @@ -547,6 +552,7 @@ impl<R: Reader> From<R> for EhFrame<R> { EhFrame { section, address_size: mem::size_of::<usize>() as u8, + vendor: Vendor::Default, } } } @@ -627,6 +633,9 @@ pub trait _UnwindSectionPrivate<R: Reader> { /// The segment size to use if `has_address_and_segment_sizes` returns false. fn segment_size(&self) -> u8; + + /// The vendor extensions to use. + fn vendor(&self) -> Vendor; } /// A section holding unwind information: either `.debug_frame` or @@ -822,6 +831,10 @@ impl<R: Reader> _UnwindSectionPrivate<R> for DebugFrame<R> { fn segment_size(&self) -> u8 { self.segment_size } + + fn vendor(&self) -> Vendor { + self.vendor + } } impl<R: Reader> UnwindSection<R> for DebugFrame<R> { @@ -862,6 +875,10 @@ impl<R: Reader> _UnwindSectionPrivate<R> for EhFrame<R> { fn segment_size(&self) -> u8 { 0 } + + fn vendor(&self) -> Vendor { + self.vendor + } } impl<R: Reader> UnwindSection<R> for EhFrame<R> { @@ -1435,6 +1452,7 @@ impl<R: Reader> CommonInformationEntry<R> { address_size: self.address_size, section: section.section(), }, + vendor: section.vendor(), } } @@ -1683,12 +1701,12 @@ impl<R: Reader> FrameDescriptionEntry<R> { let initial_address = parse_encoded_pointer(encoding, parameters, input)?; // Ignore indirection. - let initial_address = initial_address.into(); + let initial_address = initial_address.pointer(); // Address ranges cannot be relative to anything, so just grab the // data format bits from the encoding. let address_range = parse_encoded_pointer(encoding.format(), parameters, input)?; - Ok((initial_address, address_range.into())) + Ok((initial_address, address_range.pointer())) } else { let initial_address = input.read_address(cie.address_size)?; let address_range = input.read_address(cie.address_size)?; @@ -1778,6 +1796,7 @@ impl<R: Reader> FrameDescriptionEntry<R> { address_size: self.cie.address_size, section: section.section(), }, + vendor: section.vendor(), } } @@ -2414,6 +2433,18 @@ impl<'a, 'ctx, R: Reader, A: UnwindContextStorage<R>> UnwindTable<'a, 'ctx, R, A self.ctx.row_mut().saved_args_size = size; } + // AArch64 extension. + NegateRaState => { + let register = crate::AArch64::RA_SIGN_STATE; + let value = match self.ctx.row().register(register) { + RegisterRule::Undefined => 0, + RegisterRule::Constant(value) => value, + _ => return Err(Error::CfiInstructionInInvalidContext), + }; + self.ctx + .set_register_rule(register, RegisterRule::Constant(value ^ 1))?; + } + // No operation. Nop => {} }; @@ -2783,6 +2814,7 @@ impl<R: Reader> CfaRule<R> { /// has been saved and the rule to find the value for the register in the /// previous frame." #[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] pub enum RegisterRule<R: Reader> { /// > A register that has this rule has no recoverable value in the previous /// > frame. (By convention, it is not preserved by a callee.) @@ -2815,6 +2847,9 @@ pub enum RegisterRule<R: Reader> { /// "The rule is defined externally to this specification by the augmenter." Architectural, + + /// This is a pseudo-register with a constant value. + Constant(u64), } impl<R: Reader> RegisterRule<R> { @@ -2825,6 +2860,7 @@ impl<R: Reader> RegisterRule<R> { /// A parsed call frame instruction. #[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] pub enum CallFrameInstruction<R: Reader> { // 6.4.2.1 Row Creation Methods /// > 1. DW_CFA_set_loc @@ -3102,6 +3138,17 @@ pub enum CallFrameInstruction<R: Reader> { size: u64, }, + /// > DW_CFA_AARCH64_negate_ra_state + /// > + /// > AArch64 Extension + /// > + /// > The DW_CFA_AARCH64_negate_ra_state operation negates bit[0] of the + /// > RA_SIGN_STATE pseudo-register. It does not take any operands. The + /// > DW_CFA_AARCH64_negate_ra_state must not be mixed with other DWARF Register + /// > Rule Instructions on the RA_SIGN_STATE pseudo-register in one Common + /// > Information Entry (CIE) and Frame Descriptor Entry (FDE) program sequence. + NegateRaState, + // 6.4.2.5 Padding Instruction /// > 1. DW_CFA_nop /// > @@ -3118,6 +3165,7 @@ impl<R: Reader> CallFrameInstruction<R> { input: &mut R, address_encoding: Option<DwEhPe>, parameters: &PointerEncodingParameters<R>, + vendor: Vendor, ) -> Result<CallFrameInstruction<R>> { let instruction = input.read_u8()?; let high_bits = instruction & CFI_INSTRUCTION_HIGH_BITS_MASK; @@ -3151,10 +3199,7 @@ impl<R: Reader> CallFrameInstruction<R> { constants::DW_CFA_set_loc => { let address = if let Some(encoding) = address_encoding { - match parse_encoded_pointer(encoding, parameters, input)? { - Pointer::Direct(x) => x, - _ => return Err(Error::UnsupportedPointerEncoding), - } + parse_encoded_pointer(encoding, parameters, input)?.direct()? } else { input.read_address(parameters.address_size)? }; @@ -3309,6 +3354,10 @@ impl<R: Reader> CallFrameInstruction<R> { Ok(CallFrameInstruction::ArgsSize { size }) } + constants::DW_CFA_AARCH64_negate_ra_state if vendor == Vendor::AArch64 => { + Ok(CallFrameInstruction::NegateRaState) + } + otherwise => Err(Error::UnknownCallFrameInstruction(otherwise)), } } @@ -3323,6 +3372,7 @@ pub struct CallFrameInstructionIter<'a, R: Reader> { input: R, address_encoding: Option<constants::DwEhPe>, parameters: PointerEncodingParameters<'a, R>, + vendor: Vendor, } impl<'a, R: Reader> CallFrameInstructionIter<'a, R> { @@ -3332,8 +3382,12 @@ impl<'a, R: Reader> CallFrameInstructionIter<'a, R> { return Ok(None); } - match CallFrameInstruction::parse(&mut self.input, self.address_encoding, &self.parameters) - { + match CallFrameInstruction::parse( + &mut self.input, + self.address_encoding, + &self.parameters, + self.vendor, + ) { Ok(instruction) => Ok(Some(instruction)), Err(e) => { self.input.empty(); @@ -3389,15 +3443,6 @@ impl Default for Pointer { } } -impl From<Pointer> for u64 { - #[inline] - fn from(p: Pointer) -> u64 { - match p { - Pointer::Direct(p) | Pointer::Indirect(p) => p, - } - } -} - impl Pointer { #[inline] fn new(encoding: constants::DwEhPe, address: u64) -> Pointer { @@ -3407,6 +3452,23 @@ impl Pointer { Pointer::Direct(address) } } + + /// Return the direct pointer value. + #[inline] + pub fn direct(self) -> Result<u64> { + match self { + Pointer::Direct(p) => Ok(p), + Pointer::Indirect(_) => Err(Error::UnsupportedPointerEncoding), + } + } + + /// Return the pointer value, discarding indirectness information. + #[inline] + pub fn pointer(self) -> u64 { + match self { + Pointer::Direct(p) | Pointer::Indirect(p) => p, + } + } } #[derive(Clone, Debug)] @@ -3637,7 +3699,7 @@ mod tests { .uleb(cie.code_alignment_factor) .sleb(cie.data_alignment_factor) .uleb(cie.return_address_register.0.into()) - .append_bytes(cie.initial_instructions.into()) + .append_bytes(cie.initial_instructions.slice()) .mark(&end); cie.length = (&end - &start) as usize; @@ -3714,11 +3776,11 @@ mod tests { let section = section.uleb(u64::from(fde.cie.address_size)); match fde.cie.address_size { 4 => section.D32({ - let x: u64 = lsda.into(); + let x: u64 = lsda.pointer(); x as u32 }), 8 => section.D64({ - let x: u64 = lsda.into(); + let x: u64 = lsda.pointer(); x }), x => panic!("Unsupported address size: {}", x), @@ -3732,7 +3794,7 @@ mod tests { section }; - let section = section.append_bytes(fde.instructions.into()).mark(&end); + let section = section.append_bytes(fde.instructions.slice()).mark(&end); fde.length = (&end - &start) as usize; length.set_const(fde.length as u64); @@ -4445,7 +4507,7 @@ mod tests { address_size, section: &R::default(), }; - CallFrameInstruction::parse(input, None, parameters) + CallFrameInstruction::parse(input, None, parameters, Vendor::Default) } #[test] @@ -4558,7 +4620,12 @@ mod tests { section: &EndianSlice::new(&[], LittleEndian), }; assert_eq!( - CallFrameInstruction::parse(input, Some(constants::DW_EH_PE_textrel), parameters), + CallFrameInstruction::parse( + input, + Some(constants::DW_EH_PE_textrel), + parameters, + Vendor::Default + ), Ok(CallFrameInstruction::SetLoc { address: expected_addr, }) @@ -5018,6 +5085,27 @@ mod tests { } #[test] + fn test_parse_cfi_instruction_negate_ra_state() { + let expected_rest = [1, 2, 3, 4]; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_AARCH64_negate_ra_state.0) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + let parameters = &PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 8, + section: &EndianSlice::default(), + }; + assert_eq!( + CallFrameInstruction::parse(input, None, parameters, Vendor::AArch64), + Ok(CallFrameInstruction::NegateRaState) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] fn test_parse_cfi_instruction_unknown_instruction() { let expected_rest = [1, 2, 3, 4]; let unknown_instr = constants::DwCfa(0b0011_1111); @@ -5065,6 +5153,7 @@ mod tests { input, address_encoding: None, parameters, + vendor: Vendor::Default, }; assert_eq!( @@ -5102,6 +5191,7 @@ mod tests { input, address_encoding: None, parameters, + vendor: Vendor::Default, }; assert_eq!( @@ -5580,6 +5670,55 @@ mod tests { } #[test] + fn test_eval_negate_ra_state() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(1)) + .unwrap(); + let instructions = [(Ok(false), CallFrameInstruction::NegateRaState)]; + assert_eval(ctx, expected, cie, None, instructions); + + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(0)) + .unwrap(); + let instructions = [ + (Ok(false), CallFrameInstruction::NegateRaState), + (Ok(false), CallFrameInstruction::NegateRaState), + ]; + assert_eval(ctx, expected, cie, None, instructions); + + // NegateRaState can't be used with other instructions. + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule( + crate::AArch64::RA_SIGN_STATE, + RegisterRule::Offset(cie.data_alignment_factor as i64), + ) + .unwrap(); + let instructions = [ + ( + Ok(false), + CallFrameInstruction::Offset { + register: crate::AArch64::RA_SIGN_STATE, + factored_offset: 1, + }, + ), + ( + Err(Error::CfiInstructionInInvalidContext), + CallFrameInstruction::NegateRaState, + ), + ]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] fn test_eval_nop() { let cie = make_test_cie(); let ctx = UnwindContext::new(); @@ -6262,7 +6401,6 @@ mod tests { section.start().set_const(0); let section = section.get_contents().unwrap(); - let section = EndianSlice::new(§ion, LittleEndian); let eh_frame = kind.section(§ion); // Setup eh_frame_hdr diff --git a/vendor/gimli/src/read/endian_slice.rs b/vendor/gimli/src/read/endian_slice.rs index d0fd67c0b..fbf5cbb79 100644 --- a/vendor/gimli/src/read/endian_slice.rs +++ b/vendor/gimli/src/read/endian_slice.rs @@ -4,7 +4,7 @@ use alloc::borrow::Cow; #[cfg(feature = "read")] use alloc::string::String; -use core::ops::{Deref, Index, Range, RangeFrom, RangeTo}; +use core::ops::{Deref, Range, RangeFrom, RangeTo}; use core::str; use crate::endianity::Endianity; @@ -57,7 +57,7 @@ where (self.range_to(..idx), self.range_from(idx..)) } - /// Find the first occurence of a byte in the slice, and return its index. + /// Find the first occurrence of a byte in the slice, and return its index. #[inline] pub fn find(&self, byte: u8) -> Option<usize> { self.slice.iter().position(|ch| *ch == byte) @@ -167,26 +167,6 @@ where } } -impl<'input, Endian> Index<usize> for EndianSlice<'input, Endian> -where - Endian: Endianity, -{ - type Output = u8; - fn index(&self, idx: usize) -> &Self::Output { - &self.slice[idx] - } -} - -impl<'input, Endian> Index<RangeFrom<usize>> for EndianSlice<'input, Endian> -where - Endian: Endianity, -{ - type Output = [u8]; - fn index(&self, idx: RangeFrom<usize>) -> &Self::Output { - &self.slice[idx] - } -} - impl<'input, Endian> Deref for EndianSlice<'input, Endian> where Endian: Endianity, @@ -197,15 +177,6 @@ where } } -impl<'input, Endian> From<EndianSlice<'input, Endian>> for &'input [u8] -where - Endian: Endianity, -{ - fn from(endian_slice: EndianSlice<'input, Endian>) -> &'input [u8] { - endian_slice.slice - } -} - impl<'input, Endian> Reader for EndianSlice<'input, Endian> where Endian: Endianity, diff --git a/vendor/gimli/src/read/line.rs b/vendor/gimli/src/read/line.rs index 65400a99e..47eae92e6 100644 --- a/vendor/gimli/src/read/line.rs +++ b/vendor/gimli/src/read/line.rs @@ -2327,7 +2327,7 @@ mod tests { fn test_parse_unknown_standard_opcode_many_args() { let input = [OPCODE_BASE, 1, 2, 3]; let input = EndianSlice::new(&input, LittleEndian); - let args = EndianSlice::new(&input[1..], LittleEndian); + let args = input.range_from(1..); let mut standard_opcode_lengths = Vec::new(); let mut header = make_test_header(input); standard_opcode_lengths.extend(header.standard_opcode_lengths.slice()); diff --git a/vendor/gimli/src/read/mod.rs b/vendor/gimli/src/read/mod.rs index 82b79502d..22a8e9fbe 100644 --- a/vendor/gimli/src/read/mod.rs +++ b/vendor/gimli/src/read/mod.rs @@ -41,10 +41,10 @@ //! //! Full example programs: //! -//! * [A simple parser](https://github.com/gimli-rs/gimli/blob/master/examples/simple.rs) +//! * [A simple parser](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/simple.rs) //! //! * [A `dwarfdump` -//! clone](https://github.com/gimli-rs/gimli/blob/master/examples/dwarfdump.rs) +//! clone](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/dwarfdump.rs) //! //! * [An `addr2line` clone](https://github.com/gimli-rs/addr2line) //! @@ -55,7 +55,7 @@ //! compilers used to create each compilation unit within a shared library or //! executable (via `DW_AT_producer`) //! -//! * [`dwarf-validate`](https://github.com/gimli-rs/gimli/blob/master/examples/dwarf-validate.rs), +//! * [`dwarf-validate`](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/dwarf-validate.rs), //! a program to validate the integrity of some DWARF and its references //! between sections and compilation units. //! diff --git a/vendor/gimli/src/read/op.rs b/vendor/gimli/src/read/op.rs index 670d1ad21..0b6a71b48 100644 --- a/vendor/gimli/src/read/op.rs +++ b/vendor/gimli/src/read/op.rs @@ -985,6 +985,16 @@ impl<R: Reader> OperationIter<R> { } } +#[cfg(feature = "fallible-iterator")] +impl<R: Reader> fallible_iterator::FallibleIterator for OperationIter<R> { + type Item = Operation<R>; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> { + OperationIter::next(self) + } +} + /// Specification of what storage should be used for [`Evaluation`]. /// #[cfg_attr( diff --git a/vendor/gimli/src/read/reader.rs b/vendor/gimli/src/read/reader.rs index 1bb748bb8..e7dd4772c 100644 --- a/vendor/gimli/src/read/reader.rs +++ b/vendor/gimli/src/read/reader.rs @@ -245,7 +245,7 @@ pub trait Reader: Debug + Clone { /// it is associated with this reader. fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset>; - /// Find the index of the first occurence of the given byte. + /// Find the index of the first occurrence of the given byte. /// The offset of the reader is not changed. fn find(&self, byte: u8) -> Result<Self::Offset>; diff --git a/vendor/gimli/src/read/unit.rs b/vendor/gimli/src/read/unit.rs index 672435330..d799f0f07 100644 --- a/vendor/gimli/src/read/unit.rs +++ b/vendor/gimli/src/read/unit.rs @@ -3295,7 +3295,7 @@ mod tests { } }; - let section = section.append_bytes(unit.entries_buf.into()).mark(&end); + let section = section.append_bytes(unit.entries_buf.slice()).mark(&end); unit.unit_length = (&end - &start) as usize; length.set_const(unit.unit_length as u64); diff --git a/vendor/gimli/src/read/value.rs b/vendor/gimli/src/read/value.rs index 6f43ebb26..77b08eda5 100644 --- a/vendor/gimli/src/read/value.rs +++ b/vendor/gimli/src/read/value.rs @@ -367,7 +367,7 @@ impl Value { Value::I64(value) => Value::I64(value.wrapping_neg()), Value::F32(value) => Value::F32(-value), Value::F64(value) => Value::F64(-value), - // It's unclear if these should implicity convert to a signed value. + // It's unclear if these should implicitly convert to a signed value. // For now, we don't support them. Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => { return Err(Error::UnsupportedTypeOperation); @@ -664,7 +664,7 @@ impl Value { Value::U16(v1) => Value::U16(if v2 >= 16 { 0 } else { v1 >> v2 }), Value::U32(v1) => Value::U32(if v2 >= 32 { 0 } else { v1 >> v2 }), Value::U64(v1) => Value::U64(if v2 >= 64 { 0 } else { v1 >> v2 }), - // It's unclear if signed values should implicity convert to an unsigned value. + // It's unclear if signed values should implicitly convert to an unsigned value. // For now, we don't support them. Value::I8(_) | Value::I16(_) | Value::I32(_) | Value::I64(_) => { return Err(Error::UnsupportedTypeOperation); @@ -737,7 +737,7 @@ impl Value { } else { v1 >> v2 }), - // It's unclear if unsigned values should implicity convert to a signed value. + // It's unclear if unsigned values should implicitly convert to a signed value. // For now, we don't support them. Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => { return Err(Error::UnsupportedTypeOperation); diff --git a/vendor/gimli/src/write/cfi.rs b/vendor/gimli/src/write/cfi.rs index 718cb69ad..5e108f15a 100644 --- a/vendor/gimli/src/write/cfi.rs +++ b/vendor/gimli/src/write/cfi.rs @@ -377,6 +377,7 @@ impl FrameDescriptionEntry { /// /// This may be a CFA definition, a register rule, or some other directive. #[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[non_exhaustive] pub enum CallFrameInstruction { /// Define the CFA rule to use the provided register and offset. Cfa(Register, i32), @@ -410,6 +411,9 @@ pub enum CallFrameInstruction { RestoreState, /// The size of the arguments that have been pushed onto the stack. ArgsSize(u32), + + /// AAarch64 extension: negate the `RA_SIGN_STATE` pseudo-register. + NegateRaState, } impl CallFrameInstruction { @@ -523,6 +527,9 @@ impl CallFrameInstruction { w.write_u8(constants::DW_CFA_GNU_args_size.0)?; w.write_uleb128(size.into())?; } + CallFrameInstruction::NegateRaState => { + w.write_u8(constants::DW_CFA_AARCH64_negate_ra_state.0)?; + } } Ok(()) } @@ -834,6 +841,7 @@ pub(crate) mod convert { read::CallFrameInstruction::ArgsSize { size } => { CallFrameInstruction::ArgsSize(size as u32) } + read::CallFrameInstruction::NegateRaState => CallFrameInstruction::NegateRaState, read::CallFrameInstruction::Nop => return Ok(None), })) } @@ -847,7 +855,7 @@ mod tests { use crate::arch::X86_64; use crate::read; use crate::write::EndianVec; - use crate::LittleEndian; + use crate::{LittleEndian, Vendor}; #[test] fn test_frame_table() { @@ -980,44 +988,61 @@ mod tests { (28 + 0x20280, CallFrameInstruction::ArgsSize(23)), ]; + let fde_instructions_aarch64 = [(0, CallFrameInstruction::NegateRaState)]; + for &version in &[1, 3, 4] { for &address_size in &[4, 8] { - for &format in &[Format::Dwarf32, Format::Dwarf64] { - let encoding = Encoding { - format, - version, - address_size, - }; - let mut frames = FrameTable::default(); - - let mut cie = CommonInformationEntry::new(encoding, 2, 8, X86_64::RA); - for i in &cie_instructions { - cie.add_instruction(i.clone()); - } - let cie_id = frames.add_cie(cie); + for &vendor in &[Vendor::Default, Vendor::AArch64] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let mut frames = FrameTable::default(); + + let mut cie = CommonInformationEntry::new(encoding, 2, 8, X86_64::RA); + for i in &cie_instructions { + cie.add_instruction(i.clone()); + } + let cie_id = frames.add_cie(cie); - let mut fde = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10); - for (o, i) in &fde_instructions { - fde.add_instruction(*o, i.clone()); - } - frames.add_fde(cie_id, fde); + let mut fde = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10); + for (o, i) in &fde_instructions { + fde.add_instruction(*o, i.clone()); + } + frames.add_fde(cie_id, fde); + + if vendor == Vendor::AArch64 { + let mut fde = + FrameDescriptionEntry::new(Address::Constant(0x2000), 0x10); + for (o, i) in &fde_instructions_aarch64 { + fde.add_instruction(*o, i.clone()); + } + frames.add_fde(cie_id, fde); + } - let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian)); - frames.write_debug_frame(&mut debug_frame).unwrap(); + let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian)); + frames.write_debug_frame(&mut debug_frame).unwrap(); - let mut read_debug_frame = - read::DebugFrame::new(debug_frame.slice(), LittleEndian); - read_debug_frame.set_address_size(address_size); - let frames = FrameTable::from(&read_debug_frame, &|address| { - Some(Address::Constant(address)) - }) - .unwrap(); + let mut read_debug_frame = + read::DebugFrame::new(debug_frame.slice(), LittleEndian); + read_debug_frame.set_address_size(address_size); + read_debug_frame.set_vendor(vendor); + let frames = FrameTable::from(&read_debug_frame, &|address| { + Some(Address::Constant(address)) + }) + .unwrap(); - assert_eq!( - &frames.cies.get_index(0).unwrap().instructions, - &cie_instructions - ); - assert_eq!(&frames.fdes[0].1.instructions, &fde_instructions); + assert_eq!( + &frames.cies.get_index(0).unwrap().instructions, + &cie_instructions + ); + assert_eq!(&frames.fdes[0].1.instructions, &fde_instructions); + if vendor == Vendor::AArch64 { + assert_eq!(&frames.fdes[1].1.instructions, &fde_instructions_aarch64); + } + } } } } diff --git a/vendor/gimli/src/write/unit.rs b/vendor/gimli/src/write/unit.rs index 23027bc2c..dd8ba6748 100644 --- a/vendor/gimli/src/write/unit.rs +++ b/vendor/gimli/src/write/unit.rs @@ -4,7 +4,7 @@ use std::{slice, usize}; use crate::common::{ DebugAbbrevOffset, DebugInfoOffset, DebugLineOffset, DebugMacinfoOffset, DebugMacroOffset, - DebugStrOffset, DebugTypeSignature, DwoId, Encoding, Format, SectionId, + DebugStrOffset, DebugTypeSignature, Encoding, Format, SectionId, }; use crate::constants; use crate::leb128::write::{sleb128_size, uleb128_size}; @@ -159,7 +159,7 @@ pub struct Unit { // - entries can be added in any order // - entries have a fixed id // - able to quickly lookup an entry from its id - // Limitations of current implemention: + // Limitations of current implementation: // - mutable iteration of children is messy due to borrow checker entries: Vec<DebuggingInformationEntry>, /// The index of the root entry in entries. @@ -1378,6 +1378,7 @@ pub struct DebugInfoOffsets { impl DebugInfoOffsets { #[cfg(test)] + #[cfg(feature = "read")] pub(crate) fn unit_offsets(&self, unit: UnitId) -> &UnitOffsets { debug_assert_eq!(self.base_id, unit.base_id); &self.units[unit.index] @@ -1408,6 +1409,7 @@ pub(crate) struct UnitOffsets { impl UnitOffsets { #[cfg(test)] + #[cfg(feature = "read")] fn none() -> Self { UnitOffsets { base_id: BaseId::default(), @@ -1471,7 +1473,7 @@ pub(crate) struct DebugInfoReference { #[cfg(feature = "read")] pub(crate) mod convert { use super::*; - use crate::common::UnitSectionOffset; + use crate::common::{DwoId, UnitSectionOffset}; use crate::read::{self, Reader}; use crate::write::{self, ConvertError, ConvertResult, LocationList, RangeList}; use std::collections::HashMap; diff --git a/vendor/gimli/tests/convert_self.rs b/vendor/gimli/tests/convert_self.rs deleted file mode 100644 index 7c069ebd6..000000000 --- a/vendor/gimli/tests/convert_self.rs +++ /dev/null @@ -1,158 +0,0 @@ -#![cfg(all(feature = "read", feature = "write"))] - -use std::env; -use std::fs::File; -use std::io::Read; -use std::path::PathBuf; - -use gimli::read; -use gimli::write::{self, Address, EndianVec}; -use gimli::LittleEndian; - -fn read_section(section: &str) -> Vec<u8> { - let mut path = PathBuf::new(); - if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") { - path.push(dir); - } - path.push("fixtures/self"); - path.push(section); - - println!("Reading section \"{}\" at path {:?}", section, path); - assert!(path.is_file()); - let mut file = File::open(path).unwrap(); - - let mut buf = Vec::new(); - file.read_to_end(&mut buf).unwrap(); - buf -} - -#[test] -fn test_convert_debug_info() { - // Convert existing sections - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = read::DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_info = read_section("debug_info"); - let debug_info = read::DebugInfo::new(&debug_info, LittleEndian); - - let debug_line = read_section("debug_line"); - let debug_line = read::DebugLine::new(&debug_line, LittleEndian); - - let debug_str = read_section("debug_str"); - let debug_str = read::DebugStr::new(&debug_str, LittleEndian); - - let debug_ranges = read_section("debug_ranges"); - let debug_ranges = read::DebugRanges::new(&debug_ranges, LittleEndian); - - let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian); - - let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists); - - let debug_loc = read_section("debug_loc"); - let debug_loc = read::DebugLoc::new(&debug_loc, LittleEndian); - - let debug_loclists = read::DebugLocLists::new(&[], LittleEndian); - - let locations = gimli::LocationLists::new(debug_loc, debug_loclists); - - let dwarf = read::Dwarf { - debug_abbrev, - debug_info, - debug_line, - debug_str, - ranges, - locations, - ..Default::default() - }; - - let mut dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address))) - .expect("Should convert DWARF information"); - - assert_eq!(dwarf.units.count(), 23); - let entries: usize = (0..dwarf.units.count()) - .map(|i| dwarf.units.get(dwarf.units.id(i)).count()) - .sum(); - assert_eq!(entries, 29_560); - assert_eq!(dwarf.line_strings.count(), 0); - assert_eq!(dwarf.strings.count(), 3921); - - // Write to new sections - let mut write_sections = write::Sections::new(EndianVec::new(LittleEndian)); - dwarf - .write(&mut write_sections) - .expect("Should write DWARF information"); - let debug_info_data = write_sections.debug_info.slice(); - let debug_abbrev_data = write_sections.debug_abbrev.slice(); - let debug_line_data = write_sections.debug_line.slice(); - let debug_ranges_data = write_sections.debug_ranges.slice(); - let debug_loc_data = write_sections.debug_loc.slice(); - let debug_str_data = write_sections.debug_str.slice(); - assert_eq!(debug_info_data.len(), 394_930); - assert_eq!(debug_abbrev_data.len(), 9701); - assert_eq!(debug_line_data.len(), 105_797); - assert_eq!(debug_ranges_data.len(), 155_712); - assert_eq!(debug_loc_data.len(), 245_168); - assert_eq!(debug_str_data.len(), 144_731); - - // Convert new sections - let debug_abbrev = read::DebugAbbrev::new(debug_abbrev_data, LittleEndian); - let debug_info = read::DebugInfo::new(debug_info_data, LittleEndian); - let debug_line = read::DebugLine::new(debug_line_data, LittleEndian); - let debug_str = read::DebugStr::new(debug_str_data, LittleEndian); - let debug_ranges = read::DebugRanges::new(debug_ranges_data, LittleEndian); - let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian); - let debug_loc = read::DebugLoc::new(debug_loc_data, LittleEndian); - let debug_loclists = read::DebugLocLists::new(&[], LittleEndian); - - let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists); - let locations = gimli::LocationLists::new(debug_loc, debug_loclists); - - let dwarf = read::Dwarf { - debug_abbrev, - debug_info, - debug_line, - debug_str, - ranges, - locations, - ..Default::default() - }; - - let dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address))) - .expect("Should convert DWARF information"); - - assert_eq!(dwarf.units.count(), 23); - let entries: usize = (0..dwarf.units.count()) - .map(|i| dwarf.units.get(dwarf.units.id(i)).count()) - .sum(); - assert_eq!(entries, 29_560); - assert_eq!(dwarf.strings.count(), 3921); -} - -#[test] -fn test_convert_eh_frame() { - // Convert existing section - let eh_frame = read_section("eh_frame"); - let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian); - // The `.eh_frame` fixture data was created on a 64-bit machine. - eh_frame.set_address_size(8); - let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address))) - .expect("Should convert eh_frame information"); - assert_eq!(frames.cie_count(), 2); - assert_eq!(frames.fde_count(), 3482); - - // Write to new section - let mut write_eh_frame = write::EhFrame(EndianVec::new(LittleEndian)); - frames - .write_eh_frame(&mut write_eh_frame) - .expect("Should write eh_frame information"); - let eh_frame = write_eh_frame.slice(); - assert_eq!(eh_frame.len(), 147144); - - // Convert new section - let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian); - eh_frame.set_address_size(8); - let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address))) - .expect("Should convert eh_frame information"); - assert_eq!(frames.cie_count(), 2); - assert_eq!(frames.fde_count(), 3482); -} diff --git a/vendor/gimli/tests/parse_self.rs b/vendor/gimli/tests/parse_self.rs deleted file mode 100755 index fb316314e..000000000 --- a/vendor/gimli/tests/parse_self.rs +++ /dev/null @@ -1,431 +0,0 @@ -#![cfg(all(feature = "read", feature = "std", feature = "endian-reader"))] - -use gimli::{ - AttributeValue, DebugAbbrev, DebugAddr, DebugAddrBase, DebugAranges, DebugInfo, DebugLine, - DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges, DebugRngLists, DebugStr, - Encoding, EndianSlice, Expression, LittleEndian, LocationLists, Operation, RangeLists, - RangeListsOffset, Reader, -}; -use std::collections::hash_map::HashMap; -use std::env; -use std::fs::File; -use std::io::Read; -use std::path::PathBuf; -use std::rc::Rc; - -fn read_section(section: &str) -> Vec<u8> { - let mut path = PathBuf::new(); - if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") { - path.push(dir); - } - path.push("fixtures/self"); - path.push(section); - - println!("Reading section \"{}\" at path {:?}", section, path); - assert!(path.is_file()); - let mut file = File::open(path).unwrap(); - - let mut buf = Vec::new(); - file.read_to_end(&mut buf).unwrap(); - buf -} - -fn parse_expression<R: Reader>(expr: Expression<R>, encoding: Encoding) { - let mut pc = expr.0.clone(); - while !pc.is_empty() { - Operation::parse(&mut pc, encoding).expect("Should parse operation"); - } - - // Also attempt to evaluate some of it. - let mut eval = expr.evaluation(encoding); - eval.set_initial_value(0); - eval.evaluate().expect("Should evaluate expression"); -} - -fn impl_parse_self_debug_info<R: gimli::Reader>( - debug_info: &DebugInfo<R>, - debug_abbrev: &DebugAbbrev<R>, -) { - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - - while cursor.next_dfs().expect("Should parse next dfs").is_some() { - let entry = cursor.current().expect("Should have a current entry"); - - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { - if let AttributeValue::Exprloc(expression) = attr.value() { - parse_expression(expression, unit.encoding()); - } - } - } - } -} - -#[test] -fn test_parse_self_debug_info() { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - impl_parse_self_debug_info(&debug_info, &debug_abbrev); -} - -#[test] -fn test_parse_self_debug_info_with_endian_rc_slice() { - let debug_info = read_section("debug_info"); - let debug_info = Rc::from(&debug_info[..]); - let debug_info = gimli::EndianRcSlice::new(debug_info, LittleEndian); - let debug_info = DebugInfo::from(debug_info); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = Rc::from(&debug_abbrev[..]); - let debug_abbrev = gimli::EndianRcSlice::new(debug_abbrev, LittleEndian); - let debug_abbrev = DebugAbbrev::from(debug_abbrev); - - impl_parse_self_debug_info(&debug_info, &debug_abbrev); -} - -#[test] -fn test_parse_self_debug_line() { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_line = read_section("debug_line"); - let debug_line = DebugLine::new(&debug_line, LittleEndian); - - let debug_str = read_section("debug_str"); - let debug_str = DebugStr::new(&debug_str, LittleEndian); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - cursor.next_dfs().expect("Should parse next dfs"); - - let unit_entry = cursor.current().expect("Should have a root entry"); - - let comp_dir = unit_entry - .attr_value(gimli::DW_AT_comp_dir) - .expect("Should parse comp_dir attribute") - .and_then(|val| val.string_value(&debug_str)); - let comp_name = unit_entry - .attr_value(gimli::DW_AT_name) - .expect("Should parse name attribute") - .and_then(|val| val.string_value(&debug_str)); - - if let Some(AttributeValue::DebugLineRef(offset)) = unit_entry - .attr_value(gimli::DW_AT_stmt_list) - .expect("Should parse stmt_list") - { - let program = debug_line - .program(offset, unit.address_size(), comp_dir, comp_name) - .expect("should parse line number program header"); - - let mut results = Vec::new(); - let mut rows = program.rows(); - while let Some((_, row)) = rows - .next_row() - .expect("Should parse and execute all rows in the line number program") - { - results.push(*row); - } - results.reverse(); - - let program = debug_line - .program(offset, unit.address_size(), comp_dir, comp_name) - .expect("should parse line number program header"); - let (program, sequences) = program - .sequences() - .expect("should parse and execute the entire line number program"); - assert!(!sequences.is_empty()); // Should be at least one sequence. - for sequence in sequences { - let mut rows = program.resume_from(&sequence); - while let Some((_, row)) = rows - .next_row() - .expect("Should parse and execute all rows after resuming") - { - let other_row = results.pop().unwrap(); - assert!(row.address() >= sequence.start); - assert!(row.address() <= sequence.end); - assert_eq!(row.address(), other_row.address()); - assert_eq!(row.line(), other_row.line()); - } - } - assert!(results.is_empty()); - } - } -} - -#[test] -fn test_parse_self_debug_loc() { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); - let debug_addr_base = DebugAddrBase(0); - - let debug_loc = read_section("debug_loc"); - let debug_loc = DebugLoc::new(&debug_loc, LittleEndian); - let debug_loclists = DebugLocLists::new(&[], LittleEndian); - let loclists = LocationLists::new(debug_loc, debug_loclists); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - cursor.next_dfs().expect("Should parse next dfs"); - - let mut low_pc = 0; - - { - let unit_entry = cursor.current().expect("Should have a root entry"); - let low_pc_attr = unit_entry - .attr_value(gimli::DW_AT_low_pc) - .expect("Should parse low_pc"); - if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr { - low_pc = address; - } - } - - while cursor.next_dfs().expect("Should parse next dfs").is_some() { - let entry = cursor.current().expect("Should have a current entry"); - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { - if let AttributeValue::LocationListsRef(offset) = attr.value() { - let mut locs = loclists - .locations( - offset, - unit.encoding(), - low_pc, - &debug_addr, - debug_addr_base, - ) - .expect("Should parse locations OK"); - while let Some(loc) = locs.next().expect("Should parse next location") { - assert!(loc.range.begin <= loc.range.end); - parse_expression(loc.data, unit.encoding()); - } - } - } - } - } -} - -#[test] -fn test_parse_self_debug_ranges() { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian)); - let debug_addr_base = DebugAddrBase(0); - - let debug_ranges = read_section("debug_ranges"); - let debug_ranges = DebugRanges::new(&debug_ranges, LittleEndian); - let debug_rnglists = DebugRngLists::new(&[], LittleEndian); - let rnglists = RangeLists::new(debug_ranges, debug_rnglists); - - let mut iter = debug_info.units(); - while let Some(unit) = iter.next().expect("Should parse compilation unit") { - let abbrevs = unit - .abbreviations(&debug_abbrev) - .expect("Should parse abbreviations"); - - let mut cursor = unit.entries(&abbrevs); - cursor.next_dfs().expect("Should parse next dfs"); - - let mut low_pc = 0; - - { - let unit_entry = cursor.current().expect("Should have a root entry"); - let low_pc_attr = unit_entry - .attr_value(gimli::DW_AT_low_pc) - .expect("Should parse low_pc"); - if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr { - low_pc = address; - } - } - - while cursor.next_dfs().expect("Should parse next dfs").is_some() { - let entry = cursor.current().expect("Should have a current entry"); - let mut attrs = entry.attrs(); - while let Some(attr) = attrs.next().expect("Should parse entry's attribute") { - if let AttributeValue::RangeListsRef(offset) = attr.value() { - let mut ranges = rnglists - .ranges( - RangeListsOffset(offset.0), - unit.encoding(), - low_pc, - &debug_addr, - debug_addr_base, - ) - .expect("Should parse ranges OK"); - while let Some(range) = ranges.next().expect("Should parse next range") { - assert!(range.begin <= range.end); - } - } - } - } - } -} - -#[test] -fn test_parse_self_debug_aranges() { - let debug_aranges = read_section("debug_aranges"); - let debug_aranges = DebugAranges::new(&debug_aranges, LittleEndian); - - let mut headers = debug_aranges.headers(); - while let Some(header) = headers.next().expect("Should parse arange header OK") { - let mut entries = header.entries(); - while let Some(_) = entries.next().expect("Should parse arange entry OK") { - // Not really anything else we can check right now. - } - } -} - -#[test] -fn test_parse_self_debug_pubnames() { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_pubnames = read_section("debug_pubnames"); - let debug_pubnames = DebugPubNames::new(&debug_pubnames, LittleEndian); - - let mut units = HashMap::new(); - let mut abbrevs = HashMap::new(); - let mut pubnames = debug_pubnames.items(); - while let Some(entry) = pubnames.next().expect("Should parse pubname OK") { - let unit_offset = entry.unit_header_offset(); - let unit = units.entry(unit_offset).or_insert_with(|| { - debug_info - .header_from_offset(unit_offset) - .expect("Should parse unit header OK") - }); - let abbrev_offset = unit.debug_abbrev_offset(); - let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| { - debug_abbrev - .abbreviations(abbrev_offset) - .expect("Should parse abbreviations OK") - }); - let mut cursor = unit - .entries_at_offset(abbrevs, entry.die_offset()) - .expect("DIE offset should be valid"); - assert!(cursor.next_dfs().expect("Should parse DIE").is_some()); - } -} - -#[test] -fn test_parse_self_debug_pubtypes() { - let debug_info = read_section("debug_info"); - let debug_info = DebugInfo::new(&debug_info, LittleEndian); - - let debug_abbrev = read_section("debug_abbrev"); - let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian); - - let debug_pubtypes = read_section("debug_pubtypes"); - let debug_pubtypes = DebugPubTypes::new(&debug_pubtypes, LittleEndian); - - let mut units = HashMap::new(); - let mut abbrevs = HashMap::new(); - let mut pubtypes = debug_pubtypes.items(); - while let Some(entry) = pubtypes.next().expect("Should parse pubtype OK") { - let unit_offset = entry.unit_header_offset(); - let unit = units.entry(unit_offset).or_insert_with(|| { - debug_info - .header_from_offset(unit_offset) - .expect("Should parse unit header OK") - }); - let abbrev_offset = unit.debug_abbrev_offset(); - let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| { - debug_abbrev - .abbreviations(abbrev_offset) - .expect("Should parse abbreviations OK") - }); - let mut cursor = unit - .entries_at_offset(abbrevs, entry.die_offset()) - .expect("DIE offset should be valid"); - assert!(cursor.next_dfs().expect("Should parse DIE").is_some()); - } -} - -#[test] -fn test_parse_self_eh_frame() { - use gimli::{BaseAddresses, CieOrFde, EhFrame, UnwindSection}; - - let eh_frame = read_section("eh_frame"); - let mut eh_frame = EhFrame::new(&eh_frame, LittleEndian); - // The `.eh_frame` fixture data was created on a 64-bit machine. - eh_frame.set_address_size(8); - - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_text(0) - .set_got(0); - let mut entries = eh_frame.entries(&bases); - while let Some(entry) = entries.next().expect("Should parse CFI entry OK") { - match entry { - CieOrFde::Cie(cie) => { - let mut instrs = cie.instructions(&eh_frame, &bases); - while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") { - // TODO FITZGEN - } - } - CieOrFde::Fde(partial) => { - let fde = partial - .parse(UnwindSection::cie_from_offset) - .expect("Should be able to get CIE for FDE"); - - let mut instrs = fde.instructions(&eh_frame, &bases); - while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") { - // TODO FITZGEN - } - } - } - } -} - -#[test] -fn test_parse_self_eh_frame_hdr() { - use gimli::{BaseAddresses, EhFrameHdr}; - - let eh_frame_hdr = read_section("eh_frame_hdr"); - let eh_frame_hdr = EhFrameHdr::new(&eh_frame_hdr, LittleEndian); - - let bases = BaseAddresses::default() - .set_eh_frame(0) - .set_eh_frame_hdr(0) - .set_text(0) - .set_got(0); - - // `.eh_frame_hdr` was generated on a 64 bit machine. - let address_size = 8; - - let _parsed_header = eh_frame_hdr - .parse(&bases, address_size) - .expect("we can parse the `.eh_frame_hdr` section OK"); -} |