Files

447 lines
12 KiB
C++
Executable File

// Copyright (c) Microsoft Corporation. All rights reserved.
#pragma once
#include "ehdata4_export.h"
#include "ehdata.h"
#if !defined(RENAME_EH_EXTERN)
#define RENAME_EH_EXTERN(x) x
#endif
#if _EH_RELATIVE_FUNCINFO
inline uintptr_t __FuncRelToRealOffset(
DispatcherContext *pDC,
unsigned int funcRelOffset
)
{
return (uintptr_t)(pDC->ImageBase + pDC->FunctionEntry->BeginAddress + funcRelOffset);
}
inline uintptr_t __RVAtoRealOffset(
DispatcherContext *pDC,
int RVA
)
{
return (uintptr_t)(pDC->ImageBase + RVA);
}
#endif
class RENAME_EH_EXTERN(__FrameHandler3)
{
public:
using FuncInfo = FuncInfo;
using HandlerType = HandlerType;
using TryBlockMapEntry = TryBlockMapEntry;
static TryBlockMapEntry * CatchTryBlock(
FuncInfo *pFuncInfo,
__ehstate_t curState
);
static bool ExecutionInCatch(
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
static __ehstate_t StateFromControlPc(
FuncInfo *pFuncInfo,
DispatcherContext *pDC
);
static __ehstate_t StateFromIp(
FuncInfo *pFuncInfo,
DispatcherContext *pDC,
uintptr_t Ip
);
static void FrameUnwindToState(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo,
__ehstate_t targetState
);
static void FrameUnwindToEmptyState(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
inline static __ehstate_t GetHandlerSearchState(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
static __ehstate_t GetMaxState(
DispatcherContext* /*pDC*/,
FuncInfo *pFuncInfo
)
{
return pFuncInfo->maxState;
};
static int TypeMatch(
HandlerType *pCatch,
CatchableType *pCatchable,
ThrowInfo *pThrow
);
#if _EH_RELATIVE_FUNCINFO
static EHRegistrationNode * GetEstablisherFrame(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo,
EHRegistrationNode *pEstablisher
);
#endif
static int BuildCatchObjectHelper(
EHExceptionRecord *pExcept,
void *pRN,
HandlerType *pCatch,
CatchableType *pConv
);
static void BuildCatchObject(
EHExceptionRecord *pExcept,
void *pRN,
HandlerType *pCatch,
CatchableType *pConv
);
#if _EH_RELATIVE_FUNCINFO
static void UnwindNestedFrames(
EHRegistrationNode *pFrame,
EHExceptionRecord *pExcept,
CONTEXT *pContext,
EHRegistrationNode *pEstablisher,
void *Handler,
FuncInfo *pFuncInfo,
__ehstate_t TargetUnwindState,
__ehstate_t CatchState,
HandlerType *pCatch,
DispatcherContext *pDC,
BOOLEAN recursive
);
#endif
inline static bool isEHs(FuncInfo* pFuncInfo)
{
return !!(FUNC_FLAGS(*pFuncInfo) & FI_EHS_FLAG);
}
inline static bool isNoExcept(FuncInfo* pFuncInfo)
{
return !!(FUNC_FLAGS(*pFuncInfo) & FI_EHNOEXCEPT_FLAG);
}
inline static uint32_t getMagicNum(FuncInfo* pFuncInfo)
{
return FUNC_MAGICNUM(*pFuncInfo);
}
inline static ESTypeList* getESTypes(FuncInfo* pFuncInfo);
static __ehstate_t GetCurrentState(
EHRegistrationNode *pFrame,
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
static void SetState(
EHRegistrationNode *pRN,
FuncInfo *pFuncInfo,
__ehstate_t newState
);
static void SetUnwindTryBlock(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo,
int curState
);
static __ehstate_t GetUnwindTryBlock(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
static void * CxxCallCatchBlock(EXCEPTION_RECORD* pExcept);
class TryBlockMap
{
public:
TryBlockMap(FuncInfo *pFuncInfo, uintptr_t imageBase) :
_pFuncInfo(pFuncInfo), _imageBase(imageBase) {}
class iterator
{
public:
iterator(TryBlockMap &tryBlockMap, unsigned index):
_tryBlockMap(tryBlockMap), _index(index) {}
iterator& operator++()
{
_index++;
return *this;
}
TryBlockMapEntry operator*()
{
#if _EH_RELATIVE_FUNCINFO
return *(FUNC_PTRYBLOCK(*_tryBlockMap._pFuncInfo, _index, (uintptr_t)(_tryBlockMap._imageBase)));
#else
return *(FUNC_PTRYBLOCK(*_tryBlockMap._pFuncInfo, _index));
#endif
}
bool operator!=(const iterator &other) const
{
return (_index != other._index);
}
bool operator<(const iterator &other) const
{
return (_index < other._index);
}
iterator& operator=(const iterator &other)
{
this->_index = other._index;
return *this;
}
private:
TryBlockMap & _tryBlockMap;
unsigned _index;
};
unsigned getNumTryBlocks()
{
return FUNC_NTRYBLOCKS(*_pFuncInfo);
}
using IteratorPair = std::pair<iterator, iterator>;
private:
FuncInfo* _pFuncInfo;
uintptr_t _imageBase;
};
static TryBlockMap::IteratorPair GetRangeOfTrysToCheck(
TryBlockMap &TryBlockMap,
__ehstate_t curState,
DispatcherContext *pDC,
FuncInfo *pFuncInfo,
int CatchDepth
);
class HandlerMap
{
public:
#pragma warning(push)
#pragma warning(disable: 4100) // unreferenced formal parameter
HandlerMap(TryBlockMapEntry *tryMap, uintptr_t imageBase, uint32_t functionStart)
{
#if _EH_RELATIVE_FUNCINFO
_handler = (HandlerType *)((uintptr_t)(imageBase + tryMap->dispHandlerArray));
#else
_handler = (HandlerType *)tryMap->pHandlerArray;
#endif
_numHandlers = tryMap->nCatches;
}
#pragma warning(pop)
class iterator
{
public:
iterator(HandlerMap & handlerMap, unsigned currBlock)
: _handlerMap(handlerMap), _currBlock(currBlock)
{}
iterator& operator++()
{
_currBlock++;
return *this;
}
HandlerType operator*()
{
return *((HandlerType *)(_handlerMap._handler + _currBlock));
}
bool operator==(const iterator &other) const
{
return (_currBlock == other._currBlock);
}
bool operator!=(const iterator &other) const
{
return !(*this == other);
}
private:
HandlerMap & _handlerMap;
unsigned _currBlock;
};
iterator begin()
{
return iterator(*this, 0);
}
iterator end()
{
return iterator(*this, _numHandlers);
}
HandlerType* getLastEntry()
{
return (HandlerType *)(_handler + _numHandlers - 1);
}
private:
unsigned _numHandlers;
HandlerType *_handler;
};
};
class RENAME_EH_EXTERN(__FrameHandler4)
{
public:
using FuncInfo = FH4::FuncInfo4;
using HandlerType = FH4::HandlerType4;
using TryBlockMapEntry = FH4::TryBlockMapEntry4;
using UWMap = FH4::UWMap4;
using TryBlockMap = FH4::TryBlockMap4;
using HandlerMap = FH4::HandlerMap4;
static bool ExecutionInCatch(
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
static __ehstate_t StateFromControlPc(
FuncInfo *pFuncInfo,
DispatcherContext *pDC
);
static __ehstate_t StateFromIp(
FuncInfo *pFuncInfo,
DispatcherContext *pDC,
uintptr_t Ip
);
static void FrameUnwindToState(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo,
__ehstate_t targetState
);
static void FrameUnwindToEmptyState(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
inline static __ehstate_t GetHandlerSearchState(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo
);
#if _EH_RELATIVE_FUNCINFO
static __ehstate_t GetMaxState(
DispatcherContext *pDC,
FuncInfo *pFuncInfo
)
{
if (pFuncInfo->dispUnwindMap)
{
uint8_t * buffer = reinterpret_cast<uint8_t *>(__RVAtoRealOffset(pDC, pFuncInfo->dispUnwindMap));
return FH4::ReadUnsigned(&buffer);
}
return 0;
}
#endif
static int TypeMatch(
HandlerType *pCatch,
CatchableType *pCatchable,
ThrowInfo *pThrow
);
static int BuildCatchObjectHelper(
EHExceptionRecord *pExcept,
void *pRN,
HandlerType *pCatch,
CatchableType *pConv
);
static void BuildCatchObject(
EHExceptionRecord *pExcept,
void *pRN,
HandlerType *pCatch,
CatchableType *pConv
);
static void UnwindNestedFrames(
EHRegistrationNode *pFrame,
EHExceptionRecord *pExcept,
CONTEXT *pContext,
EHRegistrationNode *pEstablisher,
void *Handler,
FuncInfo *pFuncInfo,
__ehstate_t TargetUnwindState,
__ehstate_t CatchState,
HandlerType *pCatch,
DispatcherContext *pDC,
BOOLEAN recursive
);
static EHRegistrationNode * GetEstablisherFrame(
EHRegistrationNode *pRN,
DispatcherContext *pDC,
FuncInfo *pFuncInfo,
EHRegistrationNode *pEstablisher
);
inline static bool isEHs(FuncInfo* pFuncInfo)
{
return pFuncInfo->header.EHs;
}
inline static bool isNoExcept(FuncInfo* pFuncInfo)
{
return pFuncInfo->header.NoExcept;
}
// For simplicity in merging, treat FrameHandler4 as having a magic number
inline static uint32_t getMagicNum(FuncInfo* /*pFuncInfo*/)
{
return EH_MAGIC_NUMBER3;
}
// Not supported under FrameHandler4
inline static ESTypeList* getESTypes(FuncInfo* /*pFuncInfo*/)
{
return nullptr;
}
static void * CxxCallCatchBlock(EXCEPTION_RECORD* pExcept);
static TryBlockMap::IteratorPair GetRangeOfTrysToCheck(
TryBlockMap &TryBlockMap,
__ehstate_t curState,
DispatcherContext *pDC,
FuncInfo *pFuncInfo,
int CatchDepth
);
};