Ubuntu20.04 gcc交叉编译 & qemu虚拟机安装arm64架构系统
1. 在 Ubuntu 上安装能够运行 aarch64 (64-bit ARM ISA)应用的 Qemu 虚拟机(qemu-aarch64)
1. 安装qemu-system-aarch64
sudo apt intall qemu-system-aarch64
验证是否安装成功:
2. UEFI固件下载
wget http://releases.linaro.org/components/kernel/uefi-linaro/16.02/release/qemu64/QEMU_EFI.fd
3. aarch64架构操作系统下载
这里采用的是arm64架构的ubuntu16.04
http://cdimage.ubuntu.com/releases/16.04/release/ubuntu-16.04.4-server-arm64.iso
4. 创建虚拟硬盘
qemu-img create ubuntu16.04-arm64.img 16G
此时文件夹目录中文件情况如下,可以开始虚拟机安装
5. 虚拟机安装
执行如下命令
qemu-system-aarch64 -m 2048 -cpu cortex-a57 -smp 2 -M virt -bios QEMU_EFI.fd -nographic -drive if=none,file=ubuntu-16.04.4-server-arm64.iso,id=cdrom,media=cdrom -device virtio-scsi-device -device scsi-cd,drive=cdrom -drive if=none,file=ubuntu16.04-arm64.img,id=hd0 -device virtio-blk-device,drive=hd0
部分安装截图
6. 虚拟机启动
qemu-system-aarch64 \
-m 2048 \
-cpu cortex-a57 \
-smp 2 \
-M virt \
-bios QEMU_EFI.fd \
-nographic \
-drive if=none,file=ubuntu16.04-arm64.img,id=hd0 -device virtio-blk-device,drive=hd0 \
-netdev type=tap,id=net0 -device virtio-net-device,netdev=net0
该报错是由于UEFI固件没有找到ESP分区导致的,需要手动选择EFI文件启动系统。
输入exit进入UEFI管理界面后,选择Boot Maintenance Manager-> Boot From File -> 选择grubaa64.efi
虚拟机启动成功
2. 安装 aarch64 的 GCC 工具链(gcc-10-arm-linux-gnueabi)
安装步骤:
sudo apt install gcc
sudo apt install gcc-10-arm-linux-gnueabi
sudo apt install gcc-10-aarch64-linux-gnu
sudo apt install gcc-aarch64-linux-gnu
3. 用 aarch64 的 GCC 工具链交叉编译 loop.c (-O2),生成 可执行文件 loop.aarch64.gcc,并用 qemu-aarch64 运行 loop.aarch64.gcc
aarch64-linux-gnu-gcc -O2 ./loop.c -o ./loop.aarch64.gcc
通过FTP服务器实现qemu虚拟机与主机共享文件
1. 主机安装ftp服务器
sudo apt-get install vsftpd
2. 主机启动服务器
sudo service vsftpd restart
3. 虚拟机安装lftp服务器
sudo apt-get install lftp
4. 虚拟机登录主机ftp服务器
lftp
lftp 192.168.124.129 -u lyf
登陆成功,输入ls列出目录
5. 下载远端文件
mget loop.aarch64.gcc
quit退出ftp服务器
6. 在qemu-aarch64下运行loop.aarch64.gcc
chmod +x ./loop.aarch64.gcc
./loop.aarch64.gcc 10
4. 用 clang 交叉编译 loop.c(-O2),生成可执行文件 loop.aarch64.clang ,并用 qemu-aarch64 运 行 loop.aarch64.clang
sudo apt install gcc-multilib
clang -target -arm64 loop.c -o loop.aarch64.clang
发生报错,是由于编译工具链不一致导致的,但花了很长时间也没有成功解决
替代方法是直接在qemu虚拟器中使用clang对loop.c进行编译,得到编译后可运行的程序并进行测试
clang ./loop.c -o ./loop.aarch64.clang -O2
5. 用 qemu-aarch64 分 别 运 行 前 面 编 译 出 来 的 loop.aarch64.gcc 和 loop.aarch64.clang(分别用参数 5、10、20、40、80 进行测试),记下每次测试的执行时间并以图形方式呈现。
6. 用 host 机器上的 gcc 和 clang 分别编译(-O2)出 loop.x64.gcc 和 loop.x64.clang,并对这两个执行文件 分别用参数 5、10、20、40、80 进行测试,记下每次测试 的执行时间并以图形方式呈现,进而与前一步 qemu 仿真 测试的结果进行比较。
gcc loop.c -o loop.x64.gcc -O2
clang loop.c -o loop.x64.clang -O2
host机器上运行速度明显快于qemu仿真机器上的结果,但考虑到qemu虚拟机性能下降的问题,无法直接对x86和aarch64两种架构的运行速度作判断
7. 安装支持多 ISA 的 gdb 调试器(gdb-multiarch)
sudo apt install gdb-multiarch
8. 用 gdb-multiarch 结 合 qemu-aarch64 对 loop.aarch64.gcc.debug 进行源码级调试
aarch64-linux-gnu-gcc -g loop.c -o loop.aarch64.gcc.debug
为了进行调试,需要在虚拟机上启动gdbserver服务器,并在主机上远程连接gdbserver。
因此需要先配置主机与虚拟机网络桥接,使得主机与虚拟机网络上连通。
1. 主机网络配置
安装软件包
apt-get install bridge-utils # 虚拟网桥工具
apt-get install uml-utilities # UML(User-mode linux)工具
使用brctl配置网桥
tunctl -t tap0 -u root # 创建一个tap0接口,只允许指定用户访问
brctl addif br0 tap0 # 在虚拟网桥中增加一个tap0接口
ifconfig tap0 0.0.0.0 promisc up # 打开tap0接口
brctl addif br0 ens33 # 在网桥中增加ens33接口
ifconfig br0 192.168.124.111 # 设置br0接口ip
查看当前网络接口情况 ifconfig -a
查看br0网桥情况 brctl showstp br0
修改/etc/qemu-ifup 和 /etc/qemu-ifdown
qemu-ifup
#! /bin/sh
switch=br0
ifconfig $1 up
#ip link set $1 up
brctl addif ${switch} $1
qemu-ifdown
#! /bin/sh
switch=br0
brctl delif ${switch} $1
ifconfig $1 down
#ip link set $1 down
#tunctl -d $1
赋予执行权限
chmod +x /etc/qemu-ifup
chmod +x /etc/qemu-ifdown
2. 虚拟机启动参数设置
加上以下参数
-netdev type=tap,id=net0 -device virtio-net-device,netdev=net0
启动后虚拟机启用网络
/sbin/dhclient
查看网络情况
主机ping虚拟机
虚拟机ping主机
主机与虚拟机网络已连通
(这两步实在太难了)
3. 虚拟机启动gdbserver
qemu虚拟机安装gdbserver
sudo apt install gdbserver
启动gdbserver,指定主机ip,端口,调试程序
gdbserver 192.168.124.111:1234 loop.aarch64.gcc.debug 5
4. 主机通过gdb-multiarch连接虚拟机服务器进行调试
gdb-multiarch
(gdb) target remote 192.168.124.130:1234
连接成功后开始调试,用法同本地gdb
部分调试结果如图: