Skip to content

Commit

Permalink
tests::verify: Get initial stack pointer
Browse files Browse the repository at this point in the history
  • Loading branch information
Urhengulas committed Jun 15, 2021
1 parent cc6223e commit 36f282f
Showing 1 changed file with 86 additions and 0 deletions.
86 changes: 86 additions & 0 deletions tests/verify.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
use std::fs;

/// Path to test app
const CRATE: &str = "test-flip-link-app";
/// Example firmware in `$CRATE/examples`
const FILES: [&str; 4] = ["crash", "exception", "hello", "panic"];
/// Compilation target firmware is build for
const TARGET: &str = "thumbv7m-none-eabi";

#[test]
fn should_link_example_firmware() -> anyhow::Result<()> {
Expand All @@ -14,6 +21,30 @@ fn should_link_example_firmware() -> anyhow::Result<()> {
Ok(())
}

#[test]
fn should_verify_memory_layout() -> anyhow::Result<()> {
// Arrange
cargo::check_flip_link();

// Act
cargo::build_example_firmware(CRATE)?;

// Assert
for elf_path in elf::paths() {
// read and parse elf-file
let elf = fs::read(elf_path)?;
let object = object::File::parse(&*elf)?;

// get the relevant sections
let (bss, data, uninit, vector_table) = elf::get_sections(&object)?;
// compute the initial stack-pointer from `.vector_table`
let initial_sp = elf::compute_initial_sp(&vector_table)?;
}

// ---
Ok(())
}

mod cargo {
use std::process::Command;

Expand Down Expand Up @@ -43,3 +74,58 @@ mod cargo {
.success();
}
}

mod elf {
use std::convert::TryInto;

use anyhow::anyhow;
use object::{File, Object, ObjectSection, Section};

use super::{CRATE, FILES, TARGET};

/// Get the initial stack pointer.
///
/// It is the first 32-bit word in the `.vector_table` section,
/// according to the "ARMv6-M Architecture Reference Manual".
pub fn compute_initial_sp(vector_table: &Section) -> anyhow::Result<u64> {
let data = vector_table.uncompressed_data()?;
let sp = u32::from_le_bytes(data[..4].try_into()?);
Ok(sp as u64)
}

/// Get the following sections from the elf-file:
/// * `.bss`
/// * `.data`
/// * `.uninit`
/// * `.vector_table`
pub fn get_sections<'data, 'file>(
object: &'file File<'data>,
) -> anyhow::Result<(
Section<'data, 'file>,
Section<'data, 'file>,
Section<'data, 'file>,
Section<'data, 'file>,
)> {
// try to get section, else error
let get_section = |section_name| {
object
.section_by_name(section_name)
.ok_or(anyhow!("error getting section `{}`", section_name))
};

Ok((
get_section(".bss")?,
get_section(".data")?,
get_section(".uninit")?,
get_section(".vector_table")?,
))
}

/// Paths to firmware binaries.
pub fn paths() -> Vec<String> {
FILES
.iter()
.map(|file_name| format!("{}/target/{}/debug/examples/{}", CRATE, TARGET, file_name))
.collect()
}
}

0 comments on commit 36f282f

Please sign in to comment.