如何解决qemu gdb调试错误:远程'g'数据包回复太长了?

Jaa*_*nen 8 x86 gcc gdb qemu osdev

我正在进入引导程序和内核开发(非常开始)我正在关注https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev的组合 .pdfhttps://github.com/cfenollosa/os-tutorial中的代码

唯一不同的是,我的目标是x86_64而不是i386.我也使用qemu模拟(qemu-system-x86_64).现在跟随GitHub回购到第16部分视频驱动程序之后,我被卡住了,因为屏幕驱动程序确实在屏幕上打印了一些东西,但是有些事情正在发生,数据不对齐.接下来我想尝试调试我的程序.这部分也包含在回购的第14部分检查点中.所以我为目标x86_64-elf构建了gdb.但是,当我尝试运行qemu和gdb使用system-qemu-x86_64 -s -S -fda os-image ,然后运行gdb并尝试通过运行连接到qemu target remote localhost:1234,一旦我运行,我得到以下错误消息

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
Run Code Online (Sandbox Code Playgroud)

关于我遗失/做错的任何想法?如果需要更多信息,请告诉我.

谢谢

编辑:我已经应用了@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 ?? ()
Run Code Online (Sandbox Code Playgroud)

但是我能够在函数和行号上设置断点.但是当我尝试打印当前位置应该可用的变量时,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
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

Mic*_*tch 4

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

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

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

如果调试 32 位代码,您可能需要使用qemu-system-i386. 你会遇到更少的麻烦。