Skip to content

Add Linker Support For L4Re #54425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
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 src/librustc_codegen_llvm/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
(None, Some(flavor)) => Some((PathBuf::from(match flavor {
LinkerFlavor::Em => if cfg!(windows) { "emcc.bat" } else { "emcc" },
LinkerFlavor::Gcc => "cc",
LinkerFlavor::L4Bender => "l4-bender",
LinkerFlavor::Ld => "ld",
LinkerFlavor::Msvc => "link.exe",
LinkerFlavor::Lld(_) => "lld",
Expand Down
168 changes: 168 additions & 0 deletions src/librustc_codegen_llvm/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// except according to those terms.

use rustc_data_structures::fx::FxHashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::{self, File};
use std::io::prelude::*;
Expand Down Expand Up @@ -85,6 +86,9 @@ impl LinkerInfo {
}) as Box<dyn Linker>
}

LinkerFlavor::L4Bender => {
Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
},
LinkerFlavor::Lld(LldFlavor::Wasm) => {
Box::new(WasmLd {
cmd,
Expand Down Expand Up @@ -1088,3 +1092,167 @@ impl<'a> Linker for WasmLd<'a> {
// Do nothing for now
}
}

/// 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: &str) {
self.link_staticlib(lib); // do not support dynamic linking for now
}
fn link_staticlib(&mut self, lib: &str) {
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 args(&mut self, args: &[String]) { self.cmd.args(args); }

fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { self.link_dylib(lib); }

fn link_framework(&mut self, _: &str) {
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: &str, _: &[PathBuf]) {
self.hint_static();
self.cmd.arg("--whole-archive");
self.cmd.arg("-l").arg(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) {
match self.sess.opts.debuginfo {
DebugInfo::None => {
// If we are building without debuginfo enabled and we were called with
// `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
// found when linking to get rid of symbols from libstd.
match self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
Some(true) => { self.cmd.arg("-S"); },
_ => {},
}
},
_ => {},
};
}

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) {
bug!("Not implemented");
}

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

fn finalize(&mut self) -> Command {
self.hint_static(); // Reset to default before returning the composed command line.
let mut cmd = Command::new("");
::std::mem::swap(&mut cmd, &mut self.cmd);
cmd
}

fn group_start(&mut self) { self.cmd.arg("--start-group"); }
fn group_end(&mut self) { self.cmd.arg("--end-group"); }
fn cross_lang_lto(&mut self) {
// do nothing
}
}

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;
}
}
}
14 changes: 1 addition & 13 deletions src/librustc_target/spec/l4re_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,6 @@

use spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
use std::default::Default;
//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()
//}

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
Expand All @@ -32,7 +20,7 @@ pub fn opts() -> TargetOptions {
has_elf_tls: false,
exe_allocation_crate: None,
panic_strategy: PanicStrategy::Abort,
linker: Some("ld".to_string()),
linker: Some("l4-bender".to_string()),
pre_link_args: args,
target_family: Some("unix".to_string()),
.. Default::default()
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ mod riscv_base;
pub enum LinkerFlavor {
Em,
Gcc,
L4Bender,
Ld,
Msvc,
Lld(LldFlavor),
Expand Down Expand Up @@ -150,6 +151,7 @@ macro_rules! flavor_mappings {
flavor_mappings! {
((LinkerFlavor::Em), "em"),
((LinkerFlavor::Gcc), "gcc"),
((LinkerFlavor::L4Bender), "l4-bender"),
((LinkerFlavor::Ld), "ld"),
((LinkerFlavor::Msvc), "msvc"),
((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn target() -> TargetResult {
target_os: "l4re".to_string(),
target_env: "uclibc".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Ld,
linker_flavor: LinkerFlavor::L4Bender,
options: base,
})
}