From 2c9b82513f1c2db46d23bf443f78ee5a11173d50 Mon Sep 17 00:00:00 2001 From: Urhengulas Date: Thu, 1 Apr 2021 23:36:45 +0200 Subject: [PATCH] `mod linking` --- src/linking.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 51 +++++--------------------------------------------- 2 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 src/linking.rs diff --git a/src/linking.rs b/src/linking.rs new file mode 100644 index 0000000..0ab3578 --- /dev/null +++ b/src/linking.rs @@ -0,0 +1,46 @@ +use std::{path::Path, process::Command}; + +use tempfile::TempDir; + +const EXIT_CODE_FAILURE: i32 = 1; +// TODO make this configurable (via command-line flag or similar) +const LINKER: &str = "rust-lld"; + +pub fn link_normally(args: &[String]) -> Result<(), i32> { + let mut c = Command::new(LINKER); + c.args(args); + log::trace!("{:?}", c); + + success_or_exitstatus(c) +} + +pub fn link_again( + args: &[String], + current_dir: &Path, + new_origin: u64, + tempdir: &TempDir, +) -> Result<(), i32> { + let mut c = Command::new(LINKER); + // add the current dir to the linker search path to include all unmodified scripts there + // HACK `-L` needs to go after `-flavor gnu`; position is currently hardcoded + c.args(&args[..2]) + .arg("-L".to_string()) + .arg(current_dir) + .args(&args[2..]) + // we need to override `_stack_start` to make the stack start below fake RAM + .arg(format!("--defsym=_stack_start={}", new_origin)) + // set working directory to temporary directory containing our new linker script + // this makes sure that it takes precedence over the original one + .current_dir(tempdir.path()); + log::trace!("{:?}", c); + + success_or_exitstatus(c) +} + +fn success_or_exitstatus(mut c: Command) -> Result<(), i32> { + let status = c.status().unwrap(); + if !status.success() { + return Err(status.code().unwrap_or(EXIT_CODE_FAILURE)); + } + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index d994b35..9ceb434 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +mod linking; + use std::{ borrow::Cow, env, @@ -5,16 +7,12 @@ use std::{ io::Write, ops::RangeInclusive, path::{Path, PathBuf}, - process::{self, Command}, + process, }; use anyhow::anyhow; use object::{elf, Object as _, ObjectSection, SectionFlags}; -use tempfile::TempDir; -const EXIT_CODE_FAILURE: i32 = 1; -// TODO make this configurable (via command-line flag or similar) -const LINKER: &str = "rust-lld"; /// Stack Pointer alignment required by the ARM architecture const SP_ALIGN: u64 = 8; @@ -25,7 +23,7 @@ fn main() -> anyhow::Result<()> { let args = env::args().skip(1).collect::>(); // if linking succeeds then linker scripts are well-formed; we'll rely on that in the parser - link_normally(&args).unwrap_or_else(|code| process::exit(code)); + linking::link_normally(&args).unwrap_or_else(|code| process::exit(code)); let current_dir = env::current_dir()?; let linker_scripts = get_linker_scripts(&args, ¤t_dir)?; @@ -92,51 +90,12 @@ fn main() -> anyhow::Result<()> { // commit file to disk drop(new_linker_script); - link_again(&args, ¤t_dir, new_origin, &tempdir) + linking::link_again(&args, ¤t_dir, new_origin, &tempdir) .unwrap_or_else(|code| process::exit(code)); Ok(()) } -fn link_normally(args: &[String]) -> Result<(), i32> { - let mut c = Command::new(LINKER); - c.args(args); - log::trace!("{:?}", c); - - success_or_exitstatus(c) -} - -fn link_again( - args: &[String], - current_dir: &Path, - new_origin: u64, - tempdir: &TempDir, -) -> Result<(), i32> { - let mut c = Command::new(LINKER); - // add the current dir to the linker search path to include all unmodified scripts there - // HACK `-L` needs to go after `-flavor gnu`; position is currently hardcoded - c.args(&args[..2]) - .arg("-L".to_string()) - .arg(current_dir) - .args(&args[2..]) - // we need to override `_stack_start` to make the stack start below fake RAM - .arg(format!("--defsym=_stack_start={}", new_origin)) - // set working directory to temporary directory containing our new linker script - // this makes sure that it takes precedence over the original one - .current_dir(tempdir.path()); - log::trace!("{:?}", c); - - success_or_exitstatus(c) -} - -fn success_or_exitstatus(mut c: Command) -> Result<(), i32> { - let status = c.status().unwrap(); - if !status.success() { - return Err(status.code().unwrap_or(EXIT_CODE_FAILURE)); - } - Ok(()) -} - /// Returns `(used_ram_length, used_ram_align)` fn compute_span_of_ram_sections(ram_entry: MemoryEntry, object: object::File) -> (u64, u64) { let mut used_ram_start = u64::MAX;