Skip to content

Commit

Permalink
Add x86_64-linux-kernel target
Browse files Browse the repository at this point in the history
This adds a target specification for Linux kernel modules on x86_64, as well as base code that can be shared with other architectures.
  • Loading branch information
alex committed Aug 31, 2019
1 parent b314654 commit 5e933b4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/librustc_target/spec/linux_kernel_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelroLevel, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
let mut pre_link_args = LinkArgs::new();
pre_link_args.insert(
LinkerFlavor::Gcc,

This comment has been minimized.

Copy link
@joshtriplett

joshtriplett Sep 1, 2019

Member

This will eventually need flexibility, to allow linking with lld, when the kernel supports that.

vec!["-Wl,--as-needed".to_string(), "-Wl,-z,noexecstack".to_string()],

This comment has been minimized.

Copy link
@joshtriplett

joshtriplett Sep 1, 2019

Member

If possible, we may want to leave the linking step to the kernel build system, so that people can add options in the future. I don't want to end up in a future situation where someone makes treewide build system changes to build flags and then finds they can't change Rust link options without going to the upstream Rust project.

If it's possible to override these link options, we need to document how to do so.

This comment has been minimized.

Copy link
@alex

alex Sep 1, 2019

Author Member

The way we've approached it thus far is to let cargo build a .a and then hook into the kernel build process from there.

);

TargetOptions {
disable_redzone: true,
panic_strategy: PanicStrategy::Abort,
stack_probes: true,
eliminate_frame_pointer: false,
linker_is_gnu: true,
position_independent_executables: true,

This comment has been minimized.

Copy link
@joshtriplett

joshtriplett Sep 1, 2019

Member

Is there a way we can control the use of PIE at build time using stable Rust options? The kernel has a Kconfig option to build a relocatable kernel, and if turned off then we'd want to follow suit.

This comment has been minimized.

Copy link
@alex

alex Sep 1, 2019

Author Member

Not obviously -- the target() function takes no parameters, so there's no clear way to get any state there.

There's some logic in link to disable PIE in some cases, but it doesn't seem to be user controllable in any way:

let mut position_independent_executable = false;
if t.options.position_independent_executables {
let empty_vec = Vec::new();
let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
let more_args = &sess.opts.cg.link_arg;
let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
if is_pic(sess) && !sess.crt_static() && !args.any(|x| *x == "-static") {
position_independent_executable = true;
}
}
if position_independent_executable {
cmd.position_independent_executable();
} else {
// recent versions of gcc can be configured to generate position
// independent executables by default. We have to pass -no-pie to
// explicitly turn that off. Not applicable to ld.
if sess.target.target.options.linker_is_gnu
&& flavor != LinkerFlavor::Ld {
cmd.no_position_independent_executable();
}
}

The brute-force way would be to have two different targets, but that seems excessive. The other option would be to expose a new compiler option to override the PIE setting from the target.

This comment has been minimized.

Copy link
@joshtriplett

joshtriplett Sep 1, 2019

Member

It's not critical, just something to work on in parallel to make such an option available.

needs_plt: true,
relro_level: RelroLevel::Full,
relocation_model: "static".to_string(),
target_family: Some("unix".to_string()),
pre_link_args,

..Default::default()
}
}
3 changes: 3 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ mod freebsd_base;
mod haiku_base;
mod hermit_base;
mod linux_base;
mod linux_kernel_base;
mod linux_musl_base;
mod openbsd_base;
mod netbsd_base;
Expand Down Expand Up @@ -386,6 +387,8 @@ supported_targets! {
("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
("aarch64-linux-android", aarch64_linux_android),

("x86_64-linux-kernel", x86_64_linux_kernel),

("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
("armv6-unknown-freebsd", armv6_unknown_freebsd),
("armv7-unknown-freebsd", armv7_unknown_freebsd),
Expand Down
31 changes: 31 additions & 0 deletions src/librustc_target/spec/x86_64_linux_kernel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
// generic Linux kernel options.

use crate::spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::linux_kernel_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
base.features =
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
.to_string();
base.code_model = Some("kernel".to_string());
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());

Ok(Target {
// FIXME: Some dispute, the linux-on-clang folks think this should use "Linux"

This comment has been minimized.

Copy link
@joshtriplett

joshtriplett Sep 1, 2019

Member

Either one can work, it just changes what baseline settings you need to start from.

llvm_target: "x86_64-elf".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "64".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
target_os: "none".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
arch: "x86_64".to_string(),
linker_flavor: LinkerFlavor::Gcc,

options: base,
})
}

0 comments on commit 5e933b4

Please sign in to comment.