Skip to content

Commit 9e21a91

Browse files
authored
Enable StressLogAnalyzer to read stress logs from old coreclr running with a new clrgc. (#88852)
1 parent 8bf03a6 commit 9e21a91

File tree

5 files changed

+131
-45
lines changed

5 files changed

+131
-45
lines changed

src/coreclr/inc/stresslog.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,9 @@ class StressLog {
372372
{
373373
size_t headerSize; // size of this header including size field and moduleImage
374374
uint32_t magic; // must be 'STRL'
375-
uint32_t version; // must be 0x00010001
375+
uint32_t version; // must be >=0x00010001.
376+
// 0x00010001 is the legacy short-offset format.
377+
// 0x00010002 is the large-module-offset format introduced in .NET 8.
376378
uint8_t* memoryBase; // base address of the memory mapped file
377379
uint8_t* memoryCur; // highest address currently used
378380
uint8_t* memoryLimit; // limit that can be used

src/coreclr/tools/StressLogAnalyzer/StressLogDump.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ class MapViewHolder
2222
#endif // STRESS_LOG
2323
#define STRESS_LOG_READONLY
2424
#include "../../../inc/stresslog.h"
25+
#include "StressMsgReader.h"
2526

2627

2728
void GcHistClear();
28-
void GcHistAddLog(LPCSTR msg, StressMsg* stressMsg);
29+
void GcHistAddLog(LPCSTR msg, StressMsgReader stressMsg);
2930

3031

3132
/*********************************************************************************/
@@ -57,7 +58,7 @@ ThreadStressLog* ThreadStressLog::FindLatestThreadLog() const
5758
for (const ThreadStressLog* ptr = this; ptr != NULL; ptr = ptr->next)
5859
{
5960
if (ptr->readPtr != NULL)
60-
if (latestLog == 0 || ptr->readPtr->GetTimeStamp() > latestLog->readPtr->GetTimeStamp())
61+
if (latestLog == 0 || StressMsgReader(ptr->readPtr).GetTimeStamp() > StressMsgReader(latestLog->readPtr).GetTimeStamp())
6162
latestLog = ptr;
6263
}
6364
return const_cast<ThreadStressLog*>(latestLog);
@@ -423,9 +424,9 @@ HRESULT StressLog::Dump(ULONG64 outProcLog, const char* fileName, struct IDebugD
423424

424425
// TODO: fix on 64 bit
425426
inProcPtr->Activate ();
426-
if (inProcPtr->readPtr->GetTimeStamp() > lastTimeStamp)
427+
if (StressMsgReader(inProcPtr->readPtr).GetTimeStamp() > lastTimeStamp)
427428
{
428-
lastTimeStamp = inProcPtr->readPtr->GetTimeStamp();
429+
lastTimeStamp = StressMsgReader(inProcPtr->readPtr).GetTimeStamp();
429430
}
430431

431432
outProcPtr = TO_CDADDR(inProcPtr->next);
@@ -488,40 +489,40 @@ HRESULT StressLog::Dump(ULONG64 outProcLog, const char* fileName, struct IDebugD
488489
break;
489490
}
490491

491-
StressMsg* latestMsg = latestLog->readPtr;
492-
if (latestMsg->GetFormatOffset() != 0 && !latestLog->CompletedDump())
492+
StressMsgReader latestMsg = latestLog->readPtr;
493+
if (latestMsg.GetFormatOffset() != 0 && !latestLog->CompletedDump())
493494
{
494-
TADDR taFmt = (latestMsg->GetFormatOffset()) + TO_TADDR(g_hThisInst);
495+
TADDR taFmt = (latestMsg.GetFormatOffset()) + TO_TADDR(g_hThisInst);
495496
hr = memCallBack->ReadVirtual(TO_CDADDR(taFmt), format, 256, 0);
496497
if (hr != S_OK)
497498
strcpy_s(format, ARRAY_SIZE(format), "Could not read address of format string");
498499

499-
double deltaTime = ((double) (latestMsg->GetTimeStamp() - inProcLog.startTimeStamp)) / inProcLog.tickFrequency;
500+
double deltaTime = ((double) (latestMsg.GetTimeStamp() - inProcLog.startTimeStamp)) / inProcLog.tickFrequency;
500501
if (bDoGcHist)
501502
{
502503
if (strcmp(format, ThreadStressLog::TaskSwitchMsg()) == 0)
503504
{
504-
latestLog->threadId = (unsigned)(size_t)latestMsg->args[0];
505+
latestLog->threadId = (unsigned)(size_t)latestMsg.GetArgs()[0];
505506
}
506507
GcHistAddLog(format, latestMsg);
507508
}
508509
else
509510
{
510511
if (strcmp(format, ThreadStressLog::TaskSwitchMsg()) == 0)
511512
{
512-
fprintf (file, "Task was switched from %x\n", (unsigned)(size_t)latestMsg->args[0]);
513-
latestLog->threadId = (unsigned)(size_t)latestMsg->args[0];
513+
fprintf (file, "Task was switched from %x\n", (unsigned)(size_t)latestMsg.GetArgs()[0]);
514+
latestLog->threadId = (unsigned)(size_t)latestMsg.GetArgs()[0];
514515
}
515516
else
516517
{
517-
args = latestMsg->args;
518-
formatOutput(memCallBack, file, format, (unsigned)latestLog->threadId, deltaTime, latestMsg->GetFacility(), args);
518+
args = latestMsg.GetArgs();
519+
formatOutput(memCallBack, file, format, (unsigned)latestLog->threadId, deltaTime, latestMsg.GetFacility(), args);
519520
}
520521
}
521522
msgCtr++;
522523
}
523524

524-
latestLog->readPtr = latestLog->AdvanceRead(latestMsg->GetNumberOfArgs());
525+
latestLog->readPtr = latestLog->AdvanceRead(latestMsg.GetNumberOfArgs());
525526
if (latestLog->CompletedDump())
526527
{
527528
latestLog->readPtr = NULL;

src/coreclr/tools/StressLogAnalyzer/StressLogPlugin.cpp

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ bool IsInCantAllocStressLogRegion()
4040

4141
#include <stddef.h>
4242
#include "../../../inc/stresslog.h"
43+
#include "StressMsgReader.h"
4344

4445
size_t StressLog::writing_base_address;
4546
size_t StressLog::reading_base_address;
@@ -67,7 +68,7 @@ void GcHistClear()
6768
{
6869
}
6970

70-
void GcHistAddLog(LPCSTR msg, StressMsg* stressMsg)
71+
void GcHistAddLog(LPCSTR msg, StressMsgReader stressMsg)
7172
{
7273
}
7374

@@ -531,7 +532,7 @@ bool FilterMessage(StressLog::StressLogHeader* hdr, ThreadStressLog* tsl, uint32
531532
struct StressThreadAndMsg
532533
{
533534
uint64_t threadId;
534-
StressMsg* msg;
535+
StressMsgReader msg;
535536
uint64_t msgId;
536537
};
537538

@@ -540,9 +541,9 @@ int CmpMsg(const void* p1, const void* p2)
540541
const StressThreadAndMsg* msg1 = (const StressThreadAndMsg*)p1;
541542
const StressThreadAndMsg* msg2 = (const StressThreadAndMsg*)p2;
542543

543-
if (msg1->msg->GetTimeStamp() < msg2->msg->GetTimeStamp())
544+
if (msg1->msg.GetTimeStamp() < msg2->msg.GetTimeStamp())
544545
return 1;
545-
if (msg1->msg->GetTimeStamp() > msg2->msg->GetTimeStamp())
546+
if (msg1->msg.GetTimeStamp() > msg2->msg.GetTimeStamp())
546547
return -11;
547548

548549
if (msg1->threadId < msg2->threadId)
@@ -564,7 +565,7 @@ struct ThreadStressLogDesc
564565
volatile LONG workStarted;
565566
volatile LONG workFinished;
566567
ThreadStressLog* tsl;
567-
StressMsg* earliestMessage;
568+
StressMsgReader earliestMessage;
568569

569570
ThreadStressLogDesc() : workStarted(0), workFinished(0), tsl(nullptr), earliestMessage(nullptr)
570571
{
@@ -584,7 +585,7 @@ static double s_timeFilterStart = 0;
584585
static double s_timeFilterEnd = 0;
585586
static const char* s_outputFileName = nullptr;
586587

587-
static StressLog::StressLogHeader* s_hdr;
588+
StressLog::StressLogHeader* s_hdr;
588589

589590
static bool s_fPrintFormatStrings;
590591

@@ -1056,7 +1057,7 @@ bool ParseOptions(int argc, char* argv[])
10561057
return true;
10571058
}
10581059

1059-
static void IncludeMessage(uint64_t threadId, StressMsg* msg)
1060+
static void IncludeMessage(uint64_t threadId, StressMsgReader msg)
10601061
{
10611062
LONGLONG msgCount = InterlockedIncrement64(&s_msgCount) - 1;
10621063
if (msgCount < MAX_MESSAGE_COUNT)
@@ -1089,10 +1090,10 @@ DWORD WINAPI ProcessStresslogWorker(LPVOID)
10891090
wrappedWriteThreadCount++;
10901091
}
10911092
// printf("thread: %zx\n", tsl->threadId);
1092-
StressMsg* msg = StressLog::TranslateMemoryMappedPointer(tsl->curPtr);
1093+
void* msg = StressLog::TranslateMemoryMappedPointer(tsl->curPtr);
10931094
StressLogChunk* slc = StressLog::TranslateMemoryMappedPointer(tsl->curWriteChunk);
10941095
int chunkCount = 0;
1095-
StressMsg* prevMsg = nullptr;
1096+
void* prevMsg = nullptr;
10961097
while (true)
10971098
{
10981099
// printf("stress log chunk %zx\n", (size_t)slc);
@@ -1135,14 +1136,15 @@ DWORD WINAPI ProcessStresslogWorker(LPVOID)
11351136
{
11361137
while (p < end && *p == 0)
11371138
p++;
1138-
msg = (StressMsg*)p;
1139+
msg = (void*)p;
11391140
}
1140-
StressMsg* endMsg = (StressMsg*)end;
1141+
void* endMsg = (void*)end;
11411142
while (msg < endMsg)
11421143
{
1144+
StressMsgReader msgReader(msg);
11431145
totalMsgCount++;
1144-
char* format = (char*)(hdr->moduleImage + msg->GetFormatOffset());
1145-
double deltaTime = ((double)(msg->GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
1146+
char* format = (char*)(hdr->moduleImage + msgReader.GetFormatOffset());
1147+
double deltaTime = ((double)(msgReader.GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
11461148
bool fIgnoreMessage = false;
11471149
if (fTimeFilter)
11481150
{
@@ -1156,17 +1158,17 @@ DWORD WINAPI ProcessStresslogWorker(LPVOID)
11561158
fIgnoreMessage = true;
11571159
}
11581160
}
1159-
int numberOfArgs = msg->GetNumberOfArgs();
1161+
int numberOfArgs = msgReader.GetNumberOfArgs();
11601162
if (!fIgnoreMessage)
11611163
{
1162-
bool fIncludeMessage = s_showAllMessages || FilterMessage(hdr, tsl, msg->GetFacility(), format, deltaTime, numberOfArgs, msg->args);
1164+
bool fIncludeMessage = s_showAllMessages || FilterMessage(hdr, tsl, msgReader.GetFacility(), format, deltaTime, numberOfArgs, msgReader.GetArgs());
11631165
if (!fIncludeMessage && s_valueFilterCount > 0)
11641166
{
11651167
for (int i = 0; i < numberOfArgs; i++)
11661168
{
11671169
for (int j = 0; j < s_valueFilterCount; j++)
11681170
{
1169-
if (s_valueFilter[j].start <= (size_t)msg->args[i] && (size_t)msg->args[i] <= s_valueFilter[j].end)
1171+
if (s_valueFilter[j].start <= (size_t)msgReader.GetArgs()[i] && (size_t)msgReader.GetArgs()[i] <= s_valueFilter[j].end)
11701172
{
11711173
fIncludeMessage = true;
11721174
break;
@@ -1182,7 +1184,7 @@ DWORD WINAPI ProcessStresslogWorker(LPVOID)
11821184
}
11831185
}
11841186
prevMsg = msg;
1185-
msg = (StressMsg*)&msg->args[numberOfArgs];
1187+
msg = (StressMsg*)&msgReader.GetArgs()[numberOfArgs];
11861188
}
11871189
if (slc == StressLog::TranslateMemoryMappedPointer(tsl->chunkListTail) && !tsl->writeHasWrapped)
11881190
break;
@@ -1233,16 +1235,16 @@ static void PrintFriendlyNumber(LONGLONG n)
12331235
printf("%11.9f billion", n / 1000000000.0);
12341236
}
12351237

1236-
static void PrintMessage(CorClrData& corClrData, FILE *outputFile, uint64_t threadId, StressMsg* msg)
1238+
static void PrintMessage(CorClrData& corClrData, FILE *outputFile, uint64_t threadId, StressMsgReader msg)
12371239
{
12381240
void* argBuffer[StressMsg::maxArgCnt];
1239-
char* format = (char*)(s_hdr->moduleImage + msg->GetFormatOffset());
1240-
int numberOfArgs = msg->GetNumberOfArgs();
1241+
char* format = (char*)(s_hdr->moduleImage + msg.GetFormatOffset());
1242+
int numberOfArgs = msg.GetNumberOfArgs();
12411243
for (int i = 0; i < numberOfArgs; i++)
12421244
{
1243-
argBuffer[i] = msg->args[i];
1245+
argBuffer[i] = msg.GetArgs()[i];
12441246
}
1245-
double deltaTime = ((double)(msg->GetTimeStamp() - s_hdr->startTimeStamp)) / s_hdr->tickFrequency;
1247+
double deltaTime = ((double)(msg.GetTimeStamp() - s_hdr->startTimeStamp)) / s_hdr->tickFrequency;
12461248
if (!s_printHexTidForGcThreads)
12471249
{
12481250
GcThread gcThread;
@@ -1255,7 +1257,7 @@ static void PrintMessage(CorClrData& corClrData, FILE *outputFile, uint64_t thre
12551257
threadId |= 0x4000000000000000;
12561258
}
12571259
}
1258-
formatOutput(&corClrData, outputFile, format, threadId, deltaTime, msg->GetFacility(), argBuffer, s_fPrintFormatStrings);
1260+
formatOutput(&corClrData, outputFile, format, threadId, deltaTime, msg.GetFacility(), argBuffer, s_fPrintFormatStrings);
12591261
}
12601262

12611263
int ProcessStressLog(void* baseAddress, int argc, char* argv[])
@@ -1301,7 +1303,8 @@ int ProcessStressLog(void* baseAddress, int argc, char* argv[])
13011303
StressLog::StressLogHeader* hdr = (StressLog::StressLogHeader*)baseAddress;
13021304
if (hdr->headerSize != sizeof(*hdr) ||
13031305
hdr->magic != *(uint32_t*)"LRTS" ||
1304-
hdr->version != 0x00010001)
1306+
(hdr->version != 0x00010001 &&
1307+
hdr->version != 0x00010002))
13051308
{
13061309
printf("Unrecognized file format\n");
13071310
return 1;
@@ -1383,8 +1386,8 @@ int ProcessStressLog(void* baseAddress, int argc, char* argv[])
13831386
int remMsgCount = 0;
13841387
for (int msgIndex = 0; msgIndex < s_msgCount; msgIndex++)
13851388
{
1386-
StressMsg* msg = s_threadMsgBuf[msgIndex].msg;
1387-
double deltaTime = ((double)(msg->GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
1389+
StressMsgReader msg = s_threadMsgBuf[msgIndex].msg;
1390+
double deltaTime = ((double)(msg.GetTimeStamp() - hdr->startTimeStamp)) / hdr->tickFrequency;
13881391
if (startTime <= deltaTime && deltaTime <= endTime)
13891392
{
13901393
s_threadMsgBuf[remMsgCount] = s_threadMsgBuf[msgIndex];
@@ -1463,7 +1466,7 @@ int ProcessStressLog(void* baseAddress, int argc, char* argv[])
14631466
for (LONGLONG i = 0; i < s_msgCount; i++)
14641467
{
14651468
uint64_t threadId = (unsigned)s_threadMsgBuf[i].threadId;
1466-
StressMsg* msg = s_threadMsgBuf[i].msg;
1469+
StressMsgReader msg = s_threadMsgBuf[i].msg;
14671470
PrintMessage(corClrData, outputFile, threadId, msg);
14681471
}
14691472

@@ -1500,7 +1503,7 @@ int ProcessStressLog(void* baseAddress, int argc, char* argv[])
15001503
LONGLONG earliestStartCount = s_msgCount;
15011504
for (int threadStressLogIndex = 0; threadStressLogIndex < s_threadStressLogCount; threadStressLogIndex++)
15021505
{
1503-
StressMsg* msg = s_threadStressLogDesc[threadStressLogIndex].earliestMessage;
1506+
StressMsgReader msg = s_threadStressLogDesc[threadStressLogIndex].earliestMessage;
15041507
if (msg == nullptr)
15051508
continue;
15061509
bool fIncludeMessage = s_printEarliestMessages;
@@ -1525,7 +1528,7 @@ int ProcessStressLog(void* baseAddress, int argc, char* argv[])
15251528
for (LONGLONG i = earliestStartCount; i < s_msgCount; i++)
15261529
{
15271530
uint64_t threadId = (unsigned)s_threadMsgBuf[i].threadId;
1528-
StressMsg* msg = s_threadMsgBuf[i].msg;
1531+
StressMsgReader msg = s_threadMsgBuf[i].msg;
15291532
PrintMessage(corClrData, outputFile, threadId, msg);
15301533
}
15311534
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#include <stdint.h>
5+
6+
extern StressLog::StressLogHeader* s_hdr;
7+
8+
// A version-aware reader for memory-mapped stress log messages.
9+
struct StressMsgReader
10+
{
11+
private:
12+
struct StressMsgSmallOffset
13+
{
14+
uint32_t numberOfArgsLow : 3; // at most 7 arguments here
15+
uint32_t formatOffset : 26; // low bits offset of format string in modules
16+
uint32_t numberOfArgsHigh : 3; // extend number of args in a backward compat way
17+
uint32_t facility; // facility used to log the entry
18+
uint64_t timeStamp; // time when mssg was logged
19+
void* args[0]; // variable number of arguments
20+
};
21+
22+
void* m_rawMsg;
23+
public:
24+
StressMsgReader() = default;
25+
26+
StressMsgReader(void* msg)
27+
:m_rawMsg(msg)
28+
{
29+
}
30+
31+
uint64_t GetFormatOffset() const
32+
{
33+
if (s_hdr->version == 0x00010001)
34+
{
35+
return ((StressMsgSmallOffset*)m_rawMsg)->formatOffset;
36+
}
37+
return ((StressMsg*)m_rawMsg)->GetFormatOffset();
38+
}
39+
40+
uint32_t GetNumberOfArgs() const
41+
{
42+
if (s_hdr->version == 0x00010001)
43+
{
44+
return ((StressMsgSmallOffset*)m_rawMsg)->numberOfArgsHigh << 3 | ((StressMsgSmallOffset*)m_rawMsg)->numberOfArgsLow;
45+
}
46+
return ((StressMsg*)m_rawMsg)->GetNumberOfArgs();
47+
}
48+
49+
uint32_t GetFacility() const
50+
{
51+
if (s_hdr->version == 0x00010001)
52+
{
53+
return ((StressMsgSmallOffset*)m_rawMsg)->facility;
54+
}
55+
return ((StressMsg*)m_rawMsg)->GetFacility();
56+
}
57+
58+
uint64_t GetTimeStamp() const
59+
{
60+
if (s_hdr->version == 0x00010001)
61+
{
62+
return ((StressMsgSmallOffset*)m_rawMsg)->timeStamp;
63+
}
64+
return ((StressMsg*)m_rawMsg)->GetTimeStamp();
65+
}
66+
67+
void** GetArgs() const
68+
{
69+
if (s_hdr->version == 0x00010001)
70+
{
71+
return ((StressMsgSmallOffset*)m_rawMsg)->args;
72+
}
73+
return ((StressMsg*)m_rawMsg)->args;
74+
}
75+
76+
bool operator==(std::nullptr_t) const
77+
{
78+
return m_rawMsg == nullptr;
79+
}
80+
};

src/coreclr/utilcode/stresslog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ void StressLog::Initialize(unsigned facilities, unsigned level, unsigned maxByte
266266
StressLogHeader* hdr = (StressLogHeader*)(uint8_t*)(void*)theLog.hMapView;
267267
hdr->headerSize = sizeof(StressLogHeader);
268268
hdr->magic = *(uint32_t*)"LRTS";
269-
hdr->version = 0x00010001;
269+
hdr->version = 0x00010002;
270270
hdr->memoryBase = (uint8_t*)hdr;
271271
hdr->memoryCur = hdr->memoryBase + sizeof(StressLogHeader);
272272
hdr->memoryLimit = hdr->memoryBase + maxBytesTotal;

0 commit comments

Comments
 (0)