Page 1 of 1

[SOLVED]GDB breaks after a far jump in real mode

Posted: Sat Aug 03, 2024 2:58 am
by stskyblade
I use Qemu and GDB to develop a OS. I'm on the process of "Use MBR code to load bootloader". To save addressing space, I use a far jump instruction when jump to bootloader from MBR. After that, GDB don't know where is the executing line of source code.

Source code can be found here:
https://github.com/stskyblade/StarOS

Steps to reproduce:
(You need a cross compiler)

Code: Select all

make debug

# run gdb
gdb
(gdb) b mbr.S:26
(gdb) c             # breakpoint before far jmp
(gdb) s             # execute far jmp

After far jmp, I can't use 's' to resume execution. Error message is "Cannot find bounds of current function".

MBR is loaded into memory at address 0x7c00. Bootloader is loaded into memory at address 0x7e00, which is 512 Bytes after MBR.
Before the far jmp instruction, CS:IP is something like 0x0000:0x7cxx.
After it, CS:IP is 0x7c0:0x200. This address is 0x7e00 pointing to bootloader_start.


What I tried:
I guess GDB use the value in IP register and symbol file to find the executing line of code. After far jmp, IP is 0x200, which doesn't exist on symbol file build/mbr.elf. In that file, 0x7e00 points to bootloader_start.

I generate another symbol file using new linker script. (This hasn't been pushed to Github)
In this linker script, I set the start address of .text section from 0x7c00 to 0x00. At this point, 0x200 should point to bootloader_start.

Steps to reproduce:
(You need a cross compiler)

Code: Select all

make debug

# run gdb
gdb
(gdb) symbol-file build/mbr_debug.elf
(gdb) b bootloader_start
(gdb) bootloader.S:23
(gdb) bootloader.S:24
(gdb) bootloader.S:25
(gdb) c
After presss "c", the program was executing but didn't stop on any breakpoint. It should stop on bootloader_start, then line 23, then line 24...

Re: GDB breaks after a far jump in real mode

Posted: Sat Aug 03, 2024 4:28 am
by iansjack
I note that right at the beginning of your code you set the SP register to an invalid (unaligned) value. Without looking too far into your code (I'm not really into debugging large amounts of assembly language when there are already plenty of good boot loaders), I suspect that gdb is not going to be very happy with an invalid stack.

Re: GDB breaks after a far jump in real mode

Posted: Sat Aug 03, 2024 4:41 am
by stskyblade
iansjack wrote: Sat Aug 03, 2024 4:28 am I note that right at the beginning of your code you set the SP register to an invalid (unaligned) value. Without looking too far into your code (I'm not really into debugging large amounts of assembly language when there are already plenty of good boot loaders), I suspect that gdb is not going to be very happy with an invalid stack.

I didn't notice that. This stack setting works fine. I mean when I use it to push & pop registers, GDB works fine.

Whatever, I follow your advice, and set SP to 0xFFFC. This value % 4 == 0. And same bug happens again.

Re: GDB breaks after a far jump in real mode

Posted: Sat Aug 03, 2024 10:31 pm
by Octocontrabass
stskyblade wrote: Sat Aug 03, 2024 2:58 amAfter it, CS:IP is 0x7c0:0x200.
GDB only really supports flat address spaces. Jump to 0x0:0x7e00 instead. You'll have a much easier time with everything if you leave segment registers set to 0 as much as possible in real mode.

But speaking of your stack, you put it inside the EBDA. You need to move your stack somewhere else.

Re: GDB breaks after a far jump in real mode

Posted: Sat Aug 03, 2024 10:44 pm
by stskyblade
Octocontrabass wrote: Sat Aug 03, 2024 10:31 pm
stskyblade wrote: Sat Aug 03, 2024 2:58 amAfter it, CS:IP is 0x7c0:0x200.
GDB only really supports flat address spaces. Jump to 0x0:0x7e00 instead. You'll have a much easier time with everything if you leave segment registers set to 0 as much as possible in real mode.

But speaking of your stack, you put it inside the EBDA. You need to move your stack somewhere else.
Thank you very much for your advice. It feels good to get help from you in this forum.