Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/SOS/Strike/strike.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6806,7 +6806,7 @@ DECLARE_API(GCInfo)

// Mutable table pointer since we need to pass the appropriate
// offset into the table to DumpGCTable.
GCInfoToken gcInfoToken = { table, GCINFO_VERSION };
GCInfoToken gcInfoToken = { table, GCInfoVersion() };
unsigned int methodSize = (unsigned int)codeHeaderData.MethodSize;

g_targetMachine->DumpGCInfo(gcInfoToken, methodSize, ExtOut, true /*encBytes*/, true /*bPrintHeader*/);
Expand Down Expand Up @@ -7453,7 +7453,7 @@ HRESULT displayGcInfo(BOOL fWithGCInfo, const DacpCodeHeaderData& codeHeaderData
return E_OUTOFMEMORY;
}

GCInfoToken gcInfoToken = { table, GCINFO_VERSION };
GCInfoToken gcInfoToken = { table, GCInfoVersion() };
g_targetMachine->DumpGCInfo(gcInfoToken, methodSize, DecodeGCTableEntry, false /*encBytes*/, false /*bPrintHeader*/);
}
return S_OK;
Expand Down
7 changes: 5 additions & 2 deletions src/shared/gcdump/gcdumpnonx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,11 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock,
gcPrintf("Size of parameter area: %x\n", hdrdecoder.GetSizeOfStackParameterArea());
#endif

ReturnKind returnKind = hdrdecoder.GetReturnKind();
gcPrintf("Return Kind: %s\n", ReturnKindToString(returnKind));
if (hdrdecoder.Version() < 4)
{
ReturnKind returnKind = hdrdecoder.GetReturnKind();
gcPrintf("Return Kind: %s\n", ReturnKindToString(returnKind));
}

UINT32 cbEncodedMethodSize = hdrdecoder.GetCodeLength();
gcPrintf("Code size: %x\n", cbEncodedMethodSize);
Expand Down
26 changes: 17 additions & 9 deletions src/shared/inc/gcinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// ******************************************************************************
// WARNING!!!: These values are used by SOS in the diagnostics repo. Values should
// added or removed in a backwards and forwards compatible way.
// There are scenarios in diagnostics that support parsing of old GC Info formats.
// See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfo.h
// ******************************************************************************

Expand Down Expand Up @@ -36,7 +37,18 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this"
// The current GCInfo Version
//-----------------------------------------------------------------------------

#define GCINFO_VERSION 3
#define GCINFO_VERSION 4

#ifdef SOS_INCLUDE
extern bool IsRuntimeVersionAtLeast(DWORD major);
inline int GCInfoVersion()
{
// In SOS we only care about ability to parse/dump the GC Info.
// Since v2 and v3 had the same file format and v1 is no longer supported,
// we can assume that everything before net10.0 uses GCInfo v3.
return IsRuntimeVersionAtLeast(10) ? 4 : 3;
}
#endif

//-----------------------------------------------------------------------------
// GCInfoToken: A wrapper that contains the GcInfo data and version number.
Expand Down Expand Up @@ -67,15 +79,11 @@ struct GCInfoToken

static uint32_t ReadyToRunVersionToGcInfoVersion(uint32_t readyToRunMajorVersion, uint32_t readyToRunMinorVersion)
{
// Once MINIMUM_READYTORUN_MAJOR_VERSION is bumped to 10+
// delete the following and just return GCINFO_VERSION
//
// R2R 9.0 and 9.1 use GCInfo v2
// R2R 9.2 uses GCInfo v3
if (readyToRunMajorVersion == 9 && readyToRunMinorVersion < 2)
return 2;

#ifdef SOS_INCLUDE
return GCInfoVersion();
#else
return GCINFO_VERSION;
#endif
}
};

Expand Down
52 changes: 41 additions & 11 deletions src/shared/inc/gcinfodecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#ifndef _GC_INFO_DECODER_
#define _GC_INFO_DECODER_

#ifdef SOS_INCLUDE
#define DECODE_OLD_FORMATS
#endif

#define _max(a, b) (((a) > (b)) ? (a) : (b))
#define _min(a, b) (((a) < (b)) ? (a) : (b))

