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

验证是否安装成功:

image-20211024125220787

image-20211024125603045

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

此时文件夹目录中文件情况如下,可以开始虚拟机安装

image-20211026111652388

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

部分安装截图

image-20211025101934578

image-20211025102025902

image-20211025102434654

image-20211025104615750

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

image-20211026112038204

该报错是由于UEFI固件没有找到ESP分区导致的,需要手动选择EFI文件启动系统。

输入exit进入UEFI管理界面后,选择Boot Maintenance Manager-> Boot From File -> 选择grubaa64.efi

image-20211026112209387

虚拟机启动成功

image-20211026112308364

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

image-20211026150059460

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 -u

lftp 192.168.124.129 -u lyf

登陆成功,输入ls列出目录

image-20211026112827250

image-20211026112854762

5. 下载远端文件

mget loop.aarch64.gcc

quit退出ftp服务器

6. 在qemu-aarch64下运行loop.aarch64.gcc

chmod +x ./loop.aarch64.gcc
./loop.aarch64.gcc 10

image-20211026113108142

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

image-20211026140737762

发生报错,是由于编译工具链不一致导致的,但花了很长时间也没有成功解决

替代方法是直接在qemu虚拟器中使用clang对loop.c进行编译,得到编译后可运行的程序并进行测试

clang ./loop.c -o ./loop.aarch64.clang -O2

image-20211026141941865

5. 用 qemu-aarch64 分 别 运 行 前 面 编 译 出 来 的 loop.aarch64.gcc 和 loop.aarch64.clang(分别用参数 5、10、20、40、80 进行测试),记下每次测试的执行时间并以图形方式呈现。

image-20211026141236134

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

image-20211026141601857

host机器上运行速度明显快于qemu仿真机器上的结果,但考虑到qemu虚拟机性能下降的问题,无法直接对x86和aarch64两种架构的运行速度作判断

7. 安装支持多 ISA 的 gdb 调试器(gdb-multiarch)

sudo apt install gdb-multiarch

image-20211026150252081

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

image-20211026190456687

查看br0网桥情况 brctl showstp br0

image-20211026190535812

修改/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

查看网络情况

image-20211026190747128

主机ping虚拟机

image-20211026190821223

虚拟机ping主机

image-20211026191552765

主机与虚拟机网络已连通

(这两步实在太难了)

3. 虚拟机启动gdbserver

qemu虚拟机安装gdbserver

sudo apt install gdbserver

启动gdbserver,指定主机ip,端口,调试程序

gdbserver 192.168.124.111:1234 loop.aarch64.gcc.debug 5

image-20211026191021384

4. 主机通过gdb-multiarch连接虚拟机服务器进行调试

gdb-multiarch
(gdb) target remote 192.168.124.130:1234

image-20211026191216575

连接成功后开始调试,用法同本地gdb

image-20211026192040236

部分调试结果如图:

image-20211026193556992

image-20211026193710803