Skip to content

Commit a083d65

Browse files
authored
Sync x86 GC info decoder (#5485)
This is minimal change to get support for decoding no-GC regions.
1 parent 8bbc63d commit a083d65

File tree

4 files changed

+135
-91
lines changed

4 files changed

+135
-91
lines changed

src/shared/README.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ The "shared" directory contains the common code between the runtime and diagnost
33
It is also shared by the dbgshim and SOS components.
44

55
Updated last on 8/14/2024 from the runtime repo commit hash: 96bcf7150deba280a070c6a4d85ca0640e405278
6+
X86 GC info decoding changes were cherry-picked on 5/16/2025 from the runtime repo commit hash: b85dd69a8e1acb95f70b4a9d82e97213406a3eba
67

78
runtime/src/coreclr/inc -> diagnostics/src/shared/inc
89
runtime/src/coreclr/debug/dbgutil -> diagnostics/src/shared/debug/dbgutil

src/shared/gcdump/i386/gcdumpx86.cpp

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#endif
1414
#include "gcdump.h"
1515

16-
1716
/*****************************************************************************/
1817

1918
#define castto(var,typ) (*(typ *)&var)
@@ -115,6 +114,17 @@ size_t GCDump::DumpInfoHdr (PTR_CBYTE gcInfoBlock,
115114
header->revPInvokeOffset = count;
116115
}
117116

117+
if (header->noGCRegionCnt == HAS_NOGCREGIONS)
118+
{
119+
hasArgTabOffset = TRUE;
120+
table += decodeUnsigned(table, &count);
121+
header->noGCRegionCnt = count;
122+
}
123+
else if (header->noGCRegionCnt > 0)
124+
{
125+
hasArgTabOffset = TRUE;
126+
}
127+
118128
//
119129
// First print out all the basic information
120130
//
@@ -157,6 +167,8 @@ size_t GCDump::DumpInfoHdr (PTR_CBYTE gcInfoBlock,
157167
gcPrintf(" Sync region = [%u,%u] ([0x%x,0x%x])\n",
158168
header->syncStartOffset, header->syncEndOffset,
159169
header->syncStartOffset, header->syncEndOffset);
170+
if (header->noGCRegionCnt > 0)
171+
gcPrintf(" no GC region count = %2u \n", header->noGCRegionCnt);
160172

161173
if (header->epilogCount > 1 || (header->epilogCount != 0 &&
162174
header->epilogAtEnd == 0))
@@ -205,11 +217,6 @@ size_t GCDump::DumpInfoHdr (PTR_CBYTE gcInfoBlock,
205217
}
206218

207219
/*****************************************************************************/
208-
209-
#ifdef _PREFAST_
210-
#pragma warning(push)
211-
#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
212-
#endif
213220
size_t GCDump::DumpGCTable(PTR_CBYTE table,
214221
const InfoHdr& header,
215222
unsigned methodSize,
@@ -238,6 +245,23 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table,
238245
if (header.ebxSaved) calleeSavedRegs++;
239246
}
240247

248+
/* Dump the no GC region table */
249+
250+
if (header.noGCRegionCnt > 0)
251+
{
252+
count = header.noGCRegionCnt;
253+
while (count-- > 0)
254+
{
255+
unsigned regionOffset;
256+
unsigned regionSize;
257+
258+
table += decodeUnsigned(table, &regionOffset);
259+
table += decodeUnsigned(table, &regionSize);
260+
261+
gcPrintf("[%04X-%04X) no GC region\n", regionOffset, regionOffset + regionSize);
262+
}
263+
}
264+
241265
/* Dump the untracked frame variable table */
242266

243267
count = header.untrackedCnt;
@@ -323,11 +347,7 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table,
323347

324348
gcPrintf("%s%s pointer\n",
325349
(lowBits & byref_OFFSET_FLAG) ? "byref " : "",
326-
#ifndef FEATURE_EH_FUNCLETS
327-
(lowBits & this_OFFSET_FLAG) ? "this" : ""
328-
#else
329350
(lowBits & pinned_OFFSET_FLAG) ? "pinned" : ""
330-
#endif
331351
);
332352

333353
_ASSERTE(endOffs <= methodSize);
@@ -456,10 +476,6 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table,
456476
/* non-ptr arg push */
457477

458478
curOffs += (val & 0x07);
459-
#ifndef FEATURE_EH_FUNCLETS
460-
// For funclets, non-ptr arg pushes can be reported even for EBP frames
461-
_ASSERTE(!header.ebpFrame);
462-
#endif // FEATURE_EH_FUNCLETS
463479
argCnt++;
464480

465481
DumpEncoding(bp, table-bp); bp = table;
@@ -681,9 +697,6 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table,
681697
{
682698
argTab += decodeUnsigned(argTab, &val);
683699

684-
#ifndef FEATURE_EH_FUNCLETS
685-
assert((val & this_OFFSET_FLAG) == 0);
686-
#endif
687700
unsigned stkOffs = val & ~byref_OFFSET_FLAG;
688701
unsigned lowBit = val & byref_OFFSET_FLAG;
689702

@@ -939,10 +952,6 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table,
939952

940953
return (table - tableStart);
941954
}
942-
#ifdef _PREFAST_
943-
#pragma warning(pop)
944-
#endif
945-
946955

947956
/*****************************************************************************/
948957

@@ -1016,6 +1025,12 @@ void GCDump::DumpPtrsInFrame(PTR_CBYTE gcInfoBlock,
10161025
header.revPInvokeOffset = offset;
10171026
_ASSERTE(offset != INVALID_REV_PINVOKE_OFFSET);
10181027
}
1028+
if (header.noGCRegionCnt == HAS_NOGCREGIONS)
1029+
{
1030+
unsigned count;
1031+
table += decodeUnsigned(table, &count);
1032+
header.noGCRegionCnt = count;
1033+
}
10191034

10201035
prologSize = header.prologSize;
10211036
epilogSize = header.epilogSize;

src/shared/inc/gcdecoder.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,22 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header
205205
nextByte = *table++;
206206
encoding = nextByte & ADJ_ENCODING_MAX;
207207
// encoding here always corresponds to codes in InfoHdrAdjust2 set
208-
209-
_ASSERTE(encoding < SET_RET_KIND_MAX);
210-
header->returnKind = (ReturnKind)encoding;
208+
if (encoding <= SET_RET_KIND_MAX)
209+
{
210+
header->returnKind = (ReturnKind)encoding;
211+
}
212+
else if (encoding < FFFF_NOGCREGION_CNT)
213+
{
214+
header->noGCRegionCnt = encoding - SET_NOGCREGIONS_CNT;
215+
}
216+
else if (encoding == FFFF_NOGCREGION_CNT)
217+
{
218+
header->noGCRegionCnt = HAS_NOGCREGIONS;
219+
}
220+
else
221+
{
222+
_ASSERTE(!"Unexpected encoding");
223+
}
211224
break;
212225
}
213226
}
@@ -470,7 +483,8 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const
470483
target.varPtrTableSize != HAS_VARPTR &&
471484
target.gsCookieOffset != HAS_GS_COOKIE_OFFSET &&
472485
target.syncStartOffset != HAS_SYNC_OFFSET &&
473-
target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET);
486+
target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET &&
487+
target.noGCRegionCnt != HAS_NOGCREGIONS);
474488
#endif
475489

476490
// compare two InfoHdr's up to but not including the untrackCnt field
@@ -495,7 +509,10 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const
495509
if (target.syncStartOffset != INVALID_SYNC_OFFSET)
496510
return false;
497511

498-
if (target.revPInvokeOffset!= INVALID_REV_PINVOKE_OFFSET)
512+
if (target.revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET)
513+
return false;
514+
515+
if (target.noGCRegionCnt > 0)
499516
return false;
500517

501518
return true;

0 commit comments

Comments
 (0)