summaryrefslogtreecommitdiff
path: root/src/vm/stackwalk.cpp
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-05-06 23:43:46 -0700
committerJan Kotas <jkotas@microsoft.com>2015-05-07 12:03:00 -0700
commit484a2cf0b0c4e304a5093ec26e07fe41f8896c3c (patch)
tree348b56df4cdb235bb87ba9bc9118711c8db13bfd /src/vm/stackwalk.cpp
parentc6efc7047edb38075310cfef8ea28b91717b8108 (diff)
downloadcoreclr-484a2cf0b0c4e304a5093ec26e07fe41f8896c3c.tar.gz
coreclr-484a2cf0b0c4e304a5093ec26e07fe41f8896c3c.tar.bz2
coreclr-484a2cf0b0c4e304a5093ec26e07fe41f8896c3c.zip
Merge changes from parent branch
[tfs-changeset: 1466545]
Diffstat (limited to 'src/vm/stackwalk.cpp')
-rw-r--r--src/vm/stackwalk.cpp27
1 files changed, 26 insertions, 1 deletions
diff --git a/src/vm/stackwalk.cpp b/src/vm/stackwalk.cpp
index d39ce06ef4..3301dec092 100644
--- a/src/vm/stackwalk.cpp
+++ b/src/vm/stackwalk.cpp
@@ -1510,6 +1510,7 @@ void StackFrameIterator::ResetCrawlFrame()
m_crawl.isFilterFunclet = false;
m_crawl.isFilterFuncletCached = false;
m_crawl.fShouldParentToFuncletSkipReportingGCReferences = false;
+ m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = false;
#endif // WIN64EXCEPTIONS
m_crawl.pThread = this->m_pThread;
@@ -1669,6 +1670,10 @@ StackWalkAction StackFrameIterator::Filter(void)
// CrawlFrame
m_crawl.fShouldCrawlframeReportGCReferences = true;
+ // By default, assume that parent frame is going to report GC references from
+ // the actual location reported by the stack walk.
+ m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = false;
+
if (!m_sfParent.IsNull())
{
// we are now skipping frames to get to the funclet's parent
@@ -1887,7 +1892,7 @@ ProcessFuncletsForGCReporting:
_ASSERTE(m_fDidFuncletReportGCReferences);
m_fDidFuncletReportGCReferences = false;
-
+
STRESS_LOG0(LF_GCROOTS, LL_INFO100, "Unwound funclet will skip reporting references\n");
}
}
@@ -1913,6 +1918,9 @@ ProcessFuncletsForGCReporting:
if (m_sfParent.IsMaxVal() ||
ExceptionTracker::IsUnwoundToTargetParentFrame(&m_crawl, m_sfParent))
{
+ // Reset flag as we have reached target method frame so no more skipping required
+ fSkippingFunclet = false;
+
// We've finished skipping as told. Now check again.
if ((m_fProcessIntermediaryNonFilterFunclet == true) || (m_fProcessNonFilterFunclet == true))
@@ -1997,6 +2005,23 @@ ProcessFuncletsForGCReporting:
// now that we've found the parent that will report roots reset our state.
m_fDidFuncletReportGCReferences = true;
+
+ // After funclet gets unwound parent will begin to report gc references. Reporting GC references
+ // using the IP of throw in parent method can crash application. Parent could have locals objects
+ // which might not have been reported by funclet as live and would have already been collected
+ // when funclet was on stack. Now if parent starts using IP of throw to report gc references it
+ // would report garbage values as live objects. So instead parent can use the IP of the resume
+ // address of catch funclet to report live GC references.
+ m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = true;
+ // Store catch clause info. Helps retrieve IP of resume address.
+ m_crawl.ehClauseForCatch = pTracker->GetEHClauseForCatch();
+
+ STRESS_LOG3(LF_GCROOTS, LL_INFO100,
+ "STACKWALK: Parent of funclet which didn't report GC roots is handling an exception at 0x%p"
+ "(EH handler range [%x, %x) ), so we need to specially report roots to ensure variables alive"
+ " in its handler stay live.\n",
+ pTracker->GetCatchToCallPC(), m_crawl.ehClauseForCatch.HandlerStartPC,
+ m_crawl.ehClauseForCatch.HandlerEndPC);
}
else if (!m_crawl.IsFunclet())
{