(Fixed) Different Panic Values

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.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

(Fixed) Different Panic Values

Post by Octacone »

Original problem: wrong panic values, different values on different emulators
Solution: bitwise AND your segment registers by 0xFFFF, a common handler must match your registers struct
Last edited by Octacone on Tue Apr 18, 2017 6:15 am, edited 4 times in total.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Peterbjornx
Member
Member
Posts: 116
Joined: Thu May 06, 2010 4:34 am
Libera.chat IRC: peterbjornx
Location: Leiden, The Netherlands
Contact:

Re: Different Panic Values

Post by Peterbjornx »

Your structure is wrong, the segment registers are 16 bits long, hence they will only be pushed as uint16_t, not 32_t ( x86 does not require stack alignment on 32 bit words so no upcasting is done ), you are thus reading the wrong parts of the stack.

An important indicator of this failure is getting a value > 0xFFFF for a 16 bit register, which is simply not possible ( your other post where you said "I had no idea a 16 bit int could hold a 24 bit number" is simply nonsensical as a native 16 bit register generally only consists of 16 memory elements )
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Different Panic Values

Post by Octacone »

Peterbjornx wrote:Your structure is wrong, the segment registers are 16 bits long, hence they will only be pushed as uint16_t, not 32_t ( x86 does not require stack alignment on 32 bit words so no upcasting is done ), you are thus reading the wrong parts of the stack.

An important indicator of this failure is getting a value > 0xFFFF for a 16 bit register, which is simply not possible ( your other post where you said "I had no idea a 16 bit int could hold a 24 bit number" is simply nonsensical as a native 16 bit register generally only consists of 16 memory elements )
I was suspecting that too, but nothing has changed. Now I am just getting zeros. Some things are okay, but most of them are not.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Re: Different Panic Values

Post by JAAman »

Peterbjornx wrote:Your structure is wrong, the segment registers are 16 bits long, hence they will only be pushed as uint16_t, not 32_t ( x86 does not require stack alignment on 32 bit words so no upcasting is done ), you are thus reading the wrong parts of the stack.
that is wrong... when you push a segment register in 32-bit mode (that is, with a 32-bit operation size), the register will be zero-extended to 32-bits (not 16-bits)

if you push with a 16-bit size (in 16-bit mode, or 32-bit mode with an o32 override) then you are correct, but in 32-bit mode (while nothing enforces the stack alignment) all pushes are 32-bits wide, including pushes of segment registers

note pushes of 16-bit GPRs require an o32 override (which will change the write size to 16-bit) so pushes of 16-bit GPRs do appear on the stack as 16-bit values, but pushes of segment registers (without an o32) will appear as 32-bit values on the stack -- of course if you add a pointless o32 to a push segment register instruction, then only 16-bits will be pushed to the stack, but otherwise, 32-bits will always be pushed to the stack
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

Re: Different Panic Values

Post by Ch4ozz »

Peterbjornx wrote:Your structure is wrong, the segment registers are 16 bits long, hence they will only be pushed as uint16_t, not 32_t ( x86 does not require stack alignment on 32 bit words so no upcasting is done ), you are thus reading the wrong parts of the stack.

An important indicator of this failure is getting a value > 0xFFFF for a 16 bit register, which is simply not possible ( your other post where you said "I had no idea a 16 bit int could hold a 24 bit number" is simply nonsensical as a native 16 bit register generally only consists of 16 memory elements )
This is wrong, in 32 bit protected mode all stack pushes are aligned to 32 bit...
Changing it to 16bit and still having the keyword packed will **** up hard time
Incase you change the registers to uint16_t you need to pad the rest 16 bits with an empty/unused variable!
Actually the first 2 digits of your selectors are pretty much right, so simply and them with 0xFFFF or change uint32_t to 2 uint16_t's

This is mine:

Code: Select all

typedef struct
{
    // pushed by stub
    uint32_t eax;
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;
    uint32_t esi;
    uint32_t edi;
    uint32_t ebp;
    uint16_t ds, ds_pad;
    uint16_t es, es_pad;
    uint16_t fs, fs_pad;
    uint16_t gs, gs_pad;
	
    uint32_t intr;
    uint32_t error;
	
    // pushed by cpu
    uint32_t eip;
    uint16_t cs, cs_pad;
    uint32_t eflags;
    uint32_t esp;
    uint16_t ss, ss_pad;
} __attribute__((packed)) CPU_STATE;
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Different Panic Values

