OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 16, 2024 1:46 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Exception handling error
PostPosted: Wed Oct 21, 2020 12:13 pm 
Offline
Member
Member

Joined: Mon Apr 20, 2020 11:02 am
Posts: 91
I was trying to get interrupts working on my OS, I set up the IDT and PIC, and I even successfully implemented 8254 IRQ 0 and tested it. Before going on to keyboard driver, I decided to implement handler for all exceptions, as they are currently handled by a dummy handler which does nothing.

Firstly, I implemented Division by zero, by calling a C function from assembly to print a message and wait for 5 seconds and then simply return. When I manually called the interrupt, it works fine. However, if I actually made a divide by zero error, it calls the interrupt, but that's the problem; it keeps calling it. I even tried to "return" to a different function, but as soon as it returned, it immediately gets re-triggered.

What is happening? I couldn't find anything in osdev like this.

_________________
A beginner developer/student. Likes to know stuff. Don't have an OS to put here.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 12:31 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
Most exceptions are exact. This means that the CS:EIP in the IRET frame points to the faulting instruction. In your case, you have a faulting "div" instruction (or similar), so the IRET frame contains the address of that instruction, and when you IRET, you return exactly back to the faulting instruction. Which immediately faults again.

Now, sometimes this is what you want. Consider the case of a page fault, where some access fails, but only because a page has been removed temporarily. In that case, you suspend the faulting process, fix the problem, and return to the process when you're done. That way, the process can repeat the instruction that failed, and this time it won't fail.

But in most cases, you cannot handle an exception by simply returning, as the fault will just re-occur. Most faults in kernel space should probably be handled by a kernel panic. That means: Print as much information about the fault that occurred as you can (exception number, EIP and ESP of the failing context, maybe the other registers, and a stack trace is always helpful), and then stop the system. If you support multiple CPUs, send IPIs to them to stop them, then execute HLT in an endless loop. The reason is that in that case the kernel is faulty and must be stopped.

If a userspace program failed, then it is really up to you to decide what should happen. UNIX sends a signal to the program, Windows causes an exception to happen (which, if not caught, leads to the wonderful "foobar.exe does not work anymore" screen we all know and love). Whatever you do, don't just return, as that won't fix things.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 12:42 pm 
Offline
Member
Member

Joined: Mon Apr 20, 2020 11:02 am
Posts: 91
nullplan wrote:
Most exceptions are exact. This means that the CS:EIP in the IRET frame points to the faulting instruction. In your case, you have a faulting "div" instruction (or similar), so the IRET frame contains the address of that instruction, and when you IRET, you return exactly back to the faulting instruction. Which immediately faults again.


But I tried changing the return address by poping the flags and then poping the return address to ebx, changing it to another function, pushing ebx and then flags and then issuing iret instruction. The same thing happens again. But this time, it flickers for a split second showing the output of the function I had given

_________________
A beginner developer/student. Likes to know stuff. Don't have an OS to put here.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 12:51 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5134
Does that function try to return using the garbage left on the stack by the previous function?


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 12:52 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
You know, you can just modify things in memory, without having to pop them off the stack. Besides, EIP is on top of stack before IRET. If you did what you described, then you changed CS, not EIP. So, you want:
Code:
mov [esp], other_func
iretd

It would seem to me you managed to divert your interrupt return somewhere else, but that somewhere else just ended up faulting on its own.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 12:57 pm 
Offline
Member
Member

Joined: Mon Apr 20, 2020 11:02 am
Posts: 91
nullplan wrote:
You know, you can just modify things in memory, without having to pop them off the stack. Besides, EIP is on top of stack before IRET. If you did what you described, then you changed CS, not EIP.


Can I set it to ebp to simultaneously clear the garbage in stack before jumping to new location?

Also, doesn't interrupts causes flags to be pushed on to the stack? So how should I set up the stack? flags, return or vice versa?

_________________
A beginner developer/student. Likes to know stuff. Don't have an OS to put here.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 1:39 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5134
pranavappu007 wrote:
Can I set it to ebp to simultaneously clear the garbage in stack before jumping to new location?

What will it return to if you do that? Can you guarantee that EBP holds a reasonable value?


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 9:18 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
pranavappu007 wrote:
Can I set it to ebp to simultaneously clear the garbage in stack before jumping to new location?
IRET removes the frame from stack. That is, if no change of privilege takes place, it increases ESP by 12. If a change of privilege takes place, the point is kind of moot, since stacks are switched.

pranavappu007 wrote:
Also, doesn't interrupts causes flags to be pushed on to the stack? So how should I set up the stack? flags, return or vice versa?
It does, but it pushes flags first. You would know that if your read the processor manual. Search for Intel Software Developer's Manual, or for AMD Architecture Programmer's Manual, depending on taste. They are both describing the same architecture, so the differences are minuscule. You want volume 2 in either case, since that is system programming for both vendors. And they will tell you that in 32-bit mode, an interrupt frame contains EIP, CS, and flags, in that order on stack (looking up from ESP). If the CS indicates that a change in privilege took place, then ESP and SS follow.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 9:32 pm 
Offline
Member
Member

