我应该如何在 u-boot linux 引导调试期间应用 add-symbol-file 命令?

How should I apply add-symbol-file command during u-boot linux boot debug?

我正在 qemu 虚拟机上使用 u-boot(使用 SPL falcon 模式,其中 u-boot-spl 直接启动 linux)进行引导加载。现在代码跳转到 linux 内核,因为我已经完成了 add-symbol-file vmlinux 0x80081000 我可以使用连接到虚拟机的 gdb 一步步跟随内核代码。实际上我加载了内核映像到0x80080000但是我不得不将地址设置为0x80081000以使源代码根据PC值正确地出现在gdb上(我不知道为什么需要这个0x1000的差异)。
后来我发现内核设置页面table(身份映射和交换table)并跳转到__primary_switched,这是PC第一次使用纯内核虚拟地址的地方。这是在 head.S 文件末尾进行调用的地方。

ldr x8, =__primary_switched
adrp    x0, __PHYS_OFFSET
br  x8

在符号文件(vmlinux,一个elf文件)中,__primary_switched之前的符号都是映射到虚拟地址(从0xffffffc0.....高地址开始)但是即使 PC 值使用物理地址,gdb 也可以跟踪源。 (PC 最初加载了内核启动的物理地址,并且一直使用 PC 相对跳转,直到它跳转到 __primary_switched,禁用 mmu 或使用身份映射)这是否意味着,仅执行 add-symbol-file符号与文本开头的偏移量很重要吗?
另一个问题:我可以使用 gdb 跟踪内核源代码,但在 __primary_switched 之后,我看不到源代码。根据现在的内核虚拟 PC 值,调试器没有显示正确的源位置。我是否应该再次使用 add-symbol-file 告诉调试器使用正确的偏移量?如果是怎么办?

添加(UTC,2022 年 1 月 12 日星期三上午 8:32)
我从 gdb 手册中找到,

"add-symbol-file filename [ -readnow | -readnever ] [ -o offset ] [ textaddress ] [ -s section address ... ] The add-symbol-file command reads additional symbol table information from the file filename. You would use this command when filename has been dynamically loaded (by some other means) into the program that is running. The textaddress parameter gives the memory address at which the file's text section has been loaded. You can additionally specify the base address of other sections using an arbitrary number of '-s section address' pairs. If a section is omitted, gdb will use its default addresses as found in filename. Any address or textaddress can be given as an expression. ..."

我稍微更改了我的程序以解决问题。 readelf 显示从 ffffffc010080800 开始的 .text 部分。 所以我将命令调整为“add-symbol-file vmlinux 0x80000800”,gdb 在跳转到 linux 后显示正确的内核源代码。 在 __primary_switched.

之后仍然没有显示源代码
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .head.text        PROGBITS         ffffffc010080000  00010000
       0000000000000040  0000000000000000  AX       0     0     4
  [ 2] .text             PROGBITS         ffffffc010080800  00010800
       0000000000304370  0000000000000000  AX       0     0     2048
  [ 3] .rodata           PROGBITS         ffffffc010390000  00320000
   .... (skip) ...
  [12] .notes            NOTE             ffffffc01045be18  003ebe18
       000000000000003c  0000000000000000   A       0     0     4
  [13] .init.text        PROGBITS         ffffffc010470000  003f0000
       0000000000027ec8  0000000000000000  AX       0     0     4
  [14] .exit.text        PROGBITS         ffffffc010497ec8  00417ec8
       000000000000046c  0000000000000000  AX       0     0     4

由于“__primary_switched”位于 .init.text 部分,我尝试添加“-s .init.text 0xffffffc010470000”或“-s .init_text 0x803ef800”(物理的 地址)到添加符号文件命令无济于事。我的命令错了吗?或者这可能是来自页面 table(虚拟 -> 物理)的问题,因为我在输入 __primary_switched 后立即看到同步异常(我看到 PC 值已变为 0x200。如果异常向量位于 0x0,这是未定义指令等同步异常的向量入口。我还应该检查向量基地址是否设置不正确。)

我发现我的内核加载地址是错误的(__PHYS_OFFSET 低于物理 ddr 地址开始)。 修复后,PC 正常增加内核虚拟地址,我应该使用虚拟地址应用 add-symbol-file 命令。
这是新版块地址。

        Section Headers:
          [Nr] Name              Type             Address           Offset
               Size              EntSize          Flags  Link  Info  Align
          [ 0]                   NULL             0000000000000000  00000000
               0000000000000000  0000000000000000           0     0     0
          [ 1] .head.text        PROGBITS         ffffffc010080000  00010000
               0000000000000040  0000000000000000  AX       0     0     4
          [ 2] .text             PROGBITS         ffffffc010080800  00010800
               0000000000304370  0000000000000000  AX       0     0     2048
          [ 3] .rodata           PROGBITS         ffffffc010390000  00320000
               00000000000a6385  0000000000000000  WA       0     0     4096
          [ 4] .modinfo          PROGBITS         ffffffc010436385  003c6385
               00000000000018ff  0000000000000000   A       0     0     1
          [ 5] .pci_fixup        PROGBITS         ffffffc010437c90  003c7c90
               00000000000020f0  0000000000000000   A       0     0     16
          [ 6] __ksymtab         PROGBITS         ffffffc010439d80  003c9d80
               0000000000006d20  0000000000000000   A       0     0     4
          [ 7] __ksymtab_gpl     PROGBITS         ffffffc010440aa0  003d0aa0
               0000000000005808  0000000000000000   A       0     0     4
          [ 8] __ksymtab_strings PROGBITS         ffffffc0104462a8  003d62a8
               00000000000134f2  0000000000000000   A       0     0     1
          [ 9] __param           PROGBITS         ffffffc0104597a0  003e97a0
               0000000000000b68  0000000000000000   A       0     0     8
          [10] __modver          PROGBITS         ffffffc01045a308  003ea308
               0000000000000cf8  0000000000000000   A       0     0     8
          [11] __ex_table        PROGBITS         ffffffc01045b000  003eb000
               0000000000000e18  0000000000000000   A       0     0     8
          [12] .notes            NOTE             ffffffc01045be18  003ebe18
               000000000000003c  0000000000000000   A       0     0     4
          [13] .init.text        PROGBITS         ffffffc010470000  003f0000
               0000000000027ec8  0000000000000000  AX       0     0     4
  [14] .exit.text        PROGBITS         ffffffc010497ec8  00417ec8

最终内核映像加载到 0x80080000。那么__PHYS_OFFSET就变成了0x80000000。 (TEXT_OFFSET 默认为 0x80000)。现在我可以使用这个命令在 __primary_switch 之前调试内核源代码。

add-symbol-file images/vmlinux 0x80080800 -s .head.text 0x80080000 -s .init.text 0x803f7800

在内核进入__primary_switched(现在使用内核虚拟地址)后,我添加了这个命令来查看源代码,我可以逐步使用qemu和gdb跟随代码。

add-symbol-file images/vmlinux 0xffffffc010080800 -s .head.text 0xffffffc010080000 -s .init.text 0xffffffc010470000 Hope this helps someone later.

但几天后,我想我可以使用 add-symbol-file images/vmlinux 0xffffffc010080800(应用所有部分信息)。