Post by Octacone »

Ch4ozz wrote:
Peterbjornx wrote:Your structure is wrong, the segment registers are 16 bits long, hence they will only be pushed as uint16_t, not 32_t ( x86 does not require stack alignment on 32 bit words so no upcasting is done ), you are thus reading the wrong parts of the stack.

An important indicator of this failure is getting a value > 0xFFFF for a 16 bit register, which is simply not possible ( your other post where you said "I had no idea a 16 bit int could hold a 24 bit number" is simply nonsensical as a native 16 bit register generally only consists of 16 memory elements )
This is wrong, in 32 bit protected mode all stack pushes are aligned to 32 bit...
Changing it to 16bit and still having the keyword packed will **** up hard time
Incase you change the registers to uint16_t you need to pad the rest 16 bits with an empty/unused variable!
Actually the first 2 digits of your selectors are pretty much right, so simply and them with 0xFFFF or change uint32_t to 2 uint16_t's

This is mine:

Code: Select all

typedef struct
{
    // pushed by stub
    uint32_t eax;
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;
    uint32_t esi;
    uint32_t edi;
    uint32_t ebp;
    uint16_t ds, ds_pad;
    uint16_t es, es_pad;
    uint16_t fs, fs_pad;
    uint16_t gs, gs_pad;
	
    uint32_t intr;
    uint32_t error;
	
    // pushed by cpu
    uint32_t eip;
    uint16_t cs, cs_pad;
    uint32_t eflags;
    uint32_t esp;
    uint16_t ss, ss_pad;
} __attribute__((packed)) CPU_STATE;
Hey Ch4ozz, I tried both of your suggestions and neither of them worked. I am confused. Does the struct order matter? Does it have to go like: eax, ebx, ecx, edx...,ds, es, fs... I guess it has to match with the values that are being pushed one by one.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Different Panic Values

Post by Octocontrabass »

octacone wrote:Do these panic values seem okay to you?
As far as I can tell, it's all normal.

Your SS and (user) ESP values are garbage because there's no privilege level change. If you cause a fault in usermode, you'll see normal values there. Since you're causing a fault in kernel mode, the CPU didn't push SS:ESP onto the stack. (Also, you should rename "esp" in your struct to "useless_padding".)
octacone wrote:3 different emulator 3 different outputs!?
Yep.

The segment registers are different because some emulators zero the high 16 bits of the dword when they push a segment register to a 32-bit stack, and other emulators leave the high bits alone. Cast to uint16_t or bitwise AND with 0xFFFF before printing them.

I suspect EFLAGS.RF, CR0.CD, and CR0.NW are different because you didn't initialize them. (Be careful if you decide to mess with CR0. The CD and NW bits mean different things on different CPUs.)
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Different Panic Values

Post by Octacone »

Octocontrabass wrote:
octacone wrote:Do these panic values seem okay to you?
As far as I can tell, it's all normal.

Your SS and (user) ESP values are garbage because there's no privilege level change. If you cause a fault in usermode, you'll see normal values there. Since you're causing a fault in kernel mode, the CPU didn't push SS:ESP onto the stack. (Also, you should rename "esp" in your struct to "useless_padding".)
octacone wrote:3 different emulator 3 different outputs!?
Yep.

The segment registers are different because some emulators zero the high 16 bits of the dword when they push a segment register to a 32-bit stack, and other emulators leave the high bits alone. Cast to uint16_t or bitwise AND with 0xFFFF before printing them.

I suspect EFLAGS.RF, CR0.CD, and CR0.NW are different because you didn't initialize them. (Be careful if you decide to mess with CR0. The CD and NW bits mean different things on different CPUs.)


Thanks for explaining. Now it makes much more sense.

I did as you said and here is how it looks now:
...removed...for post clearance...

I think something is very wrong -> This is how I am triggering my fault: TUI.Put_Int(1 / 0, 0x0F); -> whenever I change that number to lets say 6, I get a corresponding error message. Something must be wrong. Is my common handler fine? Does that struct have any specific order in which I should put it. Does it matter how those values are defined one after other?
Last edited by Octacone on Tue Apr 18, 2017 6:17 am, edited 2 times in total.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Different Panic Values

