Fix ELF not running when load address not start from zero
This commit is contained in:
parent
09bac3d4b5
commit
a9574ca22e
@ -309,7 +309,12 @@ fn init_auxvec(process_vm: &ProcessVM, exec_elf_file: &ElfFile) -> Result<AuxVec
|
||||
auxvec.set(AuxKey::AT_PHENT, exec_elf_header.e_phentsize as u64)?;
|
||||
auxvec.set(AuxKey::AT_PHNUM, exec_elf_header.e_phnum as u64)?;
|
||||
auxvec.set(AuxKey::AT_PHDR, exec_elf_base + exec_elf_header.e_phoff)?;
|
||||
auxvec.set(AuxKey::AT_ENTRY, exec_elf_base + exec_elf_header.e_entry)?;
|
||||
|
||||
let base_load_address_offset = exec_elf_file.base_load_address_offset();
|
||||
auxvec.set(
|
||||
AuxKey::AT_ENTRY,
|
||||
exec_elf_base + exec_elf_header.e_entry - base_load_address_offset,
|
||||
)?;
|
||||
|
||||
let ldso_elf_base = process_vm.get_elf_ranges()[1].start() as u64;
|
||||
auxvec.set(AuxKey::AT_BASE, ldso_elf_base)?;
|
||||
|
@ -136,6 +136,12 @@ impl<'a> ElfFile<'a> {
|
||||
)?;
|
||||
Ok(elf_hdr)
|
||||
}
|
||||
|
||||
// An offset to be subtracted from ELF vaddr for PIE
|
||||
pub fn base_load_address_offset(&self) -> u64 {
|
||||
let phdr = self.program_headers().nth(0).unwrap();
|
||||
phdr.p_vaddr - phdr.p_offset
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ProgramHeaderExt<'a> {
|
||||
|
@ -212,14 +212,17 @@ impl<'a, 'b> ProcessVMBuilder<'a, 'b> {
|
||||
fn init_elf_memory(elf_range: &VMRange, elf_file: &ElfFile) -> Result<()> {
|
||||
// Destination buffer: ELF appeared in the process
|
||||
let elf_proc_buf = unsafe { elf_range.as_slice_mut() };
|
||||
let mut empty_offset_vec: Vec<(usize, usize)> = Vec::with_capacity(3); // usally two loadable segments
|
||||
// Source buffer: ELF stored in the ELF file
|
||||
let elf_file_buf = elf_file.as_slice();
|
||||
|
||||
let base_load_address_offset = elf_file.base_load_address_offset() as usize;
|
||||
|
||||
// Offsets to track zerolized range
|
||||
let mut empty_start_offset = 0;
|
||||
let mut empty_end_offset = 0;
|
||||
|
||||
// Source buffer: ELF stored in the ELF file
|
||||
let elf_file_buf = elf_file.as_slice();
|
||||
// Init all loadable segements
|
||||
let loadable_segments = elf_file
|
||||
elf_file
|
||||
.program_headers()
|
||||
.filter(|segment| segment.loadable())
|
||||
.for_each(|segment| {
|
||||
@ -227,27 +230,26 @@ impl<'a, 'b> ProcessVMBuilder<'a, 'b> {
|
||||
let file_offset = segment.p_offset as usize;
|
||||
let mem_addr = segment.p_vaddr as usize;
|
||||
let mem_size = segment.p_memsz as usize;
|
||||
let alignment = segment.p_align as usize;
|
||||
debug_assert!(file_size <= mem_size);
|
||||
|
||||
// The first file_size bytes are loaded from the ELF file,
|
||||
// the remaining (mem_size - file_size) bytes are zeros.
|
||||
let mem_start_offset = mem_addr - base_load_address_offset;
|
||||
|
||||
// Initialize empty part to zero based on alignment
|
||||
empty_start_offset = align_down(mem_start_offset, alignment);
|
||||
for b in &mut elf_proc_buf[empty_start_offset..mem_start_offset] {
|
||||
*b = 0;
|
||||
}
|
||||
|
||||
// Bytes of file_size length are loaded from the ELF file
|
||||
elf_file.file_inode().read_at(
|
||||
file_offset,
|
||||
&mut elf_proc_buf[mem_addr..mem_addr + file_size],
|
||||
&mut elf_proc_buf[mem_start_offset..mem_start_offset + file_size],
|
||||
);
|
||||
|
||||
empty_end_offset = mem_addr;
|
||||
empty_offset_vec.push((empty_start_offset, empty_end_offset));
|
||||
empty_start_offset = empty_end_offset + file_size;
|
||||
});
|
||||
|
||||
empty_offset_vec.push((empty_start_offset, elf_proc_buf.len()));
|
||||
|
||||
// Set zero for the remain part of the buffer
|
||||
empty_offset_vec
|
||||
.iter()
|
||||
.for_each(|(start_offset, end_offset)| {
|
||||
for b in &mut elf_proc_buf[*start_offset..*end_offset] {
|
||||
// Set the remaining part to zero based on alignment
|
||||
empty_end_offset = align_up(mem_start_offset + file_size, alignment);
|
||||
for b in &mut elf_proc_buf[mem_start_offset + file_size..empty_end_offset] {
|
||||
*b = 0;
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user