I'm currently getting into bootloaders and kernel development (very much beginning) I'm following a combination of https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf and the code found in https://github.com/cfenollosa/os-tutorial
The only thing im doing differently is that I'm targeting x86_64 instead of i386. Also I'm using qemu to emulate (qemu-system-x86_64).
Now after following the GitHub repo to part 16-video-driver I get stuck as the screen driver does print some stuff to the screen but something's going on with a misalignment of data or something. So next I wanted to try to debug my program. This is also covered in part 14-checkpoint of the repo. So I built gdb for target x86_64-elf. But when I try to run qemu and gdb using system-qemu-x86_64 -s -S -fda os-image
and then just run gdb
and try to connect to qemu by running target remote localhost:1234
, as soon as I run that I get the following error message
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
Any ideas on what I'm missing / doing wrong? If more information is needed please let me know.
Thanks
EDIT:
I've applied the patch mentioned by @MichaelPetch and now the g packet error is gone. However it looks like gdb can't interpret my executable as after running target remote localhost:1234
and then symbol-file kernel.elf
, the terminal now returns
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 ?? ()
I am however able to set breakpoints on functions and line numbers. But when trying to print variables that should be available at the current location using print terminal_buffer
I get
No symbol "terminal_buffer" in current context.
terminal_buffer being a variable declared in the current scope.
However when I print a variable declared outside the scope of the function in which I have put my breakpoint, an int for example, print
does return a value but the value is 0 (I presume that is the initial value of the type), however it should already have been set to a new value according to my code. Also when trying next
it returns Cannot find bounds of current function
which leads to me thinking it's not able to interpret some part.
In my bootloader I change into protected protected mode to run the 64-bit kernel using this method:
[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
Any thoughts?
The reason for all the issues is that you are compiling 64-bit code and running it in 32-bit protected mode. 64-bit code will not run in that environment properly. Oddly enough it often manifests itself at first when trying to write to the video display. Often things will print but not quite the way you want. Improperly decoded instructions will cause the debugger to work erratically as you observed.
One way to fix your problem is to compile and link the kernel as a 32-bit executable. You are using a 64-bit compiler so you'll need to add -m32
CFLAGS (or your GCC command line). if using LD to link -melf_i386
will be needed. Assembling with NASM should be -felf32
rather than -felf64
.
Alternatively you would have to place the processor into 64-bit long mode in the bootloader. You can read more about that process on the OSDev wiki.
If debugging 32-bit code you will probably want to use qemu-system-i386
. You will have fewer hassles.
Connect and disconnect
I got it working as detailed at: How to debug the Linux kernel with GDB and QEMU?
The key thing was connect and disconnect on GDB as:
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'
Related: Remote 'g' packet reply is too long
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With