1

を呼び出して、gcc を使用して x64 Windows で SEH をセットアップしようとしていますRtlAddFunctionTable。残念ながら、API 呼び出しは成功を返しますが、私のハンドラーは呼び出されないようです。そして、何が悪いのかわかりません。私の小さな例は次のとおりです。

EXCEPTION_DISPOSITION catchDivZero( struct _EXCEPTION_RECORD* rec
                                  , void* arg1 __attribute__((unused))
                                  , struct _CONTEXT* ctxt __attribute__((unused))
                                  , void* arg2 __attribute__((unused))
                                  )
{
    printf("Exception will be handled!\n");
    return ExceptionContinueSearch;
}

HMODULE GetCurrentModule()
{ // NB: XP+ solution!
    HMODULE hModule = NULL;
    GetModuleHandleEx(
        GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
        (LPCTSTR)GetCurrentModule,
        &hModule);

    return hModule;
}

typedef struct {
    UINT8  Version : 3;
    UINT8  Flags : 5;
    UINT8  SizeOfProlog;
    UINT8  CountOfUnwindCodes;
    UINT8  FrameRegister : 4;
    UINT8  FrameRegisterOffset : 4;
    ULONG  ExceptionHandler;
} UNWIND_INFO;

/* Hack, for bug in ld.  Will be removed soon.  */
#if defined(__GNUC__)
#define __ImageBase __MINGW_LSYMBOL(_image_base__)
#endif

/* Get the end of the text section.  */
extern char etext[] asm("etext");

/* Get the base of the module.       */
/* This symbol is defined by ld.     */
extern IMAGE_DOS_HEADER __ImageBase;

static UNWIND_INFO info[1];
static RUNTIME_FUNCTION handlers[1];

#define base (ULONG)((HINSTANCE)&__ImageBase)

int main()
{
    HANDLE hProcess = GetCurrentProcess();
    HMODULE hModule = GetCurrentModule();

    MODULEINFO mi;
    GetModuleInformation(hProcess, hModule, &mi, sizeof(mi));

    printf( "Module: 0x%.8X (0x%.8X) 0x%.8X |0x%.8X| [0x%.8X] {0x%.8X}\n\n"
          , mi.lpBaseOfDll
          , base
          , (char*)etext
          , mi.SizeOfImage
          , &catchDivZero
          , (ULONG)(&catchDivZero - base)
          );

    printf("Building UNWIND_INFO..\n");

    info[0].Version             = 1;
    info[0].Flags               = UNW_FLAG_EHANDLER;
    info[0].SizeOfProlog        = 0;
    info[0].CountOfUnwindCodes  = 0;
    info[0].FrameRegister       = 0;
    info[0].FrameRegisterOffset = 0;
    info[0].ExceptionHandler    = (ULONG)(&catchDivZero - base);

    printf("Created UNWIND_INFO at {0x%.8X}\n", info[0].ExceptionHandler);

    printf("Building SEH handlers...\n");

    handlers[0].BeginAddress = 0;
    handlers[0].EndAddress   = (ULONG)(etext - base);
    handlers[0].UnwindData   = (ULONG)((char*)info - base);

    printf("Adding SEH handlers to .pdata..\n");
    printf("Handler Unwind: 0x%.8X\n", &info);
    printf( "Handler Info:: s: 0x%.8X, e: 0x%.8X, u: 0x%.8X\n"
          , handlers[0].BeginAddress
          , handlers[0].EndAddress
          , handlers[0].UnwindData
          );

    if (RtlAddFunctionTable(handlers, 1, (DWORD64)base))
    {
        printf("Hook succeeded.\nTesting..\n");
        printf("Things to do: %i\n", 12 / 0);
    }
    else 
    {
        printf("Hook failed\n");
        DWORD result = GetLastError();
        printf("Error code: 0x%.8X\n", result);
    }
}

ただし、呼び出されたときに得られる出力は次のとおりです。

> .\a.exe
Module: 0x00400000 (0x00400000) 0x00402FF0 |0x00022000| [0x00401530] {0x00001530}

Building UNWIND_INFO..
Created UNWIND_INFO at {0x00001530}
Building SEH handlers...
Adding SEH handlers to .pdata..
Handler Unwind: 0x00407030
Handler Info:: s: 0x00000000, e: 0x00002FF0, u: 0x00007030
Hook succeeded.
Testing..

私のハンドラーのメッセージは決して出力されません。

ヘルプ/ポインタは大歓迎です。

4

2 に答える 2