Skip to content

Fix x86 EH for UnmanagedCallersOnly methods #58796

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 9, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/coreclr/vm/stackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "interpreter.h"
#endif // FEATURE_INTERPRETER

#include "gcinfodecoder.h"

#ifdef FEATURE_EH_FUNCLETS
#define PROCESS_EXPLICIT_FRAME_BEFORE_MANAGED_FRAME
#endif
Expand Down Expand Up @@ -3135,6 +3137,12 @@ void StackFrameIterator::PostProcessingForManagedFrames(void)
m_exInfoWalk.WalkToPosition(GetRegdisplaySP(m_crawl.pRD), (m_flags & POPFRAMES));
#endif // ELIMINATE_FEF

#ifdef TARGET_X86
hdrInfo gcHdrInfo;
DecodeGCHdrInfo(m_crawl.codeInfo.GetGCInfoToken(), 0, &gcHdrInfo);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All other places that decode GCInfo in this file go through m_crawl.GetCodeManager(). Is it worth following the pattern?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, but let me do that as a separate cleanup so that this change is just a fix for the bug. I will need to add a new method to the EECodeManager and then I'd use it in the exceptionhandling.cpp too where we currently also have this raw decoding.

bool hasReversePInvoke = gcHdrInfo.revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET;
#endif // TARGET_X86

ProcessIp(GetControlPC(m_crawl.pRD));

// if we have unwound to a native stack frame, stop and set the frame state accordingly
Expand All @@ -3143,6 +3151,18 @@ void StackFrameIterator::PostProcessingForManagedFrames(void)
m_frameState = SFITER_NATIVE_MARKER_FRAME;
m_crawl.isNativeMarker = true;
}
#ifdef TARGET_X86
else if (hasReversePInvoke)
{
// The managed frame we've unwound from had reverse PInvoke frame. Since we are on a frameless
// frame, that means that the method was called from managed code without any native frames in between.
// On x86, the InlinedCallFrame of the pinvoke would get skipped as we've just unwound to the pinvoke IL stub and
// for this architecture, the inlined call frames are supposed to be processed before the managed frame they are stored in.
// So we force the stack frame iterator to process the InlinedCallFrame before the IL stub.
_ASSERTE(InlinedCallFrame::FrameHasActiveCall(m_crawl.pFrame));
m_crawl.isFrameless = false;
}
#endif
} // StackFrameIterator::PostProcessingForManagedFrames()

//---------------------------------------------------------------------------------------
Expand Down