Debugging the OS with VirtualBox

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: Debugging the OS with VirtualBox

Post by Gigasoft »

So I'm a bit retarded when I need to code in assembly...
Wouldn't it be a better idea to learn the x86 architecture before trying to write an OS for it?
User avatar
Bonfra
Member
Member
Posts: 270
Joined: Wed Feb 19, 2020 1:08 pm
Libera.chat IRC: Bonfra
Location: Italy

Re: Debugging the OS with VirtualBox

Post by Bonfra »

Ok, it seems to work! Awesome! The VBR loads the final bootloader in memory. Now I'm a bit over the limit of 512 bytes so I need to cut something in the code (just 4 bytes).
I went through the code a few times but the only part that seems to be overcomplicated is this one:

Code: Select all

%define LIN_TO_FAR_ADDR(linaddr) (((linaddr >> 4) << 16) | (linaddr & 0xf))
mov ebx, dword LIN_TO_FAR_ADDR(0x00007E00)
[...]

;inside a loop
; increase address
    xor eax, eax
    mov ax, word [bpb_SectorsPerCluster]
    mul word [bpb_BytesPerSector]
    mov ecx, eax
    shr eax, 4
    shl eax, 16
    and ecx, 0xF
    or eax, ecx
    add ebx, eax
    ; check if riporto
    mov eax, ebx
    and eax, (1 << 4)
    cmp eax, 0
    je .nextCluster
    ; fix riporto
    xor ebx, 1 << 4
    add ebx, 1 << 16
    jmp .nextCluster
basically what it does is adding to ebx (which contains a far address) a a certain bias calculated in the first lines. I wasn't sure about how to increase a non linear addresso so I went for this approach; it works but it's a bit clunky, do you know a better way?
Regards, Bonfra.
User avatar
Bonfra
Member
Member
Posts: 270
Joined: Wed Feb 19, 2020 1:08 pm
Libera.chat IRC: Bonfra
Location: Italy

Re: Debugging the OS with VirtualBox

Post by Bonfra »

Gigasoft wrote:
So I'm a bit retarded when I need to code in assembly...
Wouldn't it be a better idea to learn the x86 architecture before trying to write an OS for it?
Theoretically, I learned it and I can code using it but I still can only do very simple tasks. I know the syntax, I get the logic, the only thing that I miss is experience and I hope to retrieve it by tinkering with this bootloader.
I can't say that I know how to code in assembly 'cause I miss that immediacy I have with c/c++ to recognize immediately the problem. I'm watching some series on youtube about assembly and I'm still learning so, yea, you are totally right
Regards, Bonfra.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Debugging the OS with VirtualBox

Post by Octocontrabass »

Bonfra wrote:basically what it does is adding to ebx (which contains a far address) a a certain bias calculated in the first lines. I wasn't sure about how to increase a non linear addresso so I went for this approach; it works but it's a bit clunky, do you know a better way?
Sectors are always a multiple of 16 bytes large, so you never need to modify the offset part of the address, just the segment part. You can remove all of the code to adjust the offset part.
User avatar
Bonfra
Member
Member
Posts: 270
Joined: Wed Feb 19, 2020 1:08 pm
Libera.chat IRC: Bonfra
Location: Italy

Re: Debugging the OS with VirtualBox

Post by Bonfra »

Yay, it works. Thanks! the VBR successfully loads the actual bootloader and jumps to it. Obviously, now that error is solved another problem came out... Whenever I enable paging and protected mode updating the content of CR0, VirtualBox throws what it calls "a critical error"... I've tried to locate something useful in the log file but I couldn't find anything so I'm posing it here.
Regards, Bonfra.
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: Debugging the OS with VirtualBox

Post by sj95126 »

Well, if I'm reading the VirtualBox output right, you're going into 64-bit mode with an invalid GDT.
User avatar
Bonfra
Member
Member
Posts: 270
Joined: Wed Feb 19, 2020 1:08 pm
Libera.chat IRC: Bonfra
Location: Italy

