From: Aleksey Kliger (λgeek) Date: Thu, 1 Aug 2024 17:22:16 +0000 (-0400) Subject: .net9+: prefer the canonical method table over EEClass (#4758) X-Git-Tag: accepted/tizen/unified/20241231.014852~39^2^2~113 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7d16e79c93bb10d165f1cb7af5dd96bd37972dcd;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git .net9+: prefer the canonical method table over EEClass (#4758) Co-authored-by: Jan Kotas --- diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 9cc7c472f..282182b23 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -1048,7 +1048,8 @@ DECLARE_API(DumpClass) EnableDMLHolder dmlHolder(dml); CLRDATA_ADDRESS methodTable; - if ((Status=g_sos->GetMethodTableForEEClass(TO_CDADDR(dwStartAddr), &methodTable)) != S_OK) + BOOL preferMT = FALSE; + if (!SUCCEEDED(Status = PreferCanonMTOverEEClass(TO_CDADDR(dwStartAddr), &preferMT, &methodTable))) { ExtOut("Invalid EEClass address\n"); return Status; @@ -1081,9 +1082,20 @@ DECLARE_API(DumpClass) ParentEEClass = mtdataparent.Class; } - DMLOut("Parent Class: %s\n", DMLClass(ParentEEClass)); + if (!preferMT) + { + DMLOut("Parent Class: %s\n", DMLClass(ParentEEClass)); + } + else + { + DMLOut("Parent MethodTable: %s\n", DMLMethodTable(mtdata.ParentMethodTable)); + } DMLOut("Module: %s\n", DMLModule(mtdata.Module)); DMLOut("Method Table: %s\n", DMLMethodTable(methodTable)); + if (preferMT) + { + DMLOut("Canonical MethodTable: %s\n", DMLClass(mtdata.Class)); + } ExtOut("Vtable Slots: %x\n", mtdata.wNumVirtuals); ExtOut("Total Method Slots: %x\n", mtdata.wNumVtableSlots); ExtOut("Class Attributes: %x ", mtdata.dwAttrClass); @@ -1189,7 +1201,15 @@ DECLARE_API(DumpMT) DacpMethodTableCollectibleData vMethTableCollectible; vMethTableCollectible.Request(g_sos, TO_CDADDR(dwStartAddr)); - table.WriteRow("EEClass:", EEClassPtr(vMethTable.Class)); + BOOL preferCanonMT = FALSE; + if (SUCCEEDED(PreferCanonMTOverEEClass(vMethTable.Class, &preferCanonMT)) && preferCanonMT) + { + table.WriteRow("Canonical MethodTable:", EEClassPtr(vMethTable.Class)); + } + else + { + table.WriteRow("EEClass:", EEClassPtr(vMethTable.Class)); + } table.WriteRow("Module:", ModulePtr(vMethTable.Module)); @@ -1347,7 +1367,15 @@ HRESULT PrintVC(TADDR taMT, TADDR taObject, BOOL bPrintFields = TRUE) ExtOut("Name: %S\n", g_mdName); DMLOut("MethodTable: %s\n", DMLMethodTable(taMT)); - DMLOut("EEClass: %s\n", DMLClass(mtabledata.Class)); + BOOL preferCanonMT = FALSE; + if (SUCCEEDED(PreferCanonMTOverEEClass(TO_CDADDR(taMT), &preferCanonMT)) && preferCanonMT) + { + DMLOut("Canonical MethodTable: %s\n", DMLClass(mtabledata.Class)); + } + else + { + DMLOut("EEClass: %s\n", DMLClass(mtabledata.Class)); + } ExtOut("Size: %d(0x%x) bytes\n", size, size); FileNameForModule(TO_TADDR(mtabledata.Module), g_mdName); @@ -1440,7 +1468,15 @@ HRESULT PrintObj(TADDR taObj, BOOL bPrintFields = TRUE) DacpMethodTableData mtabledata; if ((Status=mtabledata.Request(g_sos,objData.MethodTable)) == S_OK) { - DMLOut("EEClass: %s\n", DMLClass(mtabledata.Class)); + BOOL preferCanonMT = FALSE; + if (SUCCEEDED(PreferCanonMTOverEEClass(mtabledata.Class, &preferCanonMT)) && preferCanonMT) + { + DMLOut("Canonical MethodTable: %s\n", DMLClass(mtabledata.Class)); + } + else + { + DMLOut("EEClass: %s\n", DMLClass(mtabledata.Class)); + } } else { @@ -5791,7 +5827,7 @@ BOOL CheckCLRNotificationEvent(DEBUG_LAST_EVENT_INFO_EXCEPTION* pdle) return FALSE; } - // The new DAC based interface doesn't exists so ask the debugger for the last exception information. + // The new DAC based interface doesn't exists so ask the debugger for the last exception information. #ifdef HOST_WINDOWS ULONG Type, ProcessId, ThreadId; diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index c80a47079..32be74568 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -5865,3 +5865,30 @@ HRESULT GetMetadataMemory(CLRDATA_ADDRESS address, ULONG32 bufferSize, BYTE* buf } #endif // FEATURE_PAL + +/**********************************************************************\ +* Routine Description: * +* * +* Since .NET 9+ the runtime does not expose EEClass, but instead * +* returns a pointer to the canonical MethodTable in * +* DacpMethodTableData:Class. * +* Detect that situation by calling GetMethodTableForEEClass and * +* comparing the result to the EEClass itself. * +* * +\**********************************************************************/ + +HRESULT PreferCanonMTOverEEClass(CLRDATA_ADDRESS eeClassPtr, BOOL *preferCanonMT, CLRDATA_ADDRESS *outCanonMT) +{ + HRESULT Status; + CLRDATA_ADDRESS canonMT = 0; + if (!SUCCEEDED(Status = g_sos->GetMethodTableForEEClass(eeClassPtr, &canonMT))) + { + return Status; + } + *preferCanonMT = (eeClassPtr == canonMT); + if (outCanonMT) + { + *outCanonMT = canonMT; + } + return S_OK; +} diff --git a/src/SOS/Strike/util.h b/src/SOS/Strike/util.h index 3c2bfb8bb..f63cf790d 100644 --- a/src/SOS/Strike/util.h +++ b/src/SOS/Strike/util.h @@ -2142,6 +2142,8 @@ WString MethodNameFromIP(CLRDATA_ADDRESS methodDesc, BOOL bSuppressLines = FALSE HRESULT GetGCRefs(ULONG osID, SOSStackRefData **ppRefs, unsigned int *pRefCnt, SOSStackRefError **ppErrors, unsigned int *pErrCount); WString GetFrameFromAddress(TADDR frameAddr, IXCLRDataStackWalk *pStackwalk = NULL, BOOL bAssemblyName = FALSE); +HRESULT PreferCanonMTOverEEClass(CLRDATA_ADDRESS eeClassPtr, BOOL *preferCanonMT, CLRDATA_ADDRESS *outCanonMT = NULL); + /* This cache is used to read data from the target process if the reads are known * to be sequential. */