diff options
Diffstat (limited to 'vendor/addr2line')
-rw-r--r-- | vendor/addr2line/.cargo-checksum.json | 2 | ||||
-rw-r--r-- | vendor/addr2line/CHANGELOG.md | 51 | ||||
-rw-r--r-- | vendor/addr2line/Cargo.lock | 534 | ||||
-rw-r--r-- | vendor/addr2line/Cargo.toml | 29 | ||||
-rw-r--r-- | vendor/addr2line/examples/addr2line.rs | 128 | ||||
-rw-r--r-- | vendor/addr2line/src/builtin_split_dwarf_loader.rs | 164 | ||||
-rw-r--r-- | vendor/addr2line/src/function.rs | 133 | ||||
-rw-r--r-- | vendor/addr2line/src/lazy.rs | 4 | ||||
-rw-r--r-- | vendor/addr2line/src/lib.rs | 755 | ||||
-rw-r--r-- | vendor/addr2line/tests/correctness.rs | 56 | ||||
-rw-r--r-- | vendor/addr2line/tests/output_equivalence.rs | 35 | ||||
-rw-r--r-- | vendor/addr2line/tests/parse.rs | 12 |
12 files changed, 1463 insertions, 440 deletions
diff --git a/vendor/addr2line/.cargo-checksum.json b/vendor/addr2line/.cargo-checksum.json index 43f25b3ba..5b12782dc 100644 --- a/vendor/addr2line/.cargo-checksum.json +++ b/vendor/addr2line/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"59733fc6186af0929ca4b6508e10ea1777f757c333a355d8154498332aee259f","Cargo.lock":"0b30594b7d3f093b44ca9c53366bbcb3f28a97ed24da65e56fe9961e7250c3c2","Cargo.toml":"c68ebf21efe63bb706716dd7b4bb7d33734629f13db36014d6be49fed6c8d731","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"624548450eda1c8491fe4de60f0a96d20ef9c0d70770de2d76d803850319c876","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/function.rs":"caa2458f48509a0e0e2c4920719383997e9ccab44efceeabcf3019587f438a57","src/lazy.rs":"21bc1a7d8593c11e93577f1f17163705dbbadf752a007fae4401a4150ec9e473","src/lib.rs":"41d575590b9a683349552d7c4c845ef9a2739e7a4a9e01d53d4e0f4a4947fc45","tests/correctness.rs":"0bd7f9bc9d333cca0649d7bb85e07ebc14855ec2f2b9082f4ec752ccea77e1d6","tests/output_equivalence.rs":"9b637de957f4760ed8bdbfac9e1bacf57f0123c54ed0fbfeb8c2c3b7077f3d81","tests/parse.rs":"f0b2437d0c0b204f6527975b10015a62636a61e5b6e20661824c6ddbdfe3eefe"},"package":"a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"}
\ No newline at end of file +{"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 index ed47aa90d..8754c715a 100644 --- a/vendor/addr2line/CHANGELOG.md +++ b/vendor/addr2line/CHANGELOG.md @@ -1,3 +1,52 @@ +# `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 @@ -281,7 +330,7 @@ ### Changed * [#108](https://github.com/gimli-rs/addr2line/issues/108) - `demangle` no longer ouputs the hash for rust symbols. + `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 index 330f3f544..3c2300260 100644 --- a/vendor/addr2line/Cargo.lock +++ b/vendor/addr2line/Cargo.lock @@ -4,16 +4,16 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ - "gimli 0.26.2", + "gimli 0.27.2", ] [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" dependencies = [ "backtrace", "clap", @@ -21,13 +21,13 @@ dependencies = [ "cpp_demangle", "fallible-iterator", "findshlibs", - "gimli 0.27.0", + "gimli 0.28.0", + "libtest-mimic", "memmap2", - "object 0.30.0", + "object 0.32.0", "rustc-demangle", "rustc-std-workspace-alloc", "rustc-std-workspace-core", - "rustc-test", "smallvec", "typed-arena", ] @@ -39,34 +39,66 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "atty" -version = "0.2.14" +name = "anstream" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" dependencies = [ - "hermit-abi", - "libc", - "winapi 0.3.9", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "anstyle" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +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.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ - "addr2line 0.17.0", + "addr2line 0.19.0", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.29.0", + "object 0.30.3", "rustc-demangle", ] @@ -77,10 +109,22 @@ 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.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -90,39 +134,63 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.12" +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 = "ab8b79fe3946ceb4a0b1c080b4018992b8d27e9ff363644c1c9b6387c854614d" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" dependencies = [ - "atty", - "bitflags", + "anstream", + "anstyle", "clap_lex", - "indexmap", "strsim", - "termcolor", - "textwrap", + "terminal_size", ] [[package]] -name = "clap_lex" -version = "0.2.4" +name = "clap_derive" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ - "os_str_bytes", + "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.75" +version = "0.1.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e3183e88f659a862835db8f4b67dbeed3d93e44dd4927eef78edb1c149d784" +checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a" [[package]] name = "cpp_demangle" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442" +checksum = "2c76f98bdfc7f66172e6c7065f981ebb576ffc903fe4c0561d9f0c2509226dc6" dependencies = [ "cfg-if", ] @@ -137,10 +205,31 @@ dependencies = [ ] [[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.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "findshlibs" @@ -151,39 +240,30 @@ dependencies = [ "cc", "lazy_static", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] name = "gimli" -version = "0.26.2" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "gimli" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" dependencies = [ "compiler_builtins", "fallible-iterator", @@ -193,38 +273,46 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.12.2" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ "libc", ] [[package]] -name = "indexmap" -version = "1.9.1" +name = "hermit-abi" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "autocfg", - "hashbrown", + "hermit-abi 0.3.2", + "libc", + "windows-sys", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "is-terminal" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "hermit-abi 0.3.2", + "rustix 0.38.8", + "windows-sys", ] [[package]] @@ -235,9 +323,32 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +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 = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +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" @@ -247,58 +358,81 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.5" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +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.29.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "object" -version = "0.30.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" dependencies = [ "flate2", "memchr", + "ruzstd", ] [[package]] -name = "os_str_bytes" -version = "6.2.0" +name = "once_cell" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] -name = "rustc-demangle" -version = "0.1.21" +name = "proc-macro2" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] [[package]] -name = "rustc-serialize" -version = "0.3.24" +name = "quote" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +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" @@ -313,48 +447,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c" [[package]] -name = "rustc-test" -version = "0.3.1" +name = "rustix" +version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aacc7967b0ae83af208c8caf2781cbf96f01dac0157cd89f7f05324d6d4e59bb" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ - "getopts", + "bitflags 1.3.2", + "errno", + "io-lifetimes", "libc", - "rustc-serialize", - "rustc_version", - "term", - "time", + "linux-raw-sys 0.3.8", + "windows-sys", ] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "rustix" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "semver", + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys 0.4.5", + "windows-sys", ] [[package]] -name = "semver" -version = "0.9.0" +name = "ruzstd" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" dependencies = [ - "semver-parser", + "byteorder", + "thiserror-core", + "twox-hash", ] [[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "stable_deref_trait" @@ -363,70 +497,114 @@ 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 = "term" -version = "0.4.6" +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 = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ - "kernel32-sys", - "winapi 0.2.8", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] -name = "textwrap" -version = "0.15.0" +name = "terminal_size" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +dependencies = [ + "rustix 0.37.23", + "windows-sys", +] [[package]] -name = "time" -version = "0.1.44" +name = "thiserror-core" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" dependencies = [ - "libc", - "wasi", - "winapi 0.3.9", + "thiserror-core-impl", ] [[package]] -name = "typed-arena" -version = "2.0.1" +name = "thiserror-core-impl" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" +checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] -name = "unicode-width" -version = "0.1.9" +name = "threadpool" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] [[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" +name = "twox-hash" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] [[package]] -name = "winapi" -version = "0.2.8" +name = "typed-arena" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +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" @@ -439,12 +617,6 @@ dependencies = [ ] [[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -456,7 +628,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -464,3 +636,69 @@ 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 index 2b51239b8..b6b6b8316 100644 --- a/vendor/addr2line/Cargo.toml +++ b/vendor/addr2line/Cargo.toml @@ -10,8 +10,10 @@ # See Cargo.toml.orig for the original contents. [package] +edition = "2018" +rust-version = "1.65" name = "addr2line" -version = "0.19.0" +version = "0.21.0" exclude = [ "/benches/*", "/fixtures/*", @@ -40,12 +42,12 @@ debug = true [[example]] name = "addr2line" -required-features = ["std-object"] +required-features = ["default"] [[test]] name = "output_equivalence" harness = false -required-features = ["std-object"] +required-features = ["default"] [[test]] name = "correctness" @@ -76,17 +78,21 @@ optional = true default-features = false [dependencies.fallible-iterator] -version = "0.2" +version = "0.3.0" optional = true default-features = false [dependencies.gimli] -version = "0.27.0" +version = "0.28.0" features = ["read"] default-features = false +[dependencies.memmap2] +version = "0.5.5" +optional = true + [dependencies.object] -version = "0.30.0" +version = "0.32.0" features = ["read"] optional = true default-features = false @@ -104,16 +110,14 @@ default-features = false version = "0.3.13" [dev-dependencies.clap] -version = "3.1.6" +version = "4.3.21" +features = ["wrap_help"] [dev-dependencies.findshlibs] version = "0.10" -[dev-dependencies.memmap2] -version = "0.5.5" - -[dev-dependencies.rustc-test] -version = "0.3" +[dev-dependencies.libtest-mimic] +version = "0.6.1" [dev-dependencies.typed-arena] version = "2" @@ -125,6 +129,7 @@ default = [ "std-object", "fallible-iterator", "smallvec", + "memmap2", ] rustc-dep-of-std = [ "core", diff --git a/vendor/addr2line/examples/addr2line.rs b/vendor/addr2line/examples/addr2line.rs index fa4d8e457..97fc80222 100644 --- a/vendor/addr2line/examples/addr2line.rs +++ b/vendor/addr2line/examples/addr2line.rs @@ -1,17 +1,9 @@ -extern crate addr2line; -extern crate clap; -extern crate fallible_iterator; -extern crate gimli; -extern crate memmap2; -extern crate object; -extern crate typed_arena; - use std::borrow::Cow; use std::fs::File; use std::io::{BufRead, Lines, StdinLock, Write}; -use std::path::Path; +use std::path::{Path, PathBuf}; -use clap::{Arg, Command, Values}; +use clap::{Arg, ArgAction, Command}; use fallible_iterator::FallibleIterator; use object::{Object, ObjectSection, SymbolMap, SymbolMapName}; use typed_arena::Arena; @@ -27,7 +19,7 @@ fn parse_uint_from_hex_string(string: &str) -> Option<u64> { } enum Addrs<'a> { - Args(Values<'a>), + Args(clap::parser::ValuesRef<'a, String>), Stdin(Lines<StdinLock<'a>>), } @@ -45,8 +37,8 @@ impl<'a> Iterator for Addrs<'a> { } } -fn print_loc(loc: Option<&Location>, basenames: bool, llvm: bool) { - if let Some(ref loc) = loc { +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()) @@ -102,21 +94,35 @@ fn load_file_section<'input, 'arena, Endian: gimli::Endianity>( } fn find_name_from_symbols<'a>( - symbols: &'a SymbolMap<SymbolMapName>, + 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("0.1") + .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.", ) @@ -124,52 +130,66 @@ fn main() { 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").help( + 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").help( + 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").help( + 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").help( + 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") - .takes_value(true) - .multiple_occurrences(true) + .action(ArgAction::Append) .help("Addresses to use instead of reading from stdin."), ]) .get_matches(); let arena_data = Arena::new(); - let do_functions = matches.is_present("functions"); - let do_inlines = matches.is_present("inlines"); - let pretty = matches.is_present("pretty"); - let print_addrs = matches.is_present("addresses"); - let basenames = matches.is_present("basenames"); - let demangle = matches.is_present("demangle"); - let llvm = matches.is_present("llvm"); - let path = matches.value_of("exe").unwrap(); + 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(path).unwrap(); + let file = File::open(opts.exe).unwrap(); let map = unsafe { memmap2::Mmap::map(&file).unwrap() }; let object = &object::File::parse(&*map).unwrap(); @@ -184,7 +204,7 @@ fn main() { }; let sup_map; - let sup_object = if let Some(sup_path) = matches.value_of("sup") { + 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()) @@ -201,87 +221,95 @@ fn main() { 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 - .values_of("addrs") + .get_many::<String>("addrs") .map(Addrs::Args) .unwrap_or_else(|| Addrs::Stdin(stdin.lock().lines())); for probe in addrs { - if print_addrs { + if opts.print_addrs { let addr = probe.unwrap_or(0); - if llvm { + if opts.llvm { print!("0x{:x}", addr); } else { print!("0x{:016x}", addr); } - if pretty { + if opts.pretty { print!(": "); } else { println!(); } } - if do_functions || do_inlines { + if opts.do_functions || opts.do_inlines { let mut printed_anything = false; if let Some(probe) = probe { - let mut frames = ctx.find_frames(probe).unwrap().enumerate(); + 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 pretty && i != 0 { + if opts.pretty && i != 0 { print!(" (inlined by) "); } - if do_functions { + if opts.do_functions { if let Some(func) = frame.function { print_function( func.raw_name().ok().as_ref().map(AsRef::as_ref), func.language, - demangle, + opts.demangle, ); } else { let name = find_name_from_symbols(&symbols, probe); - print_function(name, None, demangle); + print_function(name, None, opts.demangle); } - if pretty { + if opts.pretty { print!(" at "); } else { println!(); } } - print_loc(frame.location.as_ref(), basenames, llvm); + print_loc(frame.location.as_ref(), opts.basenames, opts.llvm); printed_anything = true; - if !do_inlines { + if !opts.do_inlines { break; } } } if !printed_anything { - if do_functions { + if opts.do_functions { let name = probe.and_then(|probe| find_name_from_symbols(&symbols, probe)); - print_function(name, None, demangle); + print_function(name, None, opts.demangle); - if pretty { + if opts.pretty { print!(" at "); } else { println!(); } } - print_loc(None, basenames, llvm); + print_loc(None, opts.basenames, opts.llvm); } } else { let loc = probe.and_then(|probe| ctx.find_location(probe).unwrap()); - print_loc(loc.as_ref(), basenames, llvm); + print_loc(loc.as_ref(), opts.basenames, opts.llvm); } - if llvm { + if opts.llvm { println!(); } std::io::stdout().flush().unwrap(); diff --git a/vendor/addr2line/src/builtin_split_dwarf_loader.rs b/vendor/addr2line/src/builtin_split_dwarf_loader.rs new file mode 100644 index 000000000..471193124 --- /dev/null +++ b/vendor/addr2line/src/builtin_split_dwarf_loader.rs @@ -0,0 +1,164 @@ +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 index 44dc73f24..09c19e01e 100644 --- a/vendor/addr2line/src/function.rs +++ b/vendor/addr2line/src/function.rs @@ -5,7 +5,7 @@ use core::iter; use crate::lazy::LazyCell; use crate::maybe_small; -use crate::{Error, RangeAttributes, ResDwarf}; +use crate::{Context, DebugFile, Error, RangeAttributes}; pub(crate) struct Functions<R: gimli::Reader> { /// List of all `DW_TAG_subprogram` details in the unit. @@ -49,13 +49,16 @@ pub(crate) struct InlinedFunctionAddress { 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: u64, + 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>, dwarf: &ResDwarf<R>) -> Result<Functions<R>, Error> { + 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)?; @@ -73,8 +76,7 @@ impl<R: gimli::Reader> Functions<R> { ranges.low_pc = Some(val) } gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.low_pc = - Some(dwarf.sections.address(unit, index)?); + ranges.low_pc = Some(sections.address(unit, index)?); } _ => {} }, @@ -83,8 +85,7 @@ impl<R: gimli::Reader> Functions<R> { ranges.high_pc = Some(val) } gimli::AttributeValue::DebugAddrIndex(index) => { - ranges.high_pc = - Some(dwarf.sections.address(unit, index)?); + ranges.high_pc = Some(sections.address(unit, index)?); } gimli::AttributeValue::Udata(val) => { ranges.size = Some(val) @@ -92,9 +93,8 @@ impl<R: gimli::Reader> Functions<R> { _ => {} }, gimli::DW_AT_ranges => { - ranges.ranges_offset = dwarf - .sections - .attr_ranges_offset(unit, attr.value())?; + ranges.ranges_offset = + sections.attr_ranges_offset(unit, attr.value())?; } _ => {} }; @@ -104,7 +104,7 @@ impl<R: gimli::Reader> Functions<R> { } let function_index = functions.len(); - if ranges.for_each_range(&dwarf.sections, unit, |range| { + if ranges.for_each_range(sections, unit, |range| { addresses.push(FunctionAddress { range, function: function_index, @@ -150,13 +150,15 @@ impl<R: gimli::Reader> Functions<R> { pub(crate) fn parse_inlined_functions( &self, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, ) -> Result<(), Error> { for function in &*self.functions { function .1 - .borrow_with(|| Function::parse(function.0, unit, dwarf)) + .borrow_with(|| Function::parse(function.0, file, unit, ctx, sections)) .as_ref() .map_err(Error::clone)?; } @@ -167,8 +169,10 @@ impl<R: gimli::Reader> Functions<R> { impl<R: gimli::Reader> Function<R> { pub(crate) fn parse( dw_die_offset: gimli::UnitOffset<R::Offset>, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<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(); @@ -181,18 +185,18 @@ impl<R: gimli::Reader> Function<R> { Ok(ref attr) => { match attr.name() { gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { - if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { name = Some(val); } } gimli::DW_AT_name => { if name.is_none() { - name = dwarf.sections.attr_string(unit, attr.value()).ok(); + 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(), unit, dwarf, 16)?; + name = name_attr(attr.value(), file, unit, ctx, sections, 16)?; } } _ => {} @@ -207,8 +211,10 @@ impl<R: gimli::Reader> Function<R> { Function::parse_children( &mut entries, depth, + file, unit, - dwarf, + ctx, + sections, &mut inlined_functions, &mut inlined_addresses, 0, @@ -247,10 +253,12 @@ impl<R: gimli::Reader> Function<R> { } fn parse_children( - entries: &mut gimli::EntriesRaw<R>, + entries: &mut gimli::EntriesRaw<'_, '_, R>, depth: isize, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, inlined_functions: &mut Vec<InlinedFunction<R>>, inlined_addresses: &mut Vec<InlinedFunctionAddress>, inlined_depth: usize, @@ -272,8 +280,10 @@ impl<R: gimli::Reader> Function<R> { entries, abbrev, next_depth, + file, unit, - dwarf, + ctx, + sections, inlined_functions, inlined_addresses, inlined_depth, @@ -288,7 +298,7 @@ impl<R: gimli::Reader> Function<R> { } fn skip( - entries: &mut gimli::EntriesRaw<R>, + entries: &mut gimli::EntriesRaw<'_, '_, R>, abbrev: &gimli::Abbreviation, depth: isize, ) -> Result<(), Error> { @@ -344,18 +354,20 @@ impl<R: gimli::Reader> Function<R> { impl<R: gimli::Reader> InlinedFunction<R> { fn parse( dw_die_offset: gimli::UnitOffset<R::Offset>, - entries: &mut gimli::EntriesRaw<R>, + entries: &mut gimli::EntriesRaw<'_, '_, R>, abbrev: &gimli::Abbreviation, depth: isize, + file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<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 = 0; + let mut call_file = None; let mut call_line = 0; let mut call_column = 0; for spec in abbrev.attributes() { @@ -364,40 +376,50 @@ impl<R: gimli::Reader> InlinedFunction<R> { 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(dwarf.sections.address(unit, 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(dwarf.sections.address(unit, index)?); + ranges.high_pc = Some(sections.address(unit, index)?); } gimli::AttributeValue::Udata(val) => ranges.size = Some(val), _ => {} }, gimli::DW_AT_ranges => { - ranges.ranges_offset = - dwarf.sections.attr_ranges_offset(unit, attr.value())?; + 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) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { name = Some(val); } } gimli::DW_AT_name => { if name.is_none() { - name = dwarf.sections.attr_string(unit, attr.value()).ok(); + 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(), unit, dwarf, 16)?; + 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() { - call_file = fi; + if fi > 0 || unit.header.version() >= 5 { + call_file = Some(fi); + } } } gimli::DW_AT_call_line => { @@ -421,7 +443,7 @@ impl<R: gimli::Reader> InlinedFunction<R> { call_column, }); - ranges.for_each_range(&dwarf.sections, unit, |range| { + ranges.for_each_range(sections, unit, |range| { inlined_addresses.push(InlinedFunctionAddress { range, call_depth: inlined_depth, @@ -432,8 +454,10 @@ impl<R: gimli::Reader> InlinedFunction<R> { Function::parse_children( entries, depth, + file, unit, - dwarf, + ctx, + sections, inlined_functions, inlined_addresses, inlined_depth + 1, @@ -443,8 +467,10 @@ impl<R: gimli::Reader> InlinedFunction<R> { fn name_attr<R>( attr: gimli::AttributeValue<R>, + mut file: DebugFile, unit: &gimli::Unit<R>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, recursion_limit: usize, ) -> Result<Option<R>, Error> where @@ -455,25 +481,18 @@ where } match attr { - gimli::AttributeValue::UnitRef(offset) => name_entry(unit, offset, dwarf, recursion_limit), + gimli::AttributeValue::UnitRef(offset) => { + name_entry(file, unit, offset, ctx, sections, recursion_limit) + } gimli::AttributeValue::DebugInfoRef(dr) => { - let res_unit = dwarf.find_unit(dr)?; - name_entry( - &res_unit.dw_unit, - gimli::UnitOffset(dr.0 - res_unit.offset.0), - dwarf, - recursion_limit, - ) + 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_dwarf) = dwarf.sup.as_ref() { - let res_unit = sup_dwarf.find_unit(dr)?; - name_entry( - &res_unit.dw_unit, - gimli::UnitOffset(dr.0 - res_unit.offset.0), - sup_dwarf, - recursion_limit, - ) + 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) } @@ -483,9 +502,11 @@ where } fn name_entry<R>( + file: DebugFile, unit: &gimli::Unit<R>, offset: gimli::UnitOffset<R::Offset>, - dwarf: &ResDwarf<R>, + ctx: &Context<R>, + sections: &gimli::Dwarf<R>, recursion_limit: usize, ) -> Result<Option<R>, Error> where @@ -504,12 +525,12 @@ where 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) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { return Ok(Some(val)); } } gimli::DW_AT_name => { - if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) { + if let Ok(val) = sections.attr_string(unit, attr.value()) { name = Some(val); } } @@ -527,7 +548,7 @@ where } if let Some(next) = next { - return name_attr(next, unit, dwarf, recursion_limit - 1); + 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 index a34ed176a..2df2ed6ca 100644 --- a/vendor/addr2line/src/lazy.rs +++ b/vendor/addr2line/src/lazy.rs @@ -10,6 +10,10 @@ impl<T> LazyCell<T> { } } + 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(); diff --git a/vendor/addr2line/src/lib.rs b/vendor/addr2line/src/lib.rs index 3afa37f8f..3270aad7e 100644 --- a/vendor/addr2line/src/lib.rs +++ b/vendor/addr2line/src/lib.rs @@ -25,19 +25,18 @@ #![deny(missing_docs)] #![no_std] +#[cfg(feature = "std")] +extern crate std; + #[allow(unused_imports)] #[macro_use] extern crate alloc; -#[cfg(feature = "cpp_demangle")] -extern crate cpp_demangle; #[cfg(feature = "fallible-iterator")] pub extern crate fallible_iterator; pub extern crate gimli; #[cfg(feature = "object")] pub extern crate object; -#[cfg(feature = "rustc-demangle")] -extern crate rustc_demangle; use alloc::borrow::Cow; use alloc::boxed::Box; @@ -49,8 +48,10 @@ 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}; @@ -67,17 +68,124 @@ mod maybe_small { 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> { - dwarf: ResDwarf<R>, + 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. @@ -109,7 +217,7 @@ impl Context<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_sup` + /// 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, @@ -176,7 +284,7 @@ impl<R: gimli::Reader> Context<R> { debug_types: default_section.clone().into(), locations: gimli::LocationLists::new( default_section.clone().into(), - default_section.clone().into(), + default_section.into(), ), ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists), file_type: gimli::DwarfFileType::Main, @@ -187,18 +295,20 @@ impl<R: gimli::Reader> Context<R> { /// Construct a new `Context` from an existing [`gimli::Dwarf`] object. #[inline] - pub fn from_dwarf(sections: gimli::Dwarf<R>) -> Result<Self, Error> { - let mut dwarf = ResDwarf::parse(Arc::new(sections))?; - dwarf.sup = match dwarf.sections.sup.clone() { - Some(sup_sections) => Some(Box::new(ResDwarf::parse(sup_sections)?)), - None => None, + 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 { dwarf }) - } - - /// The dwarf sections associated with this `Context`. - pub fn dwarf(&self) -> &gimli::Dwarf<R> { - &self.dwarf.sections + 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. @@ -229,7 +339,6 @@ impl<R: gimli::Reader> Context<R> { // First up find the position in the array which could have our function // address. let pos = match self - .dwarf .unit_ranges .binary_search_by_key(&probe_high, |i| i.range.begin) { @@ -244,7 +353,7 @@ impl<R: gimli::Reader> Context<R> { // Once we have our index we iterate backwards from that position // looking for a matching CU. - self.dwarf.unit_ranges[..pos] + self.unit_ranges[..pos] .iter() .rev() .take_while(move |i| { @@ -265,25 +374,51 @@ impl<R: gimli::Reader> Context<R> { if probe_low >= i.range.end || probe_high <= i.range.begin { return None; } - Some((&self.dwarf.units[i.unit_id], &i.range)) + Some((&self.units[i.unit_id], &i.range)) }) } /// Find the DWARF unit corresponding to the given virtual memory address. - pub fn find_dwarf_unit(&self, probe: u64) -> Option<&gimli::Unit<R>> { - for unit in self.find_units(probe) { - match unit.find_function_or_location(probe, &self.dwarf) { - Ok((Some(_), _)) | Ok((_, Some(_))) => return Some(&unit.dw_unit), - _ => {} - } + 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, + }, + }) + }, + ); } - 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.dwarf.sections)? { + if let Some(location) = unit.find_location(probe, &self.sections)? { return Ok(Some(location)); } } @@ -309,33 +444,95 @@ impl<R: gimli::Reader> Context<R> { /// 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) -> Result<FrameIter<R>, Error> { - for unit in self.find_units(probe) { - match unit.find_function_or_location(probe, &self.dwarf)? { - (Some(function), location) => { - let inlined_functions = function.find_inlined_functions(probe); - return Ok(FrameIter(FrameIterState::Frames(FrameIterFrames { - unit, - sections: &self.dwarf.sections, - function, - inlined_functions, - next: location, - }))); - } - (None, Some(location)) => { - return Ok(FrameIter(FrameIterState::Location(Some(location)))); - } - _ => {} - } + 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))) } - 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.dwarf.units { - unit.parse_lines(&self.dwarf.sections)?; + for unit in self.units.iter() { + unit.parse_lines(&self.sections)?; } Ok(()) } @@ -343,8 +540,8 @@ impl<R: gimli::Reader> Context<R> { /// Initialize all function data structures. This is used for benchmarks. #[doc(hidden)] pub fn parse_functions(&self) -> Result<(), Error> { - for unit in &self.dwarf.units { - unit.parse_functions(&self.dwarf)?; + for unit in self.units.iter() { + unit.parse_functions(self).skip_all_loads()?; } Ok(()) } @@ -352,8 +549,8 @@ impl<R: gimli::Reader> Context<R> { /// 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.dwarf.units { - unit.parse_inlined_functions(&self.dwarf)?; + for unit in self.units.iter() { + unit.parse_inlined_functions(self).skip_all_loads()?; } Ok(()) } @@ -365,15 +562,22 @@ struct UnitRange { range: gimli::Range, } -struct ResDwarf<R: gimli::Reader> { - unit_ranges: Vec<UnitRange>, - units: Vec<ResUnit<R>>, - sections: Arc<gimli::Dwarf<R>>, - sup: Option<Box<ResDwarf<R>>>, +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> ResDwarf<R> { - fn parse(sections: Arc<gimli::Dwarf<R>>) -> Result<Self, Error> { +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. @@ -484,7 +688,7 @@ impl<R: gimli::Reader> ResDwarf<R> { } } } else { - have_unit_range |= ranges.for_each_range(§ions, &dw_unit, |range| { + have_unit_range |= ranges.for_each_range(sections, &dw_unit, |range| { unit_ranges.push(UnitRange { range, unit_id, @@ -500,7 +704,7 @@ impl<R: gimli::Reader> ResDwarf<R> { // 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)) + .borrow_with(|| Lines::parse(&dw_unit, ilnp.clone(), sections)) .as_ref() { for sequence in lines.sequences.iter() { @@ -523,6 +727,7 @@ impl<R: gimli::Reader> ResDwarf<R> { lang, lines, funcs: LazyCell::new(), + dwo: LazyCell::new(), }); } @@ -537,23 +742,60 @@ impl<R: gimli::Reader> ResDwarf<R> { i.max_end = max; } - Ok(ResDwarf { - units: res_units, - unit_ranges, - sections, - sup: None, - }) + Ok((unit_ranges, res_units)) } - fn find_unit(&self, offset: gimli::DebugInfoOffset<R::Offset>) -> Result<&ResUnit<R>, Error> { - 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) => Err(gimli::Error::NoEntryAtGivenOffset), - Err(i) => Ok(&self.units[i - 1]), + 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)) } } @@ -680,16 +922,247 @@ struct LineRow { column: u32, } -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>>, +/// 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), @@ -701,19 +1174,39 @@ impl<R: gimli::Reader> ResUnit<R> { .map_err(Error::clone) } - fn parse_functions(&self, dwarf: &ResDwarf<R>) -> Result<&Functions<R>, Error> { + 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(&self.dw_unit, dwarf)) + .borrow_with(|| Functions::parse(unit, sections)) .as_ref() .map_err(Error::clone) } - fn parse_inlined_functions(&self, dwarf: &ResDwarf<R>) -> Result<(), Error> { - self.funcs - .borrow_with(|| Functions::parse(&self.dw_unit, dwarf)) - .as_ref() - .map_err(Error::clone)? - .parse_inlined_functions(&self.dw_unit, dwarf) + 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( @@ -741,27 +1234,35 @@ impl<R: gimli::Reader> ResUnit<R> { LocationRangeUnitIter::new(self, sections, probe_low, probe_high) } - fn find_function_or_location( - &self, + fn find_function_or_location<'unit, 'ctx: 'unit>( + &'unit self, probe: u64, - dwarf: &ResDwarf<R>, - ) -> Result<(Option<&Function<R>>, Option<Location<'_>>), Error> { - let functions = self.parse_functions(dwarf)?; - 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, &self.dw_unit, dwarf)) - .as_ref() - .map_err(Error::clone)?, - ) - } - None => None, - }; - let location = self.find_location(probe, &dwarf.sections)?; - Ok((function, location)) + 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)) + }) } } @@ -778,7 +1279,7 @@ pub struct LocationRangeIter<'ctx, R: gimli::Reader> { 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.dwarf.sections; + let sections = &ctx.sections; let unit_iter = ctx.find_units_range(probe_low, probe_high); Ok(Self { unit_iter: Box::new(unit_iter), @@ -879,12 +1380,11 @@ impl<'ctx> LocationRangeUnitIter<'ctx> { 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)); - let idx = match idx { + match idx { Ok(x) => x, Err(0) => 0, // probe below sequence, but range could overlap Err(x) => x - 1, - }; - idx + } } else { 0 }; @@ -906,12 +1406,7 @@ impl<'ctx> Iterator for LocationRangeUnitIter<'ctx> { type Item = (u64, u64, Location<'ctx>); fn next(&mut self) -> Option<(u64, u64, Location<'ctx>)> { - loop { - let seq = match self.seqs.get(self.seq_idx) { - Some(seq) => seq, - None => break, - }; - + while let Some(seq) = self.seqs.get(self.seq_idx) { if seq.start >= self.probe_high { break; } @@ -1038,11 +1533,11 @@ impl<R: gimli::Reader> RangeAttributes<R> { /// An iterator over function frames. pub struct FrameIter<'ctx, R>(FrameIterState<'ctx, R>) where - R: gimli::Reader + 'ctx; + R: gimli::Reader; enum FrameIterState<'ctx, R> where - R: gimli::Reader + 'ctx, + R: gimli::Reader, { Empty, Location(Option<Location<'ctx>>), @@ -1051,7 +1546,7 @@ where struct FrameIterFrames<'ctx, R> where - R: gimli::Reader + 'ctx, + R: gimli::Reader, { unit: &'ctx ResUnit<R>, sections: &'ctx gimli::Dwarf<R>, @@ -1111,9 +1606,9 @@ where None }, }; - if func.call_file != 0 { + if let Some(call_file) = func.call_file { if let Some(lines) = frames.unit.parse_lines(frames.sections)? { - next.file = lines.files.get(func.call_file as usize).map(String::as_str); + next.file = lines.files.get(call_file as usize).map(String::as_str); } } frames.next = Some(next); @@ -1163,12 +1658,12 @@ pub struct FunctionName<R: gimli::Reader> { impl<R: gimli::Reader> FunctionName<R> { /// The raw name of this function before demangling. - pub fn raw_name(&self) -> Result<Cow<str>, Error> { + 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> { + pub fn demangle(&self) -> Result<Cow<'_, str>, Error> { self.raw_name().map(|x| demangle_auto(x, self.language)) } } @@ -1204,7 +1699,7 @@ pub fn demangle(name: &str, language: gimli::DwLang) -> Option<String> { /// 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> { +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) @@ -1229,6 +1724,6 @@ mod tests { #[test] fn context_is_send() { fn assert_is_send<T: Send>() {} - assert_is_send::<crate::Context<gimli::read::EndianSlice<gimli::LittleEndian>>>(); + assert_is_send::<crate::Context<gimli::read::EndianSlice<'_, gimli::LittleEndian>>>(); } } diff --git a/vendor/addr2line/tests/correctness.rs b/vendor/addr2line/tests/correctness.rs index 955e2b831..73ee462f8 100644 --- a/vendor/addr2line/tests/correctness.rs +++ b/vendor/addr2line/tests/correctness.rs @@ -1,15 +1,10 @@ -extern crate addr2line; -extern crate fallible_iterator; -extern crate findshlibs; -extern crate gimli; -extern crate memmap2; -extern crate object; - 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(); @@ -42,7 +37,37 @@ fn correctness() { let map = find_debuginfo(); let file = &object::File::parse(&*map).unwrap(); let module_base = file.relative_address_base(); - let ctx = Context::new(file).unwrap(); + + 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| { @@ -50,10 +75,12 @@ fn correctness() { IterationControl::Break }); - let test = |sym: u64, expected_prefix: &str| { + #[allow(unused_mut)] + let mut test = |sym: u64, expected_prefix: &str| { let ip = sym.wrapping_sub(bias.unwrap()); - let frames = ctx.find_frames(ip).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, @@ -87,6 +114,13 @@ fn zero_function() { let file = &object::File::parse(&*map).unwrap(); let ctx = Context::new(file).unwrap(); for probe in 0..10 { - assert!(ctx.find_frames(probe).unwrap().count().unwrap() < 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 index c0e1f8335..ef026e347 100644 --- a/vendor/addr2line/tests/output_equivalence.rs +++ b/vendor/addr2line/tests/output_equivalence.rs @@ -1,7 +1,3 @@ -extern crate backtrace; -extern crate findshlibs; -extern crate rustc_test as test; - use std::env; use std::ffi::OsStr; use std::path::Path; @@ -9,7 +5,7 @@ use std::process::Command; use backtrace::Backtrace; use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary}; -use test::{ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName}; +use libtest_mimic::{Arguments, Failed, Trial}; #[inline(never)] fn make_trace() -> Vec<String> { @@ -57,7 +53,7 @@ fn run_cmd<P: AsRef<OsStr>>(exe: P, me: &Path, flags: Option<&str>, trace: &str) String::from_utf8(output.stdout).unwrap() } -fn run_test(flags: Option<&str>) { +fn run_test(flags: Option<&str>) -> Result<(), Failed> { let me = env::current_exe().unwrap(); let mut exe = me.clone(); assert!(exe.pop()); @@ -100,11 +96,12 @@ $ {3} {0} --exe {1} {2} ours ); } + Ok(()) } -static FLAGS: &'static str = "aipsf"; +static FLAGS: &str = "aipsf"; -fn make_tests() -> Vec<TestDescAndFn> { +fn make_tests() -> Vec<Trial> { (0..(1 << FLAGS.len())) .map(|bits| { if bits == 0 { @@ -120,19 +117,11 @@ fn make_tests() -> Vec<TestDescAndFn> { Some(param) } }) - .map(|param| TestDescAndFn { - desc: TestDesc { - name: TestName::DynTestName(format!( - "addr2line {}", - param.as_ref().map_or("", String::as_str) - )), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: TestFn::DynTestFn(Box::new(move || { - run_test(param.as_ref().map(String::as_str)) - })), + .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() } @@ -141,6 +130,6 @@ fn main() { if !cfg!(target_os = "linux") { return; } - let args: Vec<_> = env::args().collect(); - test::test_main(&args, make_tests()); + 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 index 60b2300b5..4dafe385c 100644 --- a/vendor/addr2line/tests/parse.rs +++ b/vendor/addr2line/tests/parse.rs @@ -1,7 +1,3 @@ -extern crate addr2line; -extern crate memmap2; -extern crate object; - use std::borrow::Cow; use std::env; use std::fs::File; @@ -23,7 +19,7 @@ fn release_fixture_path() -> PathBuf { path } -fn with_file<F: FnOnce(&object::File)>(target: &path::Path, f: F) { +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(); @@ -44,12 +40,12 @@ fn dwarf_load<'a>(object: &object::File<'a>) -> gimli::Dwarf<Cow<'a, [u8]>> { } fn dwarf_borrow<'a>( - dwarf: &'a gimli::Dwarf<Cow<[u8]>>, + dwarf: &'a gimli::Dwarf<Cow<'_, [u8]>>, ) -> gimli::Dwarf<gimli::EndianSlice<'a, gimli::LittleEndian>> { let borrow_section: &dyn for<'b> Fn( - &'b Cow<[u8]>, + &'b Cow<'_, [u8]>, ) -> gimli::EndianSlice<'b, gimli::LittleEndian> = - &|section| gimli::EndianSlice::new(&*section, gimli::LittleEndian); + &|section| gimli::EndianSlice::new(section, gimli::LittleEndian); dwarf.borrow(&borrow_section) } |