Issue 72408 nested closures exponential
This fixes#72408.
Nested closures were resulting in exponential compilation time.
This PR is enhancing asymptotic complexity, but also increasing the constant, so I would love to see perf run results.
This fixes#72408.
Nested closures were resulting in exponential compilation time.
As a performance optimization this change introduces MiniSet,
which is a simple small storage optimized set.
Auto-generate lint documentation.
This adds a tool which will generate the lint documentation in the rustc book automatically. This is motivated by keeping the documentation up-to-date, and consistently formatted. It also ensures the examples are correct and that they actually generate the expected lint. The lint groups table is also auto-generated. See https://github.com/rust-lang/compiler-team/issues/349 for the original proposal.
An outline of how this works:
- The `declare_lint!` macro now accepts a doc comment where the documentation is written. This is inspired by how clippy works.
- A new tool `src/tools/lint-docs` scrapes the documentation and adds it to the rustc book during the build.
- It runs each example and verifies its output and embeds the output in the book.
- It does a few formatting checks.
- It verifies that every lint is documented.
- Groups are collected from `rustc -W help`.
I updated the documentation for all the missing lints. I have also added an "Explanation" section to each lint providing a reason for the lint and suggestions on how to resolve it.
This can lead towards a future enhancement of possibly showing these docs via the `--explain` flag to make them easily accessible and discoverable.
Thanks to marcusklaas' hard work in https://github.com/raphlinus/pulldown-cmark/pull/469, this fixes a lot of rustdoc bugs!
- Get rid of unnecessary `RefCell`
- Fix duplicate warnings for broken implicit reference link
- Remove unnecessary copy of links
Tracing update
This does not bring the more significant changes that are coming down the pipeline, but since I've already prepared the PR leaving it up :)
See https://github.com/rust-lang/rust/pull/76210#issuecomment-685065938:
> Unfortunately, tracing 0.1.20 — which contained the change to reduce the amount of code generated by the tracing macros — had to be yanked, as it broke previously-compiling code for some downstream crates. I've not yet had the chance to fix this and release a new patch. So, in order to benefit from the changes to reduce generated code, you'll need to wait until there's a new version of tracing as well as tracing-attributes and tracing-core.
Add derive macro for specifying diagnostics using attributes.
Introduces `#[derive(SessionDiagnostic)]`, a derive macro for specifying structs that can be converted to Diagnostics using directions given by attributes on the struct and its fields. Currently, the following attributes have been implemented:
- `#[code = "..."]` -- this sets the Diagnostic's error code, and must be provided on the struct iself (ie, not on a field). Equivalent to calling `code`.
- `#[message = "..."]` -- this sets the Diagnostic's primary error message.
- `#[label = "..."]` -- this must be applied to fields of type `Span`, and is equivalent to `span_label`
- `#[suggestion(..)]` -- this allows a suggestion message to be supplied. This attribute must be applied to a field of type `Span` or `(Span, Applicability)`, and is equivalent to calling `span_suggestion`. Valid arguments are:
- `message = "..."` -- this sets the suggestion message.
- (Optional) `code = "..."` -- this suggests code for the suggestion. Defaults to empty.
`suggestion`also comes with other variants: `#[suggestion_short(..)]`, `#[suggestion_hidden(..)]` and `#[suggestion_verbose(..)]` which all take the same keys.
Within the strings passed to each attribute, fields can be referenced without needing to be passed explicitly into the format string -- eg, `#[error = "{ident} already declared"] ` will set the error message to `format!("{} already declared", &self.ident)`. Any fields on the struct can be referenced in this way.
Additionally, for any of these attributes, Option fields can be used to only optionally apply the decoration -- for example:
```rust
#[derive(SessionDiagnostic)]
#[code = "E0123"]
struct SomeKindOfError {
...
#[suggestion(message = "informative error message")]
opt_sugg: Option<(Span, Applicability)>
...
}
```
will not emit a suggestion if `opt_sugg` is `None`.
We plan on iterating on this macro further; this PR is a start.
Closes#61132.
r? `@oli-obk`
Support dataflow problems on arbitrary lattices
This PR implements last of the proposed extensions I mentioned in the design meeting for the original dataflow refactor. It extends the current dataflow framework to work with arbitrary lattices, not just `BitSet`s. This is a prerequisite for dataflow-enabled MIR const-propagation. Personally, I am skeptical of the usefulness of doing const-propagation pre-monomorphization, since many useful constants only become known after monomorphization (e.g. `size_of::<T>()`) and users have a natural tendency to hand-optimize the rest. It's probably worth exprimenting with, however, and others have shown interest cc `@rust-lang/wg-mir-opt.`
The `Idx` associated type is moved from `AnalysisDomain` to `GenKillAnalysis` and replaced with an associated `Domain` type that must implement `JoinSemiLattice`. Like before, each `Analysis` defines the "bottom value" for its domain, but can no longer override the dataflow join operator. Analyses that want to use set intersection must now use the `lattice::Dual` newtype. `GenKillAnalysis` impls have an additional requirement that `Self::Domain: BorrowMut<BitSet<Self::Idx>>`, which effectively means that they must use `BitSet<Self::Idx>` or `lattice::Dual<BitSet<Self::Idx>>` as their domain.
Most of these changes were mechanical. However, because a `Domain` is no longer always a powerset of some index type, we can no longer use an `IndexVec<BasicBlock, GenKillSet<A::Idx>>>` to store cached block transfer functions. Instead, we use a boxed `dyn Fn` trait object. I discuss a few alternatives to the current approach in a commit message.
The majority of new lines of code are to preserve existing Graphviz diagrams for those unlucky enough to have to debug dataflow analyses. I find these diagrams incredibly useful when things are going wrong and considered regressing them unacceptable, especially the pretty-printing of `MovePathIndex`s, which are used in many dataflow analyses. This required a parallel `fmt` trait used only for printing dataflow domains, as well as a refactoring of the `graphviz` module now that we cannot expect the domain to be a `BitSet`. Some features did have to be removed, such as the gen/kill display mode (which I didn't use but existed to mirror the output of the old dataflow framework) and line wrapping. Since I had to rewrite much of it anyway, I took the opportunity to switch to a `Visitor` for printing dataflow state diffs instead of using cursors, which are error prone for code that must be generic over both forward and backward analyses. As a side-effect of this change, we no longer have quadratic behavior when writing graphviz diagrams for backward dataflow analyses.
r? `@pnkfelix`
Update expect-test to 1.0
The only change is that `expect_file` now uses path relative to the
current file (same as `include!`). Before, it used paths relative to
the workspace root, which makes no sense.
The only change is that `expect_file` now uses path relative to the
current file (same as `include!`). Before, it used paths relative to
the workspace root, which makes no sense.
Rollup of 14 pull requests
Successful merges:
- #75832 (Move to intra-doc links for wasi/ext/fs.rs, os_str_bytes.rs…)
- #75852 (Switch to intra-doc links in `core::hash`)
- #75874 (Shorten liballoc doc intra link while readable)
- #75881 (Expand rustdoc theme chooser x padding)
- #75885 (Fix another clashing_extern_declarations false positive.)
- #75892 (Fix typo in TLS Model in Unstable Book)
- #75910 (Add test for issue #27130)
- #75917 (Move to intra doc links for core::ptr::non_null)
- #75975 (Allow --bess ing expect-tests in tools)
- #75990 (Add __fastfail for Windows on arm/aarch64)
- #76015 (Fix loading pretty-printers in rust-lldb script)
- #76022 (Clean up rustdoc front-end source code)
- #76029 (Move to intra-doc links for library/core/src/sync/atomic.rs)
- #76057 (Move retokenize hack to save_analysis)
Failed merges:
r? @ghost
Update compiler-builtins
Update the compiler-builtins dependency to include latest changes.
This allows for `aarch64-unknown-linux-musl` to pass all tests.
Fixes#57820 and fixes#46651
It's a unit-test in a sense that it only checks syntax highlighting.
However, the resulting HTML is written to disk and can be easily
inspected in the browser.
To update the test, run with `--bless` argument or set
`UPDATE_EXPEC=1` env var
Introduce expect snapshot testing library into rustc
Snapshot testing is a technique for writing maintainable unit tests.
Unlike usual `assert_eq!` tests, snapshot tests allow
to *automatically* upgrade expected values on test failure.
In a sense, snapshot tests are inline-version of our beloved
UI-tests.
Example:
![expect](https://user-images.githubusercontent.com/1711539/90888810-3bcc8180-e3b7-11ea-9626-d06e89e1a0bb.gif)
A particular library we use, `expect_test` provides an `expect!`
macro, which creates a sort of self-updating string literal (by using
`file!` macro). Self-update is triggered by setting `UPDATE_EXPECT`
environmental variable (this info is printed during the test failure).
This library was extracted from rust-analyzer, where we use it for
most of our tests.
There are some other, more popular snapshot testing libraries:
* https://github.com/mitsuhiko/insta
* https://github.com/aaronabramov/k9
The main differences of `expect` are:
* first-class snapshot objects (so, tests can be written as functions,
rather than as macros)
* focus on inline-snapshots (but file snapshots are also supported)
* restricted feature set (only `assert_eq` and `assert_debug_eq`)
* no extra runtime (ie, no `cargo insta`)
See rust-analyzer/rust-analyzer#5101 for a
an extended comparison.
It is unclear if this testing style will stick with rustc in the long
run. At the moment, rustc is mainly tested via integrated UI tests.
But in the library-ified world, unit-tests will become somewhat more
important (that's why use use `rustc_lexer` library-ified library as
an example in this PR). Given that the cost of removal shouldn't be
too high, it probably makes sense to just see if this flies!
Snapshot testing is a technique for writing maintainable unit tests.
Unlike usual `assert_eq!` tests, snapshot tests allow
to *automatically* upgrade expected values on test failure.
In a sense, snapshot tests are inline-version of our beloved
UI-tests.
Example:
![expect](https://user-images.githubusercontent.com/1711539/90888810-3bcc8180-e3b7-11ea-9626-d06e89e1a0bb.gif)
A particular library we use, `expect_test` provides an `expect!`
macro, which creates a sort of self-updating string literal (by using
`file!` macro). Self-update is triggered by setting `UPDATE_EXPECT`
environmental variable (this info is printed during the test failure).
This library was extracted from rust-analyzer, where we use it for
most of our tests.
There are some other, more popular snapshot testing libraries:
* https://github.com/mitsuhiko/insta
* https://github.com/aaronabramov/k9
The main differences of `expect` are:
* first-class snapshot objects (so, tests can be written as functions,
rather than as macros)
* focus on inline-snapshots (but file snapshots are also supported)
* restricted feature set (only `assert_eq` and `assert_debug_eq`)
* no extra runtime (ie, no `cargo insta`)
See https://github.com/rust-analyzer/rust-analyzer/pull/5101 for a
an extended comparison.
It is unclear if this testing style will stick with rustc in the long
run. At the moment, rustc is mainly tested via integrated UI tests.
But in the library-ified world, unit-tests will become somewhat more
important (that's why use use `rustc_lexer` library-ified library as
an example in this PR). Given that the cost of removal shouldn't be
too high, it probably makes sense to just see if this flies!
- Move the type parameter from `encode` and `decode` methods to
the trait.
- Remove `UseSpecialized(En|De)codable` traits.
- Remove blanket impls for references.
- Add `RefDecodable` trait to allow deserializing to arena-allocated
references safely.
- Remove ability to (de)serialize HIR.
- Create proc-macros `(Ty)?(En|De)codable` to help implement these new
traits.
Move platform support to the rustc book.
This moves the [Platform Support](https://forge.rust-lang.org/release/platform-support.html) page from the forge to the rustc book. There are several reasons for doing this:
* The forge is not really oriented towards end-users (it mostly contains infrastructure, governance and policy, internal team pages, etc.). This platform support page is useful to user to know which targets are supported.
* This page can now be updated in-sync with any PRs that add or remove a target, or change its status.
* This is now automatically checked on CI to verify the list does not get out of sync. Currently it only checks the presence/absence of an entry, but more sophisticated checks could be added in the future.
I'm not 100% certain this is the best location, but I think it fits. I'd like to see the rustc guide continue to grow, including things like linking information and more platform-specific details.
Avoid deleting temporary files on error
Previously if the compiler error'd, fatally, then temporary directories which
should be preserved by -Csave-temps would be deleted due to fatal compiler
errors being implemented as panics.
cc @infinity0
(Hopefully) fixes#75275, but I haven't tested
Previously if the compiler error'd, fatally, then temporary directories which
should be preserved by -Csave-temps would be deleted due to fatal compiler
errors being implemented as panics.
By moving `{known,used}_attrs` from `SessionGlobals` to `Session`. This
means they are accessed via the `Session`, rather than via TLS. A few
`Attr` methods and `librustc_ast` functions are now methods of
`Session`.
All of this required passing a `Session` to lots of functions that didn't
already have one. Some of these functions also had arguments removed, because
those arguments could be accessed directly via the `Session` argument.
`contains_feature_attr()` was dead, and is removed.
Some functions were moved from `librustc_ast` elsewhere because they now need
to access `Session`, which isn't available in that crate.
- `entry_point_type()` --> `librustc_builtin_macros`
- `global_allocator_spans()` --> `librustc_metadata`
- `is_proc_macro_attr()` --> `Session`
We store an `ImplicitCtxt` pointer in a thread-local value (TLV). This allows
implicit access to a `GlobalCtxt` and some other things.
We also store a `GlobalCtxt` pointer in `GCX_PTR`. This is always the same
`GlobalCtxt` as the one within the `ImplicitCtxt` pointer in TLV. `GCX_PTR`
is only used in the parallel compiler's `handle_deadlock()` function.
This commit does the following.
- It removes `GCX_PTR`.
- It also adds `ImplicitCtxt::new()`, which constructs an `ImplicitCtxt` from a
`GlobalCtxt`. `ImplicitCtxt::new()` + `tls::enter_context()` is now
equivalent to the old `tls::enter_global()`.
- Makes `tls::get_tlv()` public for the parallel compiler, because it's
now used in `handle_deadlock()`.
Update cargo
14 commits in aa6872140ab0fa10f641ab0b981d5330d419e927..974eb438da8ced6e3becda2bbf63d9b643eacdeb
2020-07-23 13:46:27 +0000 to 2020-07-29 16:15:05 +0000
- Fix O0 build scripts by default without `[profile.release]` (rust-lang/cargo#8560)
- Emphasize git dependency version locking behavior. (rust-lang/cargo#8561)
- Update lock file encodings on changes (rust-lang/cargo#8554)
- Fix sporadic lto test failures. (rust-lang/cargo#8559)
- build-std: Fix libraries paths following upstream (rust-lang/cargo#8558)
- Flag git http errors as maybe spurious (rust-lang/cargo#8553)
- Display builtin aliases with `cargo --list` (rust-lang/cargo#8542)
- Check manifest for requiring nonexistent features (rust-lang/cargo#7950)
- Clarify test name filter usage (rust-lang/cargo#8552)
- Revert Cargo Book changes for default edition (rust-lang/cargo#8551)
- Prepare for not defaulting to master branch for git deps (rust-lang/cargo#8522)
- Include `+` for crates.io feature requirements in the Cargo Book section on features (rust-lang/cargo#8547)
- Update termcolor and fwdansi versions (rust-lang/cargo#8540)
- Cargo book nitpick in Manifest section (rust-lang/cargo#8543)
This commit is a proof-of-concept for switching the standard library's
backtrace symbolication mechanism on most platforms from libbacktrace to
gimli. The standard library's support for `RUST_BACKTRACE=1` requires
in-process parsing of object files and DWARF debug information to
interpret it and print the filename/line number of stack frames as part
of a backtrace.
Historically this support in the standard library has come from a
library called "libbacktrace". The libbacktrace library seems to have
been extracted from gcc at some point and is written in C. We've had a
lot of issues with libbacktrace over time, unfortunately, though. The
library does not appear to be actively maintained since we've had
patches sit for months-to-years without comments. We have discovered a
good number of soundness issues with the library itself, both when
parsing valid DWARF as well as invalid DWARF. This is enough of an issue
that the libs team has previously decided that we cannot feed untrusted
inputs to libbacktrace. This also doesn't take into account the
portability of libbacktrace which has been difficult to manage and
maintain over time. While possible there are lots of exceptions and it's
the main C dependency of the standard library right now.
For years it's been the desire to switch over to a Rust-based solution
for symbolicating backtraces. It's been assumed that we'll be using the
Gimli family of crates for this purpose, which are targeted at safely
and efficiently parsing DWARF debug information. I've been working
recently to shore up the Gimli support in the `backtrace` crate. As of a
few weeks ago the `backtrace` crate, by default, uses Gimli when loaded
from crates.io. This transition has gone well enough that I figured it
was time to start talking seriously about this change to the standard
library.
This commit is a preview of what's probably the best way to integrate
the `backtrace` crate into the standard library with the Gimli feature
turned on. While today it's used as a crates.io dependency, this commit
switches the `backtrace` crate to a submodule of this repository which
will need to be updated manually. This is not done lightly, but is
thought to be the best solution. The primary reason for this is that the
`backtrace` crate needs to do some pretty nontrivial filesystem
interactions to locate debug information. Working without `std::fs` is
not an option, and while it might be possible to do some sort of
trait-based solution when prototyped it was found to be too unergonomic.
Using a submodule allows the `backtrace` crate to build as a submodule
of the `std` crate itself, enabling it to use `std::fs` and such.
Otherwise this adds new dependencies to the standard library. This step
requires extra attention because this means that these crates are now
going to be included with all Rust programs by default. It's important
to note, however, that we're already shipping libbacktrace with all Rust
programs by default and it has a bunch of C code implementing all of
this internally anyway, so we're basically already switching
already-shipping functionality to Rust from C.
* `object` - this crate is used to parse object file headers and
contents. Very low-level support is used from this crate and almost
all of it is disabled. Largely we're just using struct definitions as
well as convenience methods internally to read bytes and such.
* `addr2line` - this is the main meat of the implementation for
symbolication. This crate depends on `gimli` for DWARF parsing and
then provides interfaces needed by the `backtrace` crate to turn an
address into a filename / line number. This crate is actually pretty
small (fits in a single file almost!) and mirrors most of what
`dwarf.c` does for libbacktrace.
* `miniz_oxide` - the libbacktrace crate transparently handles
compressed debug information which is compressed with zlib. This crate
is used to decompress compressed debug sections.
* `gimli` - not actually used directly, but a dependency of `addr2line`.
* `adler32`- not used directly either, but a dependency of
`miniz_oxide`.
The goal of this change is to improve the safety of backtrace
symbolication in the standard library, especially in the face of
possibly malformed DWARF debug information. Even to this day we're still
seeing segfaults in libbacktrace which could possibly become security
vulnerabilities. This change should almost entirely eliminate this
possibility whilc also paving the way forward to adding more features
like split debug information.
Some references for those interested are:
* Original addition of libbacktrace - #12602
* OOM with libbacktrace - #24231
* Backtrace failure due to use of uninitialized value - #28447
* Possibility to feed untrusted data to libbacktrace - #21889
* Soundness fix for libbacktrace - #33729
* Crash in libbacktrace - #39468
* Support for macOS, never merged - ianlancetaylor/libbacktrace#2
* Performance issues with libbacktrace - #29293, #37477
* Update procedure is quite complicated due to how many patches we
need to carry - #50955
* Libbacktrace doesn't work on MinGW with dynamic libs - #71060
* Segfault in libbacktrace on macOS - #71397
Switching to Rust will not make us immune to all of these issues. The
crashes are expected to go away, but correctness and performance may
still have bugs arise. The gimli and `backtrace` crates, however, are
actively maintained unlike libbacktrace, so this should enable us to at
least efficiently apply fixes as situations come up.
revise RwLock for HermitCore
- current version is derived from the wasm implementation
- increasing the readability of `Condvar`
- simplify the interface to the libos
Revert libbacktrace -> gimli
This reverts 4cbd265c11028f8d7b8513db3cc1e8d7a36d8964 (and technically 79673d3009 but it's made empty by previous reverts).
The current plan is to land this PR as a temporary change, so that we can get a better handle on the regressions introduced by it. Trying to fix/examine them in master is difficult, and we want to be better able to evaluate them without impact to other PRs being landed in the mean time.
That said, it is currently *my* belief that gimli, in one form or another, will need to land sometime soon. I think it's quite likely that it may slip a week or two, but I would personally push for re-landing it then "regardless" of the regressions. We should try to focus efforts on understanding and removing as much of the performance impact as possible, as everyone pretty much agrees that it should be quite minimal (and entirely in the linker, basically).
r? @nnethercote
Generating the coverage map
@tmandry @wesleywiser
rustc now generates the coverage map and can support (limited)
coverage report generation, at the function level.
Example commands to generate a coverage report:
```shell
$ BUILD=$HOME/rust/build/x86_64-unknown-linux-gnu
$ $BUILD/stage1/bin/rustc -Zinstrument-coverage \
$HOME/rust/src/test/run-make-fulldeps/instrument-coverage/main.rs
$ LLVM_PROFILE_FILE="main.profraw" ./main
called
$ $BUILD/llvm/bin/llvm-profdata merge -sparse main.profraw -o main.profdata
$ $BUILD/llvm/bin/llvm-cov show --instr-profile=main.profdata main
```
![rust coverage report only 20200706](https://user-images.githubusercontent.com/3827298/86697299-1cbe8f80-bfc3-11ea-8955-451b48626991.png)
r? @wesleywiser
Rust compiler MCP rust-lang/compiler-team#278
Relevant issue: #34701 - Implement support for LLVMs code coverage instrumentation
std: Switch from libbacktrace to gimli
This commit is a proof-of-concept for switching the standard library's
backtrace symbolication mechanism on most platforms from libbacktrace to
gimli. The standard library's support for `RUST_BACKTRACE=1` requires
in-process parsing of object files and DWARF debug information to
interpret it and print the filename/line number of stack frames as part
of a backtrace.
Historically this support in the standard library has come from a
library called "libbacktrace". The libbacktrace library seems to have
been extracted from gcc at some point and is written in C. We've had a
lot of issues with libbacktrace over time, unfortunately, though. The
library does not appear to be actively maintained since we've had
patches sit for months-to-years without comments. We have discovered a
good number of soundness issues with the library itself, both when
parsing valid DWARF as well as invalid DWARF. This is enough of an issue
that the libs team has previously decided that we cannot feed untrusted
inputs to libbacktrace. This also doesn't take into account the
portability of libbacktrace which has been difficult to manage and
maintain over time. While possible there are lots of exceptions and it's
the main C dependency of the standard library right now.
For years it's been the desire to switch over to a Rust-based solution
for symbolicating backtraces. It's been assumed that we'll be using the
Gimli family of crates for this purpose, which are targeted at safely
and efficiently parsing DWARF debug information. I've been working
recently to shore up the Gimli support in the `backtrace` crate. As of a
few weeks ago the `backtrace` crate, by default, uses Gimli when loaded
from crates.io. This transition has gone well enough that I figured it
was time to start talking seriously about this change to the standard
library.
This commit is a preview of what's probably the best way to integrate
the `backtrace` crate into the standard library with the Gimli feature
turned on. While today it's used as a crates.io dependency, this commit
switches the `backtrace` crate to a submodule of this repository which
will need to be updated manually. This is not done lightly, but is
thought to be the best solution. The primary reason for this is that the
`backtrace` crate needs to do some pretty nontrivial filesystem
interactions to locate debug information. Working without `std::fs` is
not an option, and while it might be possible to do some sort of
trait-based solution when prototyped it was found to be too unergonomic.
Using a submodule allows the `backtrace` crate to build as a submodule
of the `std` crate itself, enabling it to use `std::fs` and such.
Otherwise this adds new dependencies to the standard library. This step
requires extra attention because this means that these crates are now
going to be included with all Rust programs by default. It's important
to note, however, that we're already shipping libbacktrace with all Rust
programs by default and it has a bunch of C code implementing all of
this internally anyway, so we're basically already switching
already-shipping functionality to Rust from C.
* `object` - this crate is used to parse object file headers and
contents. Very low-level support is used from this crate and almost
all of it is disabled. Largely we're just using struct definitions as
well as convenience methods internally to read bytes and such.
* `addr2line` - this is the main meat of the implementation for
symbolication. This crate depends on `gimli` for DWARF parsing and
then provides interfaces needed by the `backtrace` crate to turn an
address into a filename / line number. This crate is actually pretty
small (fits in a single file almost!) and mirrors most of what
`dwarf.c` does for libbacktrace.
* `miniz_oxide` - the libbacktrace crate transparently handles
compressed debug information which is compressed with zlib. This crate
is used to decompress compressed debug sections.
* `gimli` - not actually used directly, but a dependency of `addr2line`.
* `adler32`- not used directly either, but a dependency of
`miniz_oxide`.
The goal of this change is to improve the safety of backtrace
symbolication in the standard library, especially in the face of
possibly malformed DWARF debug information. Even to this day we're still
seeing segfaults in libbacktrace which could possibly become security
vulnerabilities. This change should almost entirely eliminate this
possibility whilc also paving the way forward to adding more features
like split debug information.
Some references for those interested are:
* Original addition of libbacktrace - #12602
* OOM with libbacktrace - #24231
* Backtrace failure due to use of uninitialized value - #28447
* Possibility to feed untrusted data to libbacktrace - #21889
* Soundness fix for libbacktrace - #33729
* Crash in libbacktrace - #39468
* Support for macOS, never merged - ianlancetaylor/libbacktrace#2
* Performance issues with libbacktrace - #29293, #37477
* Update procedure is quite complicated due to how many patches we
need to carry - #50955
* Libbacktrace doesn't work on MinGW with dynamic libs - #71060
* Segfault in libbacktrace on macOS - #71397
Switching to Rust will not make us immune to all of these issues. The
crashes are expected to go away, but correctness and performance may
still have bugs arise. The gimli and `backtrace` crates, however, are
actively maintained unlike libbacktrace, so this should enable us to at
least efficiently apply fixes as situations come up.
---
I want to note that my purpose for creating a PR here is to start a conversation about this. I think that all the various pieces are in place that this is compelling enough that I think this transition should be talked about seriously. There are a number of items which still need to be addressed before actually merging this PR, however:
* [ ] `gimli` needs to be published to crates.io
* [ ] `addr2line` needs a publish
* [ ] `miniz_oxide` needs a publish
* [ ] Tests probably shouldn't recommend the `gimli` crate's traits for implementing
* [ ] The `backtrace` crate's branch changes need to be merged to the master branch (https://github.com/rust-lang/backtrace-rs/pull/349)
* [ ] The support for `libbacktrace` on some platforms needs to be audited to see if we should support more strategies in the gimli implementation - https://github.com/rust-lang/backtrace-rs/issues/325, https://github.com/rust-lang/backtrace-rs/issues/326, https://github.com/rust-lang/backtrace-rs/issues/350, https://github.com/rust-lang/backtrace-rs/issues/351
Most of the merging/publishing I'm not actively pushing on right now. It's a bit wonky for crates to support libstd so I'm holding off on pulling the trigger everywhere until there's a bit more discussion about how to go through with this. Namely https://github.com/rust-lang/backtrace-rs/pull/349 I'm going to hold off merging until we decide to go through with the submodule strategy.
In any case this is a pretty major change, so I suspect that the compiler team is likely going to be interested in this. I don't mean to force changes by dumping a bunch of code by any means. Integration of external crates into the standard library is so difficult I wanted to have a proof-of-concept to review while talking about whether to do this at all (hence the PR), but I'm more than happy to follow any processes needed to merge this. I must admit though that I'm not entirely sure myself at this time what the process would be to decide to merge this, so I'm hoping others can help me figure that out!
This commit is a proof-of-concept for switching the standard library's
backtrace symbolication mechanism on most platforms from libbacktrace to
gimli. The standard library's support for `RUST_BACKTRACE=1` requires
in-process parsing of object files and DWARF debug information to
interpret it and print the filename/line number of stack frames as part
of a backtrace.
Historically this support in the standard library has come from a
library called "libbacktrace". The libbacktrace library seems to have
been extracted from gcc at some point and is written in C. We've had a
lot of issues with libbacktrace over time, unfortunately, though. The
library does not appear to be actively maintained since we've had
patches sit for months-to-years without comments. We have discovered a
good number of soundness issues with the library itself, both when
parsing valid DWARF as well as invalid DWARF. This is enough of an issue
that the libs team has previously decided that we cannot feed untrusted
inputs to libbacktrace. This also doesn't take into account the
portability of libbacktrace which has been difficult to manage and
maintain over time. While possible there are lots of exceptions and it's
the main C dependency of the standard library right now.
For years it's been the desire to switch over to a Rust-based solution
for symbolicating backtraces. It's been assumed that we'll be using the
Gimli family of crates for this purpose, which are targeted at safely
and efficiently parsing DWARF debug information. I've been working
recently to shore up the Gimli support in the `backtrace` crate. As of a
few weeks ago the `backtrace` crate, by default, uses Gimli when loaded
from crates.io. This transition has gone well enough that I figured it
was time to start talking seriously about this change to the standard
library.
This commit is a preview of what's probably the best way to integrate
the `backtrace` crate into the standard library with the Gimli feature
turned on. While today it's used as a crates.io dependency, this commit
switches the `backtrace` crate to a submodule of this repository which
will need to be updated manually. This is not done lightly, but is
thought to be the best solution. The primary reason for this is that the
`backtrace` crate needs to do some pretty nontrivial filesystem
interactions to locate debug information. Working without `std::fs` is
not an option, and while it might be possible to do some sort of
trait-based solution when prototyped it was found to be too unergonomic.
Using a submodule allows the `backtrace` crate to build as a submodule
of the `std` crate itself, enabling it to use `std::fs` and such.
Otherwise this adds new dependencies to the standard library. This step
requires extra attention because this means that these crates are now
going to be included with all Rust programs by default. It's important
to note, however, that we're already shipping libbacktrace with all Rust
programs by default and it has a bunch of C code implementing all of
this internally anyway, so we're basically already switching
already-shipping functionality to Rust from C.
* `object` - this crate is used to parse object file headers and
contents. Very low-level support is used from this crate and almost
all of it is disabled. Largely we're just using struct definitions as
well as convenience methods internally to read bytes and such.
* `addr2line` - this is the main meat of the implementation for
symbolication. This crate depends on `gimli` for DWARF parsing and
then provides interfaces needed by the `backtrace` crate to turn an
address into a filename / line number. This crate is actually pretty
small (fits in a single file almost!) and mirrors most of what
`dwarf.c` does for libbacktrace.
* `miniz_oxide` - the libbacktrace crate transparently handles
compressed debug information which is compressed with zlib. This crate
is used to decompress compressed debug sections.
* `gimli` - not actually used directly, but a dependency of `addr2line`.
* `adler32`- not used directly either, but a dependency of
`miniz_oxide`.
The goal of this change is to improve the safety of backtrace
symbolication in the standard library, especially in the face of
possibly malformed DWARF debug information. Even to this day we're still
seeing segfaults in libbacktrace which could possibly become security
vulnerabilities. This change should almost entirely eliminate this
possibility whilc also paving the way forward to adding more features
like split debug information.
Some references for those interested are:
* Original addition of libbacktrace - #12602
* OOM with libbacktrace - #24231
* Backtrace failure due to use of uninitialized value - #28447
* Possibility to feed untrusted data to libbacktrace - #21889
* Soundness fix for libbacktrace - #33729
* Crash in libbacktrace - #39468
* Support for macOS, never merged - ianlancetaylor/libbacktrace#2
* Performance issues with libbacktrace - #29293, #37477
* Update procedure is quite complicated due to how many patches we
need to carry - #50955
* Libbacktrace doesn't work on MinGW with dynamic libs - #71060
* Segfault in libbacktrace on macOS - #71397
Switching to Rust will not make us immune to all of these issues. The
crashes are expected to go away, but correctness and performance may
still have bugs arise. The gimli and `backtrace` crates, however, are
actively maintained unlike libbacktrace, so this should enable us to at
least efficiently apply fixes as situations come up.
Fix cross compilation of LLVM to aarch64 Windows targets
When cross-compiling, the LLVM build system recurses to build tools that need to run on the host system. However, since we pass cmake defines to set the compiler and target, LLVM still compiles these tools for the target system, rather than the host. The tools then fail to execute during the LLVM build.
This change sets defines for the tools that need to run on the host (llvm-nm, llvm-tablegen, and llvm-config), so that the LLVM build does not attempt to build them, and instead relies on the tools already built.
If compiling with clang-cl, adds the `--target` option to specify the target triple. MSVC compilers do not require this, since there is a separate compiler binary for each cross-compilation target.
Related issue: #72881
Requires LLVM change: rust-lang/llvm-project#67
When cross-compiling, the LLVM build system recurses to build tools
that need to run on the host system. However, since we pass cmake defines
to set the compiler and target, LLVM still compiles these tools for the
target system, rather than the host. The tools then fail to execute
during the LLVM build.
This change sets defines for the tools that need to run on the
host (llvm-nm, llvm-tablegen, and llvm-config), so that the LLVM build
does not attempt to build them, and instead relies on the tools already built.
If compiling with clang-cl, this change also adds the `--target` option
to specify the target triple. MSVC compilers do not require this, since there
is a separate compiler binary for cross-compilation.