From: Jonghyun Park Date: Wed, 12 Apr 2017 22:09:33 +0000 (+0900) Subject: [x86/Linux] Fix ResumeEsp before resume (dotnet/coreclr#10749) X-Git-Tag: submit/tizen/20210909.063632~11030^2~7282 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f244aa41cfb13495ba556a505f50067d3d5639bc;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [x86/Linux] Fix ResumeEsp before resume (dotnet/coreclr#10749) * [x86/Linux] Correctly unwind FCALL frames * Fix Up ResumeEsp inside ProcessCLRException * Fix Context Before PC Update Commit migrated from https://github.com/dotnet/coreclr/commit/03d0d244bca38053d54eef6f4b6db51ae87f7700 --- diff --git a/src/coreclr/src/inc/eetwain.h b/src/coreclr/src/inc/eetwain.h index 54e9a34..497e0b0 100644 --- a/src/coreclr/src/inc/eetwain.h +++ b/src/coreclr/src/inc/eetwain.h @@ -652,7 +652,10 @@ HRESULT FixContextForEnC(PCONTEXT pCtx, #ifdef WIN64EXCEPTIONS static void EnsureCallerContextIsValid( PREGDISPLAY pRD, StackwalkCacheEntry* pCacheEntry, EECodeInfo * pCodeInfo = NULL ); static size_t GetCallerSp( PREGDISPLAY pRD ); -#endif +#ifdef _TARGET_X86_ + static size_t GetResumeSp( PCONTEXT pContext ); +#endif // _TARGET_X86_ +#endif // WIN64EXCEPTIONS #ifdef DACCESS_COMPILE virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); diff --git a/src/coreclr/src/vm/eetwain.cpp b/src/coreclr/src/vm/eetwain.cpp index 2c9059b..2886daa 100644 --- a/src/coreclr/src/vm/eetwain.cpp +++ b/src/coreclr/src/vm/eetwain.cpp @@ -4048,6 +4048,54 @@ bool UnwindStackFrame(PREGDISPLAY pContext, #endif // _TARGET_X86_ +#ifdef WIN64EXCEPTIONS +#ifdef _TARGET_X86_ +size_t EECodeManager::GetResumeSp( PCONTEXT pContext ) +{ + PCODE currentPc = PCODE(pContext->Eip); + + _ASSERTE(ExecutionManager::IsManagedCode(currentPc)); + + EECodeInfo codeInfo(currentPc); + + PTR_CBYTE methodStart = PTR_CBYTE(codeInfo.GetSavedMethodCode()); + + GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken(); + PTR_VOID methodInfoPtr = gcInfoToken.Info; + DWORD curOffs = codeInfo.GetRelOffset(); + + CodeManStateBuf stateBuf; + + stateBuf.hdrInfoSize = (DWORD)DecodeGCHdrInfo(gcInfoToken, + curOffs, + &stateBuf.hdrInfoBody); + + PTR_CBYTE table = dac_cast(methodInfoPtr) + stateBuf.hdrInfoSize; + + hdrInfo *info = &stateBuf.hdrInfoBody; + + _ASSERTE(info->epilogOffs == hdrInfo::NOT_IN_EPILOG && info->prologOffs == hdrInfo::NOT_IN_PROLOG); + + bool isESPFrame = !info->ebpFrame && !info->doubleAlign; + + if (codeInfo.IsFunclet()) + { + // Treat funclet's frame as ESP frame + isESPFrame = true; + } + + if (isESPFrame) + { + const size_t curESP = (size_t)(pContext->Esp); + return curESP + GetPushedArgSize(info, table, curOffs); + } + + const size_t curEBP = (size_t)(pContext->Ebp); + return GetOutermostBaseFP(curEBP, info); +} +#endif // _TARGET_X86_ +#endif // WIN64EXCEPTIONS + #ifndef CROSSGEN_COMPILE #ifndef WIN64EXCEPTIONS diff --git a/src/coreclr/src/vm/exceptionhandling.cpp b/src/coreclr/src/vm/exceptionhandling.cpp index 7e82cce..31b85bd 100644 --- a/src/coreclr/src/vm/exceptionhandling.cpp +++ b/src/coreclr/src/vm/exceptionhandling.cpp @@ -123,6 +123,24 @@ bool FixNonvolatileRegisters(UINT_PTR uOriginalSP, bool fAborting ); +void FixContext(PCONTEXT pContextRecord) +{ +#define FIXUPREG(reg, value) \ + do { \ + STRESS_LOG2(LF_GCROOTS, LL_INFO100, "Updating " #reg " %p to %p\n", \ + pContextRecord->reg, \ + (value)); \ + pContextRecord->reg = (value); \ + } while (0) + +#ifdef _TARGET_X86_ + size_t resumeSp = EECodeManager::GetResumeSp(pContextRecord); + FIXUPREG(ResumeEsp, resumeSp); +#endif // _TARGET_X86_ + +#undef FIXUPREG +} + MethodDesc * GetUserMethodForILStub(Thread * pThread, UINT_PTR uStubSP, MethodDesc * pILStubMD, Frame ** ppFrameOut); #ifdef FEATURE_PAL @@ -441,6 +459,7 @@ void ExceptionTracker::UpdateNonvolatileRegisters(CONTEXT *pContextRecord, REGDI } \ } while (0) + #if defined(_TARGET_X86_) UPDATEREG(Ebx); @@ -1181,6 +1200,8 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord pThread->SetFrame(pLimitFrame); + FixContext(pContextRecord); + SetIP(pContextRecord, (PCODE)uResumePC); }