On Sat, May 30, 2026 at 3:12 PM Richard Henderson < [email protected]> wrote:
> Pass a PGBRange structure instead of separate guest_loaddr > and guest_hiaddr parameters. This allows NULL to indicate > that the image is relocatable, so that image_range->lo == 0 > is a valid fixed setting. > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/1890 > Signed-off-by: Richard Henderson <[email protected]> > --- > linux-user/user-internals.h | 13 ++++------- > linux-user/elfload.c | 46 +++++++++++++++++-------------------- > linux-user/flatload.c | 2 +- > 3 files changed, 27 insertions(+), 34 deletions(-) > Reviewed-by: Warner Losh <[email protected]> I may have to look into a similar cleanup in bsd-user once the upstreaming backlog is done. Warner > diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h > index 73b0109e9c..3f41d3f33c 100644 > --- a/linux-user/user-internals.h > +++ b/linux-user/user-internals.h > @@ -83,24 +83,21 @@ typedef struct PGBRange { > /** > * probe_guest_base: > * @image_name: the executable being loaded > - * @loaddr: the lowest fixed address within the executable > - * @hiaddr: the highest fixed address within the executable > + * @image_range: the fixed addresses within the executable > * > * Creates the initial guest address space in the host memory space. > * > - * If @loaddr == 0, then no address in the executable is fixed, i.e. > - * it is fully relocatable. In that case @hiaddr is the size of the > - * executable minus one. > + * If @image_range is NULL, then no address in the executable is fixed, > + * i.e. it is fully relocatable. > * > * This function will not return if a valid value for guest_base > * cannot be chosen. On return, the executable loader can expect > * > - * target_mmap(loaddr, hiaddr - loaddr + 1, ...) > + * target_mmap(i->lo, i->hi - i->lo + 1, ...) > * > * to succeed. > */ > -void probe_guest_base(const char *image_name, > - abi_ulong loaddr, abi_ulong hiaddr); > +void probe_guest_base(const char *image_name, const PGBRange > *image_range); > > /* syscall.c */ > int host_to_target_waitstatus(int status); > diff --git a/linux-user/elfload.c b/linux-user/elfload.c > index 33565ad7be..10a826e658 100644 > --- a/linux-user/elfload.c > +++ b/linux-user/elfload.c > @@ -847,14 +847,13 @@ static bool pgb_try_mmap_set(const PGBAddrs *ga, > uintptr_t base, uintptr_t brk) > /** > * pgb_addr_set: > * @ga: output set of guest addrs > - * @guest_loaddr: guest image low address > - * @guest_loaddr: guest image high address > + * @image_range: fixed guest image addresses > * @identity: create for identity mapping > * > * Fill in @ga with the image, COMMPAGE and NULL page. > */ > -static bool pgb_addr_set(PGBAddrs *ga, abi_ulong guest_loaddr, > - abi_ulong guest_hiaddr, bool try_identity) > +static bool pgb_addr_set(PGBAddrs *ga, const PGBRange *image_range, > + bool try_identity) > { > int n; > > @@ -866,7 +865,7 @@ static bool pgb_addr_set(PGBAddrs *ga, abi_ulong > guest_loaddr, > if (LO_COMMPAGE != -1 && LO_COMMPAGE < mmap_min_addr) { > return false; > } > - if (guest_loaddr != 0 && guest_loaddr < mmap_min_addr) { > + if (image_range && image_range->lo < mmap_min_addr) { > return false; > } > } > @@ -892,10 +891,8 @@ static bool pgb_addr_set(PGBAddrs *ga, abi_ulong > guest_loaddr, > } > > /* Add the guest image for ET_EXEC. */ > - if (guest_loaddr) { > - ga->bounds[n].lo = guest_loaddr; > - ga->bounds[n].hi = guest_hiaddr; > - n++; > + if (image_range) { > + ga->bounds[n++] = *image_range; > } > } > > @@ -928,8 +925,8 @@ static void pgb_fail_in_use(const char *image_name) > exit(EXIT_FAILURE); > } > > -static void pgb_fixed(const char *image_name, uintptr_t guest_loaddr, > - uintptr_t guest_hiaddr, uintptr_t align) > +static void pgb_fixed(const char *image_name, const PGBRange *image_range, > + uintptr_t align) > { > PGBAddrs ga; > uintptr_t brk = (uintptr_t)sbrk(0); > @@ -941,7 +938,7 @@ static void pgb_fixed(const char *image_name, > uintptr_t guest_loaddr, > exit(EXIT_FAILURE); > } > > - if (!pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, !guest_base) > + if (!pgb_addr_set(&ga, image_range, !guest_base) > || !pgb_try_mmap_set(&ga, guest_base, brk)) { > pgb_fail_in_use(image_name); > } > @@ -1026,15 +1023,15 @@ static uintptr_t pgb_find_itree(const PGBAddrs > *ga, IntervalTreeRoot *root, > return pgb_try_mmap_set(ga, base, brk) ? base : -1; > } > > -static void pgb_dynamic(const char *image_name, uintptr_t guest_loaddr, > - uintptr_t guest_hiaddr, uintptr_t align) > +static void pgb_dynamic(const char *image_name, const PGBRange > *image_range, > + uintptr_t align) > { > IntervalTreeRoot *root; > uintptr_t brk, ret; > PGBAddrs ga; > > /* Try the identity map first. */ > - if (pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, true)) { > + if (pgb_addr_set(&ga, image_range, true)) { > brk = (uintptr_t)sbrk(0); > if (pgb_try_mmap_set(&ga, 0, brk)) { > guest_base = 0; > @@ -1046,7 +1043,7 @@ static void pgb_dynamic(const char *image_name, > uintptr_t guest_loaddr, > * Rebuild the address set for non-identity map. > * This differs in the mapping of the guest NULL page. > */ > - pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, false); > + pgb_addr_set(&ga, image_range, false); > > root = read_self_maps(); > > @@ -1085,24 +1082,23 @@ static void pgb_dynamic(const char *image_name, > uintptr_t guest_loaddr, > guest_base = ret; > } > > -void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, > - abi_ulong guest_hiaddr) > +void probe_guest_base(const char *image_name, const PGBRange *image_range) > { > /* In order to use host shmat, we must be able to honor SHMLBA. */ > uintptr_t align = MAX(SHMLBA, TARGET_PAGE_SIZE); > > /* Sanity check the guest binary. */ > - if (reserved_va && guest_hiaddr > reserved_va) { > + if (reserved_va && image_range && image_range->hi > reserved_va) { > error_report("%s: requires more than reserved virtual " > - "address space (0x%" PRIx64 " > 0x%lx)", > - image_name, (uint64_t)guest_hiaddr, reserved_va); > + "address space (0x%" VADDR_PRIx " > 0x%lx)", > + image_name, image_range->hi, reserved_va); > exit(EXIT_FAILURE); > } > > if (have_guest_base) { > - pgb_fixed(image_name, guest_loaddr, guest_hiaddr, align); > + pgb_fixed(image_name, image_range, align); > } else { > - pgb_dynamic(image_name, guest_loaddr, guest_hiaddr, align); > + pgb_dynamic(image_name, image_range, align); > } > > /* Reserve and initialize the commpage. */ > @@ -1362,10 +1358,10 @@ static void load_elf_image(const char *image_name, > const ImageSource *src, > * Make sure that the low address does not conflict with > * MMAP_MIN_ADDR or the QEMU application itself. > */ > - probe_guest_base(image_name, range.lo, range.hi); > + probe_guest_base(image_name, &range); > } else { > /* The binary is dynamic; we still need to select guest_base. > */ > - probe_guest_base(image_name, 0, 0); > + probe_guest_base(image_name, NULL); > > /* > * Avoid collision with the loader by providing a different > diff --git a/linux-user/flatload.c b/linux-user/flatload.c > index 8abdd2aef2..45d69040c6 100644 > --- a/linux-user/flatload.c > +++ b/linux-user/flatload.c > @@ -261,7 +261,7 @@ static int load_flat_file(struct linux_binprm * bprm, > /* > * Allocate the address space. > */ > - probe_guest_base(bprm->filename, 0, 0); > + probe_guest_base(bprm->filename, NULL); > > /* > * there are a couple of cases here, the separate code/data > -- > 2.43.0 > >
