From cea50bc112f38d25ac82dc028b2f1a8060d48bef Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Wed, 10 Jun 2026 22:55:09 -0400 Subject: [PATCH] Use ISOSDacInterface17 for DumpLog when available Update !DumpLog to prefer the cDAC-based ISOSDacInterface17 for stress log reading when available, falling back to the existing raw-memory path for older runtimes. This enables reading stress logs from both CoreCLR and NativeAOT processes. Changes: - Add ISOSDacInterface17, enumerator interfaces, and data structs to sospriv.h and sospriv_i.cpp - Add DumpStressLogViaInterface17() in stressLogDump.cpp that uses GetStressLogData + thread/message enumerators via the cDAC contract - Update DumpLog in strike.cpp to try the new path first with fallback - Enable stress logging env vars for all CreateDump debuggees so DumpLog tests have data to read - Add DumpLog verification to OtherCommands.script Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/SOS/Strike/stressLogDump.cpp | 269 ++++++++++++ src/SOS/Strike/strike.cpp | 20 +- src/shared/pal/prebuilt/idl/sospriv_i.cpp | 12 + src/shared/pal/prebuilt/inc/sospriv.h | 404 ++++++++++++++++++ src/tests/SOS.UnitTests/SOSRunner.cs | 7 + .../Scripts/OtherCommands.script | 2 + 6 files changed, 711 insertions(+), 3 deletions(-) diff --git a/src/SOS/Strike/stressLogDump.cpp b/src/SOS/Strike/stressLogDump.cpp index 3b851555d8..cbe823a1b1 100644 --- a/src/SOS/Strike/stressLogDump.cpp +++ b/src/SOS/Strike/stressLogDump.cpp @@ -11,6 +11,7 @@ #include "util.h" #include #include +#include #ifndef STRESS_LOG #define STRESS_LOG @@ -361,6 +362,274 @@ StressMsg* GetStressMsgInLatestVersion(StressMsg* rawMsg, int version) return rawMsg; } +/*********************************************************************************/ +// Try to dump the stress log using ISOSDacInterface17 (cDAC contract-based). +// Returns S_OK on success, S_FALSE if no messages, or E_NOINTERFACE if the +// interface is not available (caller should fall back to legacy path). +HRESULT DumpStressLogViaInterface17(const char* fileName, struct IDebugDataSpaces* memCallBack) +{ + // Allow forcing the legacy path for A/B testing + if (GetEnvironmentVariableA("DOTNET_SOS_FORCE_LEGACY_STRESSLOG", NULL, 0) > 0) + { + return E_NOINTERFACE; + } + + // Try to get ISOSDacInterface17 + ISOSDacInterface17* pSos17 = NULL; + HRESULT hr = g_clrData->QueryInterface(__uuidof(ISOSDacInterface17), (void**)&pSos17); + if (FAILED(hr) || pSos17 == NULL) + { + return E_NOINTERFACE; + } + + // Check if stress log is available + hr = pSos17->IsStressLogAvailable(); + if (hr != S_OK) + { + pSos17->Release(); + return FAILED(hr) ? hr : S_FALSE; + } + + // Get stress log header data + DacpStressLogData logData; + hr = pSos17->GetStressLogData(&logData); + if (FAILED(hr)) + { + pSos17->Release(); + return hr; + } + + BOOL bDoGcHist = (fileName == NULL); + FILE* file = NULL; + + if (bDoGcHist) + { + GcHistClear(); + } + + // Get thread enumerator + ISOSStressLogThreadEnum* pThreadEnum = NULL; + hr = pSos17->GetStressLogThreadEnumerator(&pThreadEnum); + if (FAILED(hr) || pThreadEnum == NULL) + { + pSos17->Release(); + return FAILED(hr) ? hr : E_FAIL; + } + + // Collect all threads + struct ThreadInfo + { + DacpThreadStressLogData data; + uint64_t latestTimestamp; + }; + + std::vector threads; + DacpThreadStressLogData threadData; + unsigned int fetched = 0; + for (;;) + { + fetched = 0; + hr = pThreadEnum->Next(1, &threadData, &fetched); + if (fetched == 0) + break; + threads.push_back({ threadData, 0 }); + if (hr == S_OK) // S_OK means enumeration complete (no more items) + break; + } + pThreadEnum->Release(); + + if (threads.empty()) + { + pSos17->Release(); + ExtOut("----- No thread logs in the image -----\n"); + return S_FALSE; + } + + // Create message enumerators for each thread and find the latest timestamp + struct ThreadMsgState + { + ISOSStressLogMsgEnum* pEnum; + DacpStressMsgData currentMsg; + bool hasMsg; + uint64_t threadId; + }; + + std::vector msgStates; + uint64_t lastTimeStamp = 0; + + for (auto& t : threads) + { + ISOSStressLogMsgEnum* pMsgEnum = NULL; + hr = pSos17->GetStressLogMessageEnumerator(t.data.ThreadLogAddress, &pMsgEnum); + if (FAILED(hr) || pMsgEnum == NULL) + continue; + + ThreadMsgState state; + state.pEnum = pMsgEnum; + state.threadId = t.data.ThreadId; + state.hasMsg = false; + + // Prime the enumerator with the first message + fetched = 0; + hr = pMsgEnum->Next(1, &state.currentMsg, &fetched); + if (SUCCEEDED(hr) && fetched > 0) + { + state.hasMsg = true; + if (state.currentMsg.Timestamp > lastTimeStamp) + lastTimeStamp = state.currentMsg.Timestamp; + } + + msgStates.push_back(state); + } + + // Open the output file before writing header (so vDoOut can write to it) + if (!bDoGcHist) + { + if ((file = fopen(fileName, "w")) == NULL) + { + hr = GetLastError(); + for (auto& s : msgStates) s.pEnum->Release(); + pSos17->Release(); + return hr; + } + } + + // Print header -- match legacy format exactly + FILETIME startTime; + memcpy(&startTime, &logData.StartTime, sizeof(FILETIME)); + double totalSecs = 0; + if (lastTimeStamp > logData.StartTimestamp && logData.TickFrequency > 0) + { + totalSecs = ((double)(lastTimeStamp - logData.StartTimestamp)) / logData.TickFrequency; + } + FILETIME endTime; + INT64 endTimeVal = *((INT64*)&startTime) + ((INT64)(totalSecs * 1.0E7)); + memcpy(&endTime, &endTimeVal, sizeof(FILETIME)); + + WCHAR timeBuff[64]; + vDoOut(bDoGcHist, file, "STRESS LOG:\n" + " facilitiesToLog = 0x%x\n" + " levelToLog = %d\n" + " MaxLogSizePerThread = 0x%x (%d)\n" + " MaxTotalLogSize = 0x%x (%d)\n" + " CurrentTotalLogChunk = %d\n" + " ThreadsWithLogs = %d\n", + logData.LoggedFacilities, logData.Level, + logData.MaxSizePerThread, logData.MaxSizePerThread, + logData.MaxSizeTotal, logData.MaxSizeTotal, + logData.TotalChunks, (int)threads.size()); + + vDoOut(bDoGcHist, file, " Clock frequency = %5.3f GHz\n", logData.TickFrequency / 1.0E9); + vDoOut(bDoGcHist, file, " Start time %S\n", getTime(&startTime, timeBuff, 64)); + vDoOut(bDoGcHist, file, " Last message time %S\n", getTime(&endTime, timeBuff, 64)); + vDoOut(bDoGcHist, file, " Total elapsed time %5.3f sec\n", totalSecs); + + if (!bDoGcHist) + { + fprintf(file, "\nTHREAD TIMESTAMP FACILITY MESSAGE\n"); + fprintf(file, " ID (sec from start)\n"); + fprintf(file, "--------------------------------------------------------------------------------------\n"); + } + + // Merge messages across all threads by timestamp (newest first) + char format[257]; + format[256] = format[0] = 0; + unsigned msgCtr = 0; + + for (;;) + { + // Find the thread with the newest message + int newestIdx = -1; + uint64_t newestTimestamp = 0; + + for (int i = 0; i < (int)msgStates.size(); i++) + { + if (msgStates[i].hasMsg && msgStates[i].currentMsg.Timestamp > newestTimestamp) + { + newestTimestamp = msgStates[i].currentMsg.Timestamp; + newestIdx = i; + } + } + + if (newestIdx < 0) + break; + + if (IsInterrupt()) + { + vDoOut(bDoGcHist, file, "----- Interrupted by user -----\n"); + break; + } + + ThreadMsgState& state = msgStates[newestIdx]; + DacpStressMsgData& msg = state.currentMsg; + + if (msg.FormatString != 0) + { + // Read the format string from target memory + hr = memCallBack->ReadVirtual(msg.FormatString, format, 256, 0); + if (hr != S_OK) + strcpy_s(format, ARRAY_SIZE(format), "Could not read address of format string"); + + double deltaTime = ((double)(msg.Timestamp - logData.StartTimestamp)) / logData.TickFrequency; + + // Read arguments + void* args[StressMsg::maxArgCnt] = {}; + if (msg.ArgumentCount > 0) + { + CLRDATA_ADDRESS argAddrs[StressMsg::maxArgCnt] = {}; + unsigned int argsFetched = 0; + unsigned int argsToFetch = msg.ArgumentCount; + if (argsToFetch > StressMsg::maxArgCnt) + argsToFetch = StressMsg::maxArgCnt; + state.pEnum->GetArguments(0, argsToFetch, argAddrs, &argsFetched); + for (unsigned int i = 0; i < argsFetched; i++) + args[i] = (void*)(size_t)argAddrs[i]; + } + + // Handle TaskSwitch marker the same way as the legacy path + if (strcmp(format, ThreadStressLog::TaskSwitchMsg()) == 0) + { + if (bDoGcHist) + { + state.threadId = (unsigned)(size_t)args[0]; + } + else + { + fprintf(file, "Task was switched from %x\n", (unsigned)(size_t)args[0]); + state.threadId = (unsigned)(size_t)args[0]; + } + } + else if (!bDoGcHist) + { + formatOutput(memCallBack, file, format, (unsigned)state.threadId, deltaTime, msg.Facility, args); + } + msgCtr++; + } + + // Advance to the next message for this thread + fetched = 0; + hr = state.pEnum->Next(1, &state.currentMsg, &fetched); + if (fetched == 0 || FAILED(hr)) + { + state.hasMsg = false; + } + } + + // Cleanup + for (auto& s : msgStates) + s.pEnum->Release(); + pSos17->Release(); + + // Match legacy footer format + vDoOut(bDoGcHist, file, "---------------------------- %d total entries ------------------------------------\n", msgCtr); + if (!bDoGcHist) + { + fclose(file); + } + + return msgCtr > 0 ? S_OK : S_FALSE; +} + /*********************************************************************************/ HRESULT StressLog::Dump(ULONG64 outProcLog, const char* fileName, struct IDebugDataSpaces* memCallBack) { diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 40ad2d5fa9..c7c3477f4a 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -128,6 +128,9 @@ #include "hillclimbing.h" #include "sos_md.h" +// Forward declaration for the cDAC-based stress log dump path (stressLogDump.cpp). +HRESULT DumpStressLogViaInterface17(const char* fileName, struct IDebugDataSpaces* memCallBack); + #ifndef FEATURE_PAL #include "ExpressionNode.h" @@ -7653,9 +7656,20 @@ DECLARE_API(DumpLog) ExtOut("Attempting to dump Stress log to file '%s'\n", fileName); - - - Status = StressLog::Dump(StressLogAddress, fileName, g_ExtData); + // Try the cDAC-based path (ISOSDacInterface17) first. + // This supports both CoreCLR and NativeAOT stress logs. + { + HRESULT hrInterface17 = DumpStressLogViaInterface17(fileName, g_ExtData); + if (hrInterface17 != E_NOINTERFACE) + { + Status = hrInterface17; + } + else + { + // ISOSDacInterface17 not available -- fall back to legacy raw-read path + Status = StressLog::Dump(StressLogAddress, fileName, g_ExtData); + } + } if (Status == S_OK) ExtOut("SUCCESS: Stress log dumped\n"); diff --git a/src/shared/pal/prebuilt/idl/sospriv_i.cpp b/src/shared/pal/prebuilt/idl/sospriv_i.cpp index f3c4867a3a..c40017d9f4 100644 --- a/src/shared/pal/prebuilt/idl/sospriv_i.cpp +++ b/src/shared/pal/prebuilt/idl/sospriv_i.cpp @@ -130,6 +130,18 @@ MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface15,0x7ed81261,0x52a9,0x4a23,0xa3,0x58, MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface16,0x4ba12ff8,0xdaac,0x4e43,0xac,0x56,0x98,0xcf,0x8d,0x5c,0x59,0x5d); + +MIDL_DEFINE_GUID(IID, IID_ISOSStressLogThreadEnum,0x94a2bd3d,0xab3d,0x43bf,0x81,0xd8,0x3a,0xe9,0x6b,0x8e,0x33,0xcd); + + +MIDL_DEFINE_GUID(IID, IID_ISOSStressLogMsgEnum,0x437cb033,0xafe7,0x4c0f,0xa4,0xa7,0x82,0xc8,0x91,0xbc,0x04,0x9e); + + +MIDL_DEFINE_GUID(IID, IID_ISOSStressLogMemoryEnum,0x8e20713e,0x960c,0x4be4,0xbd,0x55,0xed,0xb9,0xa6,0x18,0xbc,0x8d); + + +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface17,0x2f4bb585,0xed50,0x479e,0xbb,0xe0,0x10,0xa9,0x5a,0x5d,0xa3,0xbb); + #undef MIDL_DEFINE_GUID #ifdef __cplusplus diff --git a/src/shared/pal/prebuilt/inc/sospriv.h b/src/shared/pal/prebuilt/inc/sospriv.h index 4ff12d95b7..e5df87986c 100644 --- a/src/shared/pal/prebuilt/inc/sospriv.h +++ b/src/shared/pal/prebuilt/inc/sospriv.h @@ -3765,6 +3765,410 @@ EXTERN_C const IID IID_ISOSDacInterface16; #endif /* __ISOSDacInterface16_INTERFACE_DEFINED__ */ +/* StressLog data structures for ISOSDacInterface17 */ + +#ifndef _DacpStressLogData_ +#define _DacpStressLogData_ + +typedef struct _DacpStressLogData +{ + unsigned int LoggedFacilities; + unsigned int Level; + unsigned int MaxSizePerThread; + unsigned int MaxSizeTotal; + int TotalChunks; + UINT64 TickFrequency; + UINT64 StartTimestamp; + UINT64 StartTime; + CLRDATA_ADDRESS Logs; + unsigned int StressMsgHeaderSize; + unsigned int ChunkSize; + unsigned int MaxMessageSize; + unsigned int PointerSize; +} DacpStressLogData; + +#endif // _DacpStressLogData_ + +#ifndef _DacpThreadStressLogData_ +#define _DacpThreadStressLogData_ + +typedef struct _DacpThreadStressLogData +{ + CLRDATA_ADDRESS ThreadLogAddress; + UINT64 ThreadId; + int WriteHasWrapped; + CLRDATA_ADDRESS CurrentPointer; + CLRDATA_ADDRESS ChunkListHead; + CLRDATA_ADDRESS ChunkListTail; + CLRDATA_ADDRESS CurrentWriteChunk; +} DacpThreadStressLogData; + +#endif // _DacpThreadStressLogData_ + +#ifndef _DacpStressMsgData_ +#define _DacpStressMsgData_ + +typedef struct _DacpStressMsgData +{ + unsigned int Facility; + CLRDATA_ADDRESS FormatString; + UINT64 Timestamp; + unsigned int ArgumentCount; + CLRDATA_ADDRESS MessageAddress; +} DacpStressMsgData; + +#endif // _DacpStressMsgData_ + +#ifndef _DacpStressLogMemoryRange_ +#define _DacpStressLogMemoryRange_ + +typedef struct _DacpStressLogMemoryRange +{ + CLRDATA_ADDRESS Address; + UINT64 Size; +} DacpStressLogMemoryRange; + +#endif // _DacpStressLogMemoryRange_ + + +#ifndef __ISOSStressLogThreadEnum_INTERFACE_DEFINED__ +#define __ISOSStressLogThreadEnum_INTERFACE_DEFINED__ + +/* interface ISOSStressLogThreadEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSStressLogThreadEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("94a2bd3d-ab3d-43bf-81d8-3ae96b8e33cd") + ISOSStressLogThreadEnum : public ISOSEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + unsigned int count, + DacpThreadStressLogData values[], + unsigned int *pFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSStressLogThreadEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSStressLogThreadEnum * This, + REFIID riid, + void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSStressLogThreadEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSStressLogThreadEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSStressLogThreadEnum * This, + unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSStressLogThreadEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSStressLogThreadEnum * This, + unsigned int *pCount); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ISOSStressLogThreadEnum * This, + unsigned int count, + DacpThreadStressLogData values[], + unsigned int *pFetched); + + END_INTERFACE + } ISOSStressLogThreadEnumVtbl; + + interface ISOSStressLogThreadEnum + { + CONST_VTBL struct ISOSStressLogThreadEnumVtbl *lpVtbl; + }; + +#endif /* C style interface */ + +#endif /* __ISOSStressLogThreadEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSStressLogMsgEnum_INTERFACE_DEFINED__ +#define __ISOSStressLogMsgEnum_INTERFACE_DEFINED__ + +/* interface ISOSStressLogMsgEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSStressLogMsgEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("437cb033-afe7-4c0f-a4a7-82c891bc049e") + ISOSStressLogMsgEnum : public ISOSEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + unsigned int count, + DacpStressMsgData values[], + unsigned int *pFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArguments( + unsigned int messageIndex, + unsigned int argCount, + CLRDATA_ADDRESS args[], + unsigned int *pFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSStressLogMsgEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSStressLogMsgEnum * This, + REFIID riid, + void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSStressLogMsgEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSStressLogMsgEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSStressLogMsgEnum * This, + unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSStressLogMsgEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSStressLogMsgEnum * This, + unsigned int *pCount); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ISOSStressLogMsgEnum * This, + unsigned int count, + DacpStressMsgData values[], + unsigned int *pFetched); + + HRESULT ( STDMETHODCALLTYPE *GetArguments )( + ISOSStressLogMsgEnum * This, + unsigned int messageIndex, + unsigned int argCount, + CLRDATA_ADDRESS args[], + unsigned int *pFetched); + + END_INTERFACE + } ISOSStressLogMsgEnumVtbl; + + interface ISOSStressLogMsgEnum + { + CONST_VTBL struct ISOSStressLogMsgEnumVtbl *lpVtbl; + }; + +#endif /* C style interface */ + +#endif /* __ISOSStressLogMsgEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSStressLogMemoryEnum_INTERFACE_DEFINED__ +#define __ISOSStressLogMemoryEnum_INTERFACE_DEFINED__ + +/* interface ISOSStressLogMemoryEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSStressLogMemoryEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8e20713e-960c-4be4-bd55-edb9a618bc8d") + ISOSStressLogMemoryEnum : public ISOSEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + unsigned int count, + DacpStressLogMemoryRange values[], + unsigned int *pFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSStressLogMemoryEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSStressLogMemoryEnum * This, + REFIID riid, + void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSStressLogMemoryEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSStressLogMemoryEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSStressLogMemoryEnum * This, + unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSStressLogMemoryEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSStressLogMemoryEnum * This, + unsigned int *pCount); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ISOSStressLogMemoryEnum * This, + unsigned int count, + DacpStressLogMemoryRange values[], + unsigned int *pFetched); + + END_INTERFACE + } ISOSStressLogMemoryEnumVtbl; + + interface ISOSStressLogMemoryEnum + { + CONST_VTBL struct ISOSStressLogMemoryEnumVtbl *lpVtbl; + }; + +#endif /* C style interface */ + +#endif /* __ISOSStressLogMemoryEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface17_INTERFACE_DEFINED__ +#define __ISOSDacInterface17_INTERFACE_DEFINED__ + +/* interface ISOSDacInterface17 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSDacInterface17; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2f4bb585-ed50-479e-bbe0-10a95a5da3bb") + ISOSDacInterface17 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsStressLogAvailable( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStressLogData( + DacpStressLogData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStressLogThreadEnumerator( + ISOSStressLogThreadEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStressLogMessageEnumerator( + CLRDATA_ADDRESS threadStressLogAddress, + ISOSStressLogMsgEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStressLogMemoryRanges( + ISOSStressLogMemoryEnum **ppEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface17Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface17 * This, + REFIID riid, + void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface17 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface17 * This); + + HRESULT ( STDMETHODCALLTYPE *IsStressLogAvailable )( + ISOSDacInterface17 * This); + + HRESULT ( STDMETHODCALLTYPE *GetStressLogData )( + ISOSDacInterface17 * This, + DacpStressLogData *data); + + HRESULT ( STDMETHODCALLTYPE *GetStressLogThreadEnumerator )( + ISOSDacInterface17 * This, + ISOSStressLogThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetStressLogMessageEnumerator )( + ISOSDacInterface17 * This, + CLRDATA_ADDRESS threadStressLogAddress, + ISOSStressLogMsgEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetStressLogMemoryRanges )( + ISOSDacInterface17 * This, + ISOSStressLogMemoryEnum **ppEnum); + + END_INTERFACE + } ISOSDacInterface17Vtbl; + + interface ISOSDacInterface17 + { + CONST_VTBL struct ISOSDacInterface17Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + +#define ISOSDacInterface17_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface17_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface17_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + +#define ISOSDacInterface17_IsStressLogAvailable(This) \ + ( (This)->lpVtbl -> IsStressLogAvailable(This) ) + +#define ISOSDacInterface17_GetStressLogData(This,data) \ + ( (This)->lpVtbl -> GetStressLogData(This,data) ) + +#define ISOSDacInterface17_GetStressLogThreadEnumerator(This,ppEnum) \ + ( (This)->lpVtbl -> GetStressLogThreadEnumerator(This,ppEnum) ) + +#define ISOSDacInterface17_GetStressLogMessageEnumerator(This,threadStressLogAddress,ppEnum) \ + ( (This)->lpVtbl -> GetStressLogMessageEnumerator(This,threadStressLogAddress,ppEnum) ) + +#define ISOSDacInterface17_GetStressLogMemoryRanges(This,ppEnum) \ + ( (This)->lpVtbl -> GetStressLogMemoryRanges(This,ppEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* __ISOSDacInterface17_INTERFACE_DEFINED__ */ + + /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ diff --git a/src/tests/SOS.UnitTests/SOSRunner.cs b/src/tests/SOS.UnitTests/SOSRunner.cs index e8a6c83760..61cea62750 100644 --- a/src/tests/SOS.UnitTests/SOSRunner.cs +++ b/src/tests/SOS.UnitTests/SOSRunner.cs @@ -340,6 +340,13 @@ public static async Task CreateDump(TestInformation information) WithRuntimeConfiguration("DbgEnableMiniDump", "1"). WithRuntimeConfiguration("DbgMiniDumpName", dumpName); + // Enable stress logging so DumpLog tests have data to read + processRunner. + WithRuntimeConfiguration("StressLog", "1"). + WithRuntimeConfiguration("LogFacility", "0xffffffbf"). + WithRuntimeConfiguration("LogLevel", "6"). + WithRuntimeConfiguration("StressLogSize", "65536"); + if (information.DumpDiagnostics) { processRunner.WithRuntimeConfiguration("CreateDumpDiagnostics", "1"); diff --git a/src/tests/SOS.UnitTests/Scripts/OtherCommands.script b/src/tests/SOS.UnitTests/Scripts/OtherCommands.script index 513dcbfcc5..7503841cfe 100644 --- a/src/tests/SOS.UnitTests/Scripts/OtherCommands.script +++ b/src/tests/SOS.UnitTests/Scripts/OtherCommands.script @@ -140,5 +140,7 @@ SOSCOMMAND:DumpGCData SOSCOMMAND:DumpRuntimeTypes +SOSCOMMAND:DumpLog + EXTCOMMAND:logclose EXTCOMMAND:logging --disable