Skip to content

Commit afc963e

Browse files
authored
Improve logging of GC ref map mismatches (#80219)
1 parent 027e19b commit afc963e

File tree

1 file changed

+102
-17
lines changed

1 file changed

+102
-17
lines changed

src/coreclr/vm/frames.cpp

Lines changed: 102 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,17 @@ UINT TransitionFrame::CbStackPopUsingGCRefMap(PTR_BYTE pGCRefMap)
13721372
}
13731373
#endif
13741374

1375+
static UINT OffsetFromGCRefMapPos(int pos)
1376+
{
1377+
#ifdef TARGET_X86
1378+
return (pos < NUM_ARGUMENT_REGISTERS) ?
1379+
(TransitionBlock::GetOffsetOfArgumentRegisters() + ARGUMENTREGISTERS_SIZE - (pos + 1) * sizeof(TADDR)) :
1380+
(TransitionBlock::GetOffsetOfArgs() + (pos - NUM_ARGUMENT_REGISTERS) * sizeof(TADDR));
1381+
#else
1382+
return TransitionBlock::GetOffsetOfFirstGCRefMapSlot() + pos * sizeof(TADDR);
1383+
#endif
1384+
}
1385+
13751386
void TransitionFrame::PromoteCallerStackUsingGCRefMap(promote_func* fn, ScanContext* sc, PTR_BYTE pGCRefMap)
13761387
{
13771388
WRAPPER_NO_CONTRACT;
@@ -1389,16 +1400,7 @@ void TransitionFrame::PromoteCallerStackUsingGCRefMap(promote_func* fn, ScanCont
13891400
{
13901401
int pos = decoder.CurrentPos();
13911402
int token = decoder.ReadToken();
1392-
1393-
int ofs;
1394-
1395-
#ifdef TARGET_X86
1396-
ofs = (pos < NUM_ARGUMENT_REGISTERS) ?
1397-
(TransitionBlock::GetOffsetOfArgumentRegisters() + ARGUMENTREGISTERS_SIZE - (pos + 1) * sizeof(TADDR)) :
1398-
(TransitionBlock::GetOffsetOfArgs() + (pos - NUM_ARGUMENT_REGISTERS) * sizeof(TADDR));
1399-
#else
1400-
ofs = TransitionBlock::GetOffsetOfFirstGCRefMapSlot() + pos * sizeof(TADDR);
1401-
#endif
1403+
int ofs = OffsetFromGCRefMapPos(pos);
14021404

14031405
PTR_TADDR ppObj = dac_cast<PTR_TADDR>(pTransitionBlock + ofs);
14041406

@@ -2060,6 +2062,76 @@ void FakeGcScanRoots(MetaSig& msig, ArgIterator& argit, MethodDesc * pMD, BYTE *
20602062
}
20612063
}
20622064

2065+
#ifdef _DEBUG
2066+
static void DumpGCRefMap(const char *name, BYTE *address)
2067+
{
2068+
GCRefMapDecoder decoder(address);
2069+
2070+
printf("%s GC ref map: ", name);
2071+
#if TARGET_X86
2072+
uint32_t stackPop = decoder.ReadStackPop();
2073+
printf("POP(0x%x)", stackPop);
2074+
#endif
2075+
2076+
int previousToken = GCREFMAP_SKIP;
2077+
while (!decoder.AtEnd())
2078+
{
2079+
int pos = decoder.CurrentPos();
2080+
int token = decoder.ReadToken();
2081+
if (token != previousToken)
2082+
{
2083+
if (previousToken != GCREFMAP_SKIP)
2084+
{
2085+
printf(") ");
2086+
}
2087+
switch (token)
2088+
{
2089+
case GCREFMAP_SKIP:
2090+
break;
2091+
2092+
case GCREFMAP_REF:
2093+
printf("R(");
2094+
break;
2095+
2096+
case GCREFMAP_INTERIOR:
2097+
printf("I(");
2098+
break;
2099+
2100+
case GCREFMAP_METHOD_PARAM:
2101+
printf("M(");
2102+
break;
2103+
2104+
case GCREFMAP_TYPE_PARAM:
2105+
printf("T(");
2106+
break;
2107+
2108+
case GCREFMAP_VASIG_COOKIE:
2109+
printf("V(");
2110+
break;
2111+
2112+
default:
2113+
// Not implemented
2114+
_ASSERTE(false);
2115+
}
2116+
}
2117+
else if (token != GCREFMAP_SKIP)
2118+
{
2119+
printf(" ");
2120+
}
2121+
if (token != GCREFMAP_SKIP)
2122+
{
2123+
printf("%02x", OffsetFromGCRefMapPos(pos));
2124+
}
2125+
previousToken = token;
2126+
}
2127+
if (previousToken != GCREFMAP_SKIP)
2128+
{
2129+
printf(")");
2130+
}
2131+
printf("\n");
2132+
}
2133+
#endif
2134+
20632135
bool CheckGCRefMapEqual(PTR_BYTE pGCRefMap, MethodDesc* pMD, bool isDispatchCell)
20642136
{
20652137
#ifdef _DEBUG
@@ -2074,16 +2146,29 @@ bool CheckGCRefMapEqual(PTR_BYTE pGCRefMap, MethodDesc* pMD, bool isDispatchCell
20742146
GCRefMapDecoder decoderNew((BYTE *)pBlob);
20752147
GCRefMapDecoder decoderExisting(pGCRefMap);
20762148

2149+
bool invalidGCRefMap = false;
2150+
20772151
#ifdef TARGET_X86
2078-
_ASSERTE(decoderNew.ReadStackPop() == decoderExisting.ReadStackPop());
2152+
if (decoderNew.ReadStackPop() != decoderExisting.ReadStackPop())
2153+
{
2154+
invalidGCRefMap = true;
2155+
}
20792156
#endif
2080-
2081-
_ASSERTE(decoderNew.AtEnd() == decoderExisting.AtEnd());
2082-
while (!decoderNew.AtEnd())
2157+
while (!invalidGCRefMap && !(decoderNew.AtEnd() && decoderExisting.AtEnd()))
2158+
{
2159+
if (decoderNew.AtEnd() != decoderExisting.AtEnd() ||
2160+
decoderNew.CurrentPos() != decoderExisting.CurrentPos() ||
2161+
decoderNew.ReadToken() != decoderExisting.ReadToken())
2162+
{
2163+
invalidGCRefMap = true;
2164+
}
2165+
}
2166+
if (invalidGCRefMap)
20832167
{
2084-
_ASSERTE(decoderNew.CurrentPos() == decoderExisting.CurrentPos());
2085-
_ASSERTE(decoderNew.ReadToken() == decoderExisting.ReadToken());
2086-
_ASSERTE(decoderNew.AtEnd() == decoderExisting.AtEnd());
2168+
printf("GC ref map mismatch detected for method: %s::%s\n", pMD->GetMethodTable()->GetDebugClassName(), pMD->GetName());
2169+
DumpGCRefMap(" Runtime", (BYTE *)pBlob);
2170+
DumpGCRefMap("Crossgen2", pGCRefMap);
2171+
_ASSERTE(false);
20872172
}
20882173
#endif
20892174
return true;

0 commit comments

Comments
 (0)