diff options
Diffstat (limited to 'vendor/backtrace-ext')
-rw-r--r-- | vendor/backtrace-ext/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/backtrace-ext/Cargo.lock | 515 | ||||
-rw-r--r-- | vendor/backtrace-ext/Cargo.toml | 27 | ||||
-rw-r--r-- | vendor/backtrace-ext/README.md | 8 | ||||
-rw-r--r-- | vendor/backtrace-ext/examples/miette.rs | 99 | ||||
-rw-r--r-- | vendor/backtrace-ext/src/lib.rs | 277 | ||||
-rw-r--r-- | vendor/backtrace-ext/src/test.rs | 524 |
7 files changed, 1451 insertions, 0 deletions
diff --git a/vendor/backtrace-ext/.cargo-checksum.json b/vendor/backtrace-ext/.cargo-checksum.json new file mode 100644 index 0000000..bde552e --- /dev/null +++ b/vendor/backtrace-ext/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"e6108103e5de7a31784d19ff1ce5f208f5ba926da8d49991f11f6b9f6b3a7a6a","Cargo.toml":"6c19e27c8d3f3c65ae6720d5715036faa3ab6f6187853d125e24d5ef5295d524","README.md":"0545686a94177567dd9c957f137256b3d49eba77560f3b12a4b5c6c8d6546179","examples/miette.rs":"9f5e1c803a14c742f37e18b6ec965b461646a1cc156c908fa7229f4e01958220","src/lib.rs":"eb0c7d3a660108416db915d94388e384c149161fa8145e8e276add714648f01a","src/test.rs":"cca4c8198af8a71e64174ba4c587fd1f3d2f3e524520c6a99b75675607ba624c"},"package":"537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"}
\ No newline at end of file diff --git a/vendor/backtrace-ext/Cargo.lock b/vendor/backtrace-ext/Cargo.lock new file mode 100644 index 0000000..3f71074 --- /dev/null +++ b/vendor/backtrace-ext/Cargo.lock @@ -0,0 +1,515 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +dependencies = [ + "backtrace", + "miette", + "thiserror", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +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 = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "io-lifetimes" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "is_ci" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "miette" +version = "5.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07749fb52853e739208049fb513287c6f448de9103dfa78b05ae01f2fc5809bb" +dependencies = [ + "backtrace", + "is-terminal", + "miette-derive", + "once_cell", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "5.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a07ad93a80d1b92bb44cb42d7c49b49c9aab1778befefad49cceb5e4c5bf460" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "proc-macro2" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "rustc-demangle" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" + +[[package]] +name = "rustix" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e78cc525325c06b4a7ff02db283472f3c042b7ff0c391f96c6d5ac6f4f91b75" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "smawk" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" + +[[package]] +name = "supports-color" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4950e7174bffabe99455511c39707310e7e9b440364a2fcb1cc21521be57b354" +dependencies = [ + "is-terminal", + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4806e0b03b9906e76b018a5d821ebf198c8e9dc0829ed3328eeeb5094aed60" +dependencies = [ + "is-terminal", +] + +[[package]] +name = "supports-unicode" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" +dependencies = [ + "is-terminal", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.12", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-linebreak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" +dependencies = [ + "hashbrown", + "regex", +] + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +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.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" diff --git a/vendor/backtrace-ext/Cargo.toml b/vendor/backtrace-ext/Cargo.toml new file mode 100644 index 0000000..2195a36 --- /dev/null +++ b/vendor/backtrace-ext/Cargo.toml @@ -0,0 +1,27 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.56" +name = "backtrace-ext" +version = "0.2.1" +description = "minor conveniences on top of the backtrace crate" +license = "MIT OR Apache-2.0" +repository = "https://github.com/gankra/backtrace-ext" +[dependencies.backtrace] +version = "0.3.61" +[dev-dependencies.miette] +version = "5.6.0" +features = ["fancy"] + +[dev-dependencies.thiserror] +version = "1.0.40" diff --git a/vendor/backtrace-ext/README.md b/vendor/backtrace-ext/README.md new file mode 100644 index 0000000..df25c6e --- /dev/null +++ b/vendor/backtrace-ext/README.md @@ -0,0 +1,8 @@ +# backtrace-ext + +[![crates.io](https://img.shields.io/crates/v/backtrace-ext.svg)](https://crates.io/crates/backtrace-ext) +[![docs](https://docs.rs/backtrace-ext/badge.svg)](https://docs.rs/backtrace-ext) +[![Rust CI](https://github.com/gankra/backtrace-ext/workflows/Rust%20CI/badge.svg?branch=main)](https://github.com/gankra/backtrace-ext/actions/workflows/ci.yml) + +Minor conveniences on top of the backtrace crate, because I don't want to copy-paste this everywhere +I override a panic handler.
\ No newline at end of file diff --git a/vendor/backtrace-ext/examples/miette.rs b/vendor/backtrace-ext/examples/miette.rs new file mode 100644 index 0000000..ae41982 --- /dev/null +++ b/vendor/backtrace-ext/examples/miette.rs @@ -0,0 +1,99 @@ +use std::fmt::Write; + +use backtrace::Backtrace; +use miette::{Context, Diagnostic, Report}; +use thiserror::Error; + +type Result<T> = std::result::Result<T, Report>; + +#[inline(never)] +fn main() { + set_panic_hook(); + do_thing(); +} + +#[inline(never)] +fn do_thing() { + panic!("ooopssie!!!"); +} + +/// Tells miette to render panics using its rendering engine. +pub fn set_panic_hook() { + std::panic::set_hook(Box::new(move |info| { + let mut message = "Something went wrong".to_string(); + let payload = info.payload(); + if let Some(msg) = payload.downcast_ref::<&str>() { + message = msg.to_string(); + } + if let Some(msg) = payload.downcast_ref::<String>() { + message = msg.clone(); + } + let mut report: Result<()> = Err(Panic(message).into()); + if let Some(loc) = info.location() { + report = report + .with_context(|| format!("at {}:{}:{}", loc.file(), loc.line(), loc.column())); + } + if let Err(err) = report.with_context(|| "Main thread panicked.".to_string()) { + eprintln!("Error: {:?}", err); + } + })); +} + +#[derive(Debug, Error, Diagnostic)] +#[error("{0}{}", Panic::backtrace())] +#[diagnostic(help("set the `RUST_BACKTRACE=1` environment variable to display a backtrace."))] +struct Panic(String); + +impl Panic { + fn backtrace() -> String { + if let Ok(var) = std::env::var("RUST_BACKTRACE") { + if !var.is_empty() && var != "0" { + const HEX_WIDTH: usize = std::mem::size_of::<usize>() + 2; + // Padding for next lines after frame's address + const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6; + let mut backtrace = String::new(); + let trace = Backtrace::new(); + let frames = backtrace_ext::short_frames_strict(&trace).enumerate(); + for (idx, (frame, sub_frames)) in frames { + let ip = frame.ip(); + let _ = write!(backtrace, "\n{:4}: {:2$?}", idx, ip, HEX_WIDTH); + + let symbols = frame.symbols(); + if symbols.is_empty() { + let _ = write!(backtrace, " - <unresolved>"); + continue; + } + + for (idx, symbol) in symbols[sub_frames].iter().enumerate() { + // Print symbols from this address, + // if there are several addresses + // we need to put it on next line + if idx != 0 { + let _ = write!(backtrace, "\n{:1$}", "", NEXT_SYMBOL_PADDING); + } + + if let Some(name) = symbol.name() { + let _ = write!(backtrace, " - {}", name); + } else { + let _ = write!(backtrace, " - <unknown>"); + } + + // See if there is debug information with file name and line + if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) { + let _ = write!( + backtrace, + "\n{:3$}at {}:{}", + "", + file.display(), + line, + NEXT_SYMBOL_PADDING + ); + } + } + } + return backtrace; + } + } + "".into() + } +} diff --git a/vendor/backtrace-ext/src/lib.rs b/vendor/backtrace-ext/src/lib.rs new file mode 100644 index 0000000..b04c59d --- /dev/null +++ b/vendor/backtrace-ext/src/lib.rs @@ -0,0 +1,277 @@ +//! Minor conveniences on top of the backtrace crate +//! +//! See [`short_frames_strict`][] for details. +use backtrace::*; +use std::ops::Range; + +#[cfg(test)] +mod test; + +/// Gets an iterator over the frames that are part of Rust's "short backtrace" range. +/// If no such range is found, the full stack is yielded. +/// +/// Rust generally tries to include special frames on the stack called `rust_end_short_backtrace` +/// and `rust_begin_short_backtrace` which delimit the "real" stackframes from "gunk" stackframes +/// like setting up main and invoking the panic runtime. This yields all the "real" frames between +/// those two (which theoretically can be nothing with enough optimization, although that's unlikely +/// for any non-trivial program). +/// +/// If only one of the special frames is present we will only clamp one side of the stack +/// (similar to `a..` or `..a`). If the special frames are in the wrong order we will discard +/// them and produce the full stack. If multiple versions of a special frame are found +/// (I've seen it in the wild), we will pick the "innermost" ones, producing the smallest +/// possible backtrace (and excluding all special frames from the output). +/// +/// Each element of the iterator includes a Range which you should use to slice +/// the frame's `symbols()` array. This handles the theoretical situation where "real" frames +/// got inlined together with the special marker frames. I want to believe this can't happen +/// but you can never trust backtraces to be reasonable! We will never yield a Frame to you +/// with an empty Range. +/// +/// Note that some "gunk" frames may still be found within the short backtrace, as there is still some +/// platform-specific and optimization-specific glue around the edges because compilers are +/// complicated and nothing's perfect. This can include: +/// +/// * `core::ops::function::FnOnce::call_once` +/// * `std::panicking::begin_panic_handler` +/// * `core::panicking::panic_fmt` +/// * `rust_begin_unwind` +/// +/// In the future we may introduce a non-strict short_frames which heuristically filters +/// those frames out too. Until then, the strict approach is safe. +/// +/// # Example +/// +/// Here's an example simple "short backtrace" implementation. +/// Note the use of `sub_frames` for the inner loop to restrict `symbols`! +/// +/// This example is based off of code found in `miette` (Apache-2.0), which itself +/// copied the logic from `human-panic` (MIT/Apache-2.0). +/// +/// FIXME: it would be nice if this example consulted `RUST_BACKTRACE=full`, +/// and maybe other vars used by rust's builtin panic handler..? +/// +/// ``` +/// fn backtrace() -> String { +/// use std::fmt::Write; +/// if let Ok(var) = std::env::var("RUST_BACKTRACE") { +/// if !var.is_empty() && var != "0" { +/// const HEX_WIDTH: usize = std::mem::size_of::<usize>() + 2; +/// // Padding for next lines after frame's address +/// const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6; +/// let mut backtrace = String::new(); +/// let trace = backtrace::Backtrace::new(); +/// let frames = backtrace_ext::short_frames_strict(&trace).enumerate(); +/// for (idx, (frame, subframes)) in frames { +/// let ip = frame.ip(); +/// let _ = write!(backtrace, "\n{:4}: {:2$?}", idx, ip, HEX_WIDTH); +/// +/// let symbols = frame.symbols(); +/// if symbols.is_empty() { +/// let _ = write!(backtrace, " - <unresolved>"); +/// continue; +/// } +/// +/// for (idx, symbol) in symbols[subframes].iter().enumerate() { +/// // Print symbols from this address, +/// // if there are several addresses +/// // we need to put it on next line +/// if idx != 0 { +/// let _ = write!(backtrace, "\n{:1$}", "", NEXT_SYMBOL_PADDING); +/// } +/// +/// if let Some(name) = symbol.name() { +/// let _ = write!(backtrace, " - {}", name); +/// } else { +/// let _ = write!(backtrace, " - <unknown>"); +/// } +/// +/// // See if there is debug information with file name and line +/// if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) { +/// let _ = write!( +/// backtrace, +/// "\n{:3$}at {}:{}", +/// "", +/// file.display(), +/// line, +/// NEXT_SYMBOL_PADDING +/// ); +/// } +/// } +/// } +/// return backtrace; +/// } +/// } +/// "".into() +/// } +/// ``` +pub fn short_frames_strict( + backtrace: &Backtrace, +) -> impl Iterator<Item = (&BacktraceFrame, Range<usize>)> { + short_frames_strict_impl(backtrace) +} + +pub(crate) fn short_frames_strict_impl<B: Backtraceish>( + backtrace: &B, +) -> impl Iterator<Item = (&B::Frame, Range<usize>)> { + // Search for the special frames + let mut short_start = None; + let mut short_end = None; + let frames = backtrace.frames(); + for (frame_idx, frame) in frames.iter().enumerate() { + let symbols = frame.symbols(); + for (subframe_idx, frame) in symbols.iter().enumerate() { + if let Some(name) = frame.name_str() { + // Yes these ARE backwards, and that's intentional! We want to print the frames from + // "newest to oldest" (show what panicked first), and that's the order that Backtrace + // gives us, but these magic labels view the stack in the opposite order. So we just + // swap it once here and forget about that weirdness. + // + // Note that due to platform/optimization wobblyness you can end up with multiple frames + // that contain these names in sequence. If that happens we just want to pick the two + // that are closest together. For the start that means just using the last one we found, + // and for the end that means taking the first one we find. + if name.contains("rust_end_short_backtrace") { + short_start = Some((frame_idx, subframe_idx)); + } + if name.contains("rust_begin_short_backtrace") && short_end.is_none() { + short_end = Some((frame_idx, subframe_idx)); + } + } + } + } + + // Check if these are in the right order, if they aren't, discard them + // This also handles the mega-cursed case of "someone made a symbol with both names + // so actually they're the exact same subframe". + if let (Some(start), Some(end)) = (short_start, short_end) { + if start >= end { + short_start = None; + short_end = None; + } + } + + // By default we want to produce a full stack trace and now we'll try to clamp it. + let mut first_frame = 0usize; + let mut first_subframe = 0usize; + // NOTE: this is INCLUSIVE + let mut last_frame = frames.len().saturating_sub(1); + // NOTE: this is EXCLUSIVE + let mut last_subframe_excl = backtrace + .frames() + .last() + .map(|frame| frame.symbols().len()) + .unwrap_or(0); + + // This code tries to be really paranoid about boundary conditions although in practice + // most of them are impossible because there's always going to be gunk on either side + // of the short backtrace to smooth out the boundaries, and panic_fmt is basically + // impossible to optimize out. Still, don't trust backtracers!!! + // + // This library has a fuckton of tests to try to catch all the little corner cases here. + + // If we found the start bound... + if let Some((idx, sub_idx)) = short_start { + if frames[idx].symbols().len() == sub_idx + 1 { + // If it was the last subframe of this frame, we want to just + // use the whole next frame! It's ok if this takes us to `first_frame = len`, + // that will be properly handled as an empty output + first_frame = idx + 1; + first_subframe = 0; + } else { + // Otherwise use this frame, and all the subframes after it + first_frame = idx; + first_subframe = sub_idx + 1; + } + } + + // If we found the end bound... + if let Some((idx, sub_idx)) = short_end { + if sub_idx == 0 { + // If it was the first subframe of this frame, we want to just + // use the whole previous frame! + if idx == 0 { + // If we were *also* on the first frame, set subframe_excl + // to 0, indicating an empty output + last_frame = 0; + last_subframe_excl = 0; + } else { + last_frame = idx - 1; + last_subframe_excl = frames[last_frame].symbols().len(); + } + } else { + // Otherwise use this frame (no need subframe math, exclusive bound!) + last_frame = idx; + last_subframe_excl = sub_idx; + } + } + + // If the two subframes managed to perfectly line up with eachother, just + // throw everything out and yield an empty range. We don't need to fix any + // other values at this point as they won't be used for anything with an + // empty iterator + let final_frames = { + let start = (first_frame, first_subframe); + let end = (last_frame, last_subframe_excl); + if start == end { + &frames[0..0] + } else { + &frames[first_frame..=last_frame] + } + }; + + // Get the index of the last frame when starting from the first frame + let adjusted_last_frame = last_frame.saturating_sub(first_frame); + + // finally do the iteration + final_frames.iter().enumerate().map(move |(idx, frame)| { + // Default to all subframes being yielded + let mut sub_start = 0; + let mut sub_end_excl = frame.symbols().len(); + // If we're on first frame, apply its subframe clamp + if idx == 0 { + sub_start = first_subframe; + } + // If we're on the last frame, apply its subframe clamp + if idx == adjusted_last_frame { + sub_end_excl = last_subframe_excl; + } + (frame, sub_start..sub_end_excl) + }) +} + +pub(crate) trait Backtraceish { + type Frame: Frameish; + fn frames(&self) -> &[Self::Frame]; +} + +pub(crate) trait Frameish { + type Symbol: Symbolish; + fn symbols(&self) -> &[Self::Symbol]; +} + +pub(crate) trait Symbolish { + fn name_str(&self) -> Option<&str>; +} + +impl Backtraceish for Backtrace { + type Frame = BacktraceFrame; + fn frames(&self) -> &[Self::Frame] { + self.frames() + } +} + +impl Frameish for BacktraceFrame { + type Symbol = BacktraceSymbol; + fn symbols(&self) -> &[Self::Symbol] { + self.symbols() + } +} + +impl Symbolish for BacktraceSymbol { + // We need to shortcut SymbolName here because + // HRTB isn't in our msrv + fn name_str(&self) -> Option<&str> { + self.name().and_then(|n| n.as_str()) + } +} diff --git a/vendor/backtrace-ext/src/test.rs b/vendor/backtrace-ext/src/test.rs new file mode 100644 index 0000000..d4d4112 --- /dev/null +++ b/vendor/backtrace-ext/src/test.rs @@ -0,0 +1,524 @@ +use super::*; + +type BT = &'static [&'static [&'static str]]; + +impl Backtraceish for BT { + type Frame = &'static [&'static str]; + fn frames(&self) -> &[Self::Frame] { + self + } +} + +impl Frameish for &'static [&'static str] { + type Symbol = &'static str; + fn symbols(&self) -> &[Self::Symbol] { + self + } +} + +impl Symbolish for &'static str { + fn name_str(&self) -> Option<&str> { + Some(self) + } +} + +fn process(bt: BT) -> Vec<&'static str> { + let mut result = vec![]; + for (frame, subframes) in short_frames_strict_impl(&bt) { + let symbols = &frame.symbols()[subframes]; + assert!(!symbols.is_empty()); + for symbol in symbols { + result.push(*symbol); + } + } + result +} + +#[test] +fn test_full() { + let bt: BT = &[&["hello"], &["there", "simple"], &["case"]]; + let expected = vec!["hello", "there", "simple", "case"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_empty() { + let bt: BT = &[]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_cursed_one_true_symbol1() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace_rust_begin_short_backtrace"], + &["there"], + ]; + let expected = vec![ + "hello", + "__rust_end_short_backtrace_rust_begin_short_backtrace", + "there", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_cursed_one_true_symbol2() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace_rust_end_short_backtrace"], + &["there"], + ]; + let expected: Vec<&str> = vec![ + "hello", + "__rust_begin_short_backtrace_rust_end_short_backtrace", + "there", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards1() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace"], + &["real"], + &["frames"], + &["rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards2() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace", "real", "frames"], + &["rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards3() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace"], + &["real", "frames", "rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards4() { + let bt: BT = &[ + &["hello"], + &[ + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + ], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_simple() { + let bt: BT = &[&["hello"], &["__rust_begin_short_backtrace"], &["case"]]; + let expected = vec!["hello"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_left_edge() { + let bt: BT = &[&["__rust_begin_short_backtrace"], &["case"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_right_edge() { + let bt: BT = &[&["hello"], &["__rust_begin_short_backtrace"]]; + let expected = vec!["hello"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_empty() { + let bt: BT = &[&["__rust_begin_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_sub() { + let bt: BT = &[ + &["real"], + &["frames", "core::rust_begin_short_backtrace", "junk"], + &["junk"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_simple() { + let bt: BT = &[&["hello"], &["__rust_end_short_backtrace"], &["case"]]; + let expected = vec!["case"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_left_edge() { + let bt: BT = &[&["_rust_end_short_backtrace"], &["case"]]; + let expected = vec!["case"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_right_edge() { + let bt: BT = &[&["hello"], &["__rust_end_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_empty() { + let bt: BT = &[&["__rust_end_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_sub() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_simple() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_various() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["core::rust_end_short_backtrace"], + &["junk"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["_rust_begin_short_backtrace"], + &["junk"], + &["core::rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_identical() { + let bt: BT = &[ + &["hello"], + &["rust_end_short_backtrace"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_invert1() { + let bt: BT = &[ + &["hello"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["junk"], + &["rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "rust_end_short_backtrace", + "real", + "frames", + "rust_begin_short_backtrace", + "junk", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_invert2() { + let bt: BT = &[ + &["hello"], + &["rust_begin_short_backtrace"], + &["junk"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "rust_begin_short_backtrace", + "junk", + "rust_end_short_backtrace", + "real", + "frames", + "rust_begin_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_adjacent() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_left_edge() { + let bt: BT = &[ + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_right_edge() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_spanned() { + let bt: BT = &[ + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["__rust_begin_short_backtrace"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_spanned_empty() { + let bt: BT = &[ + &["rust_end_short_backtrace"], + &["rust_begin_short_backtrace"], + ]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_one_super_frame_2() { + let bt: BT = &[&[ + "rust_end_short_backtrace", + "real", + "frames", + "rust_begin_short_backtrace", + ]]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_one_super_frame_1() { + let bt: BT = &[&[ + "rust_end_short_backtrace", + "real", + "rust_begin_short_backtrace", + ]]; + let expected = vec!["real"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_one_super_frame_0() { + let bt: BT = &[&["rust_end_short_backtrace", "rust_begin_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex1() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames"], + &["here", "__rust_begin_short_backtrace", "junk"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex2() { + let bt: BT = &[ + &["junk"], + &["__rust_end_short_backtrace", "real"], + &["frames"], + &["here", "__rust_begin_short_backtrace", "junk"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex3() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames"], + &["here", "__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex4() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace"], + &["real", "frames"], + &["here", "__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex5() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames", "here"], + &["__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex6() { + let bt: BT = &[ + &["junk"], + &[ + "junk", + "__rust_end_short_backtrace", + "real", + "frames", + "here", + ], + &["__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex7() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace"], + &["real", "frames", "here", "__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} |