Skip to content

Commit

Permalink
mod linking
Browse files Browse the repository at this point in the history
  • Loading branch information
Urhengulas committed Apr 1, 2021
1 parent 8e91dbf commit 2c9b825
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 46 deletions.
46 changes: 46 additions & 0 deletions src/linking.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
51 changes: 5 additions & 46 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
mod linking;

use std::{
borrow::Cow,
env,
fs::{self, File},
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;

Expand All @@ -25,7 +23,7 @@ fn main() -> anyhow::Result<()> {
let args = env::args().skip(1).collect::<Vec<_>>();

// 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, &current_dir)?;
Expand Down Expand Up @@ -92,51 +90,12 @@ fn main() -> anyhow::Result<()> {
// commit file to disk
drop(new_linker_script);

link_again(&args, &current_dir, new_origin, &tempdir)
linking::link_again(&args, &current_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;
Expand Down

0 comments on commit 2c9b825

Please sign in to comment.