【问题标题】:GDB stepping through instructions on a particular core in baremetal development on QEMUGDB 在 QEMU 上的裸机开发中逐步执行特定内核的指令
【发布时间】:2022-01-04 11:19:17
【问题描述】:

我正在学习 ARM 上的裸机开发,为此我选择在 QEMU 上模拟 Raspi3。因此,它是一个实现 ARMv8 架构的虚拟 ARM Cortex A-53。我已经编译了以下简单的裸机代码:

.global _start
_start:
1:  wfe
    b 1b

我使用 :

启动它
qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -S -s

并且 GDB 使用 :

从另一个终端连接到它
gdb-multiarch ./kernel8.elf -ex 'target remote localhost:1234' -ex 'break *0x80000' -ex 'continue'

到目前为止一切都很好,我可以注意到 gdb 中的断点。

Reading symbols from ./kernel8.elf...
Remote debugging using localhost:1234
0x0000000000000000 in ?? ()
Breakpoint 1 at 0x80000: file start.S, line 5.
Continuing.

Thread 1 hit Breakpoint 1, _start () at start.S:5
5   1:  wfe
(gdb) info threads
  Id   Target Id                    Frame
* 1    Thread 1.1 (CPU#0 [running]) _start () at start.S:5
  2    Thread 1.2 (CPU#1 [running]) 0x0000000000000300 in ?? ()
  3    Thread 1.3 (CPU#2 [running]) 0x000000000000030c in ?? ()
  4    Thread 1.4 (CPU#3 [running]) 0x000000000000030c in ?? ()
(gdb) list
1   .section ".text.boot"
2
3   .global _start
4   _start:
5   1:  wfe
6       b 1b
(gdb)

据我了解,对于 ARM,所有内核在复位时都会执行相同的代码,因此理想情况下,我的所有内核都必须运行相同的代码。我只想通过设置断点来验证这一点,这就是问题所在。其他核心的断点未命中。如果我没记错的话,在我的情况下,线程只不过是核心。我试过休息但不起作用:

(gdb) break *0x80000 thread 2
Note: breakpoint 1 (all threads) also set at pc 0x80000.
Breakpoint 2 at 0x80000: file start.S, line 5.
(gdb) thread 2
[Switching to thread 2 (Thread 1.2)]
#0  0x0000000000000300 in ?? ()
(gdb) info threads
  Id   Target Id                    Frame
  1    Thread 1.1 (CPU#0 [running]) _start () at start.S:5
* 2    Thread 1.2 (CPU#1 [running]) 0x0000000000000300 in ?? ()
  3    Thread 1.3 (CPU#2 [running]) 0x000000000000030c in ?? ()
  4    Thread 1.4 (CPU#3 [running]) 0x000000000000030c in ?? ()
(gdb) s
Cannot find bounds of current function
(gdb) c
Continuing.
[Switching to Thread 1.1]

Thread 1 hit Breakpoint 1, _start () at start.S:5
5   1:  wfe
(gdb)

我删除了core 1断点,然后core 2就永远挂了:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000080000 start.S:5
    breakpoint already hit 2 times
2       breakpoint     keep y   0x0000000000080000 start.S:5 thread 2
    stop only in thread 2
(gdb) delete br 1
(gdb) info break
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000080000 start.S:5 thread 2
    stop only in thread 2
(gdb) thread 2
[Switching to thread 2 (Thread 1.2)]
#0  0x000000000000030c in ?? ()
(gdb) c
Continuing.

如何在核心 2 上获得断点?我在这里做错了什么?

编辑

我试过set scheduler-locking on(假设这是我需要的)但这似乎对我不起作用。

(gdb) break *0x80000
Breakpoint 3 at 0x80000: file start.S, line 5.
(gdb) thread 2
[Switching to thread 2 (Thread 1.2)]
#0  0x000000000000030c in ?? ()
(gdb) set scheduler-locking on
(gdb) c
Continuing.


^C/build/gdb-OxeNvS/gdb-9.2/gdb/inline-frame.c:367: internal-error: void skip_inline_frames(thread_info*, bpstat): Assertion `find_inline_frame_state (thread) == NULL' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) n

This is a bug, please report it.  For instructions, see:
<http://www.gnu.org/software/gdb/bugs/>.

/build/gdb-OxeNvS/gdb-9.2/gdb/inline-frame.c:367: internal-error: void skip_inline_frames(thread_info*, bpstat): Assertion `find_inline_frame_state (thread) == NULL' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n)

编辑 2

根据@Frank 的建议,我在本地构建了(最新的)qemu 6.2.0,并使用了 arm 工具链中的gdb

naveen@workstation:~/.repos/src/arm64/baremetal/raspi3-tutorial/01_bareminimum$ /opt/qemu-6.2.0/build/qemu-system-aarch64 -version
QEMU emulator version 6.2.0
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

naveen@workstation:~/.repos/src/arm64/baremetal/raspi3-tutorial/01_bareminimum$ /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb -version
GNU gdb (GNU Toolchain for the A-profile Architecture 10.3-2021.07 (arm-10.29)) 10.2.90.20210621-git

但我仍然遇到问题。我的其他核心 2,3 和 4 从未达到断点。似乎他们甚至没有运行我的代码,因为他们指向的地址看起来不太好。

(gdb) info threads
  Id   Target Id                    Frame
* 1    Thread 1.1 (CPU#0 [running]) _start () at start.S:5
  2    Thread 1.2 (CPU#1 [running]) 0x000000000000030c in ?? ()
  3    Thread 1.3 (CPU#2 [running]) 0x000000000000030c in ?? ()
  4    Thread 1.4 (CPU#3 [running]) 0x000000000000030c in ?? ()

编辑 3

问题似乎出在我的 Makefile 上,因为当我按照 Frank 的建议使用命令进行构建时,它对我有用。有人可以看看这个 Makefile 有什么问题吗:

CC = /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf
CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostartfiles -nostdlib -g

all: clean kernel8.img

start.o: start.S
    ${CC}-gcc $(CFLAGS) -c start.S -o start.o

kernel8.img: start.o
    ${CC}-ld -g -nostdlib start.o -T link.ld -o kernel8.elf
    ${CC}-objcopy -O binary kernel8.elf kernel8.img

clean:
    rm kernel8.elf kernel8.img *.o >/dev/null 2>/dev/null || true

编辑 4

事实证明,当我使用 kernel8.elf 和 QEMU 进行引导时,一切正常。但是当我使用二进制格式的kernel8.img 时,我遇到了问题。通过阅读,我了解到 ELF 包含使示例工作所需的“额外”信息。但是为了澄清,我怎样才能使kernel8.img 工作?

【问题讨论】:

    标签: debugging assembly arm gdb qemu


    【解决方案1】:

    您使用的gdbqemu 的版本可能存在问题,因为我无法使用aarch64-elf-gdb 10.1 版和qemu 6.2.0 版重现您的问题-system-aarch64 在Ubuntu 20.04.3 LTS 系统上从头开始编译:

    wfe.s:

            .global _start
    _start:
    1:      wfe
            b 1b
    

    大楼wfe.elf:

    /opt/arm/10/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc -g -ffreestanding -nostdlib -nostartfiles -Wl,-Ttext=0x80000 -o wfe.elf wfe.s
    

    查看生成的代码:

    /opt/arm/10/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-objdump -d wfe.elf
    
    wfe.elf:     file format elf64-littleaarch64
    
    
    Disassembly of section .text:
    
    0000000000080000 <_stack>:
       80000:       d503205f        wfe
       80004:       17ffffff        b       80000 <_stack>
    

    在 shell 会话中启动 qemu

    /opt/qemu-6.2.0/bin/qemu-system-aarch64 -M raspi3b -kernel wfe.elf -display none -S -s
    

    在另一个开始gdb

    /opt/gdb/gdb-10.1-aarch64-elf-x86_64-linux-gnu/bin/aarch64-elf-gdb wfe.elf -ex 'target remote localhost:1234' -ex 'break *0x80000' -ex 'continue'
    

    gdb 会话:

    GNU gdb (GDB) 10.1
    Copyright (C) 2020 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-linux-gnu --target=aarch64-elf".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <https://www.gnu.org/software/gdb/bugs/>.
    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".
    Remote debugging using localhost:1234
    warning: No executable has been specified and target does not support
    determining executable automatically.  Try using the "file" command.
    0x0000000000080000 in ?? ()
    Breakpoint 1 at 0x80000
    Continuing.
    [Switching to Thread 1.4]
    
    Thread 4 hit Breakpoint 1, 0x0000000000080000 in ?? ()
    (gdb) break *0x80000 thread 2
    Note: breakpoint 1 (all threads) also set at pc 0x80000.
    Breakpoint 2 at 0x80000
    (gdb) info threads
      Id   Target Id                    Frame 
      1    Thread 1.1 (CPU#0 [running]) 0x0000000000080000 in ?? ()
      2    Thread 1.2 (CPU#1 [running]) 0x0000000000080000 in ?? ()
      3    Thread 1.3 (CPU#2 [running]) 0x0000000000080000 in ?? ()
    * 4    Thread 1.4 (CPU#3 [running]) 0x0000000000080000 in ?? ()
    (gdb) c
    Continuing.
    [Switching to Thread 1.2]
    
    Thread 2 hit Breakpoint 1, 0x0000000000080000 in ?? ()
    (gdb) info b
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x0000000000080000 
            breakpoint already hit 2 times
    2       breakpoint     keep y   0x0000000000080000  thread 2
            stop only in thread 2
            breakpoint already hit 1 time
    (gdb) del 1
    (gdb) info b
    Num     Type           Disp Enb Address            What
    2       breakpoint     keep y   0x0000000000080000  thread 2
            stop only in thread 2
            breakpoint already hit 1 time
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, 0x0000000000080000 in ?? ()
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, 0x0000000000080000 in ?? ()
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, 0x0000000000080000 in ?? ()
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, 0x0000000000080000 in ?? ()
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, 0x0000000000080000 in ?? ()
    (gdb) 
    

    因此,您的两个问题的答案是:

    1. 如何在核心 2 上获得断点?

    正是你在做什么。

    1. 我在这里做错了什么?

    没有,但可能正在使用旧版本/错误版本的 gdb 和/或 qemu - 我猜你的情况是 gdb 是罪魁祸首,但我可能错了。

    您可以使用 Arm 提供的 gcc 工具链中提供的 gdb 版本再次测试来轻松验证,AArch64 ELF bare-metal target (aarch64-none-elf) - 我试过了,效果也很好:

    /opt/arm/10/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gdb wfe.elf -ex 'target remote localhost:1234' -ex 'break *0x80000' -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-elf".
    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 wfe.elf...
    Remote debugging using localhost:1234
    _start () at wfe.s:3
    3       1:      wfe
    Breakpoint 1 at 0x80000: file wfe.s, line 3.
    Continuing.
    
    Thread 1 hit Breakpoint 1, _start () at wfe.s:3
    3       1:      wfe
    (gdb) break *0x80000 thread 2
    Note: breakpoint 1 (all threads) also set at pc 0x80000.
    Breakpoint 2 at 0x80000: file wfe.s, line 3.
    (gdb)  info threads
      Id   Target Id                    Frame 
    * 1    Thread 1.1 (CPU#0 [running]) _start () at wfe.s:3
      2    Thread 1.2 (CPU#1 [running]) _start () at wfe.s:3
      3    Thread 1.3 (CPU#2 [running]) _start () at wfe.s:3
      4    Thread 1.4 (CPU#3 [running]) _start () at wfe.s:3
    (gdb) c
    Continuing.
    [Switching to Thread 1.2]
    
    Thread 2 hit Breakpoint 1, _start () at wfe.s:3
    3       1:      wfe
    (gdb) info b
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x0000000000080000 wfe.s:3
            breakpoint already hit 2 times
    2       breakpoint     keep y   0x0000000000080000 wfe.s:3 thread 2
            stop only in thread 2
            breakpoint already hit 1 time
    (gdb) del 1
    (gdb) info b
    Num     Type           Disp Enb Address            What
    2       breakpoint     keep y   0x0000000000080000 wfe.s:3 thread 2
            stop only in thread 2
            breakpoint already hit 1 time
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, _start () at wfe.s:3
    3       1:      wfe
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, _start () at wfe.s:3
    3       1:      wfe
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, _start () at wfe.s:3
    3       1:      wfe
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, _start () at wfe.s:3
    3       1:      wfe
    (gdb) c
    Continuing.
    
    Thread 2 hit Breakpoint 2, _start () at wfe.s:3
    3       1:      wfe
    (gdb) 
    

    请注意,解释如何构建最新版本的 gdbqemu 超出了当前答案的范围。

    【讨论】:

    • 谢谢@Frank,我听从了你的建议,但我仍然遇到了这个问题。请检查Edit 2,因为评论部分较小,无法放置信息。
    • 嘿……看来问题出在我正在使用的 Makefile 上。当我使用你的命令来构建它时,它对我来说很好。你能看看我在 EDIT 3 中的 Makefile 吗
    • 如果您认为我的回答能正确回答您的问题,请随时接受。您能否使用链接器脚本的内容以及以下命令的输出来扩充您的原始问题:/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-objdump -d kernel8.elf?谢谢。
    • 我不同意:我准确地回答了你的两个问题:1)我能做些什么来获得核心 2 上的断点?正是你在做什么。 2):我在这里做错了什么?没什么 - 我猜这是正确的答案,因为您从未质疑您的可执行文件有问题,而是该问题与您用于 gdb/qemu 和 gdb 会话中的命令有关。否则,您将提供您的 Makefile 和链接器脚本。我看到你在问一个新问题的方式,我很乐意回答,但从我的角度来看,这仍然是一个新问题。
    • 以下是后续问题,如果您想回答:stackoverflow.com/questions/70603156/…
    猜你喜欢
    • 1970-01-01
    • 2014-11-27
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 2020-10-12
    • 1970-01-01
    相关资源
    最近更新 更多