Logo Search packages:      
Sourcecode: mingw-w64 version File versions  Download package

crt_handler.c

/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the w64 mingw-runtime package.
 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
 */

#include <windows.h>
#include <excpt.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <signal.h>
#include <stdio.h>

#if defined (_WIN64) && defined (__ia64__)
#error FIXME: Unsupported __ImageBase implementation.
#else
#define __ImageBase __MINGW_LSYMBOL(_image_base__)
/* This symbol is defined by the linker.  */
extern IMAGE_DOS_HEADER __ImageBase;
#endif

#pragma pack(push,1)
typedef struct _UNWIND_INFO {
  BYTE VersionAndFlags;
  BYTE PrologSize;
  BYTE CountOfUnwindCodes;
  BYTE FrameRegisterAndOffset;
  ULONG AddressOfExceptionHandler;
} UNWIND_INFO,*PUNWIND_INFO;
#pragma pack(pop)

PIMAGE_SECTION_HEADER _FindPESectionByName (const char *);
PIMAGE_SECTION_HEADER _FindPESectionExec (size_t);
PBYTE _GetPEImageBase (void);

int __mingw_init_ehandler (void);

#ifdef _WIN64
EXCEPTION_DISPOSITION __mingw_SEH_error_handler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);

#define MAX_PDATA_ENTRIES 32
static RUNTIME_FUNCTION emu_pdata[MAX_PDATA_ENTRIES];
static UNWIND_INFO emu_xdata[MAX_PDATA_ENTRIES];

int
__mingw_init_ehandler (void)
{
  static int was_here = 0;
  size_t e = 0;
  PIMAGE_SECTION_HEADER pSec;
  PBYTE _ImageBase = _GetPEImageBase ();
  
  if (was_here || !_ImageBase)
    return was_here;
  was_here = 1;
  if (_FindPESectionByName (".pdata") != NULL)
    return 1;

  /* Allocate # of e tables and entries.  */
  memset (emu_pdata, 0, sizeof (RUNTIME_FUNCTION) * MAX_PDATA_ENTRIES);
  memset (emu_xdata, 0, sizeof (UNWIND_INFO) * MAX_PDATA_ENTRIES);
    
  e = 0;
  /* Fill tables and entries.  */
  while (e < MAX_PDATA_ENTRIES && (pSec = _FindPESectionExec (e)) != NULL)
    {
      emu_xdata[e].VersionAndFlags = 9; /* UNW_FLAG_EHANDLER | UNW_VERSION */
      emu_xdata[e].AddressOfExceptionHandler =
      (DWORD)(size_t) ((LPBYTE)__mingw_SEH_error_handler - _ImageBase);
      emu_pdata[e].BeginAddress = pSec->VirtualAddress;
      emu_pdata[e].EndAddress = pSec->VirtualAddress + pSec->Misc.VirtualSize;
      emu_pdata[e].UnwindData =
      (DWORD)(size_t)((LPBYTE)&emu_xdata[e] - _ImageBase);
      ++e;
    }
#ifdef _DEBUG_CRT
  if (!e || e > MAX_PDATA_ENTRIES)
    abort ();
#endif
  /* RtlAddFunctionTable.  */
  if (e != 0)
    RtlAddFunctionTable (emu_pdata, e, (DWORD64)_ImageBase);
  return 1;
}

extern void _fpreset (void);

EXCEPTION_DISPOSITION
__mingw_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
                     void *EstablisherFrame  __attribute__ ((unused)),
                     struct _CONTEXT* ContextRecord __attribute__ ((unused)),
                     void *DispatcherContext __attribute__ ((unused)))
{
  EXCEPTION_DISPOSITION action = EXCEPTION_CONTINUE_SEARCH;
  void (*old_handler) (int);
  int reset_fpu = 0;

  switch (ExceptionRecord->ExceptionCode)
    {
    case EXCEPTION_ACCESS_VIOLATION:
      /* test if the user has set SIGSEGV */
      old_handler = signal (SIGSEGV, SIG_DFL);
      if (old_handler == SIG_IGN)
      {
        /* this is undefined if the signal was raised by anything other
           than raise ().  */
        signal (SIGSEGV, SIG_IGN);
        action = EXCEPTION_CONTINUE_EXECUTION;
      }
      else if (old_handler != SIG_DFL)
      {
        /* This means 'old' is a user defined function. Call it */
        (*old_handler) (SIGSEGV);
        action = EXCEPTION_CONTINUE_EXECUTION;
      }
      else
        action = EXCEPTION_EXECUTE_HANDLER;
      break;
    case EXCEPTION_ILLEGAL_INSTRUCTION:
    case EXCEPTION_PRIV_INSTRUCTION:
      /* test if the user has set SIGILL */
      old_handler = signal (SIGILL, SIG_DFL);
      if (old_handler == SIG_IGN)
      {
        /* this is undefined if the signal was raised by anything other
           than raise ().  */
        signal (SIGILL, SIG_IGN);
        action = EXCEPTION_CONTINUE_EXECUTION;
      }
      else if (old_handler != SIG_DFL)
      {
        /* This means 'old' is a user defined function. Call it */
        (*old_handler) (SIGILL);
        action = EXCEPTION_CONTINUE_EXECUTION;
      }
      else
        action = EXCEPTION_EXECUTE_HANDLER;
      break;
    case EXCEPTION_FLT_INVALID_OPERATION:
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_DENORMAL_OPERAND:
    case EXCEPTION_FLT_OVERFLOW:
    case EXCEPTION_FLT_UNDERFLOW:
    case EXCEPTION_FLT_INEXACT_RESULT:
      reset_fpu = 1;
      /* fall through. */

    case EXCEPTION_INT_DIVIDE_BY_ZERO:
      /* test if the user has set SIGFPE */
      old_handler = signal (SIGFPE, SIG_DFL);
      if (old_handler == SIG_IGN)
      {
        signal (SIGFPE, SIG_IGN);
        if (reset_fpu)
          _fpreset ();
        action = EXCEPTION_CONTINUE_EXECUTION;
      }
      else if (old_handler != SIG_DFL)
      {
        /* This means 'old' is a user defined function. Call it */
        (*old_handler) (SIGFPE);
        action = EXCEPTION_CONTINUE_EXECUTION;
      }
      break;
    case EXCEPTION_DATATYPE_MISALIGNMENT:
    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
    case EXCEPTION_FLT_STACK_CHECK:
    case EXCEPTION_INT_OVERFLOW:
    case EXCEPTION_INVALID_HANDLE:
    /*case EXCEPTION_POSSIBLE_DEADLOCK: */
      action = EXCEPTION_CONTINUE_EXECUTION;
      break;
    default:
      break;
    }
  return action;
}

#endif

Generated by  Doxygen 1.6.0   Back to index