Skip to content

Commit

Permalink
[bug] caliptra-image ignores ELF .rodata address. (#763)
Browse files Browse the repository at this point in the history
Depending on section alignment, this can cause .rodata to be shifted
around strangely in memory. This PR fixes that, and errors if the .data
section contains any data (supporting .data is a more involved fix).
  • Loading branch information
korran authored Sep 13, 2023
1 parent 2e055bb commit 8247d5a
Showing 1 changed file with 55 additions and 4 deletions.
59 changes: 55 additions & 4 deletions image/elf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@ pub struct ElfExecutable {
content: Vec<u8>,
}

fn load_into_image(
image: &mut Vec<u8>,
image_base_addr: u32,
section_addr: u32,
section_data: &[u8],
) -> anyhow::Result<()> {
if section_addr < image_base_addr {
bail!("Section address 0x{section_addr:08x} is below image base address 0x{image_base_addr:08x}");
}
let section_offset = usize::try_from(section_addr - image_base_addr).unwrap();
image.resize(
usize::max(image.len(), section_offset + section_data.len()),
u8::default(),
);
image[section_offset..][..section_data.len()].copy_from_slice(section_data);
Ok(())
}

impl ElfExecutable {
pub fn open(
path: &PathBuf,
Expand All @@ -55,14 +73,22 @@ impl ElfExecutable {
let elf_file = ElfBytes::<AnyEndian>::minimal_parse(elf_bytes)
.with_context(|| "Failed to parse elf file")?;

// TODO: Use the ELF program headers (readelf -l) to generate the image
// rather than sections, similar to objcopy.
let (load_addr, text) = Self::read_section(&elf_file, ".text", true)?;
content.extend_from_slice(text);
load_into_image(&mut content, load_addr, load_addr, text)?;

let (_, rodata) = Self::read_section(&elf_file, ".rodata", false)?;
content.extend_from_slice(rodata);
let (rodata_addr, rodata) = Self::read_section(&elf_file, ".rodata", false)?;
load_into_image(&mut content, load_addr, rodata_addr, rodata)?;

let (_, data) = Self::read_section(&elf_file, ".data", false)?;
content.extend_from_slice(data);
if !data.is_empty() {
// TODO: The ELF file generated by our current linker scripts does not
// tell us where the initial .data section is supposed to be staged
// from in ICCM. Typically this would be done by setting the LMA to
// the ICCM source address and the VMA to the DCCM destination.
bail!(".data sections are not yet supported")
}

let entry_point = elf_file.ehdr.e_entry as u32;

Expand Down Expand Up @@ -144,3 +170,28 @@ impl ImageGenratorExecutable for ElfExecutable {
self.content.len() as u32
}
}

#[cfg(test)]
mod test {
use crate::load_into_image;

#[test]
fn test_load_into_image() {
let mut image = Vec::new();
load_into_image(&mut image, 0x4000_0000, 0x4000_0006, b"hello world").unwrap();
load_into_image(&mut image, 0x4000_0000, 0x4000_0000, b"abcdef").unwrap();
load_into_image(&mut image, 0x4000_0000, 0x4000_0011, b"hi").unwrap();
assert_eq!(&image, b"abcdefhello worldhi");
}

#[test]
fn test_load_into_image_bad_address() {
let mut image = Vec::new();
assert_eq!(
load_into_image(&mut image, 0x4000_0000, 0x3fff_ffff, b"h")
.unwrap_err()
.to_string(),
"Section address 0x3fffffff is below image base address 0x40000000"
);
}
}

0 comments on commit 8247d5a

Please sign in to comment.