bsd-user: Use probe_guest_base

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 <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2026-05-30 00:36:09 -07:00
parent 9affb4decd
commit 58d6d6f035
2 changed files with 23 additions and 53 deletions

View File

@@ -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;

View File

@@ -541,41 +541,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,