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_PHENT, exec_elf_header.e_phentsize as u64)?;
|
||||||
auxvec.set(AuxKey::AT_PHNUM, exec_elf_header.e_phnum 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_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;
|
let ldso_elf_base = process_vm.get_elf_ranges()[1].start() as u64;
|
||||||
auxvec.set(AuxKey::AT_BASE, ldso_elf_base)?;
|
auxvec.set(AuxKey::AT_BASE, ldso_elf_base)?;
|
||||||
|
@ -136,6 +136,12 @@ impl<'a> ElfFile<'a> {
|
|||||||
)?;
|
)?;
|
||||||
Ok(elf_hdr)
|
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> {
|
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<()> {
|
fn init_elf_memory(elf_range: &VMRange, elf_file: &ElfFile) -> Result<()> {
|
||||||
// Destination buffer: ELF appeared in the process
|
// Destination buffer: ELF appeared in the process
|
||||||
let elf_proc_buf = unsafe { elf_range.as_slice_mut() };
|
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_start_offset = 0;
|
||||||
let mut empty_end_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
|
// Init all loadable segements
|
||||||
let loadable_segments = elf_file
|
elf_file
|
||||||
.program_headers()
|
.program_headers()
|
||||||
.filter(|segment| segment.loadable())
|
.filter(|segment| segment.loadable())
|
||||||
.for_each(|segment| {
|
.for_each(|segment| {
|
||||||
@ -227,27 +230,26 @@ impl<'a, 'b> ProcessVMBuilder<'a, 'b> {
|
|||||||
let file_offset = segment.p_offset as usize;
|
let file_offset = segment.p_offset as usize;
|
||||||
let mem_addr = segment.p_vaddr as usize;
|
let mem_addr = segment.p_vaddr as usize;
|
||||||
let mem_size = segment.p_memsz as usize;
|
let mem_size = segment.p_memsz as usize;
|
||||||
|
let alignment = segment.p_align as usize;
|
||||||
debug_assert!(file_size <= mem_size);
|
debug_assert!(file_size <= mem_size);
|
||||||
|
|
||||||
// The first file_size bytes are loaded from the ELF file,
|
let mem_start_offset = mem_addr - base_load_address_offset;
|
||||||
// the remaining (mem_size - file_size) bytes are zeros.
|
|
||||||
|
// 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(
|
elf_file.file_inode().read_at(
|
||||||
file_offset,
|
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;
|
// Set the remaining part to zero based on alignment
|
||||||
empty_offset_vec.push((empty_start_offset, empty_end_offset));
|
empty_end_offset = align_up(mem_start_offset + file_size, alignment);
|
||||||
empty_start_offset = empty_end_offset + file_size;
|
for b in &mut elf_proc_buf[mem_start_offset + file_size..empty_end_offset] {
|
||||||
});
|
|
||||||
|
|
||||||
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] {
|
|
||||||
*b = 0;
|
*b = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user