summaryrefslogtreecommitdiff
path: root/src/ToolBox/SOS/Strike/strike.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ToolBox/SOS/Strike/strike.cpp')
-rw-r--r--src/ToolBox/SOS/Strike/strike.cpp296
1 files changed, 291 insertions, 5 deletions
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: *