OSDev.org
https://forum.osdev.org/

Exception handling error
https://forum.osdev.org/viewtopic.php?f=1&t=37381
Page 1 of 2

Author:  pranavappu007 [ Wed Oct 21, 2020 12:13 pm ]
Post subject:  Exception handling error

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.

Author:  nullplan [ Wed Oct 21, 2020 12:31 pm ]
Post subject:  Re: Exception handling error

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.

Author:  pranavappu007 [ Wed Oct 21, 2020 12:42 pm ]
Post subject:  Re: Exception handling error

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

Author:  Octocontrabass [ Wed Oct 21, 2020 12:51 pm ]
Post subject:  Re: Exception handling error

Does that function try to return using the garbage left on the stack by the previous function?

Author:  nullplan [ Wed Oct 21, 2020 12:52 pm ]
Post subject:  Re: Exception handling error

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.

Author:  pranavappu007 [ Wed Oct 21, 2020 12:57 pm ]
Post subject:  Re: Exception handling error

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?

Author:  Octocontrabass [ Wed Oct 21, 2020 1:39 pm ]
Post subject:  Re: Exception handling error

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?

Author:  nullplan [ Wed Oct 21, 2020 9:18 pm ]
Post subject:  Re: Exception handling error

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.

Author:  pranavappu007 [ Wed Oct 21, 2020 9:32 pm ]
Post subject:  Re: Exception handling error

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?

Author:  Octocontrabass [ Wed Oct 21, 2020 9:40 pm ]
Post subject:  Re: Exception handling error

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.

Author:  pranavappu007 [ Wed Oct 21, 2020 10:04 pm ]
Post subject:  Re: Exception handling error

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?

Author:  Octocontrabass [ Wed Oct 21, 2020 10:47 pm ]
Post subject:  Re: Exception handling error

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.

Author:  pranavappu007 [ Thu Oct 22, 2020 12:16 am ]
Post subject:  Re: Exception handling error

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?

Author:  pranavappu007 [ Thu Oct 22, 2020 12:19 am ]
Post subject:  Re: Exception handling error

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?

Author:  bloodline [ Thu Oct 22, 2020 2:35 am ]
Post subject:  Re: Exception handling error

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.

Page 1 of 2 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/