From 096dd7c644c5566959dd852710f4b80723885742 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Thu, 26 Nov 2020 20:36:04 +0100 Subject: [PATCH] Forbid rustc from using -f{function,data}-sections (fixes #20 panic) Some kernel configs were panicking at the Rust example driver initialization. The `__MOD` static value had a bogus value, which meant that trying to initialize it was dropping the object that was, supposedly, there. The memory corruption happened during rootfs unpacking, which explains why it only happened in some configs (like in CI) and why it also didn't happen if there was an early error during unpacking. That memory corruption, in turn, was caused because the `__MOD` symbol was being placed after the end of the kernel reserve. That happened due to the kernel's linker script not supporting unique sections per symbol for dead code data elimination -- yet. Some arches do, but until we can rely on that, we need to disable their generation in rustc's side for the moment. Since we discussed to have the target spec on our side, and since `-Z function-sections=false` was added just a month ago, I went with the spec route. Other symbols were being placed in unexpected places, which should be fixed now too. Signed-off-by: Miguel Ojeda --- Makefile | 4 +--- arch/x86/rust/target.json | 34 ++++++++++++++++++++++++++++++++++ rust/kernel/build.rs | 3 ++- 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 arch/x86/rust/target.json diff --git a/Makefile b/Makefile index 8307664d39015b..30101bc8ba272f 100644 --- a/Makefile +++ b/Makefile @@ -510,11 +510,9 @@ KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \ KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_RUSTCFLAGS := # TODO: a simple way to update `Cargo.lock` when we add a new driver -# TODO: another option is using explicit target specs, e.g. -# `--target=$(srctree)/arch/$(SRCARCH)/rust-target-spec.json` KBUILD_CARGOFLAGS := $(CARGO_VERBOSE) --locked \ -Z build-std=core,alloc -Z unstable-options \ - --out-dir=out --target=x86_64-linux-kernel + --out-dir=out --target=$(PWD)/$(srctree)/arch/$(SRCARCH)/rust/target.json KBUILD_AFLAGS_KERNEL := KBUILD_CFLAGS_KERNEL := KBUILD_RUSTCFLAGS_KERNEL := diff --git a/arch/x86/rust/target.json b/arch/x86/rust/target.json new file mode 100644 index 00000000000000..92ffaebf59c9a5 --- /dev/null +++ b/arch/x86/rust/target.json @@ -0,0 +1,34 @@ +{ + "arch": "x86_64", + "code-model": "kernel", + "cpu": "x86-64", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "disable-redzone": true, + "eliminate-frame-pointer": false, + "env": "gnu", + "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float", + "function-sections": false, + "is-builtin": true, + "linker-flavor": "gcc", + "linker-is-gnu": true, + "llvm-target": "x86_64-elf", + "max-atomic-width": 64, + "needs-plt": true, + "os": "none", + "panic-strategy": "abort", + "position-independent-executables": true, + "pre-link-args": { + "gcc": [ + "-Wl,--as-needed", + "-Wl,-z,noexecstack", + "-m64" + ] + }, + "relocation-model": "static", + "relro-level": "full", + "stack-probes": true, + "target-c-int-width": "32", + "target-endian": "little", + "target-pointer-width": "64", + "vendor": "unknown" +} diff --git a/rust/kernel/build.rs b/rust/kernel/build.rs index 0897186b3f9241..a63ecf17c6d957 100644 --- a/rust/kernel/build.rs +++ b/rust/kernel/build.rs @@ -96,7 +96,8 @@ fn main() { let kernel_args = prepare_cflags(&cflags, &kernel_dir); - let target = env::var("TARGET").unwrap(); + // TODO: pass the proper triple to bindgen + let target = "x86_64-linux-kernel"; let mut builder = bindgen::Builder::default() .use_core()