Search code examples
linkerqemu

How does QEMU make itself loaded to a high address?


I built a qemu-x86_64 user-level emulator from qemu-8.0.5 source code. When I debug it using gdb, I found the qemu-x86_64 is loaded to a high address(0x555555554000) in memory. The lower memory address is reserved for guest program.

As far as i know, we can specify the base load address of an elf in linker script. I have searched the source code tree, and nor words about linker script neither the address string "0x555555.*" are found.

So how does QEMU make itself loaded to a high address?

Here are commands and outputs in gdb.

~/qemu-8.0.5/build$ gdb ./qemu-x86_64
/* something not important */
(gdb) starti ./test.elf
Program stopped.
0x00007ffff7dd4090 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) i proc mappings
process 26751
Mapped address spaces:

          Start Addr           End Addr       Size     Offset  Perms  objfile
      0x555555554000     0x55555572f000   0x1db000        0x0  r-xp   /path/to/qemu-8.0.5/build/qemu-x86_64
      0x55555592e000     0x555555970000    0x42000   0x1da000  rw-p   /path/to/qemu-8.0.5/build/qemu-x86_64
      0x555555970000     0x55555597e000     0xe000        0x0  rw-p   [heap]
      0x7ffff7dd3000     0x7ffff7dfc000    0x29000        0x0  r-xp   /lib/x86_64-linux-gnu/ld-2.27.so
      0x7ffff7ff7000     0x7ffff7ffa000     0x3000        0x0  r--p   [vvar]
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0  r-xp   [vdso]
      0x7ffff7ffc000     0x7ffff7ffe000     0x2000    0x29000  rw-p   /lib/x86_64-linux-gnu/ld-2.27.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0  rw-p
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0  rw-p   [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0  --xp   [vsyscall]

Solution

  • So how does QEMU make itself loaded to a high address?

    It doesn't. The address it gets loaded at is the default load address for PIE binaries.

    You will get the exact same result by running a.out built this way:

    echo "int main() { return 0; }" | gcc -xc - -o a.out -fPIE -pie
    

    P.S. If you are on a Ubuntu variant, GCC may be configured to build PIE binaries by default.