【问题标题】:Breakpoints not working for gdb while debugging remote arm target on qemu在 qemu 上调试远程 arm 目标时,断点不适用于 gdb
【发布时间】:2022-01-27 18:53:58
【问题描述】:

我已经编译了这个裸机示例:https://github.com/s-matyukevich/raspberry-pi-os/tree/master/src/lesson01。我修改了 Makefile 以具有如下调试符号:

diff --git a/src/lesson01/Makefile b/src/lesson01/Makefile
index 4f92a49..daa1f7d 100644
--- a/src/lesson01/Makefile
+++ b/src/lesson01/Makefile
@@ -1,7 +1,7 @@
-ARMGNU ?= aarch64-linux-gnu
+ARMGNU ?= /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu

-COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only
-ASMOPS = -Iinclude
+COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -g
+ASMOPS = -Iinclude -g

 BUILD_DIR = build
 SRC_DIR = src
@@ -27,5 +27,5 @@ DEP_FILES = $(OBJ_FILES:%.o=%.d)
 -include $(DEP_FILES)

 kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES)
-       $(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf  $(OBJ_FILES)
+       $(ARMGNU)-ld -g -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf  $(OBJ_FILES)
        $(ARMGNU)-objcopy $(BUILD_DIR)/kernel8.elf -O binary kernel8.img

从一个终端,我在 qemu 上运行程序:

$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio -S -s

从其他终端,我启动 gdb:

$ /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb ./build/kernel8.elf -ex 'target remote localhost:1234' -ex 'break _start' -ex 'break kernel_main' -ex 'continue'

但是断点永远不会被命中。

GNU gdb (GNU Toolchain for the A-profile Architecture 10.3-2021.07 (arm-10.29)) 10.2.90.20210621-git
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=aarch64-none-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://bugs.linaro.org/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./build/kernel8.elf...
Remote debugging using localhost:1234
_start () at src/boot.S:7
7       mrs x0, mpidr_el1
Breakpoint 1 at 0x0: file src/boot.S, line 7.
Breakpoint 2 at 0x234: file src/kernel.c, line 5.
Continuing.

我做错了什么?我查看了所有相关问题,但没有任何帮助。这是我的图片供参考:kernel8.elfkernel8.img

编辑

当我continue 时,我确实在我的控制台上得到了Hello, world!,所以kernel8.img 可以正常启动。另外,供参考:

$ qemu-system-aarch64 --version
QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.18)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers

【问题讨论】:

  • 如果我在链接描述文件SECTIONS 的开头添加. = 0x80000,断点开始工作。我无法解释这一点,因为即使在较早的情况下,kernel8.img 也可以正常启动并正确打印Hello, world!。而且,我从来没有根据地址设置断点,而是根据符号名称设置断点,所以它应该也可以更早地工作。

标签: assembly gdb qemu bare-metal gdbserver


【解决方案1】:

GDB 会根据 ELF 文件所说的代码位置来放置断点。您可以在您的脚本中看到它认为 boot.S 中的 _start 函数位于地址 0x0。但是,当您告诉 QEMU 加载您的二进制文件时,您并没有以与 ELF 文件所说的方式相匹配的方式执行此操作。因此,正在执行的实际代码位于完全不同的地址,并且断点不在与执行代码匹配的地址中,因此它们不会命中。由于您没有将代码编译为与位置无关的代码,因此当它从该地址运行时,它主要是靠运气工作(因为即使是非位置无关的 aarch64 代码通常也没有与位置相关的指令)。

地址不匹配的原因是因为您的 ELF 文件说代码从地址 0x0 开始,但是您将 QEMU 一个二进制文件传递给 -kernel 选项,这意味着“我是 Linux 内核,启动我按照 Linux 内核启动协议所说的那样做”(参见https://www.kernel.org/doc/Documentation/arm64/booting.txt)。这意味着很多事情,包括(对于当前的 QEMU 实现——这不是引导协议严格规定的)我们将映像加载到地址 0x80000,并运行由 QEMU 生成的一些存根代码,它设置一些寄存器并跳转到该位置。这就是为什么当您设置链接器脚本以将图像链接到该地址时,它恰好开始工作。

解决方案是选择您希望如何启动访客代码:

  • 您可以使其符合 Linux 内核引导协议的各种要求,并将其作为二进制文件传递给 -kernel
  • 你可以把它写成一个纯裸机镜像,在地址 0x0 包含一个向量表,然后用 QEMU“通用加载器”加载它,它会获取一个 ELF 文件并将其所有段作为 ELF 头加载指定。 (也可以将 ELF 文件传递​​给 -kernel,但在这种情况下,通用加载器更有意义。)

QEMU支持“加载此 ELF 文件并以 Raspberry Pi 固件支持运行从 SD 卡加载的 ELF 文件的方式启动它”。因此,您可能需要对仅设计用于在真实硬件上运行的裸机代码教程进行一些调整。

(有关加载访客代码的各种 QEMU 选项的更多信息,请参阅this answer。)

【讨论】:

    猜你喜欢
    • 2013-09-26
    • 1970-01-01
    • 2021-04-24
    • 2011-06-09
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 2014-12-15
    • 2022-11-04
    相关资源
    最近更新 更多