Post by Octocontrabass »

octacone wrote:I did as you said and here is how it looks now:
Your assembly handler and C struct do not match. Whatever you changed broke it.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

(Fixed) Different Panic Values

Post by Octacone »

Octocontrabass wrote:
octacone wrote:I did as you said and here is how it looks now:
Your assembly handler and C struct do not match. Whatever you changed broke it.
Solved! :D
I found my old struct and "mounted" it, now everything works perfectly.

Thanks everybody for helping me out, I just wanted to be sure that my code has no flaws.
Better work on something for days than cry later.

Final render:
Solved.png
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Peterbjornx
Member
Member
Posts: 116
Joined: Thu May 06, 2010 4:34 am
Libera.chat IRC: peterbjornx
Location: Leiden, The Netherlands
Contact:

Re: (Fixed) Different Panic Values

Post by Peterbjornx »

Please do not remove your questions after they are resolved, a forum serves not just as a way to ask questions but also to find existing solutions.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: (Fixed) Different Panic Values

Post by Octacone »

Peterbjornx wrote:Please do not remove your questions after they are resolved, a forum serves not just as a way to ask questions but also to find existing solutions.
Please do not bump old threads.

Everything important is there. I simplified the question so people browsing can find the solution right away. Please do not reply to dead threads anymore.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: (Fixed) Different Panic Values

Post by LtG »

Octacone wrote:
Peterbjornx wrote:Please do not remove your questions after they are resolved, a forum serves not just as a way to ask questions but also to find existing solutions.
Please do not bump old threads.

Everything important is there. I simplified the question so people browsing can find the solution right away. Please do not reply to dead threads anymore.
I usually don't consider three week old threads that old.. But I have to agree, modifying the OP is really annoying, modifying any post is annoying.. Fixing typo's is ok and _adding_ an edit is fine, but completely rewriting any post basically kills the flow of the thread..

If you want to help the people who might read the thread in the future then you might want to add an edit where you give the answer, but rewriting the OP shouldn't be necessary..

Just my 2c..
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: (Fixed) Different Panic Values

Post by Octacone »

LtG wrote:
Octacone wrote:
Peterbjornx wrote:Please do not remove your questions after they are resolved, a forum serves not just as a way to ask questions but also to find existing solutions.
Please do not bump old threads.

Everything important is there. I simplified the question so people browsing can find the solution right away. Please do not reply to dead threads anymore.
I usually don't consider three week old threads that old.. But I have to agree, modifying the OP is really annoying, modifying any post is annoying.. Fixing typo's is ok and _adding_ an edit is fine, but completely rewriting any post basically kills the flow of the thread..

If you want to help the people who might read the thread in the future then you might want to add an edit where you give the answer, but rewriting the OP shouldn't be necessary..

Just my 2c..
Why would that be annoying? From now on I will just leave those hard to understand questions and let people search trough ton of comments to find the answer. Why would somebody want a "broken" question? It is not any different in terms of the topic. But whatever, as you two suggested leave the 30 min to read question... Okay, not a problem.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: (Fixed) Different Panic Values

Post by Octacone »

LtG wrote:
Octacone wrote:
Peterbjornx wrote:Please do not remove your questions after they are resolved, a forum serves not just as a way to ask questions but also to find existing solutions.
Please do not bump old threads.

Everything important is there. I simplified the question so people browsing can find the solution right away. Please do not reply to dead threads anymore.
I usually don't consider three week old threads that old.. But I have to agree, modifying the OP is really annoying, modifying any post is annoying.. Fixing typo's is ok and _adding_ an edit is fine, but completely rewriting any post basically kills the flow of the thread..

If you want to help the people who might read the thread in the future then you might want to add an edit where you give the answer, but rewriting the OP shouldn't be necessary..

Just my 2c..
Why would that be annoying? From now on I will just leave those hard to understand questions and let people search trough ton of comments to find the answer. Why would somebody want a "broken" question? It is not any different in terms of the topic. But whatever, as you two suggested leave the 30 min to read question... Okay, not a problem.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Post Reply