Re: Debugging the OS with VirtualBox

Post by Bonfra »

sj95126 wrote:Well, if I'm reading the VirtualBox output right, you're going into 64-bit mode with an invalid GDT.
Well, It works with QEMU...

This is the code I use to set the GDT

Code: Select all

Mem.GDT equ 0x00004500

.loadGDT64:
    ; Copy the GDT to its memory layout location.
    mov si, GDT64.Table
    mov di, Mem.GDT
    mov cx, GDT64.Table.Size
    shr cx, 1
    rep movsw
    lgdt [GDT64.Table.Pointer]
And here are the GDT things.
Can you point where is wrong?
Regards, Bonfra.
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: Debugging the OS with VirtualBox

Post by sj95126 »

Well, I'm not entirely sure this is the problem, but you should move the lgdt immediately before enabling PE/PG.

In any case, I was going off the VirtualBox output:

Code: Select all

00:00:10.288550 Guest GDT (GCAddr=0000000000004500 limit=27):
00:00:10.288553 0008 - 00000000 00009300 - base=00000000 limit=00000000 dpl=0 DataRW Accessed Present 16-bit 
00:00:10.288555 0010 - 00000000 00209b00 - base=00000000 limit=00000000 dpl=0 CodeER Accessed Present 16-bit 
00:00:10.288556 0018 - 00000000 0000f200 - base=00000000 limit=00000000 dpl=3 DataRW Present 16-bit 
00:00:10.288557 0020 - 00000000 0020fa00 - base=00000000 limit=00000000 dpl=3 CodeER Present 16-bit 
This pattern (data cpl0, code cpl0, data cpl3, code cpl3) matches your 64-bit GDT but apparently it thinks you've set 16-bit segments.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Debugging the OS with VirtualBox

Post by Octocontrabass »

Bonfra wrote:Whenever I enable paging and protected mode updating the content of CR0, VirtualBox throws what it calls "a critical error"... I've tried to locate something useful in the log file but I couldn't find anything so I'm posing it here.
According to your log file, it's getting a bit further than that before it triple faults.

Code: Select all

00:00:10.286852 rip=000000000010c44f
That address (0x10c44f) should be somewhere inside your kernel binary. I'm not sure exactly where because I don't have a copy of your kernel binary.

Code: Select all

00:00:10.286856 cr0=0000000080000013
CR0 has PG and PE set, so there weren't any issues setting those bits.

Code: Select all

00:00:10.286905 EFER         =0000000000000500
EFER says you're definitely in long mode.

Code: Select all

00:00:10.286953 CPUM0: 0010:000000000010c44f 88 10                   mov byte [rax], dl
The log says this MOV is the cause of the triple fault. There aren't many ways for a MOV instruction to fault, it's either a non-canonical address or a page fault.

Code: Select all

00:00:10.286848 rax=000000000052c000
That looks like a canonical address to me. It's probably a page fault.
sj95126 wrote:This pattern (data cpl0, code cpl0, data cpl3, code cpl3) matches your 64-bit GDT but apparently it thinks you've set 16-bit segments.
I think it's just displaying them wrong. It shows the appropriate bits are set to put the CPU in 64-bit mode.
User avatar
Bonfra
Member
Member
Posts: 270
Joined: Wed Feb 19, 2020 1:08 pm
Libera.chat IRC: Bonfra
Location: Italy

Re: Debugging the OS with VirtualBox

Post by Bonfra »

Octocontrabass wrote: According to your log file, it's getting a bit further than that before it triple faults.
I've located the point where it triple faults with infinite jumps to the line where it enables PG and PE. (this line) maybe has to do with the way I set up paging?
I'm not 100% interested in paging right now so I've used identity mapped to later change it in the kernel code. (paging code)
Octocontrabass wrote: That address (0x10c44f) should be somewhere inside your kernel binary.
That's odd... I've tried to stick an infinite loop at the start of the kernel code but it never triggers so it can't get to that address unless some weird jump happens.
Octocontrabass wrote: I'm not sure exactly where because I don't have a copy of your kernel binary.
I've tried to attach a copy of the binary but it's too big so here is a direct link to download it, and here is the code if you want to check something particular. It links to other two libs but them are also present in that repo
Regards, Bonfra.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Debugging the OS with VirtualBox

