【问题标题】:How to solve qemu gdb debug error: Remote 'g' packet reply is too long?如何解决 qemu gdb 调试错误:远程 'g' 数据包回复太长?
【发布时间】:2018-07-15 04:39:40
【问题描述】:

我目前正在研究引导加载程序和内核开发(刚刚开始) 我正在关注以下组合 https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf 和找到的代码 https://github.com/cfenollosa/os-tutorial

我唯一不同的是我的目标是 x86_64 而不是 i386。另外我正在使用 qemu 来模拟(qemu-system-x86_64)。 现在,在遵循 GitHub 存储库的第 16 部分视频驱动程序之后,我被卡住了,因为屏幕驱动程序确实在屏幕上打印了一些东西,但是由于数据未对齐或其他原因而发生了一些事情。所以接下来我想尝试调试我的程序。这也包含在 repo 的第 14 部分检查点中。所以我为目标 x86_64-elf 构建了 gdb。但是当我尝试使用system-qemu-x86_64 -s -S -fda os-image 运行 qemu 和 gdb 时 然后只需运行gdb 并尝试通过运行target remote localhost:1234 连接到qemu,一旦我运行我就会收到以下错误消息

Remote debugging using localhost:1234
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
Remote 'g' packet reply is too long (expected 308 bytes, got 536 bytes):
000000000000000000000000000000000000000000000000630600000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000f0ff0000000000000200000000f00000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000007f03000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000801f0000

关于我缺少什么/做错了什么有什么想法吗?如果需要更多信息,请告诉我。

谢谢

编辑: 我已经应用了@MichaelPetch 提到的补丁,现在 g 数据包错误消失了。但是看起来 gdb 无法解释我的可执行文件,因为在运行 target remote localhost:1234 然后 symbol-file kernel.elf 之后,终端现在返回

Remote debugging using localhost:1234 warning: No executable has been
specified and target does not support determining executable automatically.
Try using the "file" command. 0x0000fb38 in ?? ()

但是,我可以在函数和行号上设置断点。但是当尝试使用print terminal_buffer 打印当前位置应该可用的变量时,我得到了 No symbol "terminal_buffer" in current context. terminal_buffer 是当前作用域中声明的变量。

但是,当我打印一个在放置断点的函数范围之外声明的变量时,例如一个 int,print 确实返回一个值,但该值为 0(我认为这是类型),但是根据我的代码,它应该已经设置为新值。此外,当尝试next 时,它会返回Cannot find bounds of current function,这导致我认为它无法解释某些部分。

在我的引导加载程序中,我更改为受保护的保护模式以使用此方法运行 64 位内核:

[bits 16]
switch_to_pm:
    cli ; 1. disable interrupts
    lgdt [gdt_descriptor] ; 2. load the GDT descriptor
    mov eax, cr0
    or eax, 0x1 ; 3. set 32-bit mode bit in cr0
    mov cr0, eax
    jmp CODE_SEG:init_pm ; 4. far jump by using a different segment

[bits 32]
init_pm: ; we are now using 32-bit instructions
    mov ax, DATA_SEG ; 5. update the segment registers
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov ebp, 0x90000 ; 6. update the stack right at the top of the free space
    mov esp, ebp

    call BEGIN_PM ; 7. Call a well-known label with useful code

有什么想法吗?

【问题讨论】:

  • BOCHS 可能有用:它是另一个 x86 仿真器,但它内置了调试器,而不仅仅是 GDB 远程目标。 (不过,我并没有使用太多,所以 IDK 如果 qemu-system-x86_64 以 EFI 或其他方式以长模式启动,而不是像 PC 传统 BIOS 那样以实模式启动。)
  • 在实模式和保护模式之间切换或切换到 64 位长模式时,您通常会看到此错误。 GDB 在所有情况下都不能正确跟踪模式更改,最终会出现此错误。如果调试引导加载程序,我推荐 Bochs,因为它了解模式之间的转换。在某些情况下,您可以在收到此错误后设置新架构,然后重新启动调试会话,但它并不总是有效。我似乎记得写过一个关于这个的答案,但我现在找不到那个答案。
  • OSDev Wiki 上列出了一些其他可能的解决方法:wiki.osdev.org/QEMU_and_GDB_in_long_mode
  • 我已经打了补丁,现在g包错误消失了。但是,在运行target remote localhost:1234 然后symbol-file kernel.elf 之后,gdb 似乎无法解释我的可执行文件,终端显示Remote debugging using localhost:1234 warning: No executable has been specified and target does not support determining executable automatically. Try using the "file" command. 0x0000fb38 in ?? ()

标签: gcc x86 gdb qemu osdev


【解决方案1】:

所有问题的原因是您正在编译 64 位代码并在 32 位保护模式下运行它。 64 位代码将无法在该环境中正常运行。奇怪的是,它通常在尝试写入视频显示器时首先表现出来。通常事情会打印出来,但不是你想要的那样。如您所见,解码不当的指令会导致调试器无法正常工作。

解决问题的一种方法是将内核编译并链接为 32 位可执行文件。您使用的是 64 位编译器,因此您需要添加 -m32 CFLAGS(或您的 GCC 命令行)。如果使用 LD 链接 -melf_i386 将需要。使用 NASM 组装应该是 -felf32 而不是 -felf64

或者,您必须在引导加载程序中将处理器置于 64 位长模式。您可以在OSDev wiki 上阅读有关该过程的更多信息。

如果调试 32 位代码,您可能希望使用 qemu-system-i386 。您的麻烦会更少。

【讨论】:

    【解决方案2】:

    连接和断开连接

    我得到了它的详细信息:How to debug the Linux kernel with GDB and QEMU?

    关键是在 GDB 上连接和断开连接:

    gdb \
        -ex "add-auto-load-safe-path $(pwd)" \
        -ex "file vmlinux" \
        -ex 'set arch i386:x86-64:intel' \
        -ex 'target remote localhost:1234' \
        -ex 'break start_kernel' \
        -ex 'continue' \
        -ex 'disconnect' \
        -ex 'set arch i386:x86-64' \
        -ex 'target remote localhost:1234'
    

    相关:Remote 'g' packet reply is too long

    【讨论】:

      猜你喜欢
      • 2012-01-29
      • 2015-02-09
      • 2010-10-16
      • 2013-09-22
      • 1970-01-01
      • 2017-02-03
      • 1970-01-01
      • 2011-06-09
      • 2012-01-03
      相关资源
      最近更新 更多