va_end(Args);
}
+static TADDR GetFormatAddr(StressLog& inProcLog, uint32_t formatOffset, BOOL bHasModuleTable)
+{
+ // do we have a module table, and does it look valid?
+ if (bHasModuleTable && inProcLog.moduleOffset == (size_t)inProcLog.modules[0].baseAddress &&
+ 1024 * 1024 <= inProcLog.modules[0].size && inProcLog.modules[0].size < StressMsg::maxOffset)
+ {
+ // yes: search it for a module containing this offset
+ size_t moduleOffset = 0;
+ for (int moduleIndex = 0; moduleIndex < StressLog::MAX_MODULES; moduleIndex++)
+ {
+ if (inProcLog.modules[moduleIndex].baseAddress == nullptr)
+ break;
+ size_t relativeOffset = formatOffset - moduleOffset;
+ if (relativeOffset < inProcLog.modules[moduleIndex].size)
+ {
+ return relativeOffset + TO_TADDR(inProcLog.modules[moduleIndex].baseAddress);
+ }
+ moduleOffset += inProcLog.modules[moduleIndex].size;
+ }
+ }
+ // not found or invalid module table
+ // just assume it's an old style stress log
+ return formatOffset + TO_TADDR(inProcLog.moduleOffset);
+}
/*********************************************************************************/
HRESULT StressLog::Dump(ULONG64 outProcLog, const char* fileName, struct IDebugDataSpaces* memCallBack)
void** args;
unsigned msgCtr;
msgCtr = 0;
- for (;;)
+ int version;
+ version = 0;
+ CheckBreakingRuntimeChange(&version);
+ BOOL bHasModuleTable;
+ bHasModuleTable = (version >= 3);
+ for (;;)
{
ThreadStressLog* latestLog = logs->FindLatestThreadLog();
StressMsg* latestMsg = latestLog->readPtr;
if (latestMsg->formatOffset != 0 && !latestLog->CompletedDump())
{
- TADDR taFmt = (latestMsg->formatOffset) + TO_TADDR(g_hThisInst);
+ TADDR taFmt = GetFormatAddr(inProcLog, latestMsg->formatOffset, bHasModuleTable);
hr = memCallBack->ReadVirtual(TO_CDADDR(taFmt), format, 256, 0);
if (hr != S_OK)
strcpy_s(format, _countof(format), "Could not read address of format string");
unsigned __int64 startTimeStamp; // start time from when tick counter started
FILETIME startTime; // time the application started
SIZE_T moduleOffset; // Used to compute format strings.
+ struct ModuleDesc
+ {
+ uint8_t* baseAddress;
+ size_t size;
+ };
+ static const size_t MAX_MODULES = 5;
+ ModuleDesc modules[MAX_MODULES]; // descriptor of the modules images
// private:
static void Enter(CRITSEC_COOKIE dummy = NULL);
// And make sure the timeStamp field is naturally alligned, so we don't waste
// space on 32-bit platforms
struct StressMsg {
+ static const size_t formatOffsetBits = 26;
union {
struct {
- uint32_t numberOfArgs : 3; // at most 7 arguments
- uint32_t formatOffset : 29; // offset of string in mscorwks
+ uint32_t numberOfArgs : 3; // at most 7 arguments here
+ uint32_t formatOffset : formatOffsetBits; // offset of string in coreclr/clrgc
+ uint32_t numberOfArgsX : 3; // extend number of args in a backward compat way
};
uint32_t fmtOffsCArgs; // for optimized access
};
uint64_t timeStamp; // time when mssg was logged
void* args[0]; // size given by numberOfArgs
- static const size_t maxArgCnt = 7;
- static const size_t maxOffset = 0x20000000;
- static size_t maxMsgSize ()
+ static const size_t maxArgCnt = 63;
+ static const size_t maxOffset = 1 << formatOffsetBits;
+ static size_t maxMsgSize ()
{ return sizeof(StressMsg) + maxArgCnt*sizeof(void*); }
friend class ThreadStressLog;
ThreadStressLog* next; // we keep a linked list of these
uint64_t threadId; // the id for the thread using this buffer
uint8_t isDead; // Is this thread dead
- uint8_t readHasWrapped; // set when read ptr has passed chunListTail
- uint8_t writeHasWrapped; // set when write ptr has passed chunListHead
+ uint8_t readHasWrapped; // set when read ptr has passed chunkListTail
+ uint8_t writeHasWrapped; // set when write ptr has passed chunkListHead
StressMsg* curPtr; // where packets are being put on the queue
StressMsg* readPtr; // where we are reading off the queue (used during dumping)
StressLogChunk * chunkListHead; //head of a list of stress log chunks
// For convenience it returns the new value of readPtr
inline StressMsg* ThreadStressLog::AdvanceRead() {
STATIC_CONTRACT_LEAF;
+ unsigned numberOfArgs = (readPtr->numberOfArgsX << 3) + readPtr->numberOfArgs;
// advance the marker
- readPtr = (StressMsg*)((char*)readPtr + sizeof(StressMsg) + readPtr->numberOfArgs*sizeof(void*));
+ readPtr = (StressMsg*)((char*)readPtr + sizeof(StressMsg) + numberOfArgs*sizeof(void*));
// wrap around if we need to
if (readPtr >= (StressMsg *)curReadChunk->EndPtr ())
{