Post by Octocontrabass »

Bonfra wrote:I've located the point where it triple faults with infinite jumps to the line where it enables PG and PE. (this line)
Did you use an infinite near JMP? The instruction immediately following a MOV to CR0 that sets PE needs to be a far JMP. A near JMP could cause a fault.
Bonfra wrote:That's odd... I've tried to stick an infinite loop at the start of the kernel code but it never triggers so it can't get to that address unless some weird jump happens.

Code: Select all

kernel.sys:     file format elf64-x86-64
kernel.sys
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000101008

Code: Select all

    jmp Mem.Kernel.Code + (load - 0x7E00) ; wierd elf bug

Code: Select all

Mem.Kernel.Code                     equ 0x00101000
You're not jumping to the entry point, I'd say that's a pretty weird jump. Perhaps you meant to put this variable in the .bss section? Either that, or you need to parse the headers to find the entry point.
User avatar
Bonfra
Member
Member
Posts: 270
Joined: Wed Feb 19, 2020 1:08 pm
Libera.chat IRC: Bonfra
Location: Italy

Re: Debugging the OS with VirtualBox

Post by Bonfra »

Octocontrabass wrote: Did you use an infinite near JMP? The instruction immediately following a MOV to CR0 that sets PE needs to be a far JMP. A near JMP could cause a fault.
Yes, the instruction right after the MOV to CR0 is a far jump to the 64 bit part and at the start of this I've added an infinite near jump, it crushes before reaching that jump. If I place the infinite jump before the mov it does not crush.
Octocontrabass wrote: You're not jumping to the entry point, I'd say that's a pretty weird jump.
I somewhere read that the elf header is always 0x100 bytes and that the entry point is always located after it. Obviously, I must have misunderstood.
Octocontrabass wrote: Perhaps you meant to put this variable in the .bss section? Either that, or you need to parse the headers to find the entry point.
Ups, fixed. Well it does not change the result but still is good to be fixed, thanks.
Regards, Bonfra.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Debugging the OS with VirtualBox

Post by Octocontrabass »

Bonfra wrote:Yes, the instruction right after the MOV to CR0 is a far jump to the 64 bit part and at the start of this I've added an infinite near jump, it crushes before reaching that jump. If I place the infinite jump before the mov it does not crush.
Does the log say it crashes in the same place as before? If it does, you might have better luck stepping through the code to see where it gets lost.
Bonfra wrote:I somewhere read that the elf header is always 0x100 bytes and that the entry point is always located after it. Obviously, I must have misunderstood.
The entry point is wherever you put it. If you want it to be at offset 0x1000 in the ELF file, you have to put it there.
User avatar
Bonfra
Member
Member
Posts: 270
Joined: Wed Feb 19, 2020 1:08 pm
Libera.chat IRC: Bonfra
Location: Italy

Re: Debugging the OS with VirtualBox

Post by Bonfra »

Octocontrabass wrote: Does the log say it crashes in the same place as before? If it does, you might have better luck stepping through the code to see where it gets lost.
I've double-checked and it turns out it crashes in the exact address I set the jump. So if I place the jump right at the start of the kernel it triple faults at 0x101000 (which is the address of the entry point)
Regards, Bonfra.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Debugging the OS with VirtualBox

Post by Octocontrabass »

It sounds an awful lot like interrupts are enabled...

Code: Select all

00:00:10.286859 gdtr=0000000000004500:0027  idtr=0000000000000000:ffff  eflags=00210206
Oh, how about that, interrupts are enabled. Did you forget to disable interrupts before switching to long mode? Some BIOS calls require interrupts to be enabled and will not disable them before returning to your code.
Post Reply