OS/2 codes: How to emulate COPY-ON-WRITE #2 Exception handler

In the previous article, we looked into a basic structure of a main function. In that, the last question was how to catch write access to the registered memory blocks.

Here is the answer. It's the exception. We removed WRITE permission of the memory blocks. Because of this, writing to those blocks causes an exception, so called SIGSEGV.

To catch such exceptions, we should implement exception handlers. Exception handler is like this:

ULONG _System sigsegv( PEXCEPTIONREPORTRECORD p1,
                       PEXCEPTIONREGISTRATIONRECORD p2,
                       PCONTEXTRECORD p3,
                       PVOID pv );

Out of the above parameters, p1 is the most important. p1->ExceptionNum is the exception code. Here 0xc0000005(XCPT_ACCESS_VIOLATION). p1->ExceptionInfo[0] contains flags for the cause of the exception. For example, XCPT_READ_ACCESS for READ acess and XCPT_WRITE_ACCESS for WRITE access. p1->Exceptioninfo[1] is the fault address.

Return value is XCPT_CONTINUE_EXECUTION which means an exception was handled properly or XCPT_CONTINUE_SEARCH which means a exception was not handled. If XCPT_CONTINUE_EXECUTION is returned, an exception does not propagate any more. That is, an exception is not passed to any other exception handlers in chains. Execution of a thread continues from the place where an exception occurred. If XCPT_CONTINUE_SEARCH is returned, an exception is passed to the next handlers.

Exception handlers catches all exceptions regardless of their type. It's needed to determine if the given exception is what we want.

What we want is WRITE access. In case of this, p1->ExceptionNum is XCPT_ACCESS_VIOLATION, p1->ExceptionInfo[0] contains XCPT_WRITE_ACCESS flag.
Finally, we should check the fault address because we should not process the exception occured at the place not in the registered blocks.

Real codes are like this:

/* Check if WRITE access violation */
if( p1->ExceptionNum == XCPT_ACCESS_VIOLATION
    && ( p1->ExceptionInfo[ 0 ] & XCPT_WRITE_ACCESS ))
{
    /* Exception address */
    void *pStart = ( void * )p1->ExceptionInfo[ 1 ];

    if( reallocDestMem( pStart, ( char * )pStart + 1, true ))
        return XCPT_CONTINUE_EXECUTION; /* Continue to execution */
}

/* Not processed or other signal exception occurred */

/* Continue to search other exception handler */
return XCPT_CONTINUE_SEARCH;

reallocDestMem() is the function which frees affected aliased memory blocks, allocate new memory blocks at the same address as the aliased blocks and restores access flags of the memory blocks.

To activate an exception handler, we should install the exception handler. Exception handler is registered per thread. After all, we should install the above handler on every thread. How ? Let's see in the next article. ^^


댓글

이 블로그의 인기 게시물

토렌트: < 왕좌의 게임 > 시즌 1 ~ 시즌 8 완결편 마그넷

토렌트: NGC < 코스모스 > 우리말 더빙 전편(1편~13편) 마그넷

토렌트: < 스타워즈 > Ep.1 ~ Ep.6 마그넷