Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions docs/elfio_files/bad_align_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ int main( void )
// Create a loadable segment
segment* text_seg = writer.segments.add();
text_seg->set_type( PT_LOAD );
text_seg->set_virtual_address( 0x400 );
text_seg->set_physical_address( 0x400 );
text_seg->set_virtual_address( 0x200000 );
text_seg->set_physical_address( 0x200000 );
text_seg->set_flags( PF_X | PF_R );
text_seg->set_align( 0x100 );
text_seg->set_align( 0x200000 );

// Add code section into program segment
text_seg->add_section_index( text_sec->get_index(),
Expand All @@ -80,10 +80,10 @@ int main( void )
// Create a read/write segment
segment* data_seg = writer.segments.add();
data_seg->set_type( PT_NOTE );
data_seg->set_virtual_address( 0x8888048020 );
data_seg->set_physical_address( 0x8888048020 );
data_seg->set_virtual_address( 0x8888400000 );
data_seg->set_physical_address( 0x888400000 );
data_seg->set_flags( PF_W | PF_R );
data_seg->set_align( 13 );
data_seg->set_align( 0x200000 );

// Add code section into program segment
data_seg->add_section_index( data_sec->get_index(),
Expand All @@ -103,7 +103,7 @@ int main( void )
// In this example, the code starts at the first address of the
// 'text_seg' segment. Therefore, the start address is set
// to be equal to the segment location
writer.set_entry( 0x400 );
writer.set_entry( 0x200000 );

// Create ELF file
writer.save( "test_bad_align.bin" );
Expand Down
14 changes: 7 additions & 7 deletions docs/elfio_files/basic_elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ int main( void )
// Create a loadable segment
segment* text_seg = writer.segments.add();
text_seg->set_type( PT_LOAD );
text_seg->set_virtual_address( 0x400 );
text_seg->set_physical_address( 0x0 );
text_seg->set_virtual_address( 0x200000 );
text_seg->set_physical_address( 0x200000 );
text_seg->set_flags( PF_X | PF_R );
text_seg->set_align( 0x1 );
text_seg->set_align( 0x200000 );

// Add code section into program segment
text_seg->add_section_index( text_sec->get_index(),
Expand All @@ -80,10 +80,10 @@ int main( void )
// Create a read/write segment
segment* data_seg = writer.segments.add();
data_seg->set_type( PT_LOAD );
data_seg->set_virtual_address( 0x0420 );
data_seg->set_physical_address( 0x0420 );
data_seg->set_virtual_address( 0x400000 );
data_seg->set_physical_address( 0x400000 );
data_seg->set_flags( PF_W | PF_R );
data_seg->set_align( 0x10 );
data_seg->set_align( 0x200000 );

// Add code section into program segment
data_seg->add_section_index( data_sec->get_index(),
Expand All @@ -103,7 +103,7 @@ int main( void )
// In this example, the code starts at the first address of the
// 'text_seg' segment. Therefore, the start address is set
// to be equal to the segment location
writer.set_entry( 0x400 );
writer.set_entry( 0x200000 );

// Create ELF file
writer.save( "test_elf.bin" );
Expand Down
31 changes: 28 additions & 3 deletions src/loader/elf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ impl Elf {
}
}

// x86-64 kernel must be aligned to 2MB.
const KERNEL_SEGMENT_ALIGN: u64 = 0x200000; // 2 MiB

impl KernelLoader for Elf {
/// Loads a kernel from a vmlinux elf image into guest memory.
///
Expand Down Expand Up @@ -280,6 +283,12 @@ impl KernelLoader for Elf {
None => GuestAddress(phdr.p_paddr),
};

// Ensure that mem_offset is aligned to 2M, otherwise, the kernel may hang during
// booting. Refer to the check in __startup_64() in the Linux kernel source code.
if mem_offset.raw_value() & (KERNEL_SEGMENT_ALIGN - 1) != 0 {
return Err(Error::Align.into());
}

guest_mem
.read_exact_volatile_from(mem_offset, kernel_image, phdr.p_filesz as usize)
.map_err(|_| Error::ReadKernelImage)?;
Expand Down Expand Up @@ -479,10 +488,10 @@ mod tests {
Some(highmem_start_address),
)
.unwrap();
assert_eq!(loader_result.kernel_load.raw_value(), 0x200400);
assert_eq!(loader_result.kernel_load.raw_value(), 0x400000);

loader_result = Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&image), None).unwrap();
assert_eq!(loader_result.kernel_load.raw_value(), 0x200400);
assert_eq!(loader_result.kernel_load.raw_value(), 0x400000);

loader_result = Elf::load(
&gm,
Expand All @@ -491,7 +500,7 @@ mod tests {
Some(highmem_start_address),
)
.unwrap();
assert_eq!(loader_result.kernel_load.raw_value(), 0x400);
assert_eq!(loader_result.kernel_load.raw_value(), 0x200000);

highmem_start_address = GuestAddress(0xa00000);
assert_eq!(
Expand Down Expand Up @@ -632,4 +641,20 @@ mod tests {
.err()
);
}

#[test]
fn test_unaligned_loadaddr() {
let gm = create_guest_mem();
let image = make_elf_bin();
assert_eq!(
Some(KernelLoaderError::Elf(Error::Align)),
Elf::load(
&gm,
Some(GuestAddress(0x1000)),
&mut Cursor::new(&image),
None
)
.err()
);
}
}
Binary file modified src/loader/elf/test_bad_align.bin
Binary file not shown.
Binary file modified src/loader/elf/test_elf.bin
Binary file not shown.