summaryrefslogtreecommitdiffstats
path: root/vendor/addr2line
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/addr2line')
-rw-r--r--vendor/addr2line/.cargo-checksum.json2
-rw-r--r--vendor/addr2line/CHANGELOG.md51
-rw-r--r--vendor/addr2line/Cargo.lock534
-rw-r--r--vendor/addr2line/Cargo.toml29
-rw-r--r--vendor/addr2line/examples/addr2line.rs128
-rw-r--r--vendor/addr2line/src/builtin_split_dwarf_loader.rs164
-rw-r--r--vendor/addr2line/src/function.rs133
-rw-r--r--vendor/addr2line/src/lazy.rs4
-rw-r--r--vendor/addr2line/src/lib.rs755
-rw-r--r--vendor/addr2line/tests/correctness.rs56
-rw-r--r--vendor/addr2line/tests/output_equivalence.rs35
-rw-r--r--vendor/addr2line/tests/parse.rs12
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(&sections)?;
+ 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(&sections, &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)
}