#endif
}
+// When we have fragmented unwind we usually want to refer to the
+// unwind record that includes the prolog. We can find it by searching
+// back in the sequence of unwind records.
+PTR_RUNTIME_FUNCTION FindRootEntry(PTR_RUNTIME_FUNCTION pFunctionEntry, TADDR baseAddress)
+{
+ LIMITED_METHOD_DAC_CONTRACT;
+
+ PTR_RUNTIME_FUNCTION pRootEntry = pFunctionEntry;
+
+ if (pRootEntry != NULL)
+ {
+ // Walk backwards in the RUNTIME_FUNCTION array until we find a non-fragment.
+ // We're guaranteed to find one, because we require that a fragment live in a function or funclet
+ // that has a prolog, which will have non-fragment .xdata.
+ for (;;)
+ {
+ if (!IsFunctionFragment(baseAddress, pRootEntry))
+ {
+ // This is not a fragment; we're done
+ break;
+ }
+
+ --pRootEntry;
+ }
+ }
+
+ return pRootEntry;
+}
+
#endif // EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS
#endif
TADDR baseAddress = pCodeInfo->GetModuleBase();
- TADDR funcletStartAddress = baseAddress + RUNTIME_FUNCTION__BeginAddress(pFunctionEntry);
#if defined(EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS)
- // Is the RUNTIME_FUNCTION a fragment? If so, we need to walk backwards until we find the first
- // non-fragment RUNTIME_FUNCTION, and use that one. This happens when we have very large functions
- // and multiple RUNTIME_FUNCTION entries per function or funclet. However, all but the first will
- // have the "F" bit set in the unwind data, indicating a fragment (with phantom prolog unwind codes).
-
- for (;;)
- {
- if (!IsFunctionFragment(baseAddress, pFunctionEntry))
- {
- // This is not a fragment; we're done
- break;
- }
-
- // We found a fragment. Walk backwards in the RUNTIME_FUNCTION array until we find a non-fragment.
- // We're guaranteed to find one, because we require that a fragment live in a function or funclet
- // that has a prolog, which will have non-fragment .xdata.
- --pFunctionEntry;
-
- funcletStartAddress = baseAddress + RUNTIME_FUNCTION__BeginAddress(pFunctionEntry);
- }
+ pFunctionEntry = FindRootEntry(pFunctionEntry, baseAddress);
#endif // EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS
+ TADDR funcletStartAddress = baseAddress + RUNTIME_FUNCTION__BeginAddress(pFunctionEntry);
+
return funcletStartAddress;
}
#endif // !DACCESS_COMPILE
#if defined(WIN64EXCEPTIONS)
+// Note: This returns the root unwind record (the one that describes the prolog)
+// in cases where there is fragmented unwind.
PTR_RUNTIME_FUNCTION EEJitManager::LazyGetFunctionEntry(EECodeInfo * pCodeInfo)
{
CONTRACTL {
if (RUNTIME_FUNCTION__BeginAddress(pFunctionEntry) <= address && address < RUNTIME_FUNCTION__EndAddress(pFunctionEntry, baseAddress))
{
+
+#if defined(EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS)
+ // If we may have fragmented unwind make sure we're returning the root record
+ pFunctionEntry = FindRootEntry(pFunctionEntry, baseAddress);
+#endif
+
return pFunctionEntry;
}
}