summaryrefslogtreecommitdiff
path: root/src/ToolBox
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2015-10-29 19:09:52 -0700
committerJan Kotas <jkotas@microsoft.com>2015-10-29 19:09:52 -0700
commita8192fbc7064ed96cfeb8872bcb6479c217f7b5f (patch)
tree738c092202d3ce5c7ed4ec08114c3c41b7b005d8 /src/ToolBox
parent3c50dec5796206c6042fd6adc3133a0ad22649e5 (diff)
downloadcoreclr-a8192fbc7064ed96cfeb8872bcb6479c217f7b5f.tar.gz
coreclr-a8192fbc7064ed96cfeb8872bcb6479c217f7b5f.tar.bz2
coreclr-a8192fbc7064ed96cfeb8872bcb6479c217f7b5f.zip
Port .NET Framework 4.6.1 changes
Core runtime and GC changes from https://github.com/Microsoft/dotnet/blob/master/docs/releases/net461/dotnet461-changes.md that are not in CoreCLR yet [tfs-changeset: 1543382]
Diffstat (limited to 'src/ToolBox')
-rw-r--r--src/ToolBox/SOS/Strike/eeheap.cpp9
-rw-r--r--src/ToolBox/SOS/Strike/sos.def18
-rw-r--r--src/ToolBox/SOS/Strike/strike.cpp296
3 files changed, 312 insertions, 11 deletions
diff --git a/src/ToolBox/SOS/Strike/eeheap.cpp b/src/ToolBox/SOS/Strike/eeheap.cpp
index 4b4fa1716e..d9484d2a0a 100644
--- a/src/ToolBox/SOS/Strike/eeheap.cpp
+++ b/src/ToolBox/SOS/Strike/eeheap.cpp
@@ -537,11 +537,11 @@ void GCPrintLargeHeapSegmentInfo(const DacpGcHeapDetails &heap, DWORD_PTR &total
void GCHeapInfo(const DacpGcHeapDetails &heap, DWORD_PTR &total_size)
{
GCPrintGenerationInfo(heap);
- ExtOut(WIN64_8SPACES " segment " WIN64_8SPACES " begin " WIN64_8SPACES "allocated size\n");
+ ExtOut("%" POINTERSIZE "s %" POINTERSIZE "s %" POINTERSIZE "s %" POINTERSIZE "s\n", "segment", "begin", "allocated", "size");
GCPrintSegmentInfo(heap, total_size);
ExtOut("Large object heap starts at 0x%p\n",
(ULONG64)heap.generation_table[GetMaxGeneration()+1].allocation_start);
- ExtOut(WIN64_8SPACES " segment " WIN64_8SPACES " begin " WIN64_8SPACES "allocated size\n");
+ ExtOut("%" POINTERSIZE "s %" POINTERSIZE "s %" POINTERSIZE "s %" POINTERSIZE "s\n", "segment", "begin", "allocated", "size");
GCPrintLargeHeapSegmentInfo(heap,total_size);
}
@@ -758,7 +758,7 @@ void GCGenUsageStats(TADDR start, TADDR end, const std::unordered_set<TADDR> &li
{
genUsage->freed += objSize;
}
- else if (liveObjs.find(taddrObj) == liveObjs.end())
+ else if (!(liveObjs.empty()) && liveObjs.find(taddrObj) == liveObjs.end())
{
genUsage->unrooted += objSize;
}
@@ -782,7 +782,8 @@ BOOL GCHeapUsageStats(const DacpGcHeapDetails& heap, BOOL bIncUnreachable, HeapU
#ifndef FEATURE_PAL
// this will create the bitmap of rooted objects only if bIncUnreachable is true
GCRootImpl gcroot;
- const std::unordered_set<TADDR> &liveObjs = gcroot.GetLiveObjects();
+ std::unordered_set<TADDR> emptyLiveObjs;
+ const std::unordered_set<TADDR> &liveObjs = (bIncUnreachable ? gcroot.GetLiveObjects() : emptyLiveObjs);
// 1a. enumerate all non-ephemeral segments
while (taddrSeg != (TADDR)heap.generation_table[0].start_segment)
diff --git a/src/ToolBox/SOS/Strike/sos.def b/src/ToolBox/SOS/Strike/sos.def
index e7a7ff9c7a..94dd351a28 100644
--- a/src/ToolBox/SOS/Strike/sos.def
+++ b/src/ToolBox/SOS/Strike/sos.def
@@ -21,7 +21,15 @@ EXPORTS
dumpdomain=DumpDomain
#ifdef TRACE_GC
DumpGCLog
-#endif
+ dumpgclog=DumpGCLog
+ dlog=DumpGCLog
+#endif
+ DumpGCData
+ dumpgcdata=DumpGCData
+ dgc=DumpGCData
+ DumpGCConfigLog
+ dumpgcconfiglog=DumpGCConfigLog
+ dclog=DumpGCConfigLog
DumpHeap
dumpheap=DumpHeap
DumpIL
@@ -168,6 +176,10 @@ EXPORTS
filthint
#endif
+#ifdef FEATURE_PAL
+ SetClrDebugDll
+ UnloadClrDebugDll
+#else
_EFN_GetManagedExcepStack
_EFN_GetManagedExcepStackW
_EFN_GetManagedObjectFieldInfo
@@ -194,6 +206,8 @@ EXPORTS
procinfo=ProcInfo
VerifyStackTrace
WatsonBuckets
+#endif // !FEATURE_PAL
+
#ifdef FEATURE_CORESYSTEM
// Only documented for Apollo internal usage
@@ -214,4 +228,4 @@ EXPORTS
getCodeTypeFlags=GetCodeTypeFlags
TraceToCode
tracetocode=TraceToCode
-#endif \ No newline at end of file
+#endif
diff --git a/src/ToolBox/SOS/Strike/strike.cpp b/src/ToolBox/SOS/Strike/strike.cpp
index 2434345d3c..730850eeca 100644
--- a/src/ToolBox/SOS/Strike/strike.cpp
+++ b/src/ToolBox/SOS/Strike/strike.cpp
@@ -2083,7 +2083,7 @@ struct StackTraceElement
#if defined(FEATURE_EXCEPTIONDISPATCHINFO)
// TRUE if this element represents the last frame of the foreign
// exception stack trace.
- BOOL fIsLastFrameFromForeignStackTrace;
+ BOOL fIsLastFrameFromForeignStackTrace;
#endif // defined(FEATURE_EXCEPTIONDISPATCHINFO)
};
@@ -8431,7 +8431,6 @@ DECLARE_API (DumpGCLog)
INIT_API_NODAC();
MINIDUMP_NOT_SUPPORTED();
-
if (GetEEFlavor() == UNKNOWNEE)
{
ExtOut("CLR not loaded\n");
@@ -8446,7 +8445,6 @@ DECLARE_API (DumpGCLog)
if (*args != 0)
fileName = args;
- // Try to find stress log symbols
DWORD_PTR dwAddr = GetValueFromExpression(MAIN_CLR_MODULE_NAME_A "!SVR::gc_log_buffer");
moveN (dwAddr, dwAddr);
@@ -8460,7 +8458,7 @@ DECLARE_API (DumpGCLog)
return E_FAIL;
}
}
-
+
ExtOut("Dumping GC log at %08x\n", dwAddr);
g_bDacBroken = FALSE;
@@ -8511,6 +8509,7 @@ DECLARE_API (DumpGCLog)
DWORD dwWritten = 0;
WriteFile (hGCLog, bGCLog, iRealLogSize + 1, &dwWritten, NULL);
+
Status = S_OK;
exit:
@@ -8529,9 +8528,296 @@ exit:
return Status;
}
-
#endif //TRACE_GC
+DECLARE_API (DumpGCConfigLog)
+{
+ INIT_API();
+#ifdef GC_CONFIG_DRIVEN
+ MINIDUMP_NOT_SUPPORTED();
+
+ if (GetEEFlavor() == UNKNOWNEE)
+ {
+ ExtOut("CLR not loaded\n");
+ return Status;
+ }
+
+ const char* fileName = "GCConfigLog.txt";
+
+ while (isspace (*args))
+ args ++;
+
+ if (*args != 0)
+ fileName = args;
+
+ if (!InitializeHeapData ())
+ {
+ ExtOut("GC Heap not initialized yet.\n");
+ return S_OK;
+ }
+
+ BOOL fIsServerGC = IsServerBuild();
+
+ DWORD_PTR dwAddr = 0;
+ DWORD_PTR dwAddrOffset = 0;
+
+ if (fIsServerGC)
+ {
+ dwAddr = GetValueFromExpression(MAIN_CLR_MODULE_NAME_A "!SVR::gc_config_log_buffer");
+ dwAddrOffset = GetValueFromExpression(MAIN_CLR_MODULE_NAME_A "!SVR::gc_config_log_buffer_offset");
+ }
+ else
+ {
+ dwAddr = GetValueFromExpression(MAIN_CLR_MODULE_NAME_A "!WKS::gc_config_log_buffer");
+ dwAddrOffset = GetValueFromExpression(MAIN_CLR_MODULE_NAME_A "!WKS::gc_config_log_buffer_offset");
+ }
+
+ moveN (dwAddr, dwAddr);
+ moveN (dwAddrOffset, dwAddrOffset);
+
+ if (dwAddr == 0)
+ {
+ ExtOut("Can't get either WKS or SVR GC's config log buffer");
+ return E_FAIL;
+ }
+
+ ExtOut("Dumping GC log at %08x\n", dwAddr);
+
+ g_bDacBroken = FALSE;
+
+ ExtOut("Attempting to dump GC log to file '%s'\n", fileName);
+
+ Status = E_FAIL;
+
+ HANDLE hGCLog = CreateFileA(
+ fileName,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (hGCLog == INVALID_HANDLE_VALUE)
+ {
+ ExtOut("failed to create file: %d\n", GetLastError());
+ goto exit;
+ }
+
+ int iLogSize = (int)dwAddrOffset;
+
+ BYTE* bGCLog = new NOTHROW BYTE[iLogSize];
+ if (bGCLog == NULL)
+ {
+ ReportOOM();
+ goto exit;
+ }
+
+ memset (bGCLog, 0, iLogSize);
+ if (!SafeReadMemory(dwAddr, bGCLog, iLogSize, NULL))
+ {
+ ExtOut("failed to read memory from %08x\n", dwAddr);
+ }
+
+ SetFilePointer (hGCLog, 0, 0, FILE_END);
+ DWORD dwWritten = 0;
+ WriteFile (hGCLog, bGCLog, iLogSize, &dwWritten, NULL);
+
+ Status = S_OK;
+
+exit:
+
+ if (hGCLog != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (hGCLog);
+ }
+
+ if (Status == S_OK)
+ ExtOut("SUCCESS: Stress log dumped\n");
+ else if (Status == S_FALSE)
+ ExtOut("No Stress log in the image, no file written\n");
+ else
+ ExtOut("FAILURE: Stress log not dumped\n");
+
+ return Status;
+#else
+ ExtOut("Not implemented\n");
+ return S_OK;
+#endif //GC_CONFIG_DRIVEN
+}
+
+#ifdef GC_CONFIG_DRIVEN
+static const char * const str_interesting_data_points[] =
+{
+ "pre short", // 0
+ "post short", // 1
+ "merged pins", // 2
+ "converted pins", // 3
+ "pre pin", // 4
+ "post pin", // 5
+ "pre and post pin", // 6
+ "pre short padded", // 7
+ "post short padded", // 7
+};
+
+static char* str_heap_compact_reasons[] =
+{
+ "low on ephemeral space",
+ "high fragmetation",
+ "couldn't allocate gaps",
+ "user specfied compact LOH",
+ "last GC before OOM",
+ "induced compacting GC",
+ "fragmented gen0 (ephemeral GC)",
+ "high memory load (ephemeral GC)",
+ "high memory load and frag",
+ "very high memory load and frag",
+ "no gc mode"
+};
+
+static BOOL gc_heap_compact_reason_mandatory_p[] =
+{
+ TRUE, //compact_low_ephemeral = 0,
+ FALSE, //compact_high_frag = 1,
+ TRUE, //compact_no_gaps = 2,
+ TRUE, //compact_loh_forced = 3,
+ TRUE, //compact_last_gc = 4
+ TRUE, //compact_induced_compacting = 5,
+ FALSE, //compact_fragmented_gen0 = 6,
+ FALSE, //compact_high_mem_load = 7,
+ TRUE, //compact_high_mem_frag = 8,
+ TRUE, //compact_vhigh_mem_frag = 9,
+ TRUE //compact_no_gc_mode = 10
+};
+
+static char* str_heap_expand_mechanisms[] =
+{
+ "reused seg with normal fit",
+ "reused seg with best fit",
+ "expand promoting eph",
+ "expand with a new seg",
+ "no memory for a new seg",
+ "expand in next full GC"
+};
+
+static char* str_bit_mechanisms[] =
+{
+ "using mark list",
+ "demotion"
+};
+
+static const char * const str_gc_global_mechanisms[] =
+{
+ "concurrent GCs",
+ "compacting GCs",
+ "promoting GCs",
+ "GCs that did demotion",
+ "card bundles",
+ "elevation logic"
+};
+
+void PrintInterestingGCInfo(DacpGCInterestingInfoData* dataPerHeap)
+{
+ ExtOut("Interesting data points\n");
+ size_t* data = dataPerHeap->interestingDataPoints;
+ for (int i = 0; i < NUM_GC_DATA_POINTS; i++)
+ {
+ ExtOut("%20s: %d\n", str_interesting_data_points[i], data[i]);
+ }
+
+ ExtOut("\nCompacting reasons\n");
+ data = dataPerHeap->compactReasons;
+ for (int i = 0; i < MAX_COMPACT_REASONS_COUNT; i++)
+ {
+ ExtOut("[%s]%35s: %d\n", (gc_heap_compact_reason_mandatory_p[i] ? "M" : "W"), str_heap_compact_reasons[i], data[i]);
+ }
+
+ ExtOut("\nExpansion mechanisms\n");
+ data = dataPerHeap->expandMechanisms;
+ for (int i = 0; i < MAX_EXPAND_MECHANISMS_COUNT; i++)
+ {
+ ExtOut("%30s: %d\n", str_heap_expand_mechanisms[i], data[i]);
+ }
+
+ ExtOut("\nOther mechanisms enabled\n");
+ data = dataPerHeap->bitMechanisms;
+ for (int i = 0; i < MAX_GC_MECHANISM_BITS_COUNT; i++)
+ {
+ ExtOut("%20s: %d\n", str_bit_mechanisms[i], data[i]);
+ }
+}
+#endif //GC_CONFIG_DRIVEN
+
+DECLARE_API(DumpGCData)
+{
+ INIT_API();
+
+#ifdef GC_CONFIG_DRIVEN
+ MINIDUMP_NOT_SUPPORTED();
+
+ if (!InitializeHeapData ())
+ {
+ ExtOut("GC Heap not initialized yet.\n");
+ return S_OK;
+ }
+
+ DacpGCInterestingInfoData interestingInfo;
+ interestingInfo.RequestGlobal(g_sos);
+ for (int i = 0; i < MAX_GLOBAL_GC_MECHANISMS_COUNT; i++)
+ {
+ ExtOut("%-30s: %d\n", str_gc_global_mechanisms[i], interestingInfo.globalMechanisms[i]);
+ }
+
+ ExtOut("\n[info per heap]\n");
+
+ if (!IsServerBuild())
+ {
+ if (interestingInfo.Request(g_sos) != S_OK)
+ {
+ ExtOut("Error requesting interesting GC info\n");
+ return E_FAIL;
+ }
+
+ PrintInterestingGCInfo(&interestingInfo);
+ }
+ else
+ {
+ DWORD dwNHeaps = GetGcHeapCount();
+ DWORD dwAllocSize;
+ if (!ClrSafeInt<DWORD>::multiply(sizeof(CLRDATA_ADDRESS), dwNHeaps, dwAllocSize))
+ {
+ ExtOut("Failed to get GCHeaps: integer overflow\n");
+ return Status;
+ }
+
+ CLRDATA_ADDRESS *heapAddrs = (CLRDATA_ADDRESS*)alloca(dwAllocSize);
+ if (g_sos->GetGCHeapList(dwNHeaps, heapAddrs, NULL) != S_OK)
+ {
+ ExtOut("Failed to get GCHeaps\n");
+ return Status;
+ }
+
+ for (DWORD n = 0; n < dwNHeaps; n ++)
+ {
+ if (interestingInfo.Request(g_sos, heapAddrs[n]) != S_OK)
+ {
+ ExtOut("Heap %d: Error requesting interesting GC info\n", n);
+ return E_FAIL;
+ }
+
+ ExtOut("--------info for heap %d--------\n", n);
+ PrintInterestingGCInfo(&interestingInfo);
+ ExtOut("\n");
+ }
+ }
+
+ return S_OK;
+#else
+ ExtOut("Not implemented\n");
+ return S_OK;
+#endif //GC_CONFIG_DRIVEN
+}
+
#ifndef FEATURE_PAL
/**********************************************************************\
* Routine Description: *