diff options
Diffstat (limited to 'vendor/addr2line')
-rw-r--r-- | vendor/addr2line/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/addr2line/CHANGELOG.md | 336 | ||||
-rw-r--r-- | vendor/addr2line/Cargo.lock | 704 | ||||
-rw-r--r-- | vendor/addr2line/Cargo.toml | 147 | ||||
-rw-r--r-- | vendor/addr2line/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | vendor/addr2line/LICENSE-MIT | 25 | ||||
-rw-r--r-- | vendor/addr2line/README.md | 48 | ||||
-rw-r--r-- | vendor/addr2line/bench.plot.r | 23 | ||||
-rwxr-xr-x | vendor/addr2line/benchmark.sh | 112 | ||||
-rw-r--r-- | vendor/addr2line/coverage.sh | 5 | ||||
-rw-r--r-- | vendor/addr2line/examples/addr2line.rs | 317 | ||||
-rw-r--r-- | vendor/addr2line/rustfmt.toml | 1 | ||||
-rw-r--r-- | vendor/addr2line/src/builtin_split_dwarf_loader.rs | 164 | ||||
-rw-r--r-- | vendor/addr2line/src/function.rs | 555 | ||||
-rw-r--r-- | vendor/addr2line/src/lazy.rs | 31 | ||||
-rw-r--r-- | vendor/addr2line/src/lib.rs | 1729 | ||||
-rw-r--r-- | vendor/addr2line/tests/correctness.rs | 126 | ||||
-rw-r--r-- | vendor/addr2line/tests/output_equivalence.rs | 135 | ||||
-rw-r--r-- | vendor/addr2line/tests/parse.rs | 114 |
19 files changed, 0 insertions, 4774 deletions
diff --git a/vendor/addr2line/.cargo-checksum.json b/vendor/addr2line/.cargo-checksum.json deleted file mode 100644 index 5b12782..0000000 --- a/vendor/addr2line/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"ef9fa958318e442f1da7d204494cefec75c144aa6d5d5c93b0a5d6fcdf4ef6c6","Cargo.lock":"20b23c454fc3127f08a1bcd2864bbf029793759e6411fba24d44d8f4b7831ad0","Cargo.toml":"d0f15fde73d42bdf00e93f960dff908447225bede9364cb1659e44740a536c04","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"3c5eb5a6726634df6cf53e4d67ee9f90c9ac09838303947f45c3bea1e84548b5","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/builtin_split_dwarf_loader.rs":"dc6979de81b35f82e97275e6be27ec61f3c4225ea10574a9e031813e00185174","src/function.rs":"68f047e0c78afe18ad165db255c8254ee74c35cd6df0cc07e400252981f661ed","src/lazy.rs":"0bf23f7098f1902f181e43c2ffa82a3f86df2c0dbcb9bc0ebce6a0168dd8b060","src/lib.rs":"9d6531f71fd138d31cc7596db9ab234198d0895a21ea9cb116434c19ec78b660","tests/correctness.rs":"4081f8019535305e3aa254c6a4e1436272dd873f9717c687ca0e66ea8d5871ed","tests/output_equivalence.rs":"b2cd7c59fa55808a2e66e9fe7f160d846867e3ecefe22c22a818f822c3c41f23","tests/parse.rs":"c2f7362e4679c1b4803b12ec6e8dca6da96aed7273fd210a857524a4182c30e7"},"package":"8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"}
\ No newline at end of file diff --git a/vendor/addr2line/CHANGELOG.md b/vendor/addr2line/CHANGELOG.md deleted file mode 100644 index 8754c71..0000000 --- a/vendor/addr2line/CHANGELOG.md +++ /dev/null @@ -1,336 +0,0 @@ -# `addr2line` Change Log - --------------------------------------------------------------------------------- - -## 0.21.0 (2023/08/12) - -### Breaking changes - -* Updated `gimli`, `object`, and `fallible-iterator` dependencies. - -### Changed - -* The minimum supported rust version is 1.65.0. - -* Store boxed slices instead of `Vec` objects in `Context`. - [#278](https://github.com/gimli-rs/addr2line/pull/278) - --------------------------------------------------------------------------------- - -## 0.20.0 (2023/04/15) - -### Breaking changes - -* The minimum supported rust version is 1.58.0. - -* Changed `Context::find_frames` to return `LookupResult`. - Use `LookupResult::skip_all_loads` to obtain the result without loading split DWARF. - [#260](https://github.com/gimli-rs/addr2line/pull/260) - -* Replaced `Context::find_dwarf_unit` with `Context::find_dwarf_and_unit`. - [#260](https://github.com/gimli-rs/addr2line/pull/260) - -* Updated `object` dependency. - -### Changed - -* Fix handling of file index 0 for DWARF 5. - [#264](https://github.com/gimli-rs/addr2line/pull/264) - -### Added - -* Added types and methods to support loading split DWARF: - `LookupResult`, `SplitDwarfLoad`, `SplitDwarfLoader`, `Context::preload_units`. - [#260](https://github.com/gimli-rs/addr2line/pull/260) - [#262](https://github.com/gimli-rs/addr2line/pull/262) - [#263](https://github.com/gimli-rs/addr2line/pull/263) - --------------------------------------------------------------------------------- - -## 0.19.0 (2022/11/24) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - --------------------------------------------------------------------------------- - -## 0.18.0 (2022/07/16) - -### Breaking changes - -* Updated `object` dependency. - -### Changed - -* Fixed handling of relative path for `DW_AT_comp_dir`. - [#239](https://github.com/gimli-rs/addr2line/pull/239) - -* Fixed handling of `DW_FORM_addrx` for DWARF 5 support. - [#243](https://github.com/gimli-rs/addr2line/pull/243) - -* Fixed handling of units that are missing range information. - [#249](https://github.com/gimli-rs/addr2line/pull/249) - --------------------------------------------------------------------------------- - -## 0.17.0 (2021/10/24) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - -### Changed - -* Use `skip_attributes` to improve performance. - [#236](https://github.com/gimli-rs/addr2line/pull/236) - --------------------------------------------------------------------------------- - -## 0.16.0 (2021/07/26) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - --------------------------------------------------------------------------------- - -## 0.15.2 (2021/06/04) - -### Fixed - -* Allow `Context` to be `Send`. - [#219](https://github.com/gimli-rs/addr2line/pull/219) - --------------------------------------------------------------------------------- - -## 0.15.1 (2021/05/02) - -### Fixed - -* Don't ignore aranges with address 0. - [#217](https://github.com/gimli-rs/addr2line/pull/217) - --------------------------------------------------------------------------------- - -## 0.15.0 (2021/05/02) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - [#215](https://github.com/gimli-rs/addr2line/pull/215) - -* Added `debug_aranges` parameter to `Context::from_sections`. - [#200](https://github.com/gimli-rs/addr2line/pull/200) - -### Added - -* Added `.debug_aranges` support. - [#200](https://github.com/gimli-rs/addr2line/pull/200) - -* Added supplementary object file support. - [#208](https://github.com/gimli-rs/addr2line/pull/208) - -### Fixed - -* Fixed handling of Windows paths in locations. - [#209](https://github.com/gimli-rs/addr2line/pull/209) - -* examples/addr2line: Flush stdout after each response. - [#210](https://github.com/gimli-rs/addr2line/pull/210) - -* examples/addr2line: Avoid copying every section. - [#213](https://github.com/gimli-rs/addr2line/pull/213) - --------------------------------------------------------------------------------- - -## 0.14.1 (2020/12/31) - -### Fixed - -* Fix location lookup for skeleton units. - [#201](https://github.com/gimli-rs/addr2line/pull/201) - -### Added - -* Added `Context::find_location_range`. - [#196](https://github.com/gimli-rs/addr2line/pull/196) - [#199](https://github.com/gimli-rs/addr2line/pull/199) - --------------------------------------------------------------------------------- - -## 0.14.0 (2020/10/27) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - -### Fixed - -* Handle units that only have line information. - [#188](https://github.com/gimli-rs/addr2line/pull/188) - -* Handle DWARF units with version <= 4 and no `DW_AT_name`. - [#191](https://github.com/gimli-rs/addr2line/pull/191) - -* Fix handling of `DW_FORM_ref_addr`. - [#193](https://github.com/gimli-rs/addr2line/pull/193) - --------------------------------------------------------------------------------- - -## 0.13.0 (2020/07/07) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - -* Added `rustc-dep-of-std` feature. - [#166](https://github.com/gimli-rs/addr2line/pull/166) - -### Changed - -* Improve performance by parsing function contents lazily. - [#178](https://github.com/gimli-rs/addr2line/pull/178) - -* Don't skip `.debug_info` and `.debug_line` entries with a zero address. - [#182](https://github.com/gimli-rs/addr2line/pull/182) - --------------------------------------------------------------------------------- - -## 0.12.2 (2020/06/21) - -### Fixed - -* Avoid linear search for `DW_FORM_ref_addr`. - [#175](https://github.com/gimli-rs/addr2line/pull/175) - --------------------------------------------------------------------------------- - -## 0.12.1 (2020/05/19) - -### Fixed - -* Handle units with overlapping address ranges. - [#163](https://github.com/gimli-rs/addr2line/pull/163) - -* Don't assert for functions with overlapping address ranges. - [#168](https://github.com/gimli-rs/addr2line/pull/168) - --------------------------------------------------------------------------------- - -## 0.12.0 (2020/05/12) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - -* Added more optional features: `smallvec` and `fallible-iterator`. - [#160](https://github.com/gimli-rs/addr2line/pull/160) - -### Added - -* Added `Context::dwarf` and `Context::find_dwarf_unit`. - [#159](https://github.com/gimli-rs/addr2line/pull/159) - -### Changed - -* Removed `lazycell` dependency. - [#160](https://github.com/gimli-rs/addr2line/pull/160) - --------------------------------------------------------------------------------- - -## 0.11.0 (2020/01/11) - -### Breaking changes - -* Updated `gimli` and `object` dependencies. - -* [#130](https://github.com/gimli-rs/addr2line/pull/130) - Changed `Location::file` from `Option<String>` to `Option<&str>`. - This required adding lifetime parameters to `Location` and other structs that - contain it. - -* [#152](https://github.com/gimli-rs/addr2line/pull/152) - Changed `Location::line` and `Location::column` from `Option<u64>`to `Option<u32>`. - -* [#156](https://github.com/gimli-rs/addr2line/pull/156) - Deleted `alloc` feature, and fixed `no-std` builds with stable rust. - Removed default `Reader` parameter for `Context`, and added `ObjectContext` instead. - -### Added - -* [#134](https://github.com/gimli-rs/addr2line/pull/134) - Added `Context::from_dwarf`. - -### Changed - -* [#133](https://github.com/gimli-rs/addr2line/pull/133) - Fixed handling of units that can't be parsed. - -* [#155](https://github.com/gimli-rs/addr2line/pull/155) - Fixed `addr2line` output to match binutils. - -* [#130](https://github.com/gimli-rs/addr2line/pull/130) - Improved `.debug_line` parsing performance. - -* [#148](https://github.com/gimli-rs/addr2line/pull/148) - [#150](https://github.com/gimli-rs/addr2line/pull/150) - [#151](https://github.com/gimli-rs/addr2line/pull/151) - [#152](https://github.com/gimli-rs/addr2line/pull/152) - Improved `.debug_info` parsing performance. - -* [#137](https://github.com/gimli-rs/addr2line/pull/137) - [#138](https://github.com/gimli-rs/addr2line/pull/138) - [#139](https://github.com/gimli-rs/addr2line/pull/139) - [#140](https://github.com/gimli-rs/addr2line/pull/140) - [#146](https://github.com/gimli-rs/addr2line/pull/146) - Improved benchmarks. - --------------------------------------------------------------------------------- - -## 0.10.0 (2019/07/07) - -### Breaking changes - -* [#127](https://github.com/gimli-rs/addr2line/pull/127) - Update `gimli`. - --------------------------------------------------------------------------------- - -## 0.9.0 (2019/05/02) - -### Breaking changes - -* [#121](https://github.com/gimli-rs/addr2line/pull/121) - Update `gimli`, `object`, and `fallible-iterator` dependencies. - -### Added - -* [#121](https://github.com/gimli-rs/addr2line/pull/121) - Reexport `gimli`, `object`, and `fallible-iterator`. - --------------------------------------------------------------------------------- - -## 0.8.0 (2019/02/06) - -### Breaking changes - -* [#107](https://github.com/gimli-rs/addr2line/pull/107) - Update `object` dependency to 0.11. This is part of the public API. - -### Added - -* [#101](https://github.com/gimli-rs/addr2line/pull/101) - Add `object` feature (enabled by default). Disable this feature to remove - the `object` dependency and `Context::new` API. - -* [#102](https://github.com/gimli-rs/addr2line/pull/102) - Add `std` (enabled by default) and `alloc` features. - -### Changed - -* [#108](https://github.com/gimli-rs/addr2line/issues/108) - `demangle` no longer outputs the hash for rust symbols. - -* [#109](https://github.com/gimli-rs/addr2line/issues/109) - Set default `R` for `Context<R>`. diff --git a/vendor/addr2line/Cargo.lock b/vendor/addr2line/Cargo.lock deleted file mode 100644 index 3c23002..0000000 --- a/vendor/addr2line/Cargo.lock +++ /dev/null @@ -1,704 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" -dependencies = [ - "gimli 0.27.2", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -dependencies = [ - "backtrace", - "clap", - "compiler_builtins", - "cpp_demangle", - "fallible-iterator", - "findshlibs", - "gimli 0.28.0", - "libtest-mimic", - "memmap2", - "object 0.32.0", - "rustc-demangle", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", - "smallvec", - "typed-arena", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" -dependencies = [ - "anstyle", - "windows-sys", -] - -[[package]] -name = "backtrace" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" -dependencies = [ - "addr2line 0.19.0", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object 0.30.3", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "4.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" -dependencies = [ - "clap_builder", - "clap_derive", - "once_cell", -] - -[[package]] -name = "clap_builder" -version = "4.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", - "terminal_size", -] - -[[package]] -name = "clap_derive" -version = "4.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "clap_lex" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "compiler_builtins" -version = "0.1.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a" - -[[package]] -name = "cpp_demangle" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c76f98bdfc7f66172e6c7065f981ebb576ffc903fe4c0561d9f0c2509226dc6" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "errno" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "fallible-iterator" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" - -[[package]] -name = "findshlibs" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" -dependencies = [ - "cc", - "lazy_static", - "libc", - "winapi", -] - -[[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 = "gimli" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" -dependencies = [ - "compiler_builtins", - "fallible-iterator", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.2", - "libc", - "windows-sys", -] - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.8", - "windows-sys", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "libtest-mimic" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8de370f98a6cb8a4606618e53e802f93b094ddec0f96988eaec2c27e6e9ce7" -dependencies = [ - "clap", - "termcolor", - "threadpool", -] - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - -[[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.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[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 0.2.6", - "libc", -] - -[[package]] -name = "object" -version = "0.30.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" -dependencies = [ - "memchr", -] - -[[package]] -name = "object" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" -dependencies = [ - "flate2", - "memchr", - "ruzstd", -] - -[[package]] -name = "once_cell" -version = "1.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" - -[[package]] -name = "proc-macro2" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" - -[[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 = "rustix" -version = "0.37.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] - -[[package]] -name = "rustix" -version = "0.38.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys 0.4.5", - "windows-sys", -] - -[[package]] -name = "ruzstd" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" -dependencies = [ - "byteorder", - "thiserror-core", - "twox-hash", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "terminal_size" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" -dependencies = [ - "rustix 0.37.23", - "windows-sys", -] - -[[package]] -name = "thiserror-core" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" -dependencies = [ - "thiserror-core-impl", -] - -[[package]] -name = "thiserror-core-impl" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "static_assertions", -] - -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - -[[package]] -name = "unicode-ident" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/vendor/addr2line/Cargo.toml b/vendor/addr2line/Cargo.toml deleted file mode 100644 index b6b6b83..0000000 --- a/vendor/addr2line/Cargo.toml +++ /dev/null @@ -1,147 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2018" -rust-version = "1.65" -name = "addr2line" -version = "0.21.0" -exclude = [ - "/benches/*", - "/fixtures/*", - ".github", -] -description = "A cross-platform symbolication library written in Rust, using `gimli`" -documentation = "https://docs.rs/addr2line" -readme = "./README.md" -keywords = [ - "DWARF", - "debug", - "elf", - "symbolicate", - "atos", -] -categories = ["development-tools::debugging"] -license = "Apache-2.0 OR MIT" -repository = "https://github.com/gimli-rs/addr2line" - -[profile.bench] -codegen-units = 1 -debug = true - -[profile.release] -debug = true - -[[example]] -name = "addr2line" -required-features = ["default"] - -[[test]] -name = "output_equivalence" -harness = false -required-features = ["default"] - -[[test]] -name = "correctness" -required-features = ["default"] - -[[test]] -name = "parse" -required-features = ["std-object"] - -[dependencies.alloc] -version = "1.0.0" -optional = true -package = "rustc-std-workspace-alloc" - -[dependencies.compiler_builtins] -version = "0.1.2" -optional = true - -[dependencies.core] -version = "1.0.0" -optional = true -package = "rustc-std-workspace-core" - -[dependencies.cpp_demangle] -version = "0.4" -features = ["alloc"] -optional = true -default-features = false - -[dependencies.fallible-iterator] -version = "0.3.0" -optional = true -default-features = false - -[dependencies.gimli] -version = "0.28.0" -features = ["read"] -default-features = false - -[dependencies.memmap2] -version = "0.5.5" -optional = true - -[dependencies.object] -version = "0.32.0" -features = ["read"] -optional = true -default-features = false - -[dependencies.rustc-demangle] -version = "0.1" -optional = true - -[dependencies.smallvec] -version = "1" -optional = true -default-features = false - -[dev-dependencies.backtrace] -version = "0.3.13" - -[dev-dependencies.clap] -version = "4.3.21" -features = ["wrap_help"] - -[dev-dependencies.findshlibs] -version = "0.10" - -[dev-dependencies.libtest-mimic] -version = "0.6.1" - -[dev-dependencies.typed-arena] -version = "2" - -[features] -default = [ - "rustc-demangle", - "cpp_demangle", - "std-object", - "fallible-iterator", - "smallvec", - "memmap2", -] -rustc-dep-of-std = [ - "core", - "alloc", - "compiler_builtins", - "gimli/rustc-dep-of-std", -] -std = ["gimli/std"] -std-object = [ - "std", - "object", - "object/std", - "object/compression", - "gimli/endian-reader", -] diff --git a/vendor/addr2line/LICENSE-APACHE b/vendor/addr2line/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/vendor/addr2line/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/addr2line/LICENSE-MIT b/vendor/addr2line/LICENSE-MIT deleted file mode 100644 index 3a03f1f..0000000 --- a/vendor/addr2line/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2016-2018 The gimli Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/vendor/addr2line/README.md b/vendor/addr2line/README.md deleted file mode 100644 index dc6cb93..0000000 --- a/vendor/addr2line/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# addr2line - -[![](https://img.shields.io/crates/v/addr2line.svg)](https://crates.io/crates/addr2line) -[![](https://img.shields.io/docsrs/addr2line.svg)](https://docs.rs/addr2line) -[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/addr2line/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/addr2line?branch=master) - -A cross-platform library for retrieving per-address debug information -from files with DWARF debug information. - -`addr2line` uses [`gimli`](https://github.com/gimli-rs/gimli) to parse -the debug information, and exposes an interface for finding -the source file, line number, and wrapping function for instruction -addresses within the target program. These lookups can either be -performed programmatically through `Context::find_location` and -`Context::find_frames`, or via the included example binary, -`addr2line` (named and modelled after the equivalent utility from -[GNU binutils](https://sourceware.org/binutils/docs/binutils/addr2line.html)). - -# Quickstart - - Add the [`addr2line` crate](https://crates.io/crates/addr2line) to your `Cargo.toml` - - Load the file and parse it with [`addr2line::object::read::File::parse`](https://docs.rs/object/*/object/read/struct.File.html#method.parse) - - Pass the parsed file to [`addr2line::Context::new` ](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.new) - - Use [`addr2line::Context::find_location`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_location) - or [`addr2line::Context::find_frames`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_frames) - to look up debug information for an address - -# Performance - -`addr2line` optimizes for speed over memory by caching parsed information. -The DWARF information is parsed lazily where possible. - -The library aims to perform similarly to equivalent existing tools such -as `addr2line` from binutils, `eu-addr2line` from elfutils, and -`llvm-symbolize` from the llvm project, and in the past some benchmarking -was done that indicates a comparable performance. - -## License - -Licensed under either of - - * Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT) - -at your option. - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. diff --git a/vendor/addr2line/bench.plot.r b/vendor/addr2line/bench.plot.r deleted file mode 100644 index ecbf248..0000000 --- a/vendor/addr2line/bench.plot.r +++ /dev/null @@ -1,23 +0,0 @@ -v <- read.table(file("stdin")) -t <- data.frame(prog=v[,1], funcs=(v[,2]=="func"), time=v[,3], mem=v[,4], stringsAsFactors=FALSE) - -t$prog <- as.character(t$prog) -t$prog[t$prog == "master"] <- "gimli-rs/addr2line" -t$funcs[t$funcs == TRUE] <- "With functions" -t$funcs[t$funcs == FALSE] <- "File/line only" -t$mem = t$mem / 1024.0 - -library(ggplot2) -p <- ggplot(data=t, aes(x=prog, y=time, fill=prog)) -p <- p + geom_bar(stat = "identity") -p <- p + facet_wrap(~ funcs) -p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank()) -p <- p + ylab("time (s)") + ggtitle("addr2line runtime") -ggsave('time.png',plot=p,width=10,height=6) - -p <- ggplot(data=t, aes(x=prog, y=mem, fill=prog)) -p <- p + geom_bar(stat = "identity") -p <- p + facet_wrap(~ funcs) -p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank()) -p <- p + ylab("memory (kB)") + ggtitle("addr2line memory usage") -ggsave('memory.png',plot=p,width=10,height=6) diff --git a/vendor/addr2line/benchmark.sh b/vendor/addr2line/benchmark.sh deleted file mode 100755 index ca4c4f6..0000000 --- a/vendor/addr2line/benchmark.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash -if [[ $# -le 1 ]]; then - echo "Usage: $0 <executable> [<addresses>] REFS..." - exit 1 -fi -target="$1" -shift - -addresses="" -if [[ -e "$1" ]]; then - addresses="$1" - shift -fi - -# path to "us" -# readlink -f, but more portable: -dirname=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$(dirname "$0")") - -# https://stackoverflow.com/a/2358432/472927 -{ - # compile all refs - pushd "$dirname" > /dev/null - # if the user has some local changes, preserve them - nstashed=$(git stash list | wc -l) - echo "==> Stashing any local modifications" - git stash --keep-index > /dev/null - popstash() { - # https://stackoverflow.com/q/24520791/472927 - if [[ "$(git stash list | wc -l)" -ne "$nstashed" ]]; then - echo "==> Restoring stashed state" - git stash pop > /dev/null - fi - } - # if the user has added stuff to the index, abort - if ! git diff-index --quiet HEAD --; then - echo "Refusing to overwrite outstanding git changes" - popstash - exit 2 - fi - current=$(git symbolic-ref --short HEAD) - for ref in "$@"; do - echo "==> Compiling $ref" - git checkout -q "$ref" - commit=$(git rev-parse HEAD) - fn="target/release/addr2line-$commit" - if [[ ! -e "$fn" ]]; then - cargo build --release --example addr2line - cp target/release/examples/addr2line "$fn" - fi - if [[ "$ref" != "$commit" ]]; then - ln -sfn "addr2line-$commit" target/release/addr2line-"$ref" - fi - done - git checkout -q "$current" - popstash - popd > /dev/null - - # get us some addresses to look up - if [[ -z "$addresses" ]]; then - echo "==> Looking for benchmarking addresses (this may take a while)" - addresses=$(mktemp tmp.XXXXXXXXXX) - objdump -C -x --disassemble -l "$target" \ - | grep -P '0[048]:' \ - | awk '{print $1}' \ - | sed 's/:$//' \ - > "$addresses" - echo " -> Addresses stored in $addresses; you should re-use it next time" - fi - - run() { - func="$1" - name="$2" - cmd="$3" - args="$4" - printf "%s\t%s\t" "$name" "$func" - if [[ "$cmd" =~ llvm-symbolizer ]]; then - /usr/bin/time -f '%e\t%M' "$cmd" $args -obj="$target" < "$addresses" 2>&1 >/dev/null - else - /usr/bin/time -f '%e\t%M' "$cmd" $args -e "$target" < "$addresses" 2>&1 >/dev/null - fi - } - - # run without functions - log1=$(mktemp tmp.XXXXXXXXXX) - echo "==> Benchmarking" - run nofunc binutils addr2line >> "$log1" - #run nofunc elfutils eu-addr2line >> "$log1" - run nofunc llvm-sym llvm-symbolizer -functions=none >> "$log1" - for ref in "$@"; do - run nofunc "$ref" "$dirname/target/release/addr2line-$ref" >> "$log1" - done - cat "$log1" | column -t - - # run with functions - log2=$(mktemp tmp.XXXXXXXXXX) - echo "==> Benchmarking with -f" - run func binutils addr2line "-f -i" >> "$log2" - #run func elfutils eu-addr2line "-f -i" >> "$log2" - run func llvm-sym llvm-symbolizer "-functions=linkage -demangle=0" >> "$log2" - for ref in "$@"; do - run func "$ref" "$dirname/target/release/addr2line-$ref" "-f -i" >> "$log2" - done - cat "$log2" | column -t - cat "$log2" >> "$log1"; rm "$log2" - - echo "==> Plotting" - Rscript --no-readline --no-restore --no-save "$dirname/bench.plot.r" < "$log1" - - echo "==> Cleaning up" - rm "$log1" - exit 0 -} diff --git a/vendor/addr2line/coverage.sh b/vendor/addr2line/coverage.sh deleted file mode 100644 index 892c0b7..0000000 --- a/vendor/addr2line/coverage.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -# Run tarpaulin and pycobertura to generate coverage.html. - -cargo tarpaulin --skip-clean --out Xml -pycobertura show --format html --output coverage.html cobertura.xml diff --git a/vendor/addr2line/examples/addr2line.rs b/vendor/addr2line/examples/addr2line.rs deleted file mode 100644 index 97fc802..0000000 --- a/vendor/addr2line/examples/addr2line.rs +++ /dev/null @@ -1,317 +0,0 @@ -use std::borrow::Cow; -use std::fs::File; -use std::io::{BufRead, Lines, StdinLock, Write}; -use std::path::{Path, PathBuf}; - -use clap::{Arg, ArgAction, Command}; -use fallible_iterator::FallibleIterator; -use object::{Object, ObjectSection, SymbolMap, SymbolMapName}; -use typed_arena::Arena; - -use addr2line::{Context, Location}; - -fn parse_uint_from_hex_string(string: &str) -> Option<u64> { - if string.len() > 2 && string.starts_with("0x") { - u64::from_str_radix(&string[2..], 16).ok() - } else { - u64::from_str_radix(string, 16).ok() - } -} - -enum Addrs<'a> { - Args(clap::parser::ValuesRef<'a, String>), - Stdin(Lines<StdinLock<'a>>), -} - -impl<'a> Iterator for Addrs<'a> { - type Item = Option<u64>; - - fn next(&mut self) -> Option<Option<u64>> { - let text = match *self { - Addrs::Args(ref mut vals) => vals.next().map(Cow::from), - Addrs::Stdin(ref mut lines) => lines.next().map(Result::unwrap).map(Cow::from), - }; - text.as_ref() - .map(Cow::as_ref) - .map(parse_uint_from_hex_string) - } -} - -fn print_loc(loc: Option<&Location<'_>>, basenames: bool, llvm: bool) { - if let Some(loc) = loc { - if let Some(ref file) = loc.file.as_ref() { - let path = if basenames { - Path::new(Path::new(file).file_name().unwrap()) - } else { - Path::new(file) - }; - print!("{}:", path.display()); - } else { - print!("??:"); - } - if llvm { - print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0)); - } else if let Some(line) = loc.line { - print!("{}", line); - } else { - print!("?"); - } - println!(); - } else if llvm { - println!("??:0:0"); - } else { - println!("??:0"); - } -} - -fn print_function(name: Option<&str>, language: Option<gimli::DwLang>, demangle: bool) { - if let Some(name) = name { - if demangle { - print!("{}", addr2line::demangle_auto(Cow::from(name), language)); - } else { - print!("{}", name); - } - } else { - print!("??"); - } -} - -fn load_file_section<'input, 'arena, Endian: gimli::Endianity>( - id: gimli::SectionId, - file: &object::File<'input>, - endian: Endian, - arena_data: &'arena Arena<Cow<'input, [u8]>>, -) -> Result<gimli::EndianSlice<'arena, Endian>, ()> { - // TODO: Unify with dwarfdump.rs in gimli. - let name = id.name(); - match file.section_by_name(name) { - Some(section) => match section.uncompressed_data().unwrap() { - Cow::Borrowed(b) => Ok(gimli::EndianSlice::new(b, endian)), - Cow::Owned(b) => Ok(gimli::EndianSlice::new(arena_data.alloc(b.into()), endian)), - }, - None => Ok(gimli::EndianSlice::new(&[][..], endian)), - } -} - -fn find_name_from_symbols<'a>( - symbols: &'a SymbolMap<SymbolMapName<'_>>, - probe: u64, -) -> Option<&'a str> { - symbols.get(probe).map(|x| x.name()) -} - -struct Options<'a> { - do_functions: bool, - do_inlines: bool, - pretty: bool, - print_addrs: bool, - basenames: bool, - demangle: bool, - llvm: bool, - exe: &'a PathBuf, - sup: Option<&'a PathBuf>, -} - -fn main() { - let matches = Command::new("addr2line") - .version(env!("CARGO_PKG_VERSION")) - .about("A fast addr2line Rust port") - .max_term_width(100) - .args(&[ - Arg::new("exe") - .short('e') - .long("exe") - .value_name("filename") - .value_parser(clap::value_parser!(PathBuf)) - .help( - "Specify the name of the executable for which addresses should be translated.", - ) - .required(true), - Arg::new("sup") - .long("sup") - .value_name("filename") - .value_parser(clap::value_parser!(PathBuf)) - .help("Path to supplementary object file."), - Arg::new("functions") - .short('f') - .long("functions") - .action(ArgAction::SetTrue) - .help("Display function names as well as file and line number information."), - Arg::new("pretty").short('p').long("pretty-print") - .action(ArgAction::SetTrue) - .help( - "Make the output more human friendly: each location are printed on one line.", - ), - Arg::new("inlines").short('i').long("inlines") - .action(ArgAction::SetTrue) - .help( - "If the address belongs to a function that was inlined, the source information for \ - all enclosing scopes back to the first non-inlined function will also be printed.", - ), - Arg::new("addresses").short('a').long("addresses") - .action(ArgAction::SetTrue) - .help( - "Display the address before the function name, file and line number information.", - ), - Arg::new("basenames") - .short('s') - .long("basenames") - .action(ArgAction::SetTrue) - .help("Display only the base of each file name."), - Arg::new("demangle").short('C').long("demangle") - .action(ArgAction::SetTrue) - .help( - "Demangle function names. \ - Specifying a specific demangling style (like GNU addr2line) is not supported. \ - (TODO)" - ), - Arg::new("llvm") - .long("llvm") - .action(ArgAction::SetTrue) - .help("Display output in the same format as llvm-symbolizer."), - Arg::new("addrs") - .action(ArgAction::Append) - .help("Addresses to use instead of reading from stdin."), - ]) - .get_matches(); - - let arena_data = Arena::new(); - - let opts = Options { - do_functions: matches.get_flag("functions"), - do_inlines: matches.get_flag("inlines"), - pretty: matches.get_flag("pretty"), - print_addrs: matches.get_flag("addresses"), - basenames: matches.get_flag("basenames"), - demangle: matches.get_flag("demangle"), - llvm: matches.get_flag("llvm"), - exe: matches.get_one::<PathBuf>("exe").unwrap(), - sup: matches.get_one::<PathBuf>("sup"), - }; - - let file = File::open(opts.exe).unwrap(); - let map = unsafe { memmap2::Mmap::map(&file).unwrap() }; - let object = &object::File::parse(&*map).unwrap(); - - let endian = if object.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - - let mut load_section = |id: gimli::SectionId| -> Result<_, _> { - load_file_section(id, object, endian, &arena_data) - }; - - let sup_map; - let sup_object = if let Some(sup_path) = opts.sup { - let sup_file = File::open(sup_path).unwrap(); - sup_map = unsafe { memmap2::Mmap::map(&sup_file).unwrap() }; - Some(object::File::parse(&*sup_map).unwrap()) - } else { - None - }; - - let symbols = object.symbol_map(); - let mut dwarf = gimli::Dwarf::load(&mut load_section).unwrap(); - if let Some(ref sup_object) = sup_object { - let mut load_sup_section = |id: gimli::SectionId| -> Result<_, _> { - load_file_section(id, sup_object, endian, &arena_data) - }; - dwarf.load_sup(&mut load_sup_section).unwrap(); - } - - let mut split_dwarf_loader = addr2line::builtin_split_dwarf_loader::SplitDwarfLoader::new( - |data, endian| { - gimli::EndianSlice::new(arena_data.alloc(Cow::Owned(data.into_owned())), endian) - }, - Some(opts.exe.clone()), - ); - let ctx = Context::from_dwarf(dwarf).unwrap(); - - let stdin = std::io::stdin(); - let addrs = matches - .get_many::<String>("addrs") - .map(Addrs::Args) - .unwrap_or_else(|| Addrs::Stdin(stdin.lock().lines())); - - for probe in addrs { - if opts.print_addrs { - let addr = probe.unwrap_or(0); - if opts.llvm { - print!("0x{:x}", addr); - } else { - print!("0x{:016x}", addr); - } - if opts.pretty { - print!(": "); - } else { - println!(); - } - } - - if opts.do_functions || opts.do_inlines { - let mut printed_anything = false; - if let Some(probe) = probe { - let frames = ctx.find_frames(probe); - let frames = split_dwarf_loader.run(frames).unwrap(); - let mut frames = frames.enumerate(); - while let Some((i, frame)) = frames.next().unwrap() { - if opts.pretty && i != 0 { - print!(" (inlined by) "); - } - - if opts.do_functions { - if let Some(func) = frame.function { - print_function( - func.raw_name().ok().as_ref().map(AsRef::as_ref), - func.language, - opts.demangle, - ); - } else { - let name = find_name_from_symbols(&symbols, probe); - print_function(name, None, opts.demangle); - } - - if opts.pretty { - print!(" at "); - } else { - println!(); - } - } - - print_loc(frame.location.as_ref(), opts.basenames, opts.llvm); - - printed_anything = true; - - if !opts.do_inlines { - break; - } - } - } - - if !printed_anything { - if opts.do_functions { - let name = probe.and_then(|probe| find_name_from_symbols(&symbols, probe)); - print_function(name, None, opts.demangle); - - if opts.pretty { - print!(" at "); - } else { - println!(); - } - } - - print_loc(None, opts.basenames, opts.llvm); - } - } else { - let loc = probe.and_then(|probe| ctx.find_location(probe).unwrap()); - print_loc(loc.as_ref(), opts.basenames, opts.llvm); - } - - if opts.llvm { - println!(); - } - std::io::stdout().flush().unwrap(); - } -} diff --git a/vendor/addr2line/rustfmt.toml b/vendor/addr2line/rustfmt.toml deleted file mode 100644 index 8b13789..0000000 --- a/vendor/addr2line/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/addr2line/src/builtin_split_dwarf_loader.rs b/vendor/addr2line/src/builtin_split_dwarf_loader.rs deleted file mode 100644 index 4711931..0000000 --- a/vendor/addr2line/src/builtin_split_dwarf_loader.rs +++ /dev/null @@ -1,164 +0,0 @@ -use alloc::borrow::Cow; -use alloc::sync::Arc; -use std::fs::File; -use std::path::PathBuf; - -use object::Object; - -use crate::{LookupContinuation, LookupResult}; - -#[cfg(unix)] -fn convert_path<R: gimli::Reader<Endian = gimli::RunTimeEndian>>( - r: &R, -) -> Result<PathBuf, gimli::Error> { - use std::ffi::OsStr; - use std::os::unix::ffi::OsStrExt; - let bytes = r.to_slice()?; - let s = OsStr::from_bytes(&bytes); - Ok(PathBuf::from(s)) -} - -#[cfg(not(unix))] -fn convert_path<R: gimli::Reader<Endian = gimli::RunTimeEndian>>( - r: &R, -) -> Result<PathBuf, gimli::Error> { - let bytes = r.to_slice()?; - let s = std::str::from_utf8(&bytes).map_err(|_| gimli::Error::BadUtf8)?; - Ok(PathBuf::from(s)) -} - -fn load_section<'data: 'file, 'file, O, R, F>( - id: gimli::SectionId, - file: &'file O, - endian: R::Endian, - loader: &mut F, -) -> Result<R, gimli::Error> -where - O: object::Object<'data, 'file>, - R: gimli::Reader<Endian = gimli::RunTimeEndian>, - F: FnMut(Cow<'data, [u8]>, R::Endian) -> R, -{ - use object::ObjectSection; - - let data = id - .dwo_name() - .and_then(|dwo_name| { - file.section_by_name(dwo_name) - .and_then(|section| section.uncompressed_data().ok()) - }) - .unwrap_or(Cow::Borrowed(&[])); - Ok(loader(data, endian)) -} - -/// A simple builtin split DWARF loader. -pub struct SplitDwarfLoader<R, F> -where - R: gimli::Reader<Endian = gimli::RunTimeEndian>, - F: FnMut(Cow<'_, [u8]>, R::Endian) -> R, -{ - loader: F, - dwarf_package: Option<gimli::DwarfPackage<R>>, -} - -impl<R, F> SplitDwarfLoader<R, F> -where - R: gimli::Reader<Endian = gimli::RunTimeEndian>, - F: FnMut(Cow<'_, [u8]>, R::Endian) -> R, -{ - fn load_dwarf_package(loader: &mut F, path: Option<PathBuf>) -> Option<gimli::DwarfPackage<R>> { - let mut path = path.map(Ok).unwrap_or_else(std::env::current_exe).ok()?; - let dwp_extension = path - .extension() - .map(|previous_extension| { - let mut previous_extension = previous_extension.to_os_string(); - previous_extension.push(".dwp"); - previous_extension - }) - .unwrap_or_else(|| "dwp".into()); - path.set_extension(dwp_extension); - let file = File::open(&path).ok()?; - let map = unsafe { memmap2::Mmap::map(&file).ok()? }; - let dwp = object::File::parse(&*map).ok()?; - - let endian = if dwp.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - - let empty = loader(Cow::Borrowed(&[]), endian); - gimli::DwarfPackage::load( - |section_id| load_section(section_id, &dwp, endian, loader), - empty, - ) - .ok() - } - - /// Create a new split DWARF loader. - pub fn new(mut loader: F, path: Option<PathBuf>) -> SplitDwarfLoader<R, F> { - let dwarf_package = SplitDwarfLoader::load_dwarf_package(&mut loader, path); - SplitDwarfLoader { - loader, - dwarf_package, - } - } - - /// Run the provided `LookupResult` to completion, loading any necessary - /// split DWARF along the way. - pub fn run<L>(&mut self, mut l: LookupResult<L>) -> L::Output - where - L: LookupContinuation<Buf = R>, - { - loop { - let (load, continuation) = match l { - LookupResult::Output(output) => break output, - LookupResult::Load { load, continuation } => (load, continuation), - }; - - let mut r: Option<Arc<gimli::Dwarf<_>>> = None; - if let Some(dwp) = self.dwarf_package.as_ref() { - if let Ok(Some(cu)) = dwp.find_cu(load.dwo_id, &load.parent) { - r = Some(Arc::new(cu)); - } - } - - if r.is_none() { - let mut path = PathBuf::new(); - if let Some(p) = load.comp_dir.as_ref() { - if let Ok(p) = convert_path(p) { - path.push(p); - } - } - - if let Some(p) = load.path.as_ref() { - if let Ok(p) = convert_path(p) { - path.push(p); - } - } - - if let Ok(file) = File::open(&path) { - if let Ok(map) = unsafe { memmap2::Mmap::map(&file) } { - if let Ok(file) = object::File::parse(&*map) { - let endian = if file.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - - r = gimli::Dwarf::load(|id| { - load_section(id, &file, endian, &mut self.loader) - }) - .ok() - .map(|mut dwo_dwarf| { - dwo_dwarf.make_dwo(&load.parent); - Arc::new(dwo_dwarf) - }); - } - } - } - } - - l = continuation.resume(r); - } - } -} diff --git a/vendor/addr2line/src/function.rs b/vendor/addr2line/src/function.rs deleted file mode 100644 index 09c19e0..0000000 --- a/vendor/addr2line/src/function.rs +++ /dev/null @@ -1,555 +0,0 @@ -use alloc::boxed::Box; -use alloc::vec::Vec; -use core::cmp::Ordering; -use core::iter; - -use crate::lazy::LazyCell; -use crate::maybe_small; -use crate::{Context, DebugFile, Error, RangeAttributes}; - -pub(crate) struct Functions<R: gimli::Reader> { - /// List of all `DW_TAG_subprogram` details in the unit. - pub(crate) functions: Box< - [( - gimli::UnitOffset<R::Offset>, - LazyCell<Result<Function<R>, Error>>, - )], - >, - /// List of `DW_TAG_subprogram` address ranges in the unit. - pub(crate) addresses: Box<[FunctionAddress]>, -} - -/// A single address range for a function. -/// -/// It is possible for a function to have multiple address ranges; this -/// is handled by having multiple `FunctionAddress` entries with the same -/// `function` field. -pub(crate) struct FunctionAddress { - range: gimli::Range, - /// An index into `Functions::functions`. - pub(crate) function: usize, -} - -pub(crate) struct Function<R: gimli::Reader> { - pub(crate) dw_die_offset: gimli::UnitOffset<R::Offset>, - pub(crate) name: Option<R>, - /// List of all `DW_TAG_inlined_subroutine` details in this function. - inlined_functions: Box<[InlinedFunction<R>]>, - /// List of `DW_TAG_inlined_subroutine` address ranges in this function. - inlined_addresses: Box<[InlinedFunctionAddress]>, -} - -pub(crate) struct InlinedFunctionAddress { - range: gimli::Range, - call_depth: usize, - /// An index into `Function::inlined_functions`. - function: usize, -} - -pub(crate) struct InlinedFunction<R: gimli::Reader> { - pub(crate) dw_die_offset: gimli::UnitOffset<R::Offset>, - pub(crate) name: Option<R>, - pub(crate) call_file: Option<u64>, - pub(crate) call_line: u32, - pub(crate) call_column: u32, -} - -impl<R: gimli::Reader> Functions<R> { - pub(crate) fn parse( - unit: &gimli::Unit<R>, - sections: &gimli::Dwarf<R>, - ) -> Result<Functions<R>, Error> { - let mut functions = Vec::new(); - let mut addresses = Vec::new(); - let mut entries = unit.entries_raw(None)?; - while !entries.is_empty() { - let dw_die_offset = entries.next_offset(); - if let Some(abbrev) = entries.read_abbreviation()? { - if abbrev.tag() == gimli::DW_TAG_subprogram { - let mut ranges = RangeAttributes::default(); - for spec in abbrev.attributes() { - match entries.read_attribute(*spec) { - Ok(ref attr) => { - match attr.name() { - gimli::DW_AT_low_pc => match attr.value() { - gimli::AttributeValue::Addr(val) => { - ranges.low_pc = Some(val) - } - gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.low_pc = Some(sections.address(unit, index)?); - } - _ => {} - }, - gimli::DW_AT_high_pc => match attr.value() { - gimli::AttributeValue::Addr(val) => { - ranges.high_pc = Some(val) - } - gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.high_pc = Some(sections.address(unit, index)?); - } - gimli::AttributeValue::Udata(val) => { - ranges.size = Some(val) - } - _ => {} - }, - gimli::DW_AT_ranges => { - ranges.ranges_offset = - sections.attr_ranges_offset(unit, attr.value())?; - } - _ => {} - }; - } - Err(e) => return Err(e), - } - } - - let function_index = functions.len(); - if ranges.for_each_range(sections, unit, |range| { - addresses.push(FunctionAddress { - range, - function: function_index, - }); - })? { - functions.push((dw_die_offset, LazyCell::new())); - } - } else { - entries.skip_attributes(abbrev.attributes())?; - } - } - } - - // The binary search requires the addresses to be sorted. - // - // It also requires them to be non-overlapping. In practice, overlapping - // function ranges are unlikely, so we don't try to handle that yet. - // - // It's possible for multiple functions to have the same address range if the - // compiler can detect and remove functions with identical code. In that case - // we'll nondeterministically return one of them. - addresses.sort_by_key(|x| x.range.begin); - - Ok(Functions { - functions: functions.into_boxed_slice(), - addresses: addresses.into_boxed_slice(), - }) - } - - pub(crate) fn find_address(&self, probe: u64) -> Option<usize> { - self.addresses - .binary_search_by(|address| { - if probe < address.range.begin { - Ordering::Greater - } else if probe >= address.range.end { - Ordering::Less - } else { - Ordering::Equal - } - }) - .ok() - } - - pub(crate) fn parse_inlined_functions( - &self, - file: DebugFile, - unit: &gimli::Unit<R>, - ctx: &Context<R>, - sections: &gimli::Dwarf<R>, - ) -> Result<(), Error> { - for function in &*self.functions { - function - .1 - .borrow_with(|| Function::parse(function.0, file, unit, ctx, sections)) - .as_ref() - .map_err(Error::clone)?; - } - Ok(()) - } -} - -impl<R: gimli::Reader> Function<R> { - pub(crate) fn parse( - dw_die_offset: gimli::UnitOffset<R::Offset>, - file: DebugFile, - unit: &gimli::Unit<R>, - ctx: &Context<R>, - sections: &gimli::Dwarf<R>, - ) -> Result<Self, Error> { - let mut entries = unit.entries_raw(Some(dw_die_offset))?; - let depth = entries.next_depth(); - let abbrev = entries.read_abbreviation()?.unwrap(); - debug_assert_eq!(abbrev.tag(), gimli::DW_TAG_subprogram); - - let mut name = None; - for spec in abbrev.attributes() { - match entries.read_attribute(*spec) { - Ok(ref attr) => { - match attr.name() { - gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { - if let Ok(val) = sections.attr_string(unit, attr.value()) { - name = Some(val); - } - } - gimli::DW_AT_name => { - if name.is_none() { - name = sections.attr_string(unit, attr.value()).ok(); - } - } - gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { - if name.is_none() { - name = name_attr(attr.value(), file, unit, ctx, sections, 16)?; - } - } - _ => {} - }; - } - Err(e) => return Err(e), - } - } - - let mut inlined_functions = Vec::new(); - let mut inlined_addresses = Vec::new(); - Function::parse_children( - &mut entries, - depth, - file, - unit, - ctx, - sections, - &mut inlined_functions, - &mut inlined_addresses, - 0, - )?; - - // Sort ranges in "breadth-first traversal order", i.e. first by call_depth - // and then by range.begin. This allows finding the range containing an - // address at a certain depth using binary search. - // Note: Using DFS order, i.e. ordering by range.begin first and then by - // call_depth, would not work! Consider the two examples - // "[0..10 at depth 0], [0..2 at depth 1], [6..8 at depth 1]" and - // "[0..5 at depth 0], [0..2 at depth 1], [5..10 at depth 0], [6..8 at depth 1]". - // In this example, if you want to look up address 7 at depth 0, and you - // encounter [0..2 at depth 1], are you before or after the target range? - // You don't know. - inlined_addresses.sort_by(|r1, r2| { - if r1.call_depth < r2.call_depth { - Ordering::Less - } else if r1.call_depth > r2.call_depth { - Ordering::Greater - } else if r1.range.begin < r2.range.begin { - Ordering::Less - } else if r1.range.begin > r2.range.begin { - Ordering::Greater - } else { - Ordering::Equal - } - }); - - Ok(Function { - dw_die_offset, - name, - inlined_functions: inlined_functions.into_boxed_slice(), - inlined_addresses: inlined_addresses.into_boxed_slice(), - }) - } - - fn parse_children( - entries: &mut gimli::EntriesRaw<'_, '_, R>, - depth: isize, - file: DebugFile, - unit: &gimli::Unit<R>, - ctx: &Context<R>, - sections: &gimli::Dwarf<R>, - inlined_functions: &mut Vec<InlinedFunction<R>>, - inlined_addresses: &mut Vec<InlinedFunctionAddress>, - inlined_depth: usize, - ) -> Result<(), Error> { - loop { - let dw_die_offset = entries.next_offset(); - let next_depth = entries.next_depth(); - if next_depth <= depth { - return Ok(()); - } - if let Some(abbrev) = entries.read_abbreviation()? { - match abbrev.tag() { - gimli::DW_TAG_subprogram => { - Function::skip(entries, abbrev, next_depth)?; - } - gimli::DW_TAG_inlined_subroutine => { - InlinedFunction::parse( - dw_die_offset, - entries, - abbrev, - next_depth, - file, - unit, - ctx, - sections, - inlined_functions, - inlined_addresses, - inlined_depth, - )?; - } - _ => { - entries.skip_attributes(abbrev.attributes())?; - } - } - } - } - } - - fn skip( - entries: &mut gimli::EntriesRaw<'_, '_, R>, - abbrev: &gimli::Abbreviation, - depth: isize, - ) -> Result<(), Error> { - // TODO: use DW_AT_sibling - entries.skip_attributes(abbrev.attributes())?; - while entries.next_depth() > depth { - if let Some(abbrev) = entries.read_abbreviation()? { - entries.skip_attributes(abbrev.attributes())?; - } - } - Ok(()) - } - - /// Build the list of inlined functions that contain `probe`. - pub(crate) fn find_inlined_functions( - &self, - probe: u64, - ) -> iter::Rev<maybe_small::IntoIter<&InlinedFunction<R>>> { - // `inlined_functions` is ordered from outside to inside. - let mut inlined_functions = maybe_small::Vec::new(); - let mut inlined_addresses = &self.inlined_addresses[..]; - loop { - let current_depth = inlined_functions.len(); - // Look up (probe, current_depth) in inline_ranges. - // `inlined_addresses` is sorted in "breadth-first traversal order", i.e. - // by `call_depth` first, and then by `range.begin`. See the comment at - // the sort call for more information about why. - let search = inlined_addresses.binary_search_by(|range| { - if range.call_depth > current_depth { - Ordering::Greater - } else if range.call_depth < current_depth { - Ordering::Less - } else if range.range.begin > probe { - Ordering::Greater - } else if range.range.end <= probe { - Ordering::Less - } else { - Ordering::Equal - } - }); - if let Ok(index) = search { - let function_index = inlined_addresses[index].function; - inlined_functions.push(&self.inlined_functions[function_index]); - inlined_addresses = &inlined_addresses[index + 1..]; - } else { - break; - } - } - inlined_functions.into_iter().rev() - } -} - -impl<R: gimli::Reader> InlinedFunction<R> { - fn parse( - dw_die_offset: gimli::UnitOffset<R::Offset>, - entries: &mut gimli::EntriesRaw<'_, '_, R>, - abbrev: &gimli::Abbreviation, - depth: isize, - file: DebugFile, - unit: &gimli::Unit<R>, - ctx: &Context<R>, - sections: &gimli::Dwarf<R>, - inlined_functions: &mut Vec<InlinedFunction<R>>, - inlined_addresses: &mut Vec<InlinedFunctionAddress>, - inlined_depth: usize, - ) -> Result<(), Error> { - let mut ranges = RangeAttributes::default(); - let mut name = None; - let mut call_file = None; - let mut call_line = 0; - let mut call_column = 0; - for spec in abbrev.attributes() { - match entries.read_attribute(*spec) { - Ok(ref attr) => match attr.name() { - gimli::DW_AT_low_pc => match attr.value() { - gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val), - gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.low_pc = Some(sections.address(unit, index)?); - } - _ => {} - }, - gimli::DW_AT_high_pc => match attr.value() { - gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val), - gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.high_pc = Some(sections.address(unit, index)?); - } - gimli::AttributeValue::Udata(val) => ranges.size = Some(val), - _ => {} - }, - gimli::DW_AT_ranges => { - ranges.ranges_offset = sections.attr_ranges_offset(unit, attr.value())?; - } - gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { - if let Ok(val) = sections.attr_string(unit, attr.value()) { - name = Some(val); - } - } - gimli::DW_AT_name => { - if name.is_none() { - name = sections.attr_string(unit, attr.value()).ok(); - } - } - gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { - if name.is_none() { - name = name_attr(attr.value(), file, unit, ctx, sections, 16)?; - } - } - gimli::DW_AT_call_file => { - // There is a spec issue [1] with how DW_AT_call_file is specified in DWARF 5. - // Before, a file index of 0 would indicate no source file, however in - // DWARF 5 this could be a valid index into the file table. - // - // Implementations such as LLVM generates a file index of 0 when DWARF 5 is - // used. - // - // Thus, if we see a version of 5 or later, treat a file index of 0 as such. - // [1]: http://wiki.dwarfstd.org/index.php?title=DWARF5_Line_Table_File_Numbers - if let gimli::AttributeValue::FileIndex(fi) = attr.value() { - if fi > 0 || unit.header.version() >= 5 { - call_file = Some(fi); - } - } - } - gimli::DW_AT_call_line => { - call_line = attr.udata_value().unwrap_or(0) as u32; - } - gimli::DW_AT_call_column => { - call_column = attr.udata_value().unwrap_or(0) as u32; - } - _ => {} - }, - Err(e) => return Err(e), - } - } - - let function_index = inlined_functions.len(); - inlined_functions.push(InlinedFunction { - dw_die_offset, - name, - call_file, - call_line, - call_column, - }); - - ranges.for_each_range(sections, unit, |range| { - inlined_addresses.push(InlinedFunctionAddress { - range, - call_depth: inlined_depth, - function: function_index, - }); - })?; - - Function::parse_children( - entries, - depth, - file, - unit, - ctx, - sections, - inlined_functions, - inlined_addresses, - inlined_depth + 1, - ) - } -} - -fn name_attr<R>( - attr: gimli::AttributeValue<R>, - mut file: DebugFile, - unit: &gimli::Unit<R>, - ctx: &Context<R>, - sections: &gimli::Dwarf<R>, - recursion_limit: usize, -) -> Result<Option<R>, Error> -where - R: gimli::Reader, -{ - if recursion_limit == 0 { - return Ok(None); - } - - match attr { - gimli::AttributeValue::UnitRef(offset) => { - name_entry(file, unit, offset, ctx, sections, recursion_limit) - } - gimli::AttributeValue::DebugInfoRef(dr) => { - let (unit, offset) = ctx.find_unit(dr, file)?; - name_entry(file, unit, offset, ctx, sections, recursion_limit) - } - gimli::AttributeValue::DebugInfoRefSup(dr) => { - if let Some(sup_sections) = sections.sup.as_ref() { - file = DebugFile::Supplementary; - let (unit, offset) = ctx.find_unit(dr, file)?; - name_entry(file, unit, offset, ctx, sup_sections, recursion_limit) - } else { - Ok(None) - } - } - _ => Ok(None), - } -} - -fn name_entry<R>( - file: DebugFile, - unit: &gimli::Unit<R>, - offset: gimli::UnitOffset<R::Offset>, - ctx: &Context<R>, - sections: &gimli::Dwarf<R>, - recursion_limit: usize, -) -> Result<Option<R>, Error> -where - R: gimli::Reader, -{ - let mut entries = unit.entries_raw(Some(offset))?; - let abbrev = if let Some(abbrev) = entries.read_abbreviation()? { - abbrev - } else { - return Err(gimli::Error::NoEntryAtGivenOffset); - }; - - let mut name = None; - let mut next = None; - for spec in abbrev.attributes() { - match entries.read_attribute(*spec) { - Ok(ref attr) => match attr.name() { - gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { - if let Ok(val) = sections.attr_string(unit, attr.value()) { - return Ok(Some(val)); - } - } - gimli::DW_AT_name => { - if let Ok(val) = sections.attr_string(unit, attr.value()) { - name = Some(val); - } - } - gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { - next = Some(attr.value()); - } - _ => {} - }, - Err(e) => return Err(e), - } - } - - if name.is_some() { - return Ok(name); - } - - if let Some(next) = next { - return name_attr(next, file, unit, ctx, sections, recursion_limit - 1); - } - - Ok(None) -} diff --git a/vendor/addr2line/src/lazy.rs b/vendor/addr2line/src/lazy.rs deleted file mode 100644 index 2df2ed6..0000000 --- a/vendor/addr2line/src/lazy.rs +++ /dev/null @@ -1,31 +0,0 @@ -use core::cell::UnsafeCell; - -pub struct LazyCell<T> { - contents: UnsafeCell<Option<T>>, -} -impl<T> LazyCell<T> { - pub fn new() -> LazyCell<T> { - LazyCell { - contents: UnsafeCell::new(None), - } - } - - pub fn borrow(&self) -> Option<&T> { - unsafe { &*self.contents.get() }.as_ref() - } - - pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T { - // First check if we're already initialized... - let ptr = self.contents.get(); - if let Some(val) = unsafe { &*ptr } { - return val; - } - // Note that while we're executing `closure` our `borrow_with` may - // be called recursively. This means we need to check again after - // the closure has executed. For that we use the `get_or_insert` - // method which will only perform mutation if we aren't already - // `Some`. - let val = closure(); - unsafe { (*ptr).get_or_insert(val) } - } -} diff --git a/vendor/addr2line/src/lib.rs b/vendor/addr2line/src/lib.rs deleted file mode 100644 index 3270aad..0000000 --- a/vendor/addr2line/src/lib.rs +++ /dev/null @@ -1,1729 +0,0 @@ -//! This crate provides a cross-platform library and binary for translating addresses into -//! function names, file names and line numbers. Given an address in an executable or an -//! offset in a section of a relocatable object, it uses the debugging information to -//! figure out which file name and line number are associated with it. -//! -//! When used as a library, files must first be loaded using the -//! [`object`](https://github.com/gimli-rs/object) crate. -//! A context can then be created with [`Context::new`](./struct.Context.html#method.new). -//! The context caches some of the parsed information so that multiple lookups are -//! efficient. -//! Location information is obtained with -//! [`Context::find_location`](./struct.Context.html#method.find_location) or -//! [`Context::find_location_range`](./struct.Context.html#method.find_location_range). -//! Function information is obtained with -//! [`Context::find_frames`](./struct.Context.html#method.find_frames), which returns -//! a frame for each inline function. Each frame contains both name and location. -//! -//! The crate has an example CLI wrapper around the library which provides some of -//! the functionality of the `addr2line` command line tool distributed with [GNU -//! binutils](https://www.gnu.org/software/binutils/). -//! -//! Currently this library only provides information from the DWARF debugging information, -//! which is parsed using [`gimli`](https://github.com/gimli-rs/gimli). The example CLI -//! wrapper also uses symbol table information provided by the `object` crate. -#![deny(missing_docs)] -#![no_std] - -#[cfg(feature = "std")] -extern crate std; - -#[allow(unused_imports)] -#[macro_use] -extern crate alloc; - -#[cfg(feature = "fallible-iterator")] -pub extern crate fallible_iterator; -pub extern crate gimli; -#[cfg(feature = "object")] -pub extern crate object; - -use alloc::borrow::Cow; -use alloc::boxed::Box; -#[cfg(feature = "object")] -use alloc::rc::Rc; -use alloc::string::{String, ToString}; -use alloc::sync::Arc; -use alloc::vec::Vec; - -use core::cmp::{self, Ordering}; -use core::iter; -use core::marker::PhantomData; -use core::mem; -use core::num::NonZeroU64; -use core::ops::ControlFlow; -use core::u64; - -use crate::function::{Function, Functions, InlinedFunction}; -use crate::lazy::LazyCell; - -#[cfg(feature = "smallvec")] -mod maybe_small { - pub type Vec<T> = smallvec::SmallVec<[T; 16]>; - pub type IntoIter<T> = smallvec::IntoIter<[T; 16]>; -} -#[cfg(not(feature = "smallvec"))] -mod maybe_small { - pub type Vec<T> = alloc::vec::Vec<T>; - pub type IntoIter<T> = alloc::vec::IntoIter<T>; -} - -#[cfg(all(feature = "std", feature = "object", feature = "memmap2"))] -/// A simple builtin split DWARF loader. -pub mod builtin_split_dwarf_loader; -mod function; -mod lazy; - -type Error = gimli::Error; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum DebugFile { - Primary, - Supplementary, - Dwo, -} - -/// Operations that consult debug information may require additional files -/// to be loaded if split DWARF is being used. This enum returns the result -/// of the operation in the `Break` variant, or information about the split -/// DWARF that is required and a continuation to invoke once it is available -/// in the `Continue` variant. -/// -/// This enum is intended to be used in a loop like so: -/// ```no_run -/// # use addr2line::*; -/// # use std::sync::Arc; -/// # let ctx: Context<gimli::EndianRcSlice<gimli::RunTimeEndian>> = todo!(); -/// # let do_split_dwarf_load = |load: SplitDwarfLoad<gimli::EndianRcSlice<gimli::RunTimeEndian>>| -> Option<Arc<gimli::Dwarf<gimli::EndianRcSlice<gimli::RunTimeEndian>>>> { None }; -/// const ADDRESS: u64 = 0xdeadbeef; -/// let mut r = ctx.find_frames(ADDRESS); -/// let result = loop { -/// match r { -/// LookupResult::Output(result) => break result, -/// LookupResult::Load { load, continuation } => { -/// let dwo = do_split_dwarf_load(load); -/// r = continuation.resume(dwo); -/// } -/// } -/// }; -/// ``` -pub enum LookupResult<L: LookupContinuation> { - /// The lookup requires split DWARF data to be loaded. - Load { - /// The information needed to find the split DWARF data. - load: SplitDwarfLoad<<L as LookupContinuation>::Buf>, - /// The continuation to resume with the loaded split DWARF data. - continuation: L, - }, - /// The lookup has completed and produced an output. - Output(<L as LookupContinuation>::Output), -} - -/// This trait represents a partially complete operation that can be resumed -/// once a load of needed split DWARF data is completed or abandoned by the -/// API consumer. -pub trait LookupContinuation: Sized { - /// The final output of this operation. - type Output; - /// The type of reader used. - type Buf: gimli::Reader; - - /// Resumes the operation with the provided data. - /// - /// After the caller loads the split DWARF data required, call this - /// method to resume the operation. The return value of this method - /// indicates if the computation has completed or if further data is - /// required. - /// - /// If the additional data cannot be located, or the caller does not - /// support split DWARF, `resume(None)` can be used to continue the - /// operation with the data that is available. - fn resume(self, input: Option<Arc<gimli::Dwarf<Self::Buf>>>) -> LookupResult<Self>; -} - -impl<L: LookupContinuation> LookupResult<L> { - /// Callers that do not handle split DWARF can call `skip_all_loads` - /// to fast-forward to the end result. This result is produced with - /// the data that is available and may be less accurate than the - /// the results that would be produced if the caller did properly - /// support split DWARF. - pub fn skip_all_loads(mut self) -> L::Output { - loop { - self = match self { - LookupResult::Output(t) => return t, - LookupResult::Load { continuation, .. } => continuation.resume(None), - }; - } - } - - fn map<T, F: FnOnce(L::Output) -> T>(self, f: F) -> LookupResult<MappedLookup<T, L, F>> { - match self { - LookupResult::Output(t) => LookupResult::Output(f(t)), - LookupResult::Load { load, continuation } => LookupResult::Load { - load, - continuation: MappedLookup { - original: continuation, - mutator: f, - }, - }, - } - } - - fn unwrap(self) -> L::Output { - match self { - LookupResult::Output(t) => t, - LookupResult::Load { .. } => unreachable!("Internal API misuse"), - } - } -} - -/// The state necessary to perform address to line translation. -/// -/// Constructing a `Context` is somewhat costly, so users should aim to reuse `Context`s -/// when performing lookups for many addresses in the same executable. -pub struct Context<R: gimli::Reader> { - sections: Arc<gimli::Dwarf<R>>, - unit_ranges: Box<[UnitRange]>, - units: Box<[ResUnit<R>]>, - sup_units: Box<[SupUnit<R>]>, -} - -/// The type of `Context` that supports the `new` method. -#[cfg(feature = "std-object")] -pub type ObjectContext = Context<gimli::EndianRcSlice<gimli::RunTimeEndian>>; - -#[cfg(feature = "std-object")] -impl Context<gimli::EndianRcSlice<gimli::RunTimeEndian>> { - /// Construct a new `Context`. - /// - /// The resulting `Context` uses `gimli::EndianRcSlice<gimli::RunTimeEndian>`. - /// This means it is not thread safe, has no lifetime constraints (since it copies - /// the input data), and works for any endianity. - /// - /// Performance sensitive applications may want to use `Context::from_dwarf` - /// with a more specialised `gimli::Reader` implementation. - #[inline] - pub fn new<'data: 'file, 'file, O: object::Object<'data, 'file>>( - file: &'file O, - ) -> Result<Self, Error> { - Self::new_with_sup(file, None) - } - - /// Construct a new `Context`. - /// - /// Optionally also use a supplementary object file. - /// - /// The resulting `Context` uses `gimli::EndianRcSlice<gimli::RunTimeEndian>`. - /// This means it is not thread safe, has no lifetime constraints (since it copies - /// the input data), and works for any endianity. - /// - /// Performance sensitive applications may want to use `Context::from_dwarf` - /// with a more specialised `gimli::Reader` implementation. - pub fn new_with_sup<'data: 'file, 'file, O: object::Object<'data, 'file>>( - file: &'file O, - sup_file: Option<&'file O>, - ) -> Result<Self, Error> { - let endian = if file.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - - fn load_section<'data: 'file, 'file, O, Endian>( - id: gimli::SectionId, - file: &'file O, - endian: Endian, - ) -> Result<gimli::EndianRcSlice<Endian>, Error> - where - O: object::Object<'data, 'file>, - Endian: gimli::Endianity, - { - use object::ObjectSection; - - let data = file - .section_by_name(id.name()) - .and_then(|section| section.uncompressed_data().ok()) - .unwrap_or(Cow::Borrowed(&[])); - Ok(gimli::EndianRcSlice::new(Rc::from(&*data), endian)) - } - - let mut dwarf = gimli::Dwarf::load(|id| load_section(id, file, endian))?; - if let Some(sup_file) = sup_file { - dwarf.load_sup(|id| load_section(id, sup_file, endian))?; - } - Context::from_dwarf(dwarf) - } -} - -impl<R: gimli::Reader> Context<R> { - /// Construct a new `Context` from DWARF sections. - /// - /// This method does not support using a supplementary object file. - pub fn from_sections( - debug_abbrev: gimli::DebugAbbrev<R>, - debug_addr: gimli::DebugAddr<R>, - debug_aranges: gimli::DebugAranges<R>, - debug_info: gimli::DebugInfo<R>, - debug_line: gimli::DebugLine<R>, - debug_line_str: gimli::DebugLineStr<R>, - debug_ranges: gimli::DebugRanges<R>, - debug_rnglists: gimli::DebugRngLists<R>, - debug_str: gimli::DebugStr<R>, - debug_str_offsets: gimli::DebugStrOffsets<R>, - default_section: R, - ) -> Result<Self, Error> { - Self::from_dwarf(gimli::Dwarf { - debug_abbrev, - debug_addr, - debug_aranges, - debug_info, - debug_line, - debug_line_str, - debug_str, - debug_str_offsets, - debug_types: default_section.clone().into(), - locations: gimli::LocationLists::new( - default_section.clone().into(), - default_section.into(), - ), - ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists), - file_type: gimli::DwarfFileType::Main, - sup: None, - abbreviations_cache: gimli::AbbreviationsCache::new(), - }) - } - - /// Construct a new `Context` from an existing [`gimli::Dwarf`] object. - #[inline] - pub fn from_dwarf(sections: gimli::Dwarf<R>) -> Result<Context<R>, Error> { - let sections = Arc::new(sections); - let (unit_ranges, units) = Context::parse_units(§ions)?; - let sup_units = if let Some(sup) = sections.sup.as_ref() { - Context::parse_sup(sup)? - } else { - Vec::new() - }; - Ok(Context { - sections, - unit_ranges: unit_ranges.into_boxed_slice(), - units: units.into_boxed_slice(), - sup_units: sup_units.into_boxed_slice(), - }) - } - - /// Finds the CUs for the function address given. - /// - /// There might be multiple CUs whose range contains this address. - /// Weak symbols have shown up in the wild which cause this to happen - /// but otherwise this can happen if the CU has non-contiguous functions - /// but only reports a single range. - /// - /// Consequently we return an iterator for all CUs which may contain the - /// address, and the caller must check if there is actually a function or - /// location in the CU for that address. - fn find_units(&self, probe: u64) -> impl Iterator<Item = &ResUnit<R>> { - self.find_units_range(probe, probe + 1) - .map(|(unit, _range)| unit) - } - - /// Finds the CUs covering the range of addresses given. - /// - /// The range is [low, high) (ie, the upper bound is exclusive). This can return multiple - /// ranges for the same unit. - #[inline] - fn find_units_range( - &self, - probe_low: u64, - probe_high: u64, - ) -> impl Iterator<Item = (&ResUnit<R>, &gimli::Range)> { - // First up find the position in the array which could have our function - // address. - let pos = match self - .unit_ranges - .binary_search_by_key(&probe_high, |i| i.range.begin) - { - // Although unlikely, we could find an exact match. - Ok(i) => i + 1, - // No exact match was found, but this probe would fit at slot `i`. - // This means that slot `i` is bigger than `probe`, along with all - // indices greater than `i`, so we need to search all previous - // entries. - Err(i) => i, - }; - - // Once we have our index we iterate backwards from that position - // looking for a matching CU. - self.unit_ranges[..pos] - .iter() - .rev() - .take_while(move |i| { - // We know that this CU's start is beneath the probe already because - // of our sorted array. - debug_assert!(i.range.begin <= probe_high); - - // Each entry keeps track of the maximum end address seen so far, - // starting from the beginning of the array of unit ranges. We're - // iterating in reverse so if our probe is beyond the maximum range - // of this entry, then it's guaranteed to not fit in any prior - // entries, so we break out. - probe_low < i.max_end - }) - .filter_map(move |i| { - // If this CU doesn't actually contain this address, move to the - // next CU. - if probe_low >= i.range.end || probe_high <= i.range.begin { - return None; - } - Some((&self.units[i.unit_id], &i.range)) - }) - } - - /// Find the DWARF unit corresponding to the given virtual memory address. - pub fn find_dwarf_and_unit( - &self, - probe: u64, - ) -> LookupResult< - impl LookupContinuation<Output = Option<(&gimli::Dwarf<R>, &gimli::Unit<R>)>, Buf = R>, - > { - let mut units_iter = self.find_units(probe); - if let Some(unit) = units_iter.next() { - return LoopingLookup::new_lookup( - unit.find_function_or_location(probe, self), - move |r| { - ControlFlow::Break(match r { - Ok((Some(_), _)) | Ok((_, Some(_))) => { - let (_file, sections, unit) = unit - .dwarf_and_unit_dwo(self) - // We've already been through both error cases here to get to this point. - .unwrap() - .unwrap(); - Some((sections, unit)) - } - _ => match units_iter.next() { - Some(next_unit) => { - return ControlFlow::Continue( - next_unit.find_function_or_location(probe, self), - ); - } - None => None, - }, - }) - }, - ); - } - - LoopingLookup::new_complete(None) - } - - /// Find the source file and line corresponding to the given virtual memory address. - pub fn find_location(&self, probe: u64) -> Result<Option<Location<'_>>, Error> { - for unit in self.find_units(probe) { - if let Some(location) = unit.find_location(probe, &self.sections)? { - return Ok(Some(location)); - } - } - Ok(None) - } - - /// Return source file and lines for a range of addresses. For each location it also - /// returns the address and size of the range of the underlying instructions. - pub fn find_location_range( - &self, - probe_low: u64, - probe_high: u64, - ) -> Result<LocationRangeIter<'_, R>, Error> { - LocationRangeIter::new(self, probe_low, probe_high) - } - - /// Return an iterator for the function frames corresponding to the given virtual - /// memory address. - /// - /// If the probe address is not for an inline function then only one frame is - /// returned. - /// - /// If the probe address is for an inline function then the first frame corresponds - /// to the innermost inline function. Subsequent frames contain the caller and call - /// location, until an non-inline caller is reached. - pub fn find_frames( - &self, - probe: u64, - ) -> LookupResult<impl LookupContinuation<Output = Result<FrameIter<'_, R>, Error>, Buf = R>> - { - let mut units_iter = self.find_units(probe); - if let Some(unit) = units_iter.next() { - LoopingLookup::new_lookup(unit.find_function_or_location(probe, self), move |r| { - ControlFlow::Break(match r { - Err(e) => Err(e), - Ok((Some(function), location)) => { - let inlined_functions = function.find_inlined_functions(probe); - Ok(FrameIter(FrameIterState::Frames(FrameIterFrames { - unit, - sections: &self.sections, - function, - inlined_functions, - next: location, - }))) - } - Ok((None, Some(location))) => { - Ok(FrameIter(FrameIterState::Location(Some(location)))) - } - Ok((None, None)) => match units_iter.next() { - Some(next_unit) => { - return ControlFlow::Continue( - next_unit.find_function_or_location(probe, self), - ); - } - None => Ok(FrameIter(FrameIterState::Empty)), - }, - }) - }) - } else { - LoopingLookup::new_complete(Ok(FrameIter(FrameIterState::Empty))) - } - } - - /// Preload units for `probe`. - /// - /// The iterator returns pairs of `SplitDwarfLoad`s containing the - /// information needed to locate and load split DWARF for `probe` and - /// a matching callback to invoke once that data is available. - /// - /// If this method is called, and all of the returned closures are invoked, - /// addr2line guarantees that any future API call for the address `probe` - /// will not require the loading of any split DWARF. - /// - /// ```no_run - /// # use addr2line::*; - /// # use std::sync::Arc; - /// # let ctx: Context<gimli::EndianRcSlice<gimli::RunTimeEndian>> = todo!(); - /// # let do_split_dwarf_load = |load: SplitDwarfLoad<gimli::EndianRcSlice<gimli::RunTimeEndian>>| -> Option<Arc<gimli::Dwarf<gimli::EndianRcSlice<gimli::RunTimeEndian>>>> { None }; - /// const ADDRESS: u64 = 0xdeadbeef; - /// ctx.preload_units(ADDRESS).for_each(|(load, callback)| { - /// let dwo = do_split_dwarf_load(load); - /// callback(dwo); - /// }); - /// - /// let frames_iter = match ctx.find_frames(ADDRESS) { - /// LookupResult::Output(result) => result, - /// LookupResult::Load { .. } => unreachable!("addr2line promised we wouldn't get here"), - /// }; - /// - /// // ... - /// ``` - pub fn preload_units( - &'_ self, - probe: u64, - ) -> impl Iterator< - Item = ( - SplitDwarfLoad<R>, - impl FnOnce(Option<Arc<gimli::Dwarf<R>>>) -> Result<(), gimli::Error> + '_, - ), - > { - self.find_units(probe) - .filter_map(move |unit| match unit.dwarf_and_unit_dwo(self) { - LookupResult::Output(_) => None, - LookupResult::Load { load, continuation } => Some((load, |result| { - continuation.resume(result).unwrap().map(|_| ()) - })), - }) - } - - /// Initialize all line data structures. This is used for benchmarks. - #[doc(hidden)] - pub fn parse_lines(&self) -> Result<(), Error> { - for unit in self.units.iter() { - unit.parse_lines(&self.sections)?; - } - Ok(()) - } - - /// Initialize all function data structures. This is used for benchmarks. - #[doc(hidden)] - pub fn parse_functions(&self) -> Result<(), Error> { - for unit in self.units.iter() { - unit.parse_functions(self).skip_all_loads()?; - } - Ok(()) - } - - /// Initialize all inlined function data structures. This is used for benchmarks. - #[doc(hidden)] - pub fn parse_inlined_functions(&self) -> Result<(), Error> { - for unit in self.units.iter() { - unit.parse_inlined_functions(self).skip_all_loads()?; - } - Ok(()) - } -} - -struct UnitRange { - unit_id: usize, - max_end: u64, - range: gimli::Range, -} - -struct ResUnit<R: gimli::Reader> { - offset: gimli::DebugInfoOffset<R::Offset>, - dw_unit: gimli::Unit<R>, - lang: Option<gimli::DwLang>, - lines: LazyCell<Result<Lines, Error>>, - funcs: LazyCell<Result<Functions<R>, Error>>, - dwo: LazyCell<Result<Option<Box<(Arc<gimli::Dwarf<R>>, gimli::Unit<R>)>>, Error>>, -} - -struct SupUnit<R: gimli::Reader> { - offset: gimli::DebugInfoOffset<R::Offset>, - dw_unit: gimli::Unit<R>, -} - -impl<R: gimli::Reader> Context<R> { - fn parse_units(sections: &gimli::Dwarf<R>) -> Result<(Vec<UnitRange>, Vec<ResUnit<R>>), Error> { - // Find all the references to compilation units in .debug_aranges. - // Note that we always also iterate through all of .debug_info to - // find compilation units, because .debug_aranges may be missing some. - let mut aranges = Vec::new(); - let mut headers = sections.debug_aranges.headers(); - while let Some(header) = headers.next()? { - aranges.push((header.debug_info_offset(), header.offset())); - } - aranges.sort_by_key(|i| i.0); - - let mut unit_ranges = Vec::new(); - let mut res_units = Vec::new(); - let mut units = sections.units(); - while let Some(header) = units.next()? { - let unit_id = res_units.len(); - let offset = match header.offset().as_debug_info_offset() { - Some(offset) => offset, - None => continue, - }; - // We mainly want compile units, but we may need to follow references to entries - // within other units for function names. We don't need anything from type units. - match header.type_() { - gimli::UnitType::Type { .. } | gimli::UnitType::SplitType { .. } => continue, - _ => {} - } - let dw_unit = match sections.unit(header) { - Ok(dw_unit) => dw_unit, - Err(_) => continue, - }; - - let mut lang = None; - let mut have_unit_range = false; - { - let mut entries = dw_unit.entries_raw(None)?; - - let abbrev = match entries.read_abbreviation()? { - Some(abbrev) => abbrev, - None => continue, - }; - - let mut ranges = RangeAttributes::default(); - for spec in abbrev.attributes() { - let attr = entries.read_attribute(*spec)?; - match attr.name() { - gimli::DW_AT_low_pc => match attr.value() { - gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val), - gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.low_pc = Some(sections.address(&dw_unit, index)?); - } - _ => {} - }, - gimli::DW_AT_high_pc => match attr.value() { - gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val), - gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.high_pc = Some(sections.address(&dw_unit, index)?); - } - gimli::AttributeValue::Udata(val) => ranges.size = Some(val), - _ => {} - }, - gimli::DW_AT_ranges => { - ranges.ranges_offset = - sections.attr_ranges_offset(&dw_unit, attr.value())?; - } - gimli::DW_AT_language => { - if let gimli::AttributeValue::Language(val) = attr.value() { - lang = Some(val); - } - } - _ => {} - } - } - - // Find the address ranges for the CU, using in order of preference: - // - DW_AT_ranges - // - .debug_aranges - // - DW_AT_low_pc/DW_AT_high_pc - // - // Using DW_AT_ranges before .debug_aranges is possibly an arbitrary choice, - // but the feeling is that DW_AT_ranges is more likely to be reliable or complete - // if it is present. - // - // .debug_aranges must be used before DW_AT_low_pc/DW_AT_high_pc because - // it has been observed on macOS that DW_AT_ranges was not emitted even for - // discontiguous CUs. - let i = match ranges.ranges_offset { - Some(_) => None, - None => aranges.binary_search_by_key(&offset, |x| x.0).ok(), - }; - if let Some(mut i) = i { - // There should be only one set per CU, but in practice multiple - // sets have been observed. This is probably a compiler bug, but - // either way we need to handle it. - while i > 0 && aranges[i - 1].0 == offset { - i -= 1; - } - for (_, aranges_offset) in aranges[i..].iter().take_while(|x| x.0 == offset) { - let aranges_header = sections.debug_aranges.header(*aranges_offset)?; - let mut aranges = aranges_header.entries(); - while let Some(arange) = aranges.next()? { - if arange.length() != 0 { - unit_ranges.push(UnitRange { - range: arange.range(), - unit_id, - max_end: 0, - }); - have_unit_range = true; - } - } - } - } else { - have_unit_range |= ranges.for_each_range(sections, &dw_unit, |range| { - unit_ranges.push(UnitRange { - range, - unit_id, - max_end: 0, - }); - })?; - } - } - - let lines = LazyCell::new(); - if !have_unit_range { - // The unit did not declare any ranges. - // Try to get some ranges from the line program sequences. - if let Some(ref ilnp) = dw_unit.line_program { - if let Ok(lines) = lines - .borrow_with(|| Lines::parse(&dw_unit, ilnp.clone(), sections)) - .as_ref() - { - for sequence in lines.sequences.iter() { - unit_ranges.push(UnitRange { - range: gimli::Range { - begin: sequence.start, - end: sequence.end, - }, - unit_id, - max_end: 0, - }) - } - } - } - } - - res_units.push(ResUnit { - offset, - dw_unit, - lang, - lines, - funcs: LazyCell::new(), - dwo: LazyCell::new(), - }); - } - - // Sort this for faster lookup in `find_unit_and_address` below. - unit_ranges.sort_by_key(|i| i.range.begin); - - // Calculate the `max_end` field now that we've determined the order of - // CUs. - let mut max = 0; - for i in unit_ranges.iter_mut() { - max = max.max(i.range.end); - i.max_end = max; - } - - Ok((unit_ranges, res_units)) - } - - fn parse_sup(sections: &gimli::Dwarf<R>) -> Result<Vec<SupUnit<R>>, Error> { - let mut sup_units = Vec::new(); - let mut units = sections.units(); - while let Some(header) = units.next()? { - let offset = match header.offset().as_debug_info_offset() { - Some(offset) => offset, - None => continue, - }; - let dw_unit = match sections.unit(header) { - Ok(dw_unit) => dw_unit, - Err(_) => continue, - }; - sup_units.push(SupUnit { dw_unit, offset }); - } - Ok(sup_units) - } - - // Find the unit containing the given offset, and convert the offset into a unit offset. - fn find_unit( - &self, - offset: gimli::DebugInfoOffset<R::Offset>, - file: DebugFile, - ) -> Result<(&gimli::Unit<R>, gimli::UnitOffset<R::Offset>), Error> { - let unit = match file { - DebugFile::Primary => { - match self - .units - .binary_search_by_key(&offset.0, |unit| unit.offset.0) - { - // There is never a DIE at the unit offset or before the first unit. - Ok(_) | Err(0) => return Err(gimli::Error::NoEntryAtGivenOffset), - Err(i) => &self.units[i - 1].dw_unit, - } - } - DebugFile::Supplementary => { - match self - .sup_units - .binary_search_by_key(&offset.0, |unit| unit.offset.0) - { - // There is never a DIE at the unit offset or before the first unit. - Ok(_) | Err(0) => return Err(gimli::Error::NoEntryAtGivenOffset), - Err(i) => &self.sup_units[i - 1].dw_unit, - } - } - DebugFile::Dwo => return Err(gimli::Error::NoEntryAtGivenOffset), - }; - - let unit_offset = offset - .to_unit_offset(&unit.header) - .ok_or(gimli::Error::NoEntryAtGivenOffset)?; - Ok((unit, unit_offset)) - } -} - -struct Lines { - files: Box<[String]>, - sequences: Box<[LineSequence]>, -} - -impl Lines { - fn parse<R: gimli::Reader>( - dw_unit: &gimli::Unit<R>, - ilnp: gimli::IncompleteLineProgram<R, R::Offset>, - sections: &gimli::Dwarf<R>, - ) -> Result<Self, Error> { - let mut sequences = Vec::new(); - let mut sequence_rows = Vec::<LineRow>::new(); - let mut rows = ilnp.rows(); - while let Some((_, row)) = rows.next_row()? { - if row.end_sequence() { - if let Some(start) = sequence_rows.first().map(|x| x.address) { - let end = row.address(); - let mut rows = Vec::new(); - mem::swap(&mut rows, &mut sequence_rows); - sequences.push(LineSequence { - start, - end, - rows: rows.into_boxed_slice(), - }); - } - continue; - } - - let address = row.address(); - let file_index = row.file_index(); - let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32; - let column = match row.column() { - gimli::ColumnType::LeftEdge => 0, - gimli::ColumnType::Column(x) => x.get() as u32, - }; - - if let Some(last_row) = sequence_rows.last_mut() { - if last_row.address == address { - last_row.file_index = file_index; - last_row.line = line; - last_row.column = column; - continue; - } - } - - sequence_rows.push(LineRow { - address, - file_index, - line, - column, - }); - } - sequences.sort_by_key(|x| x.start); - - let mut files = Vec::new(); - let header = rows.header(); - match header.file(0) { - Some(file) => files.push(render_file(dw_unit, file, header, sections)?), - None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index - } - let mut index = 1; - while let Some(file) = header.file(index) { - files.push(render_file(dw_unit, file, header, sections)?); - index += 1; - } - - Ok(Self { - files: files.into_boxed_slice(), - sequences: sequences.into_boxed_slice(), - }) - } -} - -fn render_file<R: gimli::Reader>( - dw_unit: &gimli::Unit<R>, - file: &gimli::FileEntry<R, R::Offset>, - header: &gimli::LineProgramHeader<R, R::Offset>, - sections: &gimli::Dwarf<R>, -) -> Result<String, gimli::Error> { - let mut path = if let Some(ref comp_dir) = dw_unit.comp_dir { - comp_dir.to_string_lossy()?.into_owned() - } else { - String::new() - }; - - // The directory index 0 is defined to correspond to the compilation unit directory. - if file.directory_index() != 0 { - if let Some(directory) = file.directory(header) { - path_push( - &mut path, - sections - .attr_string(dw_unit, directory)? - .to_string_lossy()? - .as_ref(), - ); - } - } - - path_push( - &mut path, - sections - .attr_string(dw_unit, file.path_name())? - .to_string_lossy()? - .as_ref(), - ); - - Ok(path) -} - -struct LineSequence { - start: u64, - end: u64, - rows: Box<[LineRow]>, -} - -struct LineRow { - address: u64, - file_index: u64, - line: u32, - column: u32, -} - -/// This struct contains the information needed to find split DWARF data -/// and to produce a `gimli::Dwarf<R>` for it. -pub struct SplitDwarfLoad<R> { - /// The dwo id, for looking up in a DWARF package, or for - /// verifying an unpacked dwo found on the file system - pub dwo_id: gimli::DwoId, - /// The compilation directory `path` is relative to. - pub comp_dir: Option<R>, - /// A path on the filesystem, relative to `comp_dir` to find this dwo. - pub path: Option<R>, - /// Once the split DWARF data is loaded, the loader is expected - /// to call [make_dwo(parent)](gimli::read::Dwarf::make_dwo) before - /// returning the data. - pub parent: Arc<gimli::Dwarf<R>>, -} - -struct SimpleLookup<T, R, F> -where - F: FnOnce(Option<Arc<gimli::Dwarf<R>>>) -> T, - R: gimli::Reader, -{ - f: F, - phantom: PhantomData<(T, R)>, -} - -impl<T, R, F> SimpleLookup<T, R, F> -where - F: FnOnce(Option<Arc<gimli::Dwarf<R>>>) -> T, - R: gimli::Reader, -{ - fn new_complete(t: F::Output) -> LookupResult<SimpleLookup<T, R, F>> { - LookupResult::Output(t) - } - - fn new_needs_load(load: SplitDwarfLoad<R>, f: F) -> LookupResult<SimpleLookup<T, R, F>> { - LookupResult::Load { - load, - continuation: SimpleLookup { - f, - phantom: PhantomData, - }, - } - } -} - -impl<T, R, F> LookupContinuation for SimpleLookup<T, R, F> -where - F: FnOnce(Option<Arc<gimli::Dwarf<R>>>) -> T, - R: gimli::Reader, -{ - type Output = T; - type Buf = R; - - fn resume(self, v: Option<Arc<gimli::Dwarf<Self::Buf>>>) -> LookupResult<Self> { - LookupResult::Output((self.f)(v)) - } -} - -struct MappedLookup<T, L, F> -where - L: LookupContinuation, - F: FnOnce(L::Output) -> T, -{ - original: L, - mutator: F, -} - -impl<T, L, F> LookupContinuation for MappedLookup<T, L, F> -where - L: LookupContinuation, - F: FnOnce(L::Output) -> T, -{ - type Output = T; - type Buf = L::Buf; - - fn resume(self, v: Option<Arc<gimli::Dwarf<Self::Buf>>>) -> LookupResult<Self> { - match self.original.resume(v) { - LookupResult::Output(t) => LookupResult::Output((self.mutator)(t)), - LookupResult::Load { load, continuation } => LookupResult::Load { - load, - continuation: MappedLookup { - original: continuation, - mutator: self.mutator, - }, - }, - } - } -} - -/// Some functions (e.g. `find_frames`) require considering multiple -/// compilation units, each of which might require their own split DWARF -/// lookup (and thus produce a continuation). -/// -/// We store the underlying continuation here as well as a mutator function -/// that will either a) decide that the result of this continuation is -/// what is needed and mutate it to the final result or b) produce another -/// `LookupResult`. `new_lookup` will in turn eagerly drive any non-continuation -/// `LookupResult` with successive invocations of the mutator, until a new -/// continuation or a final result is produced. And finally, the impl of -/// `LookupContinuation::resume` will call `new_lookup` each time the -/// computation is resumed. -struct LoopingLookup<T, L, F> -where - L: LookupContinuation, - F: FnMut(L::Output) -> ControlFlow<T, LookupResult<L>>, -{ - continuation: L, - mutator: F, -} - -impl<T, L, F> LoopingLookup<T, L, F> -where - L: LookupContinuation, - F: FnMut(L::Output) -> ControlFlow<T, LookupResult<L>>, -{ - fn new_complete(t: T) -> LookupResult<Self> { - LookupResult::Output(t) - } - - fn new_lookup(mut r: LookupResult<L>, mut mutator: F) -> LookupResult<Self> { - // Drive the loop eagerly so that we only ever have to represent one state - // (the r == ControlFlow::Continue state) in LoopingLookup. - loop { - match r { - LookupResult::Output(l) => match mutator(l) { - ControlFlow::Break(t) => return LookupResult::Output(t), - ControlFlow::Continue(r2) => { - r = r2; - } - }, - LookupResult::Load { load, continuation } => { - return LookupResult::Load { - load, - continuation: LoopingLookup { - continuation, - mutator, - }, - }; - } - } - } - } -} - -impl<T, L, F> LookupContinuation for LoopingLookup<T, L, F> -where - L: LookupContinuation, - F: FnMut(L::Output) -> ControlFlow<T, LookupResult<L>>, -{ - type Output = T; - type Buf = L::Buf; - - fn resume(self, v: Option<Arc<gimli::Dwarf<Self::Buf>>>) -> LookupResult<Self> { - let r = self.continuation.resume(v); - LoopingLookup::new_lookup(r, self.mutator) - } -} - -impl<R: gimli::Reader> ResUnit<R> { - fn dwarf_and_unit_dwo<'unit, 'ctx: 'unit>( - &'unit self, - ctx: &'ctx Context<R>, - ) -> LookupResult< - SimpleLookup< - Result<(DebugFile, &'unit gimli::Dwarf<R>, &'unit gimli::Unit<R>), Error>, - R, - impl FnOnce( - Option<Arc<gimli::Dwarf<R>>>, - ) - -> Result<(DebugFile, &'unit gimli::Dwarf<R>, &'unit gimli::Unit<R>), Error>, - >, - > { - loop { - break SimpleLookup::new_complete(match self.dwo.borrow() { - Some(Ok(Some(v))) => Ok((DebugFile::Dwo, &*v.0, &v.1)), - Some(Ok(None)) => Ok((DebugFile::Primary, &*ctx.sections, &self.dw_unit)), - Some(Err(e)) => Err(*e), - None => { - let dwo_id = match self.dw_unit.dwo_id { - None => { - self.dwo.borrow_with(|| Ok(None)); - continue; - } - Some(dwo_id) => dwo_id, - }; - - let comp_dir = self.dw_unit.comp_dir.clone(); - - let dwo_name = self.dw_unit.dwo_name().and_then(|s| { - if let Some(s) = s { - Ok(Some(ctx.sections.attr_string(&self.dw_unit, s)?)) - } else { - Ok(None) - } - }); - - let path = match dwo_name { - Ok(v) => v, - Err(e) => { - self.dwo.borrow_with(|| Err(e)); - continue; - } - }; - - let process_dwo = move |dwo_dwarf: Option<Arc<gimli::Dwarf<R>>>| { - let dwo_dwarf = match dwo_dwarf { - None => return Ok(None), - Some(dwo_dwarf) => dwo_dwarf, - }; - let mut dwo_units = dwo_dwarf.units(); - let dwo_header = match dwo_units.next()? { - Some(dwo_header) => dwo_header, - None => return Ok(None), - }; - - let mut dwo_unit = dwo_dwarf.unit(dwo_header)?; - dwo_unit.copy_relocated_attributes(&self.dw_unit); - Ok(Some(Box::new((dwo_dwarf, dwo_unit)))) - }; - - return SimpleLookup::new_needs_load( - SplitDwarfLoad { - dwo_id, - comp_dir, - path, - parent: ctx.sections.clone(), - }, - move |dwo_dwarf| match self.dwo.borrow_with(|| process_dwo(dwo_dwarf)) { - Ok(Some(v)) => Ok((DebugFile::Dwo, &*v.0, &v.1)), - Ok(None) => Ok((DebugFile::Primary, &*ctx.sections, &self.dw_unit)), - Err(e) => Err(*e), - }, - ); - } - }); - } - } - - fn parse_lines(&self, sections: &gimli::Dwarf<R>) -> Result<Option<&Lines>, Error> { - // NB: line information is always stored in the main debug file so this does not need - // to handle DWOs. - let ilnp = match self.dw_unit.line_program { - Some(ref ilnp) => ilnp, - None => return Ok(None), - }; - self.lines - .borrow_with(|| Lines::parse(&self.dw_unit, ilnp.clone(), sections)) - .as_ref() - .map(Some) - .map_err(Error::clone) - } - - fn parse_functions_dwarf_and_unit( - &self, - unit: &gimli::Unit<R>, - sections: &gimli::Dwarf<R>, - ) -> Result<&Functions<R>, Error> { - self.funcs - .borrow_with(|| Functions::parse(unit, sections)) - .as_ref() - .map_err(Error::clone) - } - - fn parse_functions<'unit, 'ctx: 'unit>( - &'unit self, - ctx: &'ctx Context<R>, - ) -> LookupResult<impl LookupContinuation<Output = Result<&'unit Functions<R>, Error>, Buf = R>> - { - self.dwarf_and_unit_dwo(ctx).map(move |r| { - let (_file, sections, unit) = r?; - self.parse_functions_dwarf_and_unit(unit, sections) - }) - } - fn parse_inlined_functions<'unit, 'ctx: 'unit>( - &'unit self, - ctx: &'ctx Context<R>, - ) -> LookupResult<impl LookupContinuation<Output = Result<(), Error>, Buf = R> + 'unit> { - self.dwarf_and_unit_dwo(ctx).map(move |r| { - let (file, sections, unit) = r?; - self.funcs - .borrow_with(|| Functions::parse(unit, sections)) - .as_ref() - .map_err(Error::clone)? - .parse_inlined_functions(file, unit, ctx, sections) - }) - } - - fn find_location( - &self, - probe: u64, - sections: &gimli::Dwarf<R>, - ) -> Result<Option<Location<'_>>, Error> { - if let Some(mut iter) = LocationRangeUnitIter::new(self, sections, probe, probe + 1)? { - match iter.next() { - None => Ok(None), - Some((_addr, _len, loc)) => Ok(Some(loc)), - } - } else { - Ok(None) - } - } - - #[inline] - fn find_location_range( - &self, - probe_low: u64, - probe_high: u64, - sections: &gimli::Dwarf<R>, - ) -> Result<Option<LocationRangeUnitIter<'_>>, Error> { - LocationRangeUnitIter::new(self, sections, probe_low, probe_high) - } - - fn find_function_or_location<'unit, 'ctx: 'unit>( - &'unit self, - probe: u64, - ctx: &'ctx Context<R>, - ) -> LookupResult< - impl LookupContinuation< - Output = Result<(Option<&'unit Function<R>>, Option<Location<'unit>>), Error>, - Buf = R, - >, - > { - self.dwarf_and_unit_dwo(ctx).map(move |r| { - let (file, sections, unit) = r?; - let functions = self.parse_functions_dwarf_and_unit(unit, sections)?; - let function = match functions.find_address(probe) { - Some(address) => { - let function_index = functions.addresses[address].function; - let (offset, ref function) = functions.functions[function_index]; - Some( - function - .borrow_with(|| Function::parse(offset, file, unit, ctx, sections)) - .as_ref() - .map_err(Error::clone)?, - ) - } - None => None, - }; - let location = self.find_location(probe, sections)?; - Ok((function, location)) - }) - } -} - -/// Iterator over `Location`s in a range of addresses, returned by `Context::find_location_range`. -pub struct LocationRangeIter<'ctx, R: gimli::Reader> { - unit_iter: Box<dyn Iterator<Item = (&'ctx ResUnit<R>, &'ctx gimli::Range)> + 'ctx>, - iter: Option<LocationRangeUnitIter<'ctx>>, - - probe_low: u64, - probe_high: u64, - sections: &'ctx gimli::Dwarf<R>, -} - -impl<'ctx, R: gimli::Reader> LocationRangeIter<'ctx, R> { - #[inline] - fn new(ctx: &'ctx Context<R>, probe_low: u64, probe_high: u64) -> Result<Self, Error> { - let sections = &ctx.sections; - let unit_iter = ctx.find_units_range(probe_low, probe_high); - Ok(Self { - unit_iter: Box::new(unit_iter), - iter: None, - probe_low, - probe_high, - sections, - }) - } - - fn next_loc(&mut self) -> Result<Option<(u64, u64, Location<'ctx>)>, Error> { - loop { - let iter = self.iter.take(); - match iter { - None => match self.unit_iter.next() { - Some((unit, range)) => { - self.iter = unit.find_location_range( - cmp::max(self.probe_low, range.begin), - cmp::min(self.probe_high, range.end), - self.sections, - )?; - } - None => return Ok(None), - }, - Some(mut iter) => { - if let item @ Some(_) = iter.next() { - self.iter = Some(iter); - return Ok(item); - } - } - } - } - } -} - -impl<'ctx, R> Iterator for LocationRangeIter<'ctx, R> -where - R: gimli::Reader + 'ctx, -{ - type Item = (u64, u64, Location<'ctx>); - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - match self.next_loc() { - Err(_) => None, - Ok(loc) => loc, - } - } -} - -#[cfg(feature = "fallible-iterator")] -impl<'ctx, R> fallible_iterator::FallibleIterator for LocationRangeIter<'ctx, R> -where - R: gimli::Reader + 'ctx, -{ - type Item = (u64, u64, Location<'ctx>); - type Error = Error; - - #[inline] - fn next(&mut self) -> Result<Option<Self::Item>, Self::Error> { - self.next_loc() - } -} - -struct LocationRangeUnitIter<'ctx> { - lines: &'ctx Lines, - seqs: &'ctx [LineSequence], - seq_idx: usize, - row_idx: usize, - probe_high: u64, -} - -impl<'ctx> LocationRangeUnitIter<'ctx> { - fn new<R: gimli::Reader>( - resunit: &'ctx ResUnit<R>, - sections: &gimli::Dwarf<R>, - probe_low: u64, - probe_high: u64, - ) -> Result<Option<Self>, Error> { - let lines = resunit.parse_lines(sections)?; - - if let Some(lines) = lines { - // Find index for probe_low. - let seq_idx = lines.sequences.binary_search_by(|sequence| { - if probe_low < sequence.start { - Ordering::Greater - } else if probe_low >= sequence.end { - Ordering::Less - } else { - Ordering::Equal - } - }); - let seq_idx = match seq_idx { - Ok(x) => x, - Err(0) => 0, // probe below sequence, but range could overlap - Err(_) => lines.sequences.len(), - }; - - let row_idx = if let Some(seq) = lines.sequences.get(seq_idx) { - let idx = seq.rows.binary_search_by(|row| row.address.cmp(&probe_low)); - match idx { - Ok(x) => x, - Err(0) => 0, // probe below sequence, but range could overlap - Err(x) => x - 1, - } - } else { - 0 - }; - - Ok(Some(Self { - lines, - seqs: &*lines.sequences, - seq_idx, - row_idx, - probe_high, - })) - } else { - Ok(None) - } - } -} - -impl<'ctx> Iterator for LocationRangeUnitIter<'ctx> { - type Item = (u64, u64, Location<'ctx>); - - fn next(&mut self) -> Option<(u64, u64, Location<'ctx>)> { - while let Some(seq) = self.seqs.get(self.seq_idx) { - if seq.start >= self.probe_high { - break; - } - - match seq.rows.get(self.row_idx) { - Some(row) => { - if row.address >= self.probe_high { - break; - } - - let file = self - .lines - .files - .get(row.file_index as usize) - .map(String::as_str); - let nextaddr = seq - .rows - .get(self.row_idx + 1) - .map(|row| row.address) - .unwrap_or(seq.end); - - let item = ( - row.address, - nextaddr - row.address, - Location { - file, - line: if row.line != 0 { Some(row.line) } else { None }, - column: if row.column != 0 { - Some(row.column) - } else { - None - }, - }, - ); - self.row_idx += 1; - - return Some(item); - } - None => { - self.seq_idx += 1; - self.row_idx = 0; - } - } - } - None - } -} - -fn path_push(path: &mut String, p: &str) { - if has_unix_root(p) || has_windows_root(p) { - *path = p.to_string(); - } else { - let dir_separator = if has_windows_root(path.as_str()) { - '\\' - } else { - '/' - }; - - if !path.is_empty() && !path.ends_with(dir_separator) { - path.push(dir_separator); - } - *path += p; - } -} - -/// Check if the path in the given string has a unix style root -fn has_unix_root(p: &str) -> bool { - p.starts_with('/') -} - -/// Check if the path in the given string has a windows style root -fn has_windows_root(p: &str) -> bool { - p.starts_with('\\') || p.get(1..3) == Some(":\\") -} -struct RangeAttributes<R: gimli::Reader> { - low_pc: Option<u64>, - high_pc: Option<u64>, - size: Option<u64>, - ranges_offset: Option<gimli::RangeListsOffset<<R as gimli::Reader>::Offset>>, -} - -impl<R: gimli::Reader> Default for RangeAttributes<R> { - fn default() -> Self { - RangeAttributes { - low_pc: None, - high_pc: None, - size: None, - ranges_offset: None, - } - } -} - -impl<R: gimli::Reader> RangeAttributes<R> { - fn for_each_range<F: FnMut(gimli::Range)>( - &self, - sections: &gimli::Dwarf<R>, - unit: &gimli::Unit<R>, - mut f: F, - ) -> Result<bool, Error> { - let mut added_any = false; - let mut add_range = |range: gimli::Range| { - if range.begin < range.end { - f(range); - added_any = true - } - }; - if let Some(ranges_offset) = self.ranges_offset { - let mut range_list = sections.ranges(unit, ranges_offset)?; - while let Some(range) = range_list.next()? { - add_range(range); - } - } else if let (Some(begin), Some(end)) = (self.low_pc, self.high_pc) { - add_range(gimli::Range { begin, end }); - } else if let (Some(begin), Some(size)) = (self.low_pc, self.size) { - add_range(gimli::Range { - begin, - end: begin + size, - }); - } - Ok(added_any) - } -} - -/// An iterator over function frames. -pub struct FrameIter<'ctx, R>(FrameIterState<'ctx, R>) -where - R: gimli::Reader; - -enum FrameIterState<'ctx, R> -where - R: gimli::Reader, -{ - Empty, - Location(Option<Location<'ctx>>), - Frames(FrameIterFrames<'ctx, R>), -} - -struct FrameIterFrames<'ctx, R> -where - R: gimli::Reader, -{ - unit: &'ctx ResUnit<R>, - sections: &'ctx gimli::Dwarf<R>, - function: &'ctx Function<R>, - inlined_functions: iter::Rev<maybe_small::IntoIter<&'ctx InlinedFunction<R>>>, - next: Option<Location<'ctx>>, -} - -impl<'ctx, R> FrameIter<'ctx, R> -where - R: gimli::Reader + 'ctx, -{ - /// Advances the iterator and returns the next frame. - pub fn next(&mut self) -> Result<Option<Frame<'ctx, R>>, Error> { - let frames = match &mut self.0 { - FrameIterState::Empty => return Ok(None), - FrameIterState::Location(location) => { - // We can't move out of a mutable reference, so use `take` instead. - let location = location.take(); - self.0 = FrameIterState::Empty; - return Ok(Some(Frame { - dw_die_offset: None, - function: None, - location, - })); - } - FrameIterState::Frames(frames) => frames, - }; - - let loc = frames.next.take(); - let func = match frames.inlined_functions.next() { - Some(func) => func, - None => { - let frame = Frame { - dw_die_offset: Some(frames.function.dw_die_offset), - function: frames.function.name.clone().map(|name| FunctionName { - name, - language: frames.unit.lang, - }), - location: loc, - }; - self.0 = FrameIterState::Empty; - return Ok(Some(frame)); - } - }; - - let mut next = Location { - file: None, - line: if func.call_line != 0 { - Some(func.call_line) - } else { - None - }, - column: if func.call_column != 0 { - Some(func.call_column) - } else { - None - }, - }; - if let Some(call_file) = func.call_file { - if let Some(lines) = frames.unit.parse_lines(frames.sections)? { - next.file = lines.files.get(call_file as usize).map(String::as_str); - } - } - frames.next = Some(next); - - Ok(Some(Frame { - dw_die_offset: Some(func.dw_die_offset), - function: func.name.clone().map(|name| FunctionName { - name, - language: frames.unit.lang, - }), - location: loc, - })) - } -} - -#[cfg(feature = "fallible-iterator")] -impl<'ctx, R> fallible_iterator::FallibleIterator for FrameIter<'ctx, R> -where - R: gimli::Reader + 'ctx, -{ - type Item = Frame<'ctx, R>; - type Error = Error; - - #[inline] - fn next(&mut self) -> Result<Option<Frame<'ctx, R>>, Error> { - self.next() - } -} - -/// A function frame. -pub struct Frame<'ctx, R: gimli::Reader> { - /// The DWARF unit offset corresponding to the DIE of the function. - pub dw_die_offset: Option<gimli::UnitOffset<R::Offset>>, - /// The name of the function. - pub function: Option<FunctionName<R>>, - /// The source location corresponding to this frame. - pub location: Option<Location<'ctx>>, -} - -/// A function name. -pub struct FunctionName<R: gimli::Reader> { - /// The name of the function. - pub name: R, - /// The language of the compilation unit containing this function. - pub language: Option<gimli::DwLang>, -} - -impl<R: gimli::Reader> FunctionName<R> { - /// The raw name of this function before demangling. - pub fn raw_name(&self) -> Result<Cow<'_, str>, Error> { - self.name.to_string_lossy() - } - - /// The name of this function after demangling (if applicable). - pub fn demangle(&self) -> Result<Cow<'_, str>, Error> { - self.raw_name().map(|x| demangle_auto(x, self.language)) - } -} - -/// Demangle a symbol name using the demangling scheme for the given language. -/// -/// Returns `None` if demangling failed or is not required. -#[allow(unused_variables)] -pub fn demangle(name: &str, language: gimli::DwLang) -> Option<String> { - match language { - #[cfg(feature = "rustc-demangle")] - gimli::DW_LANG_Rust => rustc_demangle::try_demangle(name) - .ok() - .as_ref() - .map(|x| format!("{:#}", x)), - #[cfg(feature = "cpp_demangle")] - gimli::DW_LANG_C_plus_plus - | gimli::DW_LANG_C_plus_plus_03 - | gimli::DW_LANG_C_plus_plus_11 - | gimli::DW_LANG_C_plus_plus_14 => cpp_demangle::Symbol::new(name) - .ok() - .and_then(|x| x.demangle(&Default::default()).ok()), - _ => None, - } -} - -/// Apply 'best effort' demangling of a symbol name. -/// -/// If `language` is given, then only the demangling scheme for that language -/// is used. -/// -/// If `language` is `None`, then heuristics are used to determine how to -/// demangle the name. Currently, these heuristics are very basic. -/// -/// If demangling fails or is not required, then `name` is returned unchanged. -pub fn demangle_auto(name: Cow<'_, str>, language: Option<gimli::DwLang>) -> Cow<'_, str> { - match language { - Some(language) => demangle(name.as_ref(), language), - None => demangle(name.as_ref(), gimli::DW_LANG_Rust) - .or_else(|| demangle(name.as_ref(), gimli::DW_LANG_C_plus_plus)), - } - .map(Cow::from) - .unwrap_or(name) -} - -/// A source location. -pub struct Location<'a> { - /// The file name. - pub file: Option<&'a str>, - /// The line number. - pub line: Option<u32>, - /// The column number. - pub column: Option<u32>, -} - -#[cfg(test)] -mod tests { - #[test] - fn context_is_send() { - fn assert_is_send<T: Send>() {} - assert_is_send::<crate::Context<gimli::read::EndianSlice<'_, gimli::LittleEndian>>>(); - } -} diff --git a/vendor/addr2line/tests/correctness.rs b/vendor/addr2line/tests/correctness.rs deleted file mode 100644 index 73ee462..0000000 --- a/vendor/addr2line/tests/correctness.rs +++ /dev/null @@ -1,126 +0,0 @@ -use addr2line::Context; -use fallible_iterator::FallibleIterator; -use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary}; -use object::Object; -use std::borrow::Cow; -use std::fs::File; -use std::sync::Arc; - -fn find_debuginfo() -> memmap2::Mmap { - let path = std::env::current_exe().unwrap(); - let file = File::open(&path).unwrap(); - let map = unsafe { memmap2::Mmap::map(&file).unwrap() }; - let file = &object::File::parse(&*map).unwrap(); - if let Ok(uuid) = file.mach_uuid() { - for candidate in path.parent().unwrap().read_dir().unwrap() { - let path = candidate.unwrap().path(); - if !path.to_str().unwrap().ends_with(".dSYM") { - continue; - } - for candidate in path.join("Contents/Resources/DWARF").read_dir().unwrap() { - let path = candidate.unwrap().path(); - let file = File::open(&path).unwrap(); - let map = unsafe { memmap2::Mmap::map(&file).unwrap() }; - let file = &object::File::parse(&*map).unwrap(); - if file.mach_uuid().unwrap() == uuid { - return map; - } - } - } - } - - return map; -} - -#[test] -fn correctness() { - let map = find_debuginfo(); - let file = &object::File::parse(&*map).unwrap(); - let module_base = file.relative_address_base(); - - let endian = if file.is_little_endian() { - gimli::RunTimeEndian::Little - } else { - gimli::RunTimeEndian::Big - }; - - fn load_section<'data: 'file, 'file, O, Endian>( - id: gimli::SectionId, - file: &'file O, - endian: Endian, - ) -> Result<gimli::EndianArcSlice<Endian>, gimli::Error> - where - O: object::Object<'data, 'file>, - Endian: gimli::Endianity, - { - use object::ObjectSection; - - let data = file - .section_by_name(id.name()) - .and_then(|section| section.uncompressed_data().ok()) - .unwrap_or(Cow::Borrowed(&[])); - Ok(gimli::EndianArcSlice::new(Arc::from(&*data), endian)) - } - - let dwarf = gimli::Dwarf::load(|id| load_section(id, file, endian)).unwrap(); - let ctx = Context::from_dwarf(dwarf).unwrap(); - let mut split_dwarf_loader = addr2line::builtin_split_dwarf_loader::SplitDwarfLoader::new( - |data, endian| gimli::EndianArcSlice::new(Arc::from(&*data), endian), - None, - ); - - let mut bias = None; - TargetSharedLibrary::each(|lib| { - bias = Some((lib.virtual_memory_bias().0 as u64).wrapping_sub(module_base)); - IterationControl::Break - }); - - #[allow(unused_mut)] - let mut test = |sym: u64, expected_prefix: &str| { - let ip = sym.wrapping_sub(bias.unwrap()); - - let frames = ctx.find_frames(ip); - let frames = split_dwarf_loader.run(frames).unwrap(); - let frame = frames.last().unwrap().unwrap(); - let name = frame.function.as_ref().unwrap().demangle().unwrap(); - // Old rust versions generate DWARF with wrong linkage name, - // so only check the start. - if !name.starts_with(expected_prefix) { - panic!("incorrect name '{}', expected {:?}", name, expected_prefix); - } - }; - - test(test_function as u64, "correctness::test_function"); - test( - small::test_function as u64, - "correctness::small::test_function", - ); - test(auxiliary::foo as u64, "auxiliary::foo"); -} - -mod small { - pub fn test_function() { - println!("y"); - } -} - -fn test_function() { - println!("x"); -} - -#[test] -fn zero_function() { - let map = find_debuginfo(); - let file = &object::File::parse(&*map).unwrap(); - let ctx = Context::new(file).unwrap(); - for probe in 0..10 { - assert!( - ctx.find_frames(probe) - .skip_all_loads() - .unwrap() - .count() - .unwrap() - < 10 - ); - } -} diff --git a/vendor/addr2line/tests/output_equivalence.rs b/vendor/addr2line/tests/output_equivalence.rs deleted file mode 100644 index ef026e3..0000000 --- a/vendor/addr2line/tests/output_equivalence.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::env; -use std::ffi::OsStr; -use std::path::Path; -use std::process::Command; - -use backtrace::Backtrace; -use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary}; -use libtest_mimic::{Arguments, Failed, Trial}; - -#[inline(never)] -fn make_trace() -> Vec<String> { - fn foo() -> Backtrace { - bar() - } - #[inline(never)] - fn bar() -> Backtrace { - baz() - } - #[inline(always)] - fn baz() -> Backtrace { - Backtrace::new_unresolved() - } - - let mut base_addr = None; - TargetSharedLibrary::each(|lib| { - base_addr = Some(lib.virtual_memory_bias().0 as isize); - IterationControl::Break - }); - let addrfix = -base_addr.unwrap(); - - let trace = foo(); - trace - .frames() - .iter() - .take(5) - .map(|x| format!("{:p}", (x.ip() as *const u8).wrapping_offset(addrfix))) - .collect() -} - -fn run_cmd<P: AsRef<OsStr>>(exe: P, me: &Path, flags: Option<&str>, trace: &str) -> String { - let mut cmd = Command::new(exe); - cmd.env("LC_ALL", "C"); // GNU addr2line is localized, we aren't - cmd.env("RUST_BACKTRACE", "1"); // if a child crashes, we want to know why - - if let Some(flags) = flags { - cmd.arg(flags); - } - cmd.arg("--exe").arg(me).arg(trace); - - let output = cmd.output().unwrap(); - - assert!(output.status.success()); - String::from_utf8(output.stdout).unwrap() -} - -fn run_test(flags: Option<&str>) -> Result<(), Failed> { - let me = env::current_exe().unwrap(); - let mut exe = me.clone(); - assert!(exe.pop()); - if exe.file_name().unwrap().to_str().unwrap() == "deps" { - assert!(exe.pop()); - } - exe.push("examples"); - exe.push("addr2line"); - - assert!(exe.is_file()); - - let trace = make_trace(); - - // HACK: GNU addr2line has a bug where looking up multiple addresses can cause the second - // lookup to fail. Workaround by doing one address at a time. - for addr in &trace { - let theirs = run_cmd("addr2line", &me, flags, addr); - let ours = run_cmd(&exe, &me, flags, addr); - - // HACK: GNU addr2line does not tidy up paths properly, causing double slashes to be printed. - // We consider our behavior to be correct, so we fix their output to match ours. - let theirs = theirs.replace("//", "/"); - - assert!( - theirs == ours, - "Output not equivalent: - -$ addr2line {0} --exe {1} {2} -{4} -$ {3} {0} --exe {1} {2} -{5} - - -", - flags.unwrap_or(""), - me.display(), - trace.join(" "), - exe.display(), - theirs, - ours - ); - } - Ok(()) -} - -static FLAGS: &str = "aipsf"; - -fn make_tests() -> Vec<Trial> { - (0..(1 << FLAGS.len())) - .map(|bits| { - if bits == 0 { - None - } else { - let mut param = String::new(); - param.push('-'); - for (i, flag) in FLAGS.chars().enumerate() { - if (bits & (1 << i)) != 0 { - param.push(flag); - } - } - Some(param) - } - }) - .map(|param| { - Trial::test( - format!("addr2line {}", param.as_ref().map_or("", String::as_str)), - move || run_test(param.as_ref().map(String::as_str)), - ) - }) - .collect() -} - -fn main() { - if !cfg!(target_os = "linux") { - return; - } - let args = Arguments::from_args(); - libtest_mimic::run(&args, make_tests()).exit(); -} diff --git a/vendor/addr2line/tests/parse.rs b/vendor/addr2line/tests/parse.rs deleted file mode 100644 index 4dafe38..0000000 --- a/vendor/addr2line/tests/parse.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::borrow::Cow; -use std::env; -use std::fs::File; -use std::path::{self, PathBuf}; - -use object::Object; - -fn release_fixture_path() -> PathBuf { - if let Ok(p) = env::var("ADDR2LINE_FIXTURE_PATH") { - return p.into(); - } - - let mut path = PathBuf::new(); - if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") { - path.push(dir); - } - path.push("fixtures"); - path.push("addr2line-release"); - path -} - -fn with_file<F: FnOnce(&object::File<'_>)>(target: &path::Path, f: F) { - let file = File::open(target).unwrap(); - let map = unsafe { memmap2::Mmap::map(&file).unwrap() }; - let file = object::File::parse(&*map).unwrap(); - f(&file) -} - -fn dwarf_load<'a>(object: &object::File<'a>) -> gimli::Dwarf<Cow<'a, [u8]>> { - let load_section = |id: gimli::SectionId| -> Result<Cow<'a, [u8]>, gimli::Error> { - use object::ObjectSection; - - let data = object - .section_by_name(id.name()) - .and_then(|section| section.data().ok()) - .unwrap_or(&[][..]); - Ok(Cow::Borrowed(data)) - }; - gimli::Dwarf::load(&load_section).unwrap() -} - -fn dwarf_borrow<'a>( - dwarf: &'a gimli::Dwarf<Cow<'_, [u8]>>, -) -> gimli::Dwarf<gimli::EndianSlice<'a, gimli::LittleEndian>> { - let borrow_section: &dyn for<'b> Fn( - &'b Cow<'_, [u8]>, - ) -> gimli::EndianSlice<'b, gimli::LittleEndian> = - &|section| gimli::EndianSlice::new(section, gimli::LittleEndian); - dwarf.borrow(&borrow_section) -} - -#[test] -fn parse_base_rc() { - let target = release_fixture_path(); - - with_file(&target, |file| { - addr2line::ObjectContext::new(file).unwrap(); - }); -} - -#[test] -fn parse_base_slice() { - let target = release_fixture_path(); - - with_file(&target, |file| { - let dwarf = dwarf_load(file); - let dwarf = dwarf_borrow(&dwarf); - addr2line::Context::from_dwarf(dwarf).unwrap(); - }); -} - -#[test] -fn parse_lines_rc() { - let target = release_fixture_path(); - - with_file(&target, |file| { - let context = addr2line::ObjectContext::new(file).unwrap(); - context.parse_lines().unwrap(); - }); -} - -#[test] -fn parse_lines_slice() { - let target = release_fixture_path(); - - with_file(&target, |file| { - let dwarf = dwarf_load(file); - let dwarf = dwarf_borrow(&dwarf); - let context = addr2line::Context::from_dwarf(dwarf).unwrap(); - context.parse_lines().unwrap(); - }); -} - -#[test] -fn parse_functions_rc() { - let target = release_fixture_path(); - - with_file(&target, |file| { - let context = addr2line::ObjectContext::new(file).unwrap(); - context.parse_functions().unwrap(); - }); -} - -#[test] -fn parse_functions_slice() { - let target = release_fixture_path(); - - with_file(&target, |file| { - let dwarf = dwarf_load(file); - let dwarf = dwarf_borrow(&dwarf); - let context = addr2line::Context::from_dwarf(dwarf).unwrap(); - context.parse_functions().unwrap(); - }); -} |