Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add L4Bender as linker variant
  • Loading branch information
humenda authored and atopia committed Jan 21, 2022
commit d98428711e6fe1b2a7f6d963d4b337beaa3dc285
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
LinkerFlavor::Lld(_) => "lld",
LinkerFlavor::PtxLinker => "rust-ptx-linker",
LinkerFlavor::BpfLinker => "bpf-linker",
LinkerFlavor::L4Bender => "l4-bender",
}),
flavor,
)),
Expand Down
172 changes: 171 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::command::Command;
use super::symbol_export;
use rustc_span::symbol::sym;

use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::{self, File};
use std::io::prelude::*;
Expand Down Expand Up @@ -126,7 +127,6 @@ pub fn get_linker<'a>(
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
// to the linker args construction.
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");

match flavor {
LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
Expand All @@ -149,6 +149,10 @@ pub fn get_linker<'a>(
LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,

LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,

LinkerFlavor::L4Bender => {
Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
},
}
}

Expand Down Expand Up @@ -1355,6 +1359,172 @@ impl<'a> Linker for WasmLd<'a> {
}
}

/// Linker shepherd script for L4Re (Fiasco)
pub struct L4Bender<'a> {
cmd: Command,
sess: &'a Session,
hinted_static: bool,
}

impl<'a> Linker for L4Bender<'a> {
fn link_dylib(&mut self, _lib: Symbol) {
panic!("dylibs not supported yet")
}
fn link_staticlib(&mut self, lib: Symbol) {
self.hint_static();
self.cmd.arg(format!("-PC{}", lib));
}
fn link_rlib(&mut self, lib: &Path) {
self.hint_static();
self.cmd.arg(lib);
}
fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}
fn framework_path(&mut self, _: &Path) {
bug!("Frameworks are not supported on L4Re!");
}
fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
// not sure about pie on L4Re
fn position_independent_executable(&mut self) { }
fn no_position_independent_executable(&mut self) { }
fn full_relro(&mut self) { self.cmd.arg("-z,relro,-z,now"); }
fn partial_relro(&mut self) { self.cmd.arg("-z,relro"); }
fn no_relro(&mut self) { self.cmd.arg("-z,norelro"); }
fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}

fn link_rust_dylib(&mut self, _: Symbol, _: &Path) {
panic!("Rust dylibs not supported");
}

fn link_framework(&mut self, _: Symbol) {
bug!("Frameworks not supported on L4Re.");
}

// Here we explicitly ask that the entire archive is included into the
// result artifact. For more details see #15460, but the gist is that
// the linker will strip away any unused objects in the archive if we
// don't otherwise explicitly reference them. This can occur for
// libraries which are just providing bindings, libraries with generic
// functions, etc.
fn link_whole_staticlib(&mut self, lib: Symbol, _: &[PathBuf]) {
self.hint_static();
self.cmd.arg("--whole-archive").arg(format!("-l{}", lib));
self.cmd.arg("--no-whole-archive");
}

fn link_whole_rlib(&mut self, lib: &Path) {
self.hint_static();
self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive");
}

fn gc_sections(&mut self, keep_metadata: bool) {
if !keep_metadata {
self.cmd.arg("--gc-sections");
}
}

fn optimize(&mut self) {
self.cmd.arg("-O2");
}

fn pgo_gen(&mut self) { }

fn debuginfo(&mut self, strip: Strip) {
match strip {
Strip::None => {}
Strip::Debuginfo => {
self.cmd().arg("--strip-debug"); }
Strip::Symbols => {
self.cmd().arg("--strip-all");
}
}
}

fn no_default_libraries(&mut self) {
self.cmd.arg("-nostdlib");
}

fn build_dylib(&mut self, _: &Path) {
bug!("not implemented");
}

fn export_symbols(&mut self, _: &Path, _: CrateType) {
// ToDo, not implemented, copy from GCC
return;
}

fn subsystem(&mut self, subsystem: &str) {
self.cmd.arg(&format!("--subsystem,{}", subsystem));
}