Joined: Mon Apr 20, 2020 11:02 am
Posts: 91
Does something like this will work?
Code:
mov esp, ebp                               ;clearing the stack
pushf                                      ;pushing the flags
mov ebx, other_function                     ;getting the pointer to non-error function
push ebx
iretd


Does this trick work at all? Does it need any modification?

_________________
A beginner developer/student. Likes to know stuff. Don't have an OS to put here.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 9:40 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5134
Can you guarantee that EBP holds a reasonable value?

What will happen when other_function() returns? What will it return to? Will it be able to restore the callee-saved registers properly?

Also, if you come up with a solution to the above problems, you still need to put a CS selector on the stack between the flags and the return address.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 10:04 pm 
Offline
Member
Member

Joined: Mon Apr 20, 2020 11:02 am
Posts: 91
Octocontrabass wrote:
Can you guarantee that EBP holds a reasonable value?

What will happen when other_function() returns? What will it return to? Will it be able to restore the callee-saved registers properly?

Also, if you come up with a solution to the above problems, you still need to put a CS selector on the stack between the flags and the return address.


If my understanding is correct, ebp holds the start of the frame created by a C function. I can make sure no division by zero exception occurs st start of my program. So if I set esp as ebp, then it should reset the stack frame by the function which caused div by zero.



For function return, it confess I didn't think about it. But now, I think I should create a managing function that never returns but manage this sort of thing. But inorder not to create unnecessary stack frames, I might do it in assembly.

So I should push the CS to the stack, before the address?

_________________
A beginner developer/student. Likes to know stuff. Don't have an OS to put here.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Wed Oct 21, 2020 10:47 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5134
pranavappu007 wrote:
If my understanding is correct, ebp holds the start of the frame created by a C function.

Only if the compiler has decided a frame pointer is necessary for the function. It may use EBP for something else, and then you have no idea where the stack will be.

pranavappu007 wrote:
For function return, it confess I didn't think about it. But now, I think I should create a managing function that never returns but manage this sort of thing. But inorder not to create unnecessary stack frames, I might do it in assembly.

In that case, why return at all? Use an ordinary jump to go to your managing function.

pranavappu007 wrote:
So I should push the CS to the stack, before the address?

Yep.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Thu Oct 22, 2020 12:16 am 
Offline
Member
Member

Joined: Mon Apr 20, 2020 11:02 am
Posts: 91
Octocontrabass wrote:
In that case, why return at all? Use an ordinary jump to go to your managing function.


If I didn't do 'iret', doesn't the entire program code then be treated as part of ISR? I still have flat overlapping memory segments, but still can you do it?How does the CPU know the exception handling is done?

_________________
A beginner developer/student. Likes to know stuff. Don't have an OS to put here.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Thu Oct 22, 2020 12:19 am 
Offline
Member
Member

Joined: Mon Apr 20, 2020 11:02 am
Posts: 91
Octocontrabass wrote:
Only if the compiler has decided a frame pointer is necessary for the function. It may use EBP for something else, and then you have no idea where the stack will be.


Then how the compiler manages the stack? If ebp is used for something else, then isn't the entire stack is lost? OR does it store the stack pointer somewhere else?

_________________
A beginner developer/student. Likes to know stuff. Don't have an OS to put here.


Top
 Profile  
 
 Post subject: Re: Exception handling error
PostPosted: Thu Oct 22, 2020 2:35 am 
Offline
Member
Member
User avatar

Joined: Tue Sep 15, 2020 8:07 am
Posts: 264
Location: London, UK
pranavappu007 wrote:
Octocontrabass wrote:
Only if the compiler has decided a frame pointer is necessary for the function. It may use EBP for something else, and then you have no idea where the stack will be.


Then how the compiler manages the stack? If ebp is used for something else, then isn't the entire stack is lost? OR does it store the stack pointer somewhere else?


I’m new to x86 asm, but as I understand it, ESP is the stack pointer, EBP is just the stack frame pointer. If the function doesn’t require its own stack frame, then the compiler can use the register for other things like passing in the address of the return variable/structure (I’ve seen gcc do this).

If you’ve entered the function via an interrupt, you know what the stack above the ESP stack pointer will contain (the interrupt stack frame and whatever you might have pushed during your interrupt handling).

-edit- if you want a clean return from a CPU exception, you need to build a recovery stack somewhere, you’ll need to manually build a stack frame to match what the CPU expects to find on the stack when it executes an iret... set the ip position in the clean stack frame to point to a recovery function. Then set the ESP register to this clean stack and execute iret.

This stuff is much easier with multitasking as you can just suspend the faulting task from the ready list, and swap in a good task.

_________________
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su


Last edited by bloodline on Thu Oct 22, 2020 3:00 am, edited 5 times in total.

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 520 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group