use std::path::PathBuf;
use std::process::Command;
mod artifact_guard;
use object::{Object, ObjectSection};
fn synth() -> &'static str {
env!("CARGO_BIN_EXE_synth")
}
fn fixture() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.join("scripts/repro/mem707_multi_sp.wat")
}
fn compile(extra: &[&str], tag: &str) -> Vec<u8> {
let fx = fixture();
let out = artifact_guard::unique_artifact(tag, "o");
let mut args = vec![
"compile",
fx.to_str().unwrap(),
"--target",
"cortex-m3",
"--native-pointer-abi",
"--all-exports",
"--relocatable",
"-o",
out.to_str().unwrap(),
];
args.extend_from_slice(extra);
let mut cmd = Command::new(synth());
cmd.args(&args);
artifact_guard::compile_bytes_or_panic(&mut cmd, &out, tag)
}
fn bss_size(data: &[u8]) -> u64 {
let obj = object::File::parse(data).expect("parse ELF");
obj.sections()
.find(|s| s.name() == Ok(".bss"))
.expect(".bss present")
.size()
}
fn global_slots(bytes: &[u8]) -> Vec<i32> {
let obj = object::File::parse(bytes).expect("parse ELF");
let data = obj
.section_by_name(".data")
.expect(".data present")
.data()
.expect(".data bytes");
data.as_chunks::<4>()
.0
.iter()
.map(|&w| i32::from_le_bytes(w))
.collect()
}
#[test]
fn all_aliased_sp_globals_rebase_707() {
let bytes = compile(&["--shadow-stack-size", "512"], "mem707_test");
assert_eq!(
global_slots(&bytes),
vec![512, 512, 512, 4096],
"the three mutable SP globals co-rebase; the immutable constant is untouched"
);
assert_eq!(bss_size(&bytes), 512);
}
#[test]
fn no_flag_leaves_multi_sp_full_707() {
let bytes = compile(&[], "mem707_noflag_test");
assert_eq!(
global_slots(&bytes),
vec![4096, 4096, 4096, 4096],
"no flag must leave every slot at its declared value"
);
assert_eq!(bss_size(&bytes), 4096);
}