Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identifying faulting address on General Protection Fault (x86)

I am trying to write a ISR for the General Protection Fault (GP#13) on x86. I am unable to figure out from the INTEL docs as to how I can find out the faulting address causing the exception. I know that for Page fault exceptions (GP#14) the cr2 register holds the faulting address. Any help is appreciated.

like image 877
rss Avatar asked Apr 28 '12 05:04

rss


People also ask

What is the most common cause of a general protection fault?

A general protection fault is more likely to occur when you are trying out beta test-version software. However, even well-seasoned applications can cause a general protection fault because a user hits some combination of keys in quick succession that the programmer could not easily anticipate.

What is General detect fault?

A General Protection Fault (GPF) is a Windows system error message. A GPF is not an error within an application, but an error in the Windows operating system itself. A GPF typically occurs when the active application is reading or writing to a section of RAM that is unavailable at that time.


1 Answers

All references I make here are from AMD64 Architecture Programmer's Manual Volume 2: System Programming, which also describes the legacy protected-mode (i.e., x86) behavior.

Figure 8-8 on page 240 shows the stack layout after an interrupt to the same privilege level (that is, the stack layout when an ISR is entered):

Stack After Interrupt to Same Privilege Level

In Section 8.2.14, you can see that #GP provides an error code and the following is also of interest:

Program Restart. #GP is a fault-type exception. In most cases, the saved instruction pointer points to the instruction that caused the #GP. See “Exceptions During a Task Switch” on page 230 for a description of the consequences when this exception occurs during a task switch.

The referenced section mentions the following:

An exception can occur during a task switch while loading a segment selector. Page faults can also occur when accessing a TSS. In these cases, the hardware task-switch mechanism completes loading the new task state from the TSS, and then triggers the appropriate exception mechanism. No other checks are performed. When this happens, the saved instruction pointer points to the first instruction in the new task.

So, unless you are using hardware task switching, the saved instruction pointer always point to the faulting instruction.

To get the address of the faulting instruction, simple get the saved EIP and CS values from the stack in your ISR. (If you're using a flat memory model and all your segments cover the whole 4GB, the saved CS is of no interest, of course).

movl 4(%esp), %eax
movw 8(%esp), %ebx

Now, EAXcontains the saved EIP and EBX the saved CS.

Edit: Of course, as pointed out by Alex in the comments, in case the #GP was caused by a memory access and you want the address of the accessed memory, you will need to decode the faulting instruction.

like image 149
mtvec Avatar answered Jan 04 '23 17:01

mtvec