-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
x86 Call to Interrupt Procedure (INT imm8) has improper definition for 16-bit real mode #7342
Comments
The only change here is restoring the stack pointer. I don't know enough about how the stack pointer works with interrupts in x86, should this be done automatically? It might be worth taking a closer look at interrupt stack behavior. We would almost certainly want to save and restore the entire stack pointer (e.g. RSP/ESP), and should definitely incorporate adding the return address to the push. |
I'm not proficient enough to give a qualified answer regarding that matter. I only read a brief description of this instruction and haven't looked into a proper manual. My only concern is related to the fact that the current p-code definition of this instruction is spoiling the stack accordingly to the decompiler output. Nonetheless, a proper implementation of this instruction for 16-bit real mode should follow the next logic: call to interrupt procedure (INT imm8 in particular) is similar to a far call, i.e. it's supposed to store 32-bit address consisting of the current code segment and the next instruction pointer (CS:IP pair) on the stack, however it's also supposed to push FLAGS register onto the stack beforehand. It is IRET instruction responsibility to restore the flags and clean up the stack before performing far return and resuming code execution. I've also been able to observe and confirm this exact behavior via DOSBox debugger. Considering the fact that this instruction behaves quite differently for various cpu modes, it's probably worth to add a distinct definition for a real mode and keep the old definition intact for the time being:
|
@swine-flu, your band-aid to the INT pcode I believe doesn't deliver the result you're actually looking for as your decompilation screenshots still shows two calls to INT 0x10 but not the actual INT function and subfunctions in the AH and AL registers.
|
@ABratovic, I've got all the necessary info regarding interrupts being displayed as comments in my project, as a matter of fact the vast majority of them is hidden behind the Turbo Pascal API and its RTL, so not having them substituted with pseudofunctions doesn't bother me that much. Better support for BIOS and DOS interrupts had been discussed already, see #2266. Implementing such a feature is a tall order and I'm not expecting to see anything like that any time soon. |
Describe the bug
Stack is not being properly cleaned up after issuing a call to this procedure in x86-16 real mode application. Improper definition of INT imm8 seems to be what causing this issue:
ghidra/Ghidra/Processors/x86/data/languages/ia.sinc
Line 3193 in 067ddfe
To Reproduce
Having an interrupt call somewhere at the beginning of the function containing local variables makes this bug apparent. Accordingly to the decompiler output, arbitrary modifications are being made to local variables lying on top of the stack while there is nothing in the assembly code which could be related to these changes.
Expected behavior
I'm not expecting INT imm8 definition to perfectly replicate its actual semantics for a real mode, i.e. storing the flags on the stack before the call and also utilizing IDT to resolve the address, performing something semantically close to a far call should suffice I presume. For the time being I ended up with the following band-aid fix:
Screenshots
Here is the comparison of two decompilations - with and without a fix:
Environment (please complete the following information):
The text was updated successfully, but these errors were encountered: