-
Couldn't load subscription status.
- Fork 5.2k
Debugger fixes for the Windows X86 EH Funclets model #115630
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
Changes from all commits
73c21b5
ca2f490
3708d1a
1e4ecc8
c4710f0
7c14b4e
b860621
d5aa015
d32e3d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -211,7 +211,7 @@ RtlpGetFunctionEndAddress ( | |
| _In_ TADDR ImageBase | ||
| ) | ||
| { | ||
| PUNWIND_INFO pUnwindInfo = (PUNWIND_INFO)(ImageBase + FunctionEntry->UnwindData); | ||
| DPTR(UNWIND_INFO) pUnwindInfo = dac_cast<DPTR(UNWIND_INFO)>(ImageBase + FunctionEntry->UnwindData); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ouch :) |
||
|
|
||
| return FunctionEntry->BeginAddress + pUnwindInfo->FunctionLength; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1578,6 +1578,22 @@ size_t GCInfo::gcInfoBlockHdrSave( | |
| assert(header->epilogCount <= 1); | ||
| } | ||
| #endif | ||
| if (compiler->UsesFunclets() && compiler->info.compFlags & CORINFO_FLG_SYNCH) | ||
| { | ||
| // While the sync start offset and end offset are not used by the stackwalker/EH system | ||
| // in funclets mode, we do need to know if the code is synchronized if we are generating | ||
| // an edit and continue method, so that we can properly manage the stack during a Remap | ||
| // operation, for determining the ParamTypeArg for collectible generics purposes, and | ||
| // for determining the offset of the localloc variable in the stack frame. | ||
| // Instead of inventing a new encoding, just encode some non-0 offsets into these fields. | ||
| // to indicate that the method is synchronized. | ||
| // | ||
| // Use 1 for both offsets, since that doesn't actually make sense and implies that the | ||
| // sync region is 0 bytes long. The JIT will never emit a sync region of 0 bytes in non- | ||
| // funclet mode. | ||
| header->syncStartOffset = 1; | ||
|
||
| header->syncEndOffset = 1; | ||
| } | ||
|
|
||
| header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET; | ||
| if (compiler->opts.IsReversePInvoke()) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -189,7 +189,12 @@ size_t DecodeGCHdrInfo(GCInfoToken gcInfoToken, | |||||||||||||
| header.syncEndOffset = decodeUnsigned(table); | ||||||||||||||
|
|
||||||||||||||
| _ASSERTE(header.syncStartOffset != INVALID_SYNC_OFFSET && header.syncEndOffset != INVALID_SYNC_OFFSET); | ||||||||||||||
| #ifdef FEATURE_EH_FUNCLETS | ||||||||||||||
| _ASSERTE(header.syncStartOffset == 1); | ||||||||||||||
| _ASSERTE(header.syncEndOffset == 1); | ||||||||||||||
| #else | ||||||||||||||
| _ASSERTE(header.syncStartOffset < header.syncEndOffset); | ||||||||||||||
| #endif | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| if (header.revPInvokeOffset == HAS_REV_PINVOKE_FRAME_OFFSET) | ||||||||||||||
|
|
@@ -366,6 +371,9 @@ size_t GetLocallocSPOffset(hdrInfo * info) | |||||||||||||
| _ASSERTE(info->localloc && info->ebpFrame); | ||||||||||||||
|
|
||||||||||||||
| unsigned position = info->savedRegsCountExclFP + | ||||||||||||||
| #ifdef FEATURE_EH_FUNCLETS | ||||||||||||||
| ((info->syncStartOffset != INVALID_SYNC_OFFSET) ? 1 : 0) + // Is this method synchronized | ||||||||||||||
| #endif | ||||||||||||||
| 1; | ||||||||||||||
| return position * sizeof(TADDR); | ||||||||||||||
| } | ||||||||||||||
|
|
@@ -377,12 +385,20 @@ size_t GetParamTypeArgOffset(hdrInfo * info) | |||||||||||||
|
|
||||||||||||||
| _ASSERTE((info->genericsContext || info->handlers) && info->ebpFrame); | ||||||||||||||
|
|
||||||||||||||
| #ifdef FEATURE_EH_FUNCLETS | ||||||||||||||
| unsigned position = info->savedRegsCountExclFP + | ||||||||||||||
| ((info->syncStartOffset != INVALID_SYNC_OFFSET) ? 1 : 0) + // Is this method synchronized | ||||||||||||||
| info->localloc + | ||||||||||||||
| 1; // For CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG | ||||||||||||||
| #else | ||||||||||||||
| unsigned position = info->savedRegsCountExclFP + | ||||||||||||||
| info->localloc + | ||||||||||||||
| 1; // For CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG | ||||||||||||||
| #endif | ||||||||||||||
| return position * sizeof(TADDR); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| #ifndef FEATURE_EH_FUNCLETS | ||||||||||||||
| inline size_t GetStartShadowSPSlotsOffset(hdrInfo * info) | ||||||||||||||
| { | ||||||||||||||
| LIMITED_METHOD_DAC_CONTRACT; | ||||||||||||||
|
|
@@ -425,6 +441,7 @@ inline size_t GetEndShadowSPSlotsOffset(hdrInfo * info, unsigned maxHandlerNesti | |||||||||||||
| return GetStartShadowSPSlotsOffset(info) + | ||||||||||||||
| (numberOfShadowSPSlots * sizeof(TADDR)); | ||||||||||||||
| } | ||||||||||||||
| #endif // FEATURE_EH_FUNCLETS | ||||||||||||||
|
|
||||||||||||||
| /***************************************************************************** | ||||||||||||||
| * returns the base frame pointer corresponding to the target nesting level. | ||||||||||||||
|
|
@@ -524,7 +541,6 @@ FrameType GetHandlerFrameInfo(hdrInfo * info, | |||||||||||||
| _ASSERTE(condition); \ | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| PTR_TADDR pFirstBaseSPslot = GetFirstBaseSPslotPtr(frameEBP, info); | ||||||||||||||
| TADDR baseSP = GetOutermostBaseFP(frameEBP, info); | ||||||||||||||
| bool nonLocalHandlers = false; // Are the funclets invoked by EE (instead of managed code itself) | ||||||||||||||
| bool hasInnerFilter = false; | ||||||||||||||
|
|
@@ -539,6 +555,7 @@ FrameType GetHandlerFrameInfo(hdrInfo * info, | |||||||||||||
| // expected to be in decreasing order. | ||||||||||||||
| size_t lvl = 0; | ||||||||||||||
| #ifndef FEATURE_EH_FUNCLETS | ||||||||||||||
| PTR_TADDR pFirstBaseSPslot = GetFirstBaseSPslotPtr(frameEBP, info); | ||||||||||||||
| PTR_TADDR pSlot; | ||||||||||||||
| for(lvl = 0, pSlot = pFirstBaseSPslot; | ||||||||||||||
| *pSlot && lvl < unwindLevel; | ||||||||||||||
|
|
@@ -653,6 +670,15 @@ inline size_t GetSizeOfFrameHeaderForEnC(hdrInfo * info) | |||||||||||||
| { | ||||||||||||||
| WRAPPER_NO_CONTRACT; | ||||||||||||||
|
|
||||||||||||||
| #ifdef FEATURE_EH_FUNCLETS | ||||||||||||||
| _ASSERTE(info->ebpFrame); | ||||||||||||||
| unsigned position = info->savedRegsCountExclFP + | ||||||||||||||
| info->localloc + | ||||||||||||||
| info->genericsContext + // For CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG | ||||||||||||||
| ((info->syncStartOffset != INVALID_SYNC_OFFSET) ? 1 : 0) // Is this method synchronized | ||||||||||||||
| + 1; // for ebpFrame | ||||||||||||||
|
Comment on lines
+677
to
+679
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Let's use an order that's closer to the reality. We also need to apply the same fix to inline
size_t GetParamTypeArgOffset(hdrInfo * info)
{
LIMITED_METHOD_DAC_CONTRACT;
_ASSERTE((info->genericsContext || info->handlers) && info->ebpFrame);
#ifdef FEATURE_EH_FUNCLETS
unsigned position = info->savedRegsCountExclFP +
info->localloc +
((info->syncStartOffset != INVALID_SYNC_OFFSET) ? 1 : 0) + // Is this method synchronized
1; // For CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG
#else
unsigned position = info->savedRegsCountExclFP +
info->localloc +
1; // For CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG
#endif
return position * sizeof(TADDR);
} |
||||||||||||||
| return position * sizeof(TADDR); | ||||||||||||||
| #else | ||||||||||||||
| // See comment above Compiler::lvaAssignFrameOffsets() in src\jit\il\lclVars.cpp | ||||||||||||||
| // for frame layout | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -664,6 +690,7 @@ inline size_t GetSizeOfFrameHeaderForEnC(hdrInfo * info) | |||||||||||||
| // to get the total size of the header. | ||||||||||||||
| return sizeof(TADDR) + | ||||||||||||||
| GetEndShadowSPSlotsOffset(info, MAX_EnC_HANDLER_NESTING_LEVEL); | ||||||||||||||
| #endif // FEATURE_EH_FUNCLETS | ||||||||||||||
| } | ||||||||||||||
| #endif // FEATURE_NATIVEAOT | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just out of curiosity for me - why is this branch only taken on non-x86? I'd expect this to be a funclet path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The x86 unwinder continues to have a subtly different set of interactions with the rest of the codebase compared to the other architectures. Its... much closer than it was before, but the frame pointer concepts are somewhat different, and when I wrote this it appeared that it is related to the nature of X86 codegen where the sp moves during code execution in a frame, and how the unwinder updates somewhat different structures as it runs.