On 10/10/2026 1:50 AM, Richard Henderson wrote: > On 10/2/26 12:52, Rick Richard wrote: >> A non-PIE qemu is loaded below 4 GiB. That includes every static >> build on FreeBSD and Linux builds configured with --disable-pie. >> With the identity map (guest_base 0), a non-PIE guest program can >> be mapped over qemu. >> >> Only use the identity map when qemu is loaded at 4 GiB or higher. >> Non-PIE programs are normally linked below 4 GiB, and PIE programs >> are loaded at or above it (ppc64 Linux loads them at exactly 4 GiB). >> >> Signed-off-by: Rick Richard <[email protected]> >> --- >> On FreeBSD a static qemu can't be PIE, so bsd-user is always loaded >> at 0x200000. pgb_dynamic() picks guest_base 0 because the initial >> image doesn't overlap qemu, but rtld later maps a non-PIE executable >> at its link address on top of qemu's own text. >> >> This isn't BSD specific, I was able to reproduce on Linux as well by >> disabling PIE. >> >> I tested the fix on Linux with static-pie and --disable-pie builds, >> and on FreeBSD with aarch64, riscv64 and x86_64 guests. When qemu is >> loaded high it still uses the identity map. When it's loaded low it >> picks a non-zero guest_base and the guest runs normally. >> >> I couldn't find an existing way in qemu to get its own load address, >> so I used __executable_start, which both GNU ld and lld provide. If >> there's a better way I'm happy to change it. > > There should be no need for this at all. The probe sequence should notice > conflicting addresses and adjust. > > What's your failure case? > > > r~
You're right about that, but there's a less obvious case that falls through the cracks: programs loaded through ld.so. qemu only loads ld.so, so that's all the probe sees, and it picks guest_base 0. Then ld.so maps the real program at its fixed address, right on top of qemu. An easy way to hit it is ldd on FreeBSD. In an aarch64 jail with the stock perl package: # ldd /usr/local/bin/perl /usr/local/bin/perl: ld-elf.so.1: /usr/local/bin/perl: mmap of entire address space failed: Cannot allocate memory Same for most other programs in FreeBSD packages. FreeBSD can't link static PIE, so qemu-*-static is always linked at 0x200000. Ports aren't built PIE unless WITH_PIE is set, and non-PIE programs on FreeBSD are linked at 0x200000 by default, the same address as qemu. FreeBSD's ldd runs a program as "ld-elf.so.1 -- prog", so ld.so is all qemu ever loads. The ports QA check runs ldd on every staged binary, and gobject-introspection runs it during its build, which is where I first ran into this. Linux distros ship static-pie, so it mostly hits FreeBSD, but a static --disable-pie build fails the same way on Linux too.
