我目前正在进入引导加载程序和内核开发(非常开始) 我跟随他们的组合 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部分 - 视频驱动程序后,我被卡住了,因为屏幕驱动程序确实在屏幕上打印了一些东西,但是有些事情正在进行,数据不对齐等等。接下来我想尝试调试我的程序。这部分也包含在回购的第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
有什么想法吗?
答案 0 :(得分:2)
所有问题的原因是您正在编译64位代码并以32位保护模式运行它。 64位代码无法在该环境中正常运行。奇怪的是,它通常在尝试写入视频显示时首先表现出来。通常情况会打印,但不是你想要的方式。解码不正确的指令会导致调试器无法正常工作。
解决问题的一种方法是将内核编译并链接为32位可执行文件。您正在使用64位编译器,因此您需要添加-m32
CFLAGS(或您的GCC命令行)。如果使用LD链接-melf_i386
则需要。使用NASM进行汇总应为-felf32
,而不是-felf64
。
或者,您必须在引导加载程序中将处理器置于64位长模式。您可以在OSDev wiki上了解有关该流程的更多信息。
如果调试32位代码,您可能希望使用qemu-system-i386
。你将减少麻烦。
答案 1 :(得分:1)
连接和断开连接
我的工作详见: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'