fn finalize(&mut self) {
self.hint_static(); // Reset to default before returning the composed command line.
}

fn group_start(&mut self) { self.cmd.arg("--start-group"); }
fn group_end(&mut self) { self.cmd.arg("--end-group"); }
fn linker_plugin_lto(&mut self) {
// do nothing
}
fn control_flow_guard(&mut self) {
self.sess.warn("Windows Control Flow Guard is not supported by this linker.");
}

fn no_crt_objects(&mut self) { }
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface looks like more or less like an ld linker, I'd suggest to avoid adding a new linker flavor for a start and reuse GccLinker (especially given that the set of linker flavors accepted by -C linker-flavor is a stable public interface).


impl<'a> L4Bender<'a> {
pub fn new(mut cmd: Command, sess: &'a Session) -> L4Bender<'a> {
if let Ok(l4bender_args) = env::var("L4_BENDER_ARGS") {
L4Bender::split_cmd_args(&mut cmd, &l4bender_args);
}

cmd.arg("--"); // separate direct l4-bender args from linker args

L4Bender {
cmd: cmd,
sess: sess,
hinted_static: false,
}
}

/// This parses a shell-escaped string and unquotes the arguments. It doesn't attempt to
/// completely understand shell, but should instead allow passing arguments like
/// `-Dlinker="ld -m x86_64"`, and a copy without quotes, but spaces preserved, is added as an
/// argument to the given Command. This means that constructs as \" are not understood, so
/// quote wisely.
fn split_cmd_args(cmd: &mut Command, shell_args: &str) {
let mut arg = String::new();
let mut quoted = false;
for character in shell_args.chars() {
match character {
' ' if !quoted => {
cmd.arg(&arg);
arg.clear();
},
'"' | '\'' => quoted = !quoted,
_ => arg.push(character),
};
}
if arg.len() > 0 {
cmd.arg(&arg);
arg.clear();
}
}

fn hint_static(&mut self) {
if !self.hinted_static {
self.cmd.arg("-static");
self.hinted_static = true;
}
}
}

pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
return exports.clone();
Expand Down
21 changes: 5 additions & 16 deletions compiler/rustc_target/src/spec/l4re_base.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
use crate::spec::{LinkerFlavor, PanicStrategy, TargetOptions};
//use std::process::Command;

// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note
// that a few files also come from L4Re, for these, the function shouldn't be
// used. This uses GCC for the location of the file, but GCC is required for L4Re anyway.
//fn get_path_or(filename: &str) -> String {
// let child = Command::new("gcc")
// .arg(format!("-print-file-name={}", filename)).output()
// .expect("Failed to execute GCC");
// String::from_utf8(child.stdout)
// .expect("Couldn't read path from GCC").trim().into()
//}
use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
TargetOptions {
Expand All @@ -19,9 +8,9 @@ pub fn opts() -> TargetOptions {
linker_flavor: LinkerFlavor::Ld,
executables: true,
panic_strategy: PanicStrategy::Abort,
linker: Some("ld".to_string()),
linker_is_gnu: false,
families: vec!["unix".to_string()],
linker: Some("l4-bender".to_string()),
pre_link_args: args,
os_family: Some("unix".to_string()),
..Default::default()
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ mod windows_uwp_msvc_base;
pub enum LinkerFlavor {
Em,
Gcc,
L4Bender,
Ld,
Msvc,
Lld(LldFlavor),
Expand Down Expand Up @@ -160,6 +161,7 @@ macro_rules! flavor_mappings {
flavor_mappings! {
((LinkerFlavor::Em), "em"),
((LinkerFlavor::Gcc), "gcc"),
((LinkerFlavor::L4Bender), "l4-bender"),
((LinkerFlavor::Ld), "ld"),
((LinkerFlavor::Msvc), "msvc"),
((LinkerFlavor::PtxLinker), "ptx-linker"),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pub fn target() -> Target {
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.to_string(),
arch: "x86_64".to_string(),
target_os: "l4re".to_string(),
target_env: "uclibc".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::L4Bender,
options: base,
}
}