rustc_target: Some more tests and fixes for linker arguments
This commit is contained in:
parent
46aba8850b
commit
456f65ec8b
11 changed files with 132 additions and 44 deletions
|
@ -8,6 +8,7 @@
|
|||
//! LLVM.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(let_else)]
|
||||
|
|
|
@ -3,13 +3,13 @@ use crate::spec::{FramePointer, LinkerFlavor, Target};
|
|||
pub fn target() -> Target {
|
||||
let mut base = super::windows_gnu_base::opts();
|
||||
base.cpu = "pentium4".into();
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe"]);
|
||||
base.max_atomic_width = Some(64);
|
||||
base.frame_pointer = FramePointer::Always; // Required for backtraces
|
||||
base.linker = Some("i686-w64-mingw32-gcc".into());
|
||||
|
||||
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
|
||||
// space available to x86 Windows binaries on x86_64.
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
|
||||
base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
|
||||
|
||||
Target {
|
||||
|
|
|
@ -3,12 +3,12 @@ use crate::spec::{FramePointer, LinkerFlavor, Target};
|
|||
pub fn target() -> Target {
|
||||
let mut base = super::windows_uwp_gnu_base::opts();
|
||||
base.cpu = "pentium4".into();
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe"]);
|
||||
base.max_atomic_width = Some(64);
|
||||
base.frame_pointer = FramePointer::Always; // Required for backtraces
|
||||
|
||||
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
|
||||
// space available to x86 Windows binaries on x86_64.
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
|
||||
base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
|
||||
|
||||
Target {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::super::*;
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
// Test target self-consistency and JSON encoding/decoding roundtrip.
|
||||
pub(super) fn test_target(target: Target) {
|
||||
|
@ -14,35 +15,105 @@ impl Target {
|
|||
assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64");
|
||||
assert!(self.is_like_windows || !self.is_like_msvc);
|
||||
|
||||
// Check that LLD with the given flavor is treated identically to the linker it emulates.
|
||||
// If your target really needs to deviate from the rules below, except it and document the
|
||||
// reasons.
|
||||
assert_eq!(
|
||||
self.linker_flavor == LinkerFlavor::Msvc
|
||||
|| self.linker_flavor == LinkerFlavor::Lld(LldFlavor::Link),
|
||||
self.lld_flavor == LldFlavor::Link,
|
||||
);
|
||||
assert_eq!(self.is_like_msvc, self.lld_flavor == LldFlavor::Link);
|
||||
for args in &[
|
||||
// Check that default linker flavor and lld flavor are compatible
|
||||
// with some other key properties.
|
||||
assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
|
||||
assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
|
||||
assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
|
||||
assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender));
|
||||
assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em));
|
||||
assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker));
|
||||
assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker));
|
||||
|
||||
for args in [
|
||||
&self.pre_link_args,
|
||||
&self.late_link_args,
|
||||
&self.late_link_args_dynamic,
|
||||
&self.late_link_args_static,
|
||||
&self.post_link_args,
|
||||
] {
|
||||
for (&flavor, flavor_args) in args {
|
||||
assert!(!flavor_args.is_empty());
|
||||
// Check that flavors mentioned in link args are compatible with the default flavor.
|
||||
match (self.linker_flavor, self.lld_flavor) {
|
||||
(
|
||||
LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc,
|
||||
LldFlavor::Ld,
|
||||
) => {
|
||||
assert_matches!(
|
||||
flavor,
|
||||
LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc
|
||||
)
|
||||
}
|
||||
(LinkerFlavor::Gcc, LldFlavor::Ld64) => {
|
||||
assert_matches!(flavor, LinkerFlavor::Gcc)
|
||||
}
|
||||
(LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link), LldFlavor::Link) => {
|
||||
assert_matches!(
|
||||
flavor,
|
||||
LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link)
|
||||
)
|
||||
}
|
||||
(LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc, LldFlavor::Wasm) => {
|
||||
assert_matches!(
|
||||
flavor,
|
||||
LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
|
||||
)
|
||||
}
|
||||
(LinkerFlavor::L4Bender, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::L4Bender)
|
||||
}
|
||||
(LinkerFlavor::Em, LldFlavor::Wasm) => {
|
||||
assert_matches!(flavor, LinkerFlavor::Em)
|
||||
}
|
||||
(LinkerFlavor::BpfLinker, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::BpfLinker)
|
||||
}
|
||||
(LinkerFlavor::PtxLinker, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::PtxLinker)
|
||||
}
|
||||
flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
|
||||
}
|
||||
|
||||
// Check that link args for cc and non-cc versions of flavors are consistent.
|
||||
let check_noncc = |noncc_flavor| {
|
||||
if let Some(noncc_args) = args.get(&noncc_flavor) {
|
||||
for arg in flavor_args {
|
||||
if let Some(suffix) = arg.strip_prefix("-Wl,") {
|
||||
assert!(noncc_args.iter().any(|a| a == suffix));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
match self.linker_flavor {
|
||||
LinkerFlavor::Gcc => match self.lld_flavor {
|
||||
LldFlavor::Ld => {
|
||||
check_noncc(LinkerFlavor::Ld);
|
||||
check_noncc(LinkerFlavor::Lld(LldFlavor::Ld));
|
||||
}
|
||||
LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)),
|
||||
LldFlavor::Ld64 | LldFlavor::Link => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that link args for lld and non-lld versions of flavors are consistent.
|
||||
assert_eq!(args.get(&LinkerFlavor::Ld), args.get(&LinkerFlavor::Lld(LldFlavor::Ld)));
|
||||
assert_eq!(
|
||||
args.get(&LinkerFlavor::Msvc),
|
||||
args.get(&LinkerFlavor::Lld(LldFlavor::Link)),
|
||||
);
|
||||
if args.contains_key(&LinkerFlavor::Msvc) {
|
||||
assert_eq!(self.lld_flavor, LldFlavor::Link);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
(self.pre_link_objects_fallback.is_empty()
|
||||
&& self.post_link_objects_fallback.is_empty())
|
||||
|| self.crt_objects_fallback.is_some()
|
||||
);
|
||||
|
||||
// If your target really needs to deviate from the rules below,
|
||||
// except it and document the reasons.
|
||||
// Keep the default "unknown" vendor instead.
|
||||
assert_ne!(self.vendor, "");
|
||||
if !self.can_use_os_unknown() {
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
use super::{cvs, wasm_base};
|
||||
use super::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
|
||||
use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut options = wasm_base::options();
|
||||
|
||||
// Rust really needs a way for users to specify exports and imports in
|
||||
// the source code. --export-dynamic isn't the right tool for this job,
|
||||
// however it does have the side effect of automatically exporting a lot
|
||||
// of symbols, which approximates what people want when compiling for
|
||||
// wasm32-unknown-unknown expect, so use it for now.
|
||||
options.add_pre_link_args(LinkerFlavor::Gcc, &["--export-dynamic"]);
|
||||
options.add_post_link_args(LinkerFlavor::Em, &["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"]);
|
||||
// Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
|
||||
let pre_link_args = LinkArgs::new();
|
||||
let post_link_args = TargetOptions::link_args(
|
||||
LinkerFlavor::Em,
|
||||
&["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"],
|
||||
);
|
||||
|
||||
let opts = TargetOptions {
|
||||
os: "emscripten".into(),
|
||||
|
@ -19,11 +16,13 @@ pub fn target() -> Target {
|
|||
// functionality, and a .wasm file.
|
||||
exe_suffix: ".js".into(),
|
||||
linker: None,
|
||||
pre_link_args,
|
||||
post_link_args,
|
||||
relocation_model: RelocModel::Pic,
|
||||
panic_strategy: PanicStrategy::Unwind,
|
||||
no_default_libraries: false,
|
||||
families: cvs!["unix", "wasm"],
|
||||
..options
|
||||
..wasm_base::options()
|
||||
};
|
||||
Target {
|
||||
llvm_target: "wasm32-unknown-emscripten".into(),
|
||||
|
|
|
@ -30,27 +30,30 @@ pub fn target() -> Target {
|
|||
options.default_adjusted_cabi = Some(Abi::Wasm);
|
||||
|
||||
options.add_pre_link_args(
|
||||
LinkerFlavor::Gcc,
|
||||
LinkerFlavor::Lld(LldFlavor::Wasm),
|
||||
&[
|
||||
// Make sure clang uses LLD as its linker and is configured appropriately
|
||||
// otherwise
|
||||
"--target=wasm32-unknown-unknown",
|
||||
// For now this target just never has an entry symbol no matter the output
|
||||
// type, so unconditionally pass this.
|
||||
"-Wl,--no-entry",
|
||||
"--no-entry",
|
||||
// Rust really needs a way for users to specify exports and imports in
|
||||
// the source code. --export-dynamic isn't the right tool for this job,
|
||||
// however it does have the side effect of automatically exporting a lot
|
||||
// of symbols, which approximates what people want when compiling for
|
||||
// wasm32-unknown-unknown expect, so use it for now.
|
||||
"--export-dynamic",
|
||||
],
|
||||
);
|
||||
options.add_pre_link_args(
|
||||
LinkerFlavor::Gcc,
|
||||
&[
|
||||
// Make sure clang uses LLD as its linker and is configured appropriately
|
||||
// otherwise
|
||||
"--target=wasm32-unknown-unknown",
|
||||
"-Wl,--no-entry",
|
||||
"-Wl,--export-dynamic",
|
||||
],
|
||||
);
|
||||
|
||||
// Add the flags to wasm-ld's args too.
|
||||
options
|
||||
.add_pre_link_args(LinkerFlavor::Lld(LldFlavor::Wasm), &["--no-entry", "--export-dynamic"]);
|
||||
|
||||
Target {
|
||||
llvm_target: "wasm32-unknown-unknown".into(),
|
||||
pointer_width: 32,
|
||||
|
|
|
@ -15,20 +15,25 @@ pub fn target() -> Target {
|
|||
options.os = "unknown".into();
|
||||
options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
|
||||
|
||||
options.add_pre_link_args(
|
||||
LinkerFlavor::Lld(LldFlavor::Wasm),
|
||||
&[
|
||||
// For now this target just never has an entry symbol no matter the output
|
||||
// type, so unconditionally pass this.
|
||||
"--no-entry",
|
||||
"-mwasm64",
|
||||
],
|
||||
);
|
||||
options.add_pre_link_args(
|
||||
LinkerFlavor::Gcc,
|
||||
&[
|
||||
// Make sure clang uses LLD as its linker and is configured appropriately
|
||||
// otherwise
|
||||
"--target=wasm64-unknown-unknown",
|
||||
// For now this target just never has an entry symbol no matter the output
|
||||
// type, so unconditionally pass this.
|
||||
"-Wl,--no-entry",
|
||||
],
|
||||
);
|
||||
|
||||
options.add_pre_link_args(LinkerFlavor::Lld(LldFlavor::Wasm), &["--no-entry", "-mwasm64"]);
|
||||
|
||||
// Any engine that implements wasm64 will surely implement the rest of these
|
||||
// features since they were all merged into the official spec by the time
|
||||
// wasm64 was designed.
|
||||
|
|
|
@ -2,15 +2,23 @@ use crate::spec::crt_objects::{self, CrtObjectsFallback};
|
|||
use crate::spec::{cvs, LinkerFlavor, TargetOptions};
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
let pre_link_args = TargetOptions::link_args(
|
||||
let mut pre_link_args = TargetOptions::link_args(
|
||||
LinkerFlavor::Ld,
|
||||
&[
|
||||
// Enable ASLR
|
||||
"--dynamicbase",
|
||||
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
|
||||
"--disable-auto-image-base",
|
||||
],
|
||||
);
|
||||
super::add_link_args(
|
||||
&mut pre_link_args,
|
||||
LinkerFlavor::Gcc,
|
||||
&[
|
||||
// Tell GCC to avoid linker plugins, because we are not bundling
|
||||
// them with Windows installer, and Rust does its own LTO anyways.
|
||||
"-fno-use-linker-plugin",
|
||||
// Enable ASLR
|
||||
"-Wl,--dynamicbase",
|
||||
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
|
||||
"-Wl,--disable-auto-image-base",
|
||||
],
|
||||
);
|
||||
|
|
|
@ -17,6 +17,7 @@ pub fn opts() -> TargetOptions {
|
|||
];
|
||||
let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
|
||||
super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
|
||||
// Reset the flags back to empty until the FIXME above is addressed.
|
||||
let late_link_args_dynamic = LinkArgs::new();
|
||||
let late_link_args_static = LinkArgs::new();
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ pub fn target() -> Target {
|
|||
let mut base = super::windows_gnu_base::opts();
|
||||
base.cpu = "x86-64".into();
|
||||
// Use high-entropy 64 bit address space for ASLR
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
|
||||
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep"]);
|
||||
base.max_atomic_width = Some(64);
|
||||
base.linker = Some("x86_64-w64-mingw32-gcc".into());
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ pub fn target() -> Target {
|
|||
let mut base = super::windows_uwp_gnu_base::opts();
|
||||
base.cpu = "x86-64".into();
|
||||
// Use high-entropy 64 bit address space for ASLR
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
|
||||
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
|
||||
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep"]);
|
||||
base.max_atomic_width = Some(64);
|
||||
|
||||
Target {
|
||||
|
|
Loading…
Reference in a new issue