General protection fault in 64 bit mode

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.
Post Reply
xaliver
Posts: 2
Joined: Thu Dec 17, 2015 9:44 am
Libera.chat IRC: xaliver

General protection fault in 64 bit mode

Post by xaliver »

I want to know how to find code address which occurs GPF, and how to use error code.

Currently I am making a x86 custom OS with C++.
Somedays ago, I added interrupt handler and enalbed interrupt.
However, general portection fault occures after interrupt is enabled.

So, I added some debugging code to find where the GPF generates.
When a GPF happens, this assembly code is executed.

Code: Select all

    
    ; #13, General Protection ISR
    _kISRGeneralProtection:
    KSAVECONTEXT                    ; Store the context and change selector to
                                    ; kernel data descriptor
                                    
    ; Insert exception number and error code to the hander and call the handler
    mov rdi, 13
    mov rsi, qword [rbp + 8]
    mov rdx, qword [rbp + 16]
    mov rcx, qword [rbp + 24]
    call _kCommonExceptionHandler
    
    KLOADCONTEXT                    ; Restore the context
    add rsp, 8                      ; Remove error code from stack
    iretq                           ; Return the event point after interrupt
                                    ; handling
The four parameters are passed to kCommonExceptionHandler.
They are the interrupt vector number, the error code, the RIP, and the CS.

The below code show how to print the values.

Code: Select all

    void kUtils::kPrintException(const char* pcVectorNumber, 
                             const char* pcErrorCode,
                             const char* pcRIP,
                             const char* pcCS)
    {
    kPrintString(0, 0,
        "===========================================================");
    kPrintString(0, 1, 
        "                     Exception Occur                       ");
    kPrintString(0, 2, 
        "                  Vector:                                  ");
    kPrintString(0, 3, 
        "              Error Code: 0x                               ");
    kPrintString(0, 4, 
        "                     RIP: 0x                               ");
    kPrintString(0, 5, 
        "                      CS: 0x                               ");
    kPrintString(0, 6, 
        "===========================================================");
    
    kPrintString(26, 2, pcVectorNumber);
    kPrintString(28, 3, pcErrorCode);
    kPrintString(28, 4, pcRIP);
    kPrintString(28, 5, pcCS);
 
    return;
    }

    void kIH::kDecodeError(unsigned long qwCode, char* cMean)
    {
    unsigned long ulMask = 0xF;
    unsigned long ulValue;
    char c;
    
    for (int i = 0; i < 16; i++)
    {
        ulValue = qwCode & ulMask;
        
        if (ulValue > 9)
        {
            c = 'A' + ulValue - 10;
        }
        else
        {
            c = '0' + ulValue;
        }
        
        cMean[15 - i] = c;
        
        qwCode = qwCode >> 4;
    }
    
    return;
    }

    // Common exception handler
    void kIH::kCommonExceptionHandler(int iVectorNumber, unsigned long qwErrorCode, unsigned long qwRIP, unsigned long qwCS)
    {
    char cNumber[3] = { 0, };
    char cErrorCode[17] = { 0, };
    char cRIP[17] = {0, };
    char cCS[17] = {0, };
    
    // Print interrupt vector number as 2 digit number
    cNumber[0] = '0' + iVectorNumber / 10;
    cNumber[1] = '0' + iVectorNumber % 10;
    
    kDecodeError(qwErrorCode, cErrorCode);
    kDecodeError(qwRIP, cRIP);
    kDecodeError(qwCS, cCS);
    
    g_pclUtils->kPrintException(cNumber, cErrorCode, cRIP, cCS);
    
    while (1);

    }
Then, the reults is

Code: Select all

          Vector: 13
    Error Code: 0x000000000020139D
              RIP: 0x00000000007FFFD0
               CS: 0x000000000000FF18
The code address for GPF can be found CS*0x10 + RIP, so 0x80FF150 is the address. However, when I dumped object of my custom OS, the last code address is 0x20367a.

What did I make a mistake? And in this case, how can I get an useful information from error code?
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: General protection fault in 64 bit mode

Post by iansjack »

Your calculation of the faulting address is at fault. It is simply the value of RIP. But your value of CS is not credible, so I don't believe your reported RIP is correct either.

Run the code under a debugger with a breakpoint set at the entry to your fault-handling routine. Then you can inspect the stack and discover the true values.
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: General protection fault in 64 bit mode

Post by Octocontrabass »

xaliver wrote:CS*0x10 + RIP
That's not how segment registers work in long mode.
Post Reply