1. 前言
qemu
中有很多的特技,此處記錄下qemu-arm
的使用方式,簡單來說qemu-system-xx
用于虛擬整個設備,包括操作系統的運行環境,而qemu-xx
僅虛擬Linux
應用程序的環境,不涉及操作系統,應用程序的系統調用有宿主系統提供。
2. 安裝
2.1 qemu-user
此處直接通過apt進行qemu-user
的安裝,該操作會一次性安裝許多平臺的仿真器。
# 大概需要65MB空間
$ sudo apt install qemu-user
0 upgraded, 2 newly installed, 0 to remove and 37 not upgraded.
Need to get 9621 kB of archives.
After this operation, 65.4 MB of additional disk space will be used.
2.2 arm-linux工具鏈
- arm的工具鏈可以通過apt命令安裝。
# 大概需要140MB空間
$ sudo apt install gcc-arm-linux-gnueabi
0 upgraded, 18 newly installed, 1 to remove and 47 not upgraded.
Need to get 43.1 MB of archives.
After this operation, 140 MB of additional disk space will be used.
- 也可以去arm developer網上下載,我下載的是arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz,大概123MB。
3. 測試程序
- 編寫一個測試程序
main.c
。
#include <stdio.h>int main(int argc, char *argv[])
{printf("hello word!!!\n");#ifdef __x86_64__printf(">>>>>> I'm x86_64 arch <<<<<<\n");#elif defined(__ARMEL__)printf(">>>>>> I'm arm arch <<<<<<\n");#endifreturn 0;
}
- 編寫一個
Makefile
# 此處定義了arm-linux工具鏈中包含的arm的動態庫,Makefile中$有特俗作用,傳遞給shell處理時需要使用$$表示$
ARM_LIBC = $(shell echo $$(dirname $$(which arm-none-linux-gnueabihf-gcc))/../arm-none-linux-gnueabihf/libc)all:# 使用主機的gcc編譯并運行gcc main.c -g -o hello_x86_64./hello_x86_64# 使用arm-linux工具鏈編譯,并設置靜態鏈接arm-none-linux-gnueabihf-gcc main.c -g -static -o hello_arm_static# 對于靜態鏈接的程序,可以使用qemu-arm直接運行qemu-arm hello_arm_static# 使用arm-linux工具鏈編譯,缺省為動態鏈接arm-none-linux-gnueabihf-gcc main.c -g -o hello_arm_dyn# 動態鏈接的程序需要使用-L參數指定hello_arm_dyn的動態庫搜索路徑qemu-arm -L $(ARM_LIBC) hello_arm_dyn# hello_arm_dyn的動態庫搜索路徑也可以使用環境變量QEMU_LD_PREFIX來設置QEMU_LD_PREFIX=$(ARM_LIBC) qemu-arm hello_arm_dyn
- 執行
make
,觀察輸出。
# 執行make命令,以下內容為makefile和可執行程序所打印,可以看到arm的程序正常運行了
$ make
gcc main.c -o hello_x86_64
./hello_x86_64
hello word!!!
>>>>>> I'm x86_64 arch <<<<<<
arm-none-linux-gnueabihf-gcc main.c -o hello_arm_static -static
qemu-arm hello_arm_static
hello word!!!
>>>>>> I'm arm arch <<<<<<
arm-none-linux-gnueabihf-gcc main.c -o hello_arm_dyn
qemu-arm -L /home/xflm/tools/exe/arm-none-linux-gnueabihf/bin/../arm-none-linux-gnueabihf/libc hello_arm_dyn
hello word!!!
>>>>>> I'm arm arch <<<<<<
QEMU_LD_PREFIX=/home/xflm/tools/exe/arm-none-linux-gnueabihf/bin/../arm-none-linux-gnueabihf/libc qemu-arm hello_arm_dyn
hello word!!!
>>>>>> I'm arm arch <<<<<<
4. binfmt_misc
- Linux有一種
binfmt_misc
機制,簡單說就是我們執行程序時,系統會根據該機制的配置信息選擇使用不同的加載器,wsl種默認就有注冊了一個解釋器WSLInterop
,內容如下。
# binfmt_misc機制以文件系統的方式存在
$ mount | grep bin
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
# 查看WSLInterop解釋器配置
$ sudo cat /proc/sys/fs/binfmt_misc/WSLInterop
enabled
# interpreter -- 啟動文件的程序,需要是絕對路徑,長度不能超過127
interpreter /init
# flags -- 可選字段,控制interpreter打開文件的行為。
# P -- 表示preserve-argv[0]保留原始的argv[0]參數。
# F -- 表示fix binary,binfmt-misc默認的行為在spwan進程時會延遲,這種方式可能會受到mount namespace和chroot的影響,設置F時會立刻打開二進制文件。
# O -- 表示open-binary,binfmt-misc默認會傳遞文件的路徑,而啟用這個參數時,binfmt-misc會打開文件,傳遞文件描述符。
# C -- 表示credentials,即會傳遞文件的setuid等權限,這個選項也隱含了O 。
flags: PF
# 文件的偏移
offset 0
# 文件的魔幻數
magic 4d5a
# 查看window上的ping.exe文件的開頭,-g表示每列1個字節,-l表示顯示4個字節,-R表示不要顯示顏色
$ xxd -g 1 -l 4 -R never $(which ping.exe)
00000000: 4d 5a 90 00 MZ..
# 查看一下wsl中編譯的hello_x86_64
xxd -g 1 -l 4 -R never hello_x86_64
00000000: 7f 45 4c 46 .ELF
- 根據這邊文章的描述Support for miscellaneous binary formats (binfmt_misc) with Ubuntu on WSL,wsl中貌似暫時不支持該特性,所以執行
sudo apt install qemu-user-binfmt
sudo modprobe binfmt_misc
sudo systemctl restart systemd-binfmt
均不生效。
5. 調試
qemu-arm還支持gdb調試。
# 啟動qemu-arm并等待gdb連接,gdbserver的端口為tcp 1234
$ qemu-arm -g 1234 hello_arm_static
# 此時qemu-arm不會直接運行程序,而是等待gdb連接
# 另外開一個窗口運行arm-none-linux-gnueabihf-gdb
$ arm-none-linux-gnueabihf-gdb
# 連接到qemu-arm開始調試
(gdb) target remote localhost:1234
# 在main()函數入口設置斷點
(gdb) b main
# 全速運行,程序運行到main()函數時會停下來
(gdb) c
上一篇:qemu(2) – 定制開發板
下一篇:qemu(4) – qemu-system-arm使用
目錄:全部文章合集
參考
QEMU的基本使用方法(MIPS)
基于QEMU和binfmt-misc透明運行不同架構程序