QEMU用户态模拟器为何被加载到高内存地址?
QEMU用户态模拟器为何被加载到高内存地址?
我从qemu-8.0.5源码编译了qemu-x86_64用户态模拟器,用gdb调试时发现它被加载到高内存地址0x555555554000,低内存地址被预留给guest程序。我知道可以通过链接脚本指定ELF加载基址,但在源码树里没找到相关链接脚本,也没搜到0x555555.*这类地址字符串,想知道QEMU是怎么做到自身加载到高地址的?
以下是gdb中的命令及输出:
~/qemu-8.0.5/build$ gdb ./qemu-x86_64 /* 无关内容省略 */ (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]
核心原因说明
- 这个高地址
0x555555554000是Linux系统默认的PIE(位置无关可执行文件)加载基址,并非QEMU源码手动指定。 - QEMU编译时默认开启PIE特性,编译链接阶段会添加
-fpie -pie参数,这类可执行文件会被动态加载器ld-linux分配到高地址区间,同时实现地址空间布局随机化(ASLR)提升安全性。 - 预留低地址给guest程序是x86用户态模拟器的刚需:原生x86程序通常默认加载在低地址(如
0x400000),QEMU需要完整模拟guest的地址空间,自身必须避开低地址范围,而PIE的加载特性恰好满足这个需求,无需手动编写链接脚本指定基址。 - 验证方式:进入QEMU的build目录执行
cat config.log | grep -E "(pie|PIE)",可看到-fpie/-pie相关编译参数;若编译时添加--disable-pie配置选项关闭PIE,QEMU会被加载到低地址,进而与guest程序的地址空间冲突。
内容的提问来源于stack exchange,提问作者Teng Wu
相关产品推荐
相关产品推荐

