Merge the PT_LOAD loop with the PT_INTERP loop, as the XXX comment suggests. Pass the probed range to probe_guest_base.
Signed-off-by: Richard Henderson <[email protected]> --- bsd-user/elfload.c | 37 +++++++++++++++++++------------------ bsd-user/main.c | 39 ++++----------------------------------- 2 files changed, 23 insertions(+), 53 deletions(-) diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index 3bca0cc9ed..a87a892eb8 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -22,6 +22,7 @@ #include "qemu.h" #include "disas/disas.h" #include "qemu/path.h" +#include "user/probe-guest-base.h" static abi_ulong target_auxents; /* Where the AUX entries are in target */ static size_t target_auxents_sz; /* Size of AUX entries including AT_NULL */ @@ -610,8 +611,9 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, abi_ulong elf_brk; int error, retval; char *elf_interpreter; - abi_ulong baddr, elf_entry, et_dyn_addr, interp_load_addr = 0; + abi_ulong elf_entry, et_dyn_addr, interp_load_addr = 0; abi_ulong reloc_func_desc = 0; + PGBRange range = { -1, 0 }; load_addr = 0; elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ @@ -654,10 +656,10 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, elf_brk = 0; - elf_interpreter = NULL; - for (i = 0; i < elf_ex.e_phnum; i++) { - if (elf_ppnt->p_type == PT_INTERP) { + for (i = 0; i < elf_ex.e_phnum; i++, elf_ppnt++) { + switch (elf_ppnt->p_type) { + case PT_INTERP: if (elf_interpreter != NULL) { free(elf_phdata); free(elf_interpreter); @@ -709,8 +711,14 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, close(bprm->fd); return retval; } + break; + + case PT_LOAD: + range.lo = MIN(range.lo, elf_ppnt->p_vaddr); + range.hi = MAX(range.hi, + elf_ppnt->p_vaddr + elf_ppnt->p_memsz - 1); + break; } - elf_ppnt++; } /* Some simple consistency checks for the interpreter */ @@ -740,19 +748,12 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, info->end_code = 0; elf_entry = (abi_ulong) elf_ex.e_entry; - /* XXX Join this with PT_INTERP search? */ - baddr = 0; - for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { - if (elf_ppnt->p_type != PT_LOAD) { - continue; - } - baddr = elf_ppnt->p_vaddr; - break; - } - et_dyn_addr = 0; - if (elf_ex.e_type == ET_DYN && baddr == 0) { - et_dyn_addr = ELF_ET_DYN_LOAD_ADDR; + if (elf_ex.e_type == ET_DYN) { + probe_guest_base(bprm->filename, NULL, NULL); + et_dyn_addr = ELF_ET_DYN_LOAD_ADDR - range.lo; + } else { + probe_guest_base(bprm->filename, &range, NULL); } /* @@ -766,7 +767,7 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, info->elf_flags = elf_ex.e_flags; error = load_elf_sections(&elf_ex, elf_phdata, bprm->fd, et_dyn_addr, - &load_addr); + &load_addr); for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { if (elf_ppnt->p_type != PT_LOAD) { continue; diff --git a/bsd-user/main.c b/bsd-user/main.c index 73aae8c327..772a26199b 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -540,41 +540,10 @@ int main(int argc, char **argv) } } - /* - * If reserving host virtual address space, do so now. - * Combined with '-B', ensure that the chosen range is free. - */ - if (reserved_va) { - void *p; - - if (have_guest_base) { - p = mmap((void *)guest_base, reserved_va + 1, PROT_NONE, - MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_EXCL, -1, 0); - } else { - p = mmap(NULL, reserved_va + 1, PROT_NONE, - MAP_ANON | MAP_PRIVATE, -1, 0); - } - if (p == MAP_FAILED) { - const char *err = strerror(errno); - char *sz = size_to_str(reserved_va + 1); - - if (have_guest_base) { - error_report("Cannot allocate %s bytes at -B %p for guest " - "address space: %s", sz, (void *)guest_base, err); - } else { - error_report("Cannot allocate %s bytes for guest " - "address space: %s", sz, err); - } - exit(1); - } - guest_base = (uintptr_t)p; - have_guest_base = true; - - /* Ensure that mmap_next_start is within range. */ - if (reserved_va <= mmap_next_start) { - mmap_next_start = (reserved_va / 4 * 3) - & TARGET_PAGE_MASK & qemu_host_page_mask; - } + /* Ensure that mmap_next_start is within range. */ + if (reserved_va && reserved_va <= mmap_next_start) { + mmap_next_start = ((reserved_va / 4 * 3) + & TARGET_PAGE_MASK & qemu_host_page_mask); } if (loader_exec(filename, argv + optind, target_environ, regs, info, -- 2.43.0
