| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- #define IS_UNIBBLE(x) (!(((size_t)x) & ~((size_t)0xF)))
- #define TO_UNIBBLE(x) (x & 0xF)
- #define IS_UINT16(x) (!(((size_t)x) & ~((size_t)0xFFFF)))
- #define TO_UINT16(x) (x & 0xFFFF)
- #define IS_UINT32(x) (!(((size_t)x) & ~((size_t)0xFFFFFFFF)))
- #define TO_UINT32(x) (x & 0xFFFFFFFF)
- enum UnwindOp : unsigned __int8 {
- UWOP_IGNORE = (unsigned __int8)-1,
- UWOP_PUSH_NONVOL = 0,
- UWOP_ALLOC_LARGE = 1,
- UWOP_ALLOC_SMALL = 2,
- UWOP_SAVE_XMM128 = 8
- };
- class PrologEncoder
- {
- private:
- #pragma pack(push, 1)
- struct UNWIND_CODE
- {
- /*
- * ntdll!UNWIND_CODE
- * +0x000 CodeOffset : UChar
- * +0x001 UnwindOp : Pos 0, 4 Bits
- * +0x001 OpInfo : Pos 4, 4 Bits
- * +0x000 FrameOffset : Uint2B
- */
- union {
- struct {
- unsigned __int8 CodeOffset;
- unsigned __int8 UnwindOp : 4;
- unsigned __int8 OpInfo : 4;
- };
- unsigned __int16 FrameOffset;
- };
- void SetOffset(unsigned __int8 offset)
- {
- CodeOffset = offset;
- }
- void SetOp(unsigned __int8 op)
- {
- Assert(IS_UNIBBLE(op));
- UnwindOp = TO_UNIBBLE(op);
- }
- void SetOpInfo(unsigned __int8 info)
- {
- Assert(IS_UNIBBLE(info));
- OpInfo = TO_UNIBBLE(info);
- }
- };
- struct UNWIND_INFO
- {
- /*
- * ntdll!UNWIND_INFO
- * +0x000 Version : Pos 0, 3 Bits
- * +0x000 Flags : Pos 3, 5 Bits
- * +0x001 SizeOfProlog : UChar
- * +0x002 CountOfCodes : UChar
- * +0x003 FrameRegister : Pos 0, 4 Bits
- * +0x003 FrameOffset : Pos 4, 4 Bits
- * +0x004 UnwindCode : [1] _UNWIND_CODE
- */
- unsigned __int8 Version : 3;
- unsigned __int8 Flags : 5;
- unsigned __int8 SizeOfProlog;
- unsigned __int8 CountOfCodes;
- unsigned __int8 FrameRegister : 4;
- unsigned __int8 FrameOffset : 4;
- UNWIND_CODE unwindCodes[0];
- };
- struct UnwindCode : public UNWIND_CODE
- {
- private:
- union {
- unsigned __int16 uint16Val;
- unsigned __int32 uint32Val;
- } u;
- public:
- void SetValue(unsigned __int16 value)
- {
- Assert(UnwindOp && (UnwindOp == UWOP_ALLOC_LARGE));
- u.uint16Val = value;
- }
- void SetValue(unsigned __int32 value)
- {
- Assert(UnwindOp && (UnwindOp == UWOP_ALLOC_LARGE));
- // insert assert to check that value actually warrants the use of
- // 32 bits to encoder.
- u.uint32Val = value;
- }
- };
- struct PData
- {
- RUNTIME_FUNCTION runtimeFunction;
- UNWIND_INFO unwindInfo;
- };
- #pragma pack(pop)
- PData *pdata;
- ArenaAllocator *alloc;
- unsigned __int8 currentUnwindCodeNodeIndex;
- unsigned __int8 requiredUnwindCodeNodeCount;
- unsigned __int8 currentInstrOffset;
- public:
- PrologEncoder(ArenaAllocator *alloc)
- : alloc(alloc),
- pdata(nullptr),
- requiredUnwindCodeNodeCount(0),
- currentUnwindCodeNodeIndex(0),
- currentInstrOffset(0)
- {
- }
- void RecordNonVolRegSave();
- void RecordXmmRegSave();
- void RecordAlloca(size_t size);
- void EncodeInstr(IR::Instr *instr, unsigned __int8 size);
- void EncodeSmallProlog(uint8 prologSize, size_t size);
- //
- // Pre-Win8 PDATA registration.
- //
- DWORD SizeOfPData();
- void SetPDataPtr(void *pdata);
- BYTE *Finalize(BYTE *functionStart,
- DWORD codeSize,
- BYTE *pdataBuffer);
- //
- // Win8 PDATA registration.
- //
- DWORD SizeOfUnwindInfo();
- BYTE *GetUnwindInfo();
- void FinalizeUnwindInfo();
- private:
- UnwindCode *GetUnwindCode(unsigned __int8 nodeCount);
- };
|