Expand Down Expand Up @@ -222,7 +226,7 @@ enum GcInfoDecoderFlags
DECODE_PROLOG_LENGTH = 0x400, // length of the prolog (used to avoid reporting generics context)
DECODE_EDIT_AND_CONTINUE = 0x800,
DECODE_REVERSE_PINVOKE_VAR = 0x1000,
DECODE_RETURN_KIND = 0x2000,
DECODE_RETURN_KIND = 0x2000, // Unused starting with v4 format
#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
DECODE_HAS_TAILCALLS = 0x4000,
#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64
Expand All @@ -248,7 +252,6 @@ enum GcInfoHeaderFlags
GC_INFO_HAS_EDIT_AND_CONTINUE_INFO = 0x100,
GC_INFO_REVERSE_PINVOKE_FRAME = 0x200,

GC_INFO_FLAGS_BIT_SIZE_VERSION_1 = 9,
GC_INFO_FLAGS_BIT_SIZE = 10,
};

Expand Down Expand Up @@ -466,6 +469,8 @@ struct GcSlotDesc
GcSlotFlags Flags;
};


template <typename GcInfoEncoding>
class GcSlotDecoder
{
public:
Expand Down Expand Up @@ -508,12 +513,13 @@ class GcSlotDecoder
};

#ifdef USE_GC_INFO_DECODER
class GcInfoDecoder
template <typename GcInfoEncoding>
class TGcInfoDecoder
{
public:

// If you are not interested in interruptibility or gc lifetime information, pass 0 as instructionOffset
GcInfoDecoder(
TGcInfoDecoder(
GCInfoToken gcInfoToken,
GcInfoDecoderFlags flags = DECODE_EVERYTHING,
UINT32 instructionOffset = 0
Expand All @@ -528,14 +534,12 @@ class GcInfoDecoder

#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
bool IsSafePoint();
bool AreSafePointsInterruptible();
bool IsInterruptibleSafePoint();
bool CouldBeInterruptibleSafePoint();
bool CouldBeSafePoint();

// This is used for gccoverage
// This is used for gcinfodumper
bool IsSafePoint(UINT32 codeOffset);

typedef void EnumerateSafePointsCallback (GcInfoDecoder* decoder, UINT32 offset, void * hCallback);
typedef void EnumerateSafePointsCallback (TGcInfoDecoder<GcInfoEncoding> * decoder, UINT32 offset, void * hCallback);
void EnumerateSafePoints(EnumerateSafePointsCallback * pCallback, void * hCallback);

#endif
Expand Down Expand Up @@ -597,6 +601,10 @@ class GcInfoDecoder
UINT32 GetSizeOfStackParameterArea();
#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA

inline UINT32 Version()
{
return m_Version;
}

private:
BitStreamReader m_Reader;
Expand All @@ -617,6 +625,7 @@ class GcInfoDecoder
#ifdef TARGET_ARM64
UINT32 m_SizeOfEditAndContinueFixedStackFrame;
#endif
// Unused starting with v4 format
ReturnKind m_ReturnKind;
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
UINT32 m_NumSafePoints;
Expand All @@ -636,6 +645,24 @@ class GcInfoDecoder
#endif
UINT32 m_Version;

inline UINT32 NormalizeCodeOffset(UINT32 offset)
{
#ifdef DECODE_OLD_FORMATS
if (Version() < 4)
return offset;
#endif
return GcInfoEncoding::NORMALIZE_CODE_OFFSET(offset);
}

inline UINT32 DenormalizeCodeOffset(UINT32 offset)
{
#ifdef DECODE_OLD_FORMATS
if (Version() < 4)
return offset;
#endif
return GcInfoEncoding::DENORMALIZE_CODE_OFFSET(offset);
}

bool PredecodeFatHeader(int remainingFlags);

static bool SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback);
Expand Down Expand Up @@ -666,7 +693,7 @@ class GcInfoDecoder
bool IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD);

void ReportUntrackedSlots(
GcSlotDecoder& slotDecoder,
GcSlotDecoder<GcInfoEncoding>& slotDecoder,
PREGDISPLAY pRD,
unsigned flags,
GCEnumCallback pCallBack,
Expand Down Expand Up @@ -694,7 +721,7 @@ class GcInfoDecoder


inline void ReportSlotToGC(
GcSlotDecoder& slotDecoder,
GcSlotDecoder<GcInfoEncoding>& slotDecoder,
UINT32 slotIndex,
PREGDISPLAY pRD,
bool reportScratchSlots,
Expand Down Expand Up @@ -751,6 +778,9 @@ class GcInfoDecoder
}
}
};

typedef TGcInfoDecoder<TargetGcInfoEncoding> GcInfoDecoder;

#endif // USE_GC_INFO_DECODER


Expand Down
Loading
Loading