Pre0、前提需求
- 安装
gdb-multiarch
调试器工具。 - 启动虚拟平台,并运行裸机程序。确保你的虚拟平台已经配置为允许远程调试。
- 可参考如下代码:
qemu-system-<arch> -machine <machine> -kernel <kernel_image> -hda <disk_image> -s -S -nographic -cpu <cpu> -m <memory> -gdb tcp::1234
其中,
<arch>
是虚拟平台的架构,例如x86_64
、arm
等;<machine>
是虚拟平台的机器类型,例如pc
、virt
等;<kernel_image>
是裸机程序的二进制文件;<disk_image>
是虚拟硬盘映像文件的路径;-s
和-S
参数用于配置远程调试。
-nographic参数为不用可视化界面显示。这里需要注意的是如果不加这个参数需要gtk支持。
1、开始调试
- 打开一个终端窗口,在命令行中输入
gdb-multiarch
命令来启动gdb-multiarch
调试器。 - 在
gdb-multiarch
提示符下,输入target remote <虚拟平台IP地址>:<端口号>
来连接到虚拟平台。例如,如果虚拟平台的 IP 地址是192.168.0.100
,端口号是1234
,则命令为:target remote 192.168.0.100:1234
。 - 接下来,可以使用
load
命令加载你的裸机程序的可执行文件。例如,load myprogram.elf
。 - 使用
break
命令设置断点或者使用symbol-file
命令加载符号表文件进行源码级调试。 - 输入
continue
命令启动程序执行,或使用其他调试命令如step
,next
,print
等进行调试。 - 调试完成后,可以使用
quit
命令退出gdb-multiarch
。
2、汇编代码转二进制文件相关步骤
- 将附【1】中的汇编代码保存为一个文件,例如
baremetal.s
。 -
- 使用交叉编译器将汇编代码编译为裸机可执行文件。这涉及到使用与目标硬件平台和架构匹配的交叉编译器。例如,在ARM架构上,你可以使用
arm-none-eabi-gcc
进行编译。运行以下命令:
- 使用交叉编译器将汇编代码编译为裸机可执行文件。这涉及到使用与目标硬件平台和架构匹配的交叉编译器。例如,在ARM架构上,你可以使用
arm-none-eabi-gcc -nostdlib -march=armv7-a -mcpu=cortex-a9 -T baremetal.ld baremetal.s -o baremetal.elf
其中,
baremetal.ld
是链接器脚本文件,用于定义程序的内存布局。代码可见附【9】。
- 使用QEMU运行裸机程序。运行以下命令:
qemu-system-arm -M <machine> -cpu <cpu> -kernel baremetal.elf
其中,
<machine>
是QEMU支持的硬件模型名称,例如virt
,versatilepb
等;<cpu>
是处理器型号,例如cortex-a9
。
附【1】部分相关代码
一个在arm设备上运行的裸金属代码 baremetal.s
:
.global _start
.section .text
_start:
mov r0, #5 @ 将值5加载到寄存器r0
add r1, r0, #7 @ 将r0的值加7,结果存入寄存器r1
mov r2, #0 @ 将值0加载到寄存器r2
loop:
add r2, r2, #1 @ 将r2的值加1
cmp r2, r1 @ 比较r2和r1的值
blt loop @ 如果r2小于r1,跳转到loop标签处
end:
b end @ 无限循环
.section .data
msg:
.asciz "Hello, World!" @ 存储字符串常量
.section .bss
上述代码所需要的链接器脚本文件 baremetal.ld
:
ENTRY(_start)
SECTIONS {
. = 0x10000; /* 裸金属程序的加载地址 */
.text : {
*(.text)
}
.data : {
*(.data)
}
.bss : {
*(.bss)
}
/DISCARD/ : {
*(.comment)
}
}