Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_codegen_gcc/src/gcc_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rustc_target::spec::Arch;

fn gcc_features_by_flags(sess: &Session, features: &mut Vec<String>) {
target_features::retpoline_features_by_flags(sess, features);
target_features::sls_features_by_flags(sess, features);
// FIXME: LLVM also sets +reserve-x18 here under some conditions.
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@ pub(crate) fn target_cpu(sess: &Session) -> &str {
/// The target features for compiler flags other than `-Ctarget-features`.
fn llvm_features_by_flags(sess: &Session, features: &mut Vec<String>) {
target_features::retpoline_features_by_flags(sess, features);
target_features::sls_features_by_flags(sess, features);

// -Zfixed-x18
if sess.opts.unstable_opts.fixed_x18 {
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ codegen_ssa_field_associated_value_expected = associated value expected for `{$n

codegen_ssa_forbidden_ctarget_feature =
target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason}
.note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
codegen_ssa_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>

codegen_ssa_forbidden_target_feature_attr =
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,6 @@ pub(crate) struct UnstableCTargetFeature<'a> {

#[derive(Diagnostic)]
#[diag(codegen_ssa_forbidden_ctarget_feature)]
#[note]
#[note(codegen_ssa_forbidden_ctarget_feature_issue)]
pub(crate) struct ForbiddenCTargetFeature<'a> {
pub feature: &'a str,
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rustc_middle::middle::codegen_fn_attrs::{TargetFeature, TargetFeatureKind};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::HardenSls;
use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON;
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
Expand Down Expand Up @@ -297,7 +298,7 @@ pub fn cfg_target_feature<'a, const N: usize>(
}
Some((_, stability, _)) => {
if let Err(reason) = stability.toggle_allowed() {
sess.dcx().emit_warn(errors::ForbiddenCTargetFeature {
sess.dcx().emit_err(errors::ForbiddenCTargetFeature {
feature: base_feature,
enabled: if enable { "enabled" } else { "disabled" },
reason,
Expand Down Expand Up @@ -415,6 +416,18 @@ pub fn retpoline_features_by_flags(sess: &Session, features: &mut Vec<String>) {
}
}

pub fn sls_features_by_flags(sess: &Session, features: &mut Vec<String>) {
match &sess.opts.unstable_opts.harden_sls {
HardenSls::None => (),
HardenSls::All => {
features.push("+harden-sls-ijmp".into());
features.push("+harden-sls-ret".into());
}
HardenSls::Return => features.push("+harden-sls-ret".into()),
HardenSls::IndirectJmp => features.push("+harden-sls-ijmp".into()),
}
}

pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
rust_target_features: |tcx, cnum| {
Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3295,11 +3295,11 @@ pub(crate) mod dep_tracking {
use super::{
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo,
CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug,
FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OomStrategy,
OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius,
RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
FunctionReturn, HardenSls, InliningThreshold, InstrumentCoverage, InstrumentXRay,
LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload,
OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry,
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
};
use crate::lint;
use crate::utils::NativeLib;
Expand Down Expand Up @@ -3403,6 +3403,7 @@ pub(crate) mod dep_tracking {
Polonius,
InliningThreshold,
FunctionReturn,
HardenSls,
Align,
);

Expand Down Expand Up @@ -3657,6 +3658,16 @@ pub enum FunctionReturn {
ThunkExtern,
}

/// The different settings that the `-Zharden-sls` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
pub enum HardenSls {
#[default]
None,
All,
Return,
IndirectJmp,
}

/// Whether extra span comments are included when dumping MIR, via the `-Z mir-include-spans` flag.
/// By default, only enabled in the NLL MIR dumps, and disabled in all other passes.
#[derive(Clone, Copy, Default, PartialEq, Debug)]
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ mod desc {
"either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
pub(crate) const parse_llvm_module_flag: &str = "<key>:<type>:<value>:<behavior>. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)";
pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`";
pub(crate) const parse_harden_sls: &str = "`none`, `all`, `return` or `indirect-jmp`";
pub(crate) const parse_wasm_c_abi: &str = "`spec`";
pub(crate) const parse_mir_include_spans: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)";
Expand Down Expand Up @@ -2033,6 +2034,17 @@ pub mod parse {
true
}

pub(crate) fn parse_harden_sls(slot: &mut HardenSls, v: Option<&str>) -> bool {
match v {
Some("none") => *slot = HardenSls::None,
Some("all") => *slot = HardenSls::All,
Some("return") => *slot = HardenSls::Return,
Some("indirect-jmp") => *slot = HardenSls::IndirectJmp,
_ => return false,
}
true
}

pub(crate) fn parse_wasm_c_abi(_slot: &mut (), v: Option<&str>) -> bool {
v == Some("spec")
}
Expand Down Expand Up @@ -2375,6 +2387,9 @@ options! {
graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
"use the given `fontname` in graphviz output; can be overridden by setting \
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
harden_sls: HardenSls = (HardenSls::None, parse_harden_sls, [TRACKED TARGET_MODIFIER],
"flag to mitigate against straight line speculation (SLS) [none|all|return|indirect-jmp] \
(default: none)"),
has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
"explicitly enable the `cfg(target_thread_local)` directive"),
higher_ranked_assumptions: bool = (false, parse_bool, [TRACKED],
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("fma", Stable, &["avx"]),
("fxsr", Stable, &[]),
("gfni", Stable, &["sse2"]),
(
"harden-sls-ijmp",
Stability::Forbidden { reason: "use `harden-sls` compiler flag instead" },
&[],
),
(
"harden-sls-ret",
Stability::Forbidden { reason: "use `harden-sls` compiler flag instead" },
&[],
),
("kl", Stable, &["sse2"]),
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
("lzcnt", Stable, &[]),
Expand Down
14 changes: 8 additions & 6 deletions src/doc/rustc-dev-guide/src/tests/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,14 @@ ignoring debuggers.

| Directive | Explanation | Supported test suites | Possible values |
|---------------------|----------------------------------------------------------------------------------------------|--------------------------------------------|--------------------------------------------------------------------------------------------|
| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
| `edition` | The edition used to build the test | All except for `run-make`/`run-make-cargo` | Any valid `--edition` value |
| `rustc-env` | Env var to set when running `rustc` | All except for `run-make`/`run-make-cargo` | `<KEY>=<VALUE>` |
| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make`/`run-make-cargo` | Any env var name |
| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A |
| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |
| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
| `minicore-compile-flags` | Additional flags passed to `rustc` when building minicore | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
| `non-aux-compile-flags` | Additional flags passed to `rustc` when building the test (not for auxiliary builds) | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
| `edition` | The edition used to build the test | All except for `run-make`/`run-make-cargo` | Any valid `--edition` value |
| `rustc-env` | Env var to set when running `rustc` | All except for `run-make`/`run-make-cargo` | `<KEY>=<VALUE>` |
| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make`/`run-make-cargo` | Any env var name |
| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A |
| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |

<div class="warning">

Expand Down
5 changes: 5 additions & 0 deletions src/doc/rustc-dev-guide/src/tests/minicore.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ The `minicore` items must be kept up to date with `core`.
For consistent diagnostic output between using `core` and `minicore`, any `diagnostic`
attributes (e.g. `on_unimplemented`) should be replicated exactly in `minicore`.

## Specific compile flags
`compile-flags` is used both for auxiliary builds (including minicore) and main test build.
`minicore-compile-flags` directive may be used to provide compile flags for minicore build only.
`non-aux-compile-flags` directive may be used to provide compile flags for main test only.

## Example codegen test that uses `minicore`

```rust,no_run
Expand Down
4 changes: 4 additions & 0 deletions src/tools/compiletest/src/directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ pub(crate) struct TestProps {
pub add_minicore: bool,
/// Add these flags to the build of `minicore`.
pub minicore_compile_flags: Vec<String>,
/// Add these flags to the non-auxiliary build.
pub non_aux_compile_flags: Vec<String>,
/// Whether line annotatins are required for the given error kind.
pub dont_require_annotations: HashSet<ErrorKind>,
/// Whether pretty printers should be disabled in gdb.
Expand Down Expand Up @@ -250,6 +252,7 @@ mod directives {
pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg";
pub const ADD_MINICORE: &'static str = "add-minicore";
pub const MINICORE_COMPILE_FLAGS: &'static str = "minicore-compile-flags";
pub const NON_AUX_COMPILE_FLAGS: &'static str = "non-aux-compile-flags";
pub const DISABLE_GDB_PRETTY_PRINTERS: &'static str = "disable-gdb-pretty-printers";
pub const COMPARE_OUTPUT_BY_LINES: &'static str = "compare-output-by-lines";
}
Expand Down Expand Up @@ -307,6 +310,7 @@ impl TestProps {
no_auto_check_cfg: false,
add_minicore: false,
minicore_compile_flags: vec![],
non_aux_compile_flags: vec![],
dont_require_annotations: Default::default(),
disable_gdb_pretty_printers: false,
compare_output_by_lines: false,
Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/directives/directive_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"needs-xray",
"no-auto-check-cfg",
"no-prefer-dynamic",
"non-aux-compile-flags",
"normalize-stderr",
"normalize-stderr-32bit",
"normalize-stderr-64bit",
Expand Down
13 changes: 13 additions & 0 deletions src/tools/compiletest/src/directives/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,19 @@ fn make_directive_handlers_map() -> HashMap<&'static str, Handler> {
props.minicore_compile_flags.extend(flags);
}
}),
handler(NON_AUX_COMPILE_FLAGS, |config, ln, props| {
if let Some(flags) = config.parse_name_value_directive(ln, NON_AUX_COMPILE_FLAGS) {
let flags = split_flags(&flags);
// FIXME(#147955): Extract and unify this with other handlers that
// check compiler flags, e.g. COMPILE_FLAGS.
for flag in &flags {
if flag == "--edition" || flag.starts_with("--edition=") {
panic!("you must use `//@ edition` to configure the edition");
}
}
props.non_aux_compile_flags.extend(flags);
}
}),
handler(DONT_REQUIRE_ANNOTATIONS, |config, ln, props| {
if let Some(err_kind) = config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS)
{
Expand Down
3 changes: 3 additions & 0 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1897,6 +1897,9 @@ impl<'test> TestCx<'test> {
}

rustc.args(&self.props.compile_flags);
if !is_aux {
rustc.args(&self.props.non_aux_compile_flags);
}

rustc
}
Expand Down
76 changes: 76 additions & 0 deletions tests/assembly-llvm/x86_64-sls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Test harden-sls flag

#![feature(core_intrinsics)]
//@ revisions: NONE ALL RET IJMP
//@ assembly-output: emit-asm
//@ compile-flags: -Copt-level=3 -Cunsafe-allow-abi-mismatch=harden-sls
//@ [NONE] compile-flags: -Zharden-sls=none
//@ [ALL] compile-flags: -Zharden-sls=all
//@ [RET] compile-flags: -Zharden-sls=return
//@ [IJMP] compile-flags: -Zharden-sls=indirect-jmp
//@ only-x86_64
#![crate_type = "lib"]

#[no_mangle]
pub fn double_return(a: i32, b: i32) -> i32 {
// CHECK-LABEL: double_return:
// CHECK: jle
// CHECK-NOT: int3
// CHECK: retq
// RET-NEXT: int3
// ALL-NEXT: int3
// IJMP-NOT: int3
// NONE-NOT: int3
// CHECK: retq
// RET-NEXT: int3
// ALL-NEXT: int3
// IJMP-NOT: int3
// NONE-NOT: int3
if a > 0 {
unsafe { std::intrinsics::unchecked_div(a, b) }
} else {
unsafe { std::intrinsics::unchecked_div(b, a) }
}
}

#[no_mangle]
pub fn indirect_branch(a: i32, b: i32, i: i32) -> i32 {
// CHECK-LABEL: indirect_branch:
// CHECK: jmpq *
// RET-NOT: int3
// NONE-NOT: int3
// IJMP-NEXT: int3
// ALL-NEXT: int3
// CHECK: retq
// RET-NEXT: int3
// ALL-NEXT: int3
// IJMP-NOT: int3
// NONE-NOT: int3
// CHECK: retq
// RET-NEXT: int3
// ALL-NEXT: int3
// IJMP-NOT: int3
// NONE-NOT: int3
match i {
0 => unsafe { std::intrinsics::unchecked_div(a, b) },
1 => unsafe { std::intrinsics::unchecked_div(b, a) },
2 => unsafe { std::intrinsics::unchecked_div(b, a) + 2 },
3 => unsafe { std::intrinsics::unchecked_div(b, a) + 3 },
4 => unsafe { std::intrinsics::unchecked_div(b, a) + 4 },
5 => unsafe { std::intrinsics::unchecked_div(b, a) + 5 },
6 => unsafe { std::intrinsics::unchecked_div(b, a) + 6 },
_ => panic!(""),
}
}

#[no_mangle]
pub fn bar(ptr: fn()) {
// CHECK-LABEL: bar:
// CHECK: jmpq *
// RET-NOT: int3
// NONE-NOT: int3
// IJMP-NEXT: int3
// ALL-NEXT: int3
// CHECK-NOT: ret
ptr()
}
35 changes: 35 additions & 0 deletions tests/codegen-llvm/harden-sls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// ignore-tidy-linelength
// Test that the `harden-sls-ijmp`, `harden-sls-ret` target features is (not) emitted when
// the `harden-sls=[none|all|return|indirect-jmp]` flag is (not) set.

//@ add-minicore
//@ revisions: none all return indirect_jmp
//@ needs-llvm-components: x86
//@ compile-flags: --target x86_64-unknown-linux-gnu
//@ [none] compile-flags: -Zharden-sls=none
//@ [all] compile-flags: -Zharden-sls=all
//@ [return] compile-flags: -Zharden-sls=return
//@ [indirect_jmp] compile-flags: -Zharden-sls=indirect-jmp

#![crate_type = "lib"]
#![feature(no_core)]
#![no_core]

extern crate minicore;
use minicore::*;

#[no_mangle]
pub fn foo() {
// CHECK: @foo() unnamed_addr #0

// none-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} }
// none-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} }

// all: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp,+harden-sls-ret{{.*}} }

// return-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} }
// return: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} }

// indirect_jmp-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} }
// indirect_jmp: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} }
}
Loading
Loading