diff options
author | Jonghyun Park <parjong@gmail.com> | 2017-01-23 19:46:37 +0900 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2017-01-23 11:46:37 +0100 |
commit | 347243f80d62d5aaa5359ef8c8d5331b6d8e4a63 (patch) | |
tree | 82fa5ea05a77885661cc070d4d84026bbb4d9536 /src | |
parent | 62ac5f04456e517b76bcfc3d386859a506eed6d1 (diff) | |
download | coreclr-347243f80d62d5aaa5359ef8c8d5331b6d8e4a63.tar.gz coreclr-347243f80d62d5aaa5359ef8c8d5331b6d8e4a63.tar.bz2 coreclr-347243f80d62d5aaa5359ef8c8d5331b6d8e4a63.zip |
[x86/Linux] Enable FEATURE_EH_FUNCLETS (#8889)
* [x86/Linux] (Partially) Enable FEATURE_EH_FUNCLETS
* Update CLR ABI Document
* Add TODO (for Funclet Prolog/Epilog Gen)
Diffstat (limited to 'src')
-rw-r--r-- | src/inc/clrnt.h | 22 | ||||
-rw-r--r-- | src/inc/win64unwind.h | 9 | ||||
-rw-r--r-- | src/jit/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/jit/codegencommon.cpp | 60 | ||||
-rw-r--r-- | src/jit/codegenxarch.cpp | 6 | ||||
-rw-r--r-- | src/jit/compiler.h | 11 | ||||
-rw-r--r-- | src/jit/target.h | 4 | ||||
-rw-r--r-- | src/jit/unwind.cpp | 32 | ||||
-rw-r--r-- | src/jit/unwindx86.cpp | 249 | ||||
-rw-r--r-- | src/pal/inc/pal.h | 2 | ||||
-rw-r--r-- | src/vm/i386/unixstubs.cpp | 10 | ||||
-rw-r--r-- | src/vm/jitinterface.cpp | 88 |
12 files changed, 389 insertions, 105 deletions
diff --git a/src/inc/clrnt.h b/src/inc/clrnt.h index 9a4601ebaf..08a93a4961 100644 --- a/src/inc/clrnt.h +++ b/src/inc/clrnt.h @@ -855,25 +855,25 @@ typedef struct _DISPATCHER_CONTEXT { #define RUNTIME_FUNCTION__SetBeginAddress(prf,addr) ((prf)->BeginAddress = (addr)) #ifdef WIN64EXCEPTIONS -EXTERN_C ULONG +#include "win64unwind.h" + +FORCEINLINE +DWORD RtlpGetFunctionEndAddress ( __in PT_RUNTIME_FUNCTION FunctionEntry, - __in ULONG ImageBase - ); + __in TADDR ImageBase + ) +{ + PUNWIND_INFO pUnwindInfo = (PUNWIND_INFO)(ImageBase + FunctionEntry->UnwindData); + + return FunctionEntry->BeginAddress + pUnwindInfo->FunctionLength; +} #define RUNTIME_FUNCTION__EndAddress(prf, ImageBase) RtlpGetFunctionEndAddress(prf, ImageBase) #define RUNTIME_FUNCTION__GetUnwindInfoAddress(prf) (prf)->UnwindData #define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf, addr) do { (prf)->UnwindData = (addr); } while(0) -#define UNW_FLAG_NHANDLER 0x0 /* any handler */ -#define UNW_FLAG_EHANDLER 0x1 /* filter handler */ -#define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ - -typedef struct _UNWIND_INFO { - // dummy -} UNWIND_INFO, *PUNWIND_INFO; - EXTERN_C NTSYSAPI PEXCEPTION_ROUTINE diff --git a/src/inc/win64unwind.h b/src/inc/win64unwind.h index 196052aca9..e4cea023b2 100644 --- a/src/inc/win64unwind.h +++ b/src/inc/win64unwind.h @@ -89,6 +89,14 @@ typedef union _UNWIND_CODE { #define UNW_FLAG_UHANDLER 0x2 #define UNW_FLAG_CHAININFO 0x4 +#ifdef _TARGET_X86_ + +typedef struct _UNWIND_INFO { + ULONG FunctionLength; +} UNWIND_INFO, *PUNWIND_INFO; + +#else // _TARGET_X86_ + typedef struct _UNWIND_INFO { UCHAR Version : 3; UCHAR Flags : 5; @@ -114,4 +122,5 @@ typedef struct _UNWIND_INFO { } UNWIND_INFO, *PUNWIND_INFO; +#endif // _TARGET_X86_ #endif // _WIN64UNWIND_H_ diff --git a/src/jit/CMakeLists.txt b/src/jit/CMakeLists.txt index 1184e69ff7..1fbbb355b0 100644 --- a/src/jit/CMakeLists.txt +++ b/src/jit/CMakeLists.txt @@ -104,6 +104,7 @@ elseif(CLR_CMAKE_TARGET_ARCH_I386) simd.cpp simdcodegenxarch.cpp targetx86.cpp + unwindx86.cpp ) elseif(CLR_CMAKE_TARGET_ARCH_ARM64) set( ARCH_SOURCES diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index f42103ebce..0cc6995d18 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -10241,6 +10241,66 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() // Look in CodeGenArm64.cpp +#elif defined(_TARGET_X86_) + +/***************************************************************************** + * + * Generates code for an EH funclet prolog. + */ + +void CodeGen::genFuncletProlog(BasicBlock* block) +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In genFuncletProlog()\n"); + } +#endif + + ScopedSetVariable<bool> _setGeneratingProlog(&compiler->compGeneratingProlog, true); + + compiler->unwindBegProlog(); + + // TODO Save callee-saved registers + + // This is the end of the OS-reported prolog for purposes of unwinding + compiler->unwindEndProlog(); +} + +/***************************************************************************** + * + * Generates code for an EH funclet epilog. + */ + +void CodeGen::genFuncletEpilog() +{ +#ifdef DEBUG + if (verbose) + { + printf("*************** In genFuncletEpilog()\n"); + } +#endif + + ScopedSetVariable<bool> _setGeneratingEpilog(&compiler->compGeneratingEpilog, true); + + // TODO Restore callee-saved registers + + instGen_Return(0); +} + +/***************************************************************************** + * + * Capture the information used to generate the funclet prologs and epilogs. + */ + +void CodeGen::genCaptureFuncletPrologEpilogInfo() +{ + if (!compiler->ehAnyFunclets()) + { + return; + } +} + #else // _TARGET_* /***************************************************************************** diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index 742edae298..c3774ea74a 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -263,10 +263,14 @@ BasicBlock* CodeGen::genCallFinally(BasicBlock* block, BasicBlock* lblk) } else { +// TODO-Linux-x86: Do we need to handle the GC information for this NOP or JMP specially, as is done for other +// architectures? +#ifndef JIT32_GCENCODER // Because of the way the flowgraph is connected, the liveness info for this one instruction // after the call is not (can not be) correct in cases where a variable has a last use in the // handler. So turn off GC reporting for this single instruction. getEmitter()->emitDisableGC(); +#endif // JIT32_GCENCODER // Now go to where the finally funclet needs to return to. if (block->bbNext->bbJumpDest == block->bbNext->bbNext) @@ -282,7 +286,9 @@ BasicBlock* CodeGen::genCallFinally(BasicBlock* block, BasicBlock* lblk) inst_JMP(EJ_jmp, block->bbNext->bbJumpDest); } +#ifndef JIT32_GCENCODER getEmitter()->emitEnableGC(); +#endif // JIT32_GCENCODER } #else // !FEATURE_EH_FUNCLETS diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 19dfbda7c3..54079b945c 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -1769,7 +1769,11 @@ public: // a PSPSym for functions with any EH. bool ehNeedsPSPSym() const { +#ifdef _TARGET_X86_ + return false; +#else // _TARGET_X86_ return compHndBBtabCount > 0; +#endif // _TARGET_X86_ } bool ehAnyFunclets(); // Are there any funclets in this function? @@ -6848,10 +6852,15 @@ private: void unwindReserveFunc(FuncInfoDsc* func); void unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode); -#if defined(_TARGET_AMD64_) +#if defined(_TARGET_AMD64_) || (defined(_TARGET_X86_) && FEATURE_EH_FUNCLETS) void unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode); void unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode); + +#endif // _TARGET_AMD64_ || (_TARGET_X86_ && FEATURE_EH_FUNCLETS) + +#if defined(_TARGET_AMD64_) + UNATIVE_OFFSET unwindGetCurrentOffset(FuncInfoDsc* func); void unwindBegPrologWindows(); diff --git a/src/jit/target.h b/src/jit/target.h index 32eb16698c..6330d52889 100644 --- a/src/jit/target.h +++ b/src/jit/target.h @@ -409,7 +409,11 @@ typedef unsigned short regPairNoSmall; // arm: need 12 bits // target #define FEATURE_EH 1 // To aid platform bring-up, eliminate exceptional EH clauses (catch, filter, // filter-handler, fault) and directly execute 'finally' clauses. +#if defined(FEATURE_PAL) && !defined(LEGACY_BACKEND) + #define FEATURE_EH_FUNCLETS 1 +#else // FEATURE_PAL && !LEGACY_BACKEND #define FEATURE_EH_FUNCLETS 0 +#endif // FEATURE_PAL && !LEGACY_BACKEND #define FEATURE_EH_CALLFINALLY_THUNKS 0 // Generate call-to-finally code in "thunks" in the enclosing EH region, // protected by "cloned finally" clauses. #ifndef LEGACY_BACKEND diff --git a/src/jit/unwind.cpp b/src/jit/unwind.cpp index 4568fed75a..b354504bb7 100644 --- a/src/jit/unwind.cpp +++ b/src/jit/unwind.cpp @@ -132,37 +132,7 @@ void Compiler::unwindGetFuncLocations(FuncInfoDsc* func, #elif defined(_TARGET_X86_) -// Stub routines that do nothing -void Compiler::unwindBegProlog() -{ -} -void Compiler::unwindEndProlog() -{ -} -void Compiler::unwindBegEpilog() -{ -} -void Compiler::unwindEndEpilog() -{ -} -void Compiler::unwindReserve() -{ -} -void Compiler::unwindEmit(void* pHotCode, void* pColdCode) -{ -} -void Compiler::unwindPush(regNumber reg) -{ -} -void Compiler::unwindAllocStack(unsigned size) -{ -} -void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset) -{ -} -void Compiler::unwindSaveReg(regNumber reg, unsigned offset) -{ -} +// See unwindX86.cpp #else // _TARGET_* diff --git a/src/jit/unwindx86.cpp b/src/jit/unwindx86.cpp new file mode 100644 index 0000000000..516155c6a2 --- /dev/null +++ b/src/jit/unwindx86.cpp @@ -0,0 +1,249 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XX XX +XX UnwindInfo XX +XX XX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +*/ + +#include "jitpch.h" +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#ifndef _TARGET_X86_ +#error "This should be included only for x86" +#endif // _TARGET_X86_ + +void Compiler::unwindBegProlog() +{ +} + +void Compiler::unwindEndProlog() +{ +} + +void Compiler::unwindBegEpilog() +{ +} + +void Compiler::unwindEndEpilog() +{ +} + +void Compiler::unwindPush(regNumber reg) +{ +} + +void Compiler::unwindAllocStack(unsigned size) +{ +} + +void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset) +{ +} + +void Compiler::unwindSaveReg(regNumber reg, unsigned offset) +{ +} + +//------------------------------------------------------------------------ +// Compiler::unwindReserve: Ask the VM to reserve space for the unwind information +// for the function and all its funclets. Called once, just before asking the VM +// for memory and emitting the generated code. Calls unwindReserveFunc() to handle +// the main function and each of the funclets, in turn. +// +void Compiler::unwindReserve() +{ +#if FEATURE_EH_FUNCLETS + assert(!compGeneratingProlog); + assert(!compGeneratingEpilog); + + assert(compFuncInfoCount > 0); + for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++) + { + unwindReserveFunc(funGetFunc(funcIdx)); + } +#endif +} + +//------------------------------------------------------------------------ +// Compiler::unwindEmit: Report all the unwind information to the VM. +// +// Arguments: +// pHotCode - Pointer to the beginning of the memory with the function and funclet hot code. +// pColdCode - Pointer to the beginning of the memory with the function and funclet cold code. +// +void Compiler::unwindEmit(void* pHotCode, void* pColdCode) +{ +#if FEATURE_EH_FUNCLETS + assert(!compGeneratingProlog); + assert(!compGeneratingEpilog); + + assert(compFuncInfoCount > 0); + for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++) + { + unwindEmitFunc(funGetFunc(funcIdx), pHotCode, pColdCode); + } +#endif // FEATURE_EH_FUNCLETS +} + +#if FEATURE_EH_FUNCLETS +//------------------------------------------------------------------------ +// Compiler::unwindReserveFunc: Reserve the unwind information from the VM for a +// given main function or funclet. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// +void Compiler::unwindReserveFunc(FuncInfoDsc* func) +{ + unwindReserveFuncHelper(func, true); + + if (fgFirstColdBlock != nullptr) + { + unwindReserveFuncHelper(func, false); + } +} + +//------------------------------------------------------------------------ +// Compiler::unwindReserveFuncHelper: Reserve the unwind information from the VM for a +// given main function or funclet, for either the hot or the cold section. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// isHotCode - 'true' to reserve the hot section, 'false' to reserve the cold section. +// +void Compiler::unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode) +{ + BOOL isFunclet = (func->funKind != FUNC_ROOT); + BOOL isColdCode = isHotCode ? FALSE : TRUE; + + eeReserveUnwindInfo(isFunclet, isColdCode, sizeof(UNWIND_INFO)); +} + +//------------------------------------------------------------------------ +// Compiler::unwindEmitFunc: Report the unwind information to the VM for a +// given main function or funclet. Reports the hot section, then the cold +// section if necessary. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// pHotCode - Pointer to the beginning of the memory with the function and funclet hot code. +// pColdCode - Pointer to the beginning of the memory with the function and funclet cold code. +// +void Compiler::unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode) +{ + // Verify that the JIT enum is in sync with the JIT-EE interface enum + static_assert_no_msg(FUNC_ROOT == (FuncKind)CORJIT_FUNC_ROOT); + static_assert_no_msg(FUNC_HANDLER == (FuncKind)CORJIT_FUNC_HANDLER); + static_assert_no_msg(FUNC_FILTER == (FuncKind)CORJIT_FUNC_FILTER); + + unwindEmitFuncHelper(func, pHotCode, pColdCode, true); + + if (pColdCode != nullptr) + { + unwindEmitFuncHelper(func, pHotCode, pColdCode, false); + } +} + +//------------------------------------------------------------------------ +// Compiler::unwindEmitFuncHelper: Report the unwind information to the VM for a +// given main function or funclet, for either the hot or cold section. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// pHotCode - Pointer to the beginning of the memory with the function and funclet hot code. +// pColdCode - Pointer to the beginning of the memory with the function and funclet cold code. +// Ignored if 'isHotCode' is true. +// isHotCode - 'true' to report the hot section, 'false' to report the cold section. +// +void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode) +{ + UNATIVE_OFFSET startOffset; + UNATIVE_OFFSET endOffset; + + if (isHotCode) + { + emitLocation* startLoc; + emitLocation* endLoc; + + unwindGetFuncLocations(func, true, &startLoc, &endLoc); + + if (startLoc == nullptr) + { + startOffset = 0; + } + else + { + startOffset = startLoc->CodeOffset(genEmitter); + } + + if (endLoc == nullptr) + { + endOffset = info.compNativeCodeSize; + } + else + { + endOffset = endLoc->CodeOffset(genEmitter); + } + } + else + { + emitLocation* coldStartLoc; + emitLocation* coldEndLoc; + + assert(fgFirstColdBlock != nullptr); + assert(func->funKind == FUNC_ROOT); // No splitting of funclets. + + unwindGetFuncLocations(func, false, &coldStartLoc, &coldEndLoc); + + if (coldStartLoc == nullptr) + { + startOffset = 0; + } + else + { + startOffset = coldStartLoc->CodeOffset(genEmitter); + } + + if (coldEndLoc == nullptr) + { + endOffset = info.compNativeCodeSize; + } + else + { + endOffset = coldEndLoc->CodeOffset(genEmitter); + } + } + + // Adjust for cold or hot code: + // 1. The VM doesn't want the cold code pointer unless this is cold code. + // 2. The startOffset and endOffset need to be from the base of the hot section for hot code + // and from the base of the cold section for cold code + + if (isHotCode) + { + assert(endOffset <= info.compTotalHotCodeSize); + pColdCode = nullptr; + } + else + { + assert(startOffset >= info.compTotalHotCodeSize); + startOffset -= info.compTotalHotCodeSize; + endOffset -= info.compTotalHotCodeSize; + } + + UNWIND_INFO unwindInfo; + + unwindInfo.FunctionLength = (ULONG)(endOffset - startOffset); + + eeAllocUnwindInfo((BYTE*)pHotCode, (BYTE*)pColdCode, startOffset, endOffset, sizeof(UNWIND_INFO), + (BYTE*)&unwindInfo, (CorJitFuncKind)func->funKind); +} +#endif // FEATURE_EH_FUNCLETS diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 8a9972f57b..f9a33dcfcb 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -3896,7 +3896,7 @@ enum { // typedef struct _RUNTIME_FUNCTION { DWORD BeginAddress; -#ifdef _AMD64_ +#ifdef _TARGET_AMD64_ DWORD EndAddress; #endif DWORD UnwindData; diff --git a/src/vm/i386/unixstubs.cpp b/src/vm/i386/unixstubs.cpp index cb08f276fe..c0c0982e71 100644 --- a/src/vm/i386/unixstubs.cpp +++ b/src/vm/i386/unixstubs.cpp @@ -93,13 +93,3 @@ FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame(DISPATCHER_CONTEXT PORTABILITY_ASSERT("GetFrameFromRedirectedStubStackFrame"); return NULL; } - -EXTERN_C ULONG -RtlpGetFunctionEndAddress ( - __in PT_RUNTIME_FUNCTION FunctionEntry, - __in ULONG ImageBase - ) -{ - PORTABILITY_ASSERT("RtlpGetFunctionEndAddress"); - return 0; -} diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 75a228f40a..0b3c9f2605 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -10970,6 +10970,33 @@ void CEEJitInfo::CompressDebugInfo() EE_TO_JIT_TRANSITION(); } +void reservePersonalityRoutineSpace(ULONG &unwindSize) +{ +#if defined(_TARGET_X86_) + // Do nothing +#elif defined(_TARGET_AMD64_) + // Add space for personality routine, it must be 4-byte aligned. + // Everything in the UNWIND_INFO up to the variable-sized UnwindCodes + // array has already had its size included in unwindSize by the caller. + unwindSize += sizeof(ULONG); + + // Note that the count of unwind codes (2 bytes each) is stored as a UBYTE + // So the largest size could be 510 bytes, plus the header and language + // specific stuff. This can't overflow. + + _ASSERTE(FitsInU4(unwindSize + sizeof(ULONG))); + unwindSize = (ULONG)(ALIGN_UP(unwindSize, sizeof(ULONG))); +#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + // The JIT passes in a 4-byte aligned block of unwind data. + _ASSERTE(IS_ALIGNED(unwindSize, sizeof(ULONG))); + + // Add space for personality routine, it must be 4-byte aligned. + unwindSize += sizeof(ULONG); +#else + PORTABILITY_ASSERT("reservePersonalityRoutineSpace"); +#endif // !defined(_TARGET_AMD64_) + +} // Reserve memory for the method/funclet's unwind information. // Note that this must be called before allocMem. It should be // called once for the main method, once for every funclet, and @@ -11002,27 +11029,7 @@ void CEEJitInfo::reserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwind ULONG currentSize = unwindSize; -#if defined(_TARGET_AMD64_) - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO up to the variable-sized UnwindCodes - // array has already had its size included in unwindSize by the caller. - currentSize += sizeof(ULONG); - - // Note that the count of unwind codes (2 bytes each) is stored as a UBYTE - // So the largest size could be 510 bytes, plus the header and language - // specific stuff. This can't overflow. - - _ASSERTE(FitsInU4(currentSize + sizeof(ULONG))); - currentSize = (ULONG)(ALIGN_UP(currentSize, sizeof(ULONG))); -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) - // The JIT passes in a 4-byte aligned block of unwind data. - _ASSERTE(IS_ALIGNED(currentSize, sizeof(ULONG))); - - // Add space for personality routine, it must be 4-byte aligned. - currentSize += sizeof(ULONG); -#else - PORTABILITY_ASSERT("CEEJitInfo::reserveUnwindInfo"); -#endif // !defined(_TARGET_AMD64_) + reservePersonalityRoutineSpace(currentSize); m_totalUnwindSize += currentSize; @@ -11107,27 +11114,7 @@ void CEEJitInfo::allocUnwindInfo ( UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *) &(m_theUnwindBlock[m_usedUnwindSize]); m_usedUnwindSize += unwindSize; -#if defined(_TARGET_AMD64_) - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO up to the variable-sized UnwindCodes - // array has already had its size included in unwindSize by the caller. - m_usedUnwindSize += sizeof(ULONG); - - // Note that the count of unwind codes (2 bytes each) is stored as a UBYTE - // So the largest size could be 510 bytes, plus the header and language - // specific stuff. This can't overflow. - - _ASSERTE(FitsInU4(m_usedUnwindSize + sizeof(ULONG))); - m_usedUnwindSize = (ULONG)(ALIGN_UP(m_usedUnwindSize,sizeof(ULONG))); -#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) - // The JIT passes in a 4-byte aligned block of unwind data. - _ASSERTE(IS_ALIGNED(m_usedUnwindSize, sizeof(ULONG))); - - // Add space for personality routine, it must be 4-byte aligned. - m_usedUnwindSize += sizeof(ULONG); -#else - PORTABILITY_ASSERT("CEEJitInfo::reserveUnwindInfo"); -#endif + reservePersonalityRoutineSpace(m_usedUnwindSize); _ASSERTE(m_usedUnwindSize <= m_totalUnwindSize); @@ -11170,7 +11157,7 @@ void CEEJitInfo::allocUnwindInfo ( RUNTIME_FUNCTION__SetBeginAddress(pRuntimeFunction, currentCodeOffset + startOffset); -#if defined(_TARGET_AMD64_) +#ifdef _TARGET_AMD64_ pRuntimeFunction->EndAddress = currentCodeOffset + endOffset; #endif @@ -11190,11 +11177,15 @@ void CEEJitInfo::allocUnwindInfo ( } #endif // _DEBUG -#if defined(_TARGET_AMD64_) - /* Copy the UnwindBlock */ memcpy(pUnwindInfo, pUnwindBlock, unwindSize); +#if defined(_TARGET_X86_) + + // Do NOTHING + +#elif defined(_TARGET_AMD64_) + pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER; ULONG * pPersonalityRoutine = (ULONG*)ALIGN_UP(&(pUnwindInfo->UnwindCode[pUnwindInfo->CountOfUnwindCodes]), sizeof(ULONG)); @@ -11202,9 +11193,6 @@ void CEEJitInfo::allocUnwindInfo ( #elif defined(_TARGET_ARM64_) - /* Copy the UnwindBlock */ - memcpy(pUnwindInfo, pUnwindBlock, unwindSize); - *(LONG *)pUnwindInfo |= (1 << 20); // X bit ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG))); @@ -11212,13 +11200,11 @@ void CEEJitInfo::allocUnwindInfo ( #elif defined(_TARGET_ARM_) - /* Copy the UnwindBlock */ - memcpy(pUnwindInfo, pUnwindBlock, unwindSize); - *(LONG *)pUnwindInfo |= (1 << 20); // X bit ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG))); *pPersonalityRoutine = (TADDR)ProcessCLRException - baseAddress; + #endif #if defined(_TARGET_AMD64_) |