Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cdac] start of RuntimeTypeSystem contract; implement GetMethodTableData SOS method #103444

Merged
merged 72 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
b98afa8
Implement GetThreadStoreData in cDAC
elinor-fung May 16, 2024
890f9c6
Add placeholder for getting thread data
elinor-fung May 17, 2024
41ba95c
Apply suggestions from code review
elinor-fung May 23, 2024
29214f0
WIP: Metadata contract
lambdageek May 14, 2024
8beced0
Merge remote-tracking branch 'elinor-fung/cdac-threadstore' into cdac…
lambdageek May 29, 2024
5213286
fix build
lambdageek May 29, 2024
622e01a
WIP: ValidateMethodTable
lambdageek May 29, 2024
e112416
DataCache.GetOrAdd
elinor-fung May 29, 2024
ae1eac9
wip
lambdageek May 30, 2024
79ea0d4
Merge remote-tracking branch 'elinor-fung/cdac-threadstore' into cdac…
lambdageek May 30, 2024
5c696da
checkpoint: ValidateWithPossibleAV
lambdageek May 30, 2024
6eaf80f
Merge remote-tracking branch 'origin/main' into cdac-wip
lambdageek May 30, 2024
3a7808d
checkpoint EEClass from MethodTable
lambdageek May 31, 2024
66e5476
checkpoint: ValidateMethodTablePointer
lambdageek May 31, 2024
95914b8
cp: delegate from legacy dac
lambdageek May 31, 2024
2b8fda3
add Metadata to runtime contract descriptor
lambdageek Jun 11, 2024
5c7d2ac
checkpoint: more MethodTable fields
lambdageek Jun 12, 2024
7be5c60
checkpoint GetMethodTableData implemented
lambdageek Jun 13, 2024
30b7b26
checkpoint: same answer as legacy dac
lambdageek Jun 13, 2024
187bcbe
Merge remote-tracking branch 'origin/main' into cdac-wip
lambdageek Jun 14, 2024
f0d1fcb
new flags for statics
lambdageek Jun 14, 2024
c53db36
fix GCC build
lambdageek Jun 14, 2024
b70bb1d
WIP: opaque MethodTableHandle
lambdageek Jun 17, 2024
a65fd50
Add contract accessors for MethodTableHandle
lambdageek Jun 18, 2024
6f844bf
fixup
lambdageek Jun 18, 2024
76e0384
simplify FreeObjectMethodTable handling
lambdageek Jun 18, 2024
cdb7543
cleanup
lambdageek Jun 18, 2024
78830ea
fixup
lambdageek Jun 18, 2024
fbbd45b
Merge remote-tracking branch 'origin/main' into cdac-wip
lambdageek Jun 18, 2024
32665b2
[dac] Return canonical MethodTable instead of EEClass
lambdageek Jun 18, 2024
acf8436
Delete unreferenced MethodTable flags
lambdageek Jun 18, 2024
f246c86
add Metadata contract doc; fixups
lambdageek Jun 19, 2024
8409f3e
Merge remote-tracking branch 'origin/main' into cdac-wip
lambdageek Jun 20, 2024
08d069a
rename DacpMethodTableData:klass field
lambdageek Jun 20, 2024
674655f
document GetMethodTableData string baseSize adjustment
lambdageek Jun 20, 2024
2ae4625
Apply suggestions from code review
lambdageek Jun 20, 2024
e18a2be
fix typo
lambdageek Jun 21, 2024
846e779
rename flag to ContainsGCPointers
lambdageek Jun 21, 2024
383af83
[vm] rename ContainsPointers flag to ContainsGCPointers
lambdageek Jun 21, 2024
0f8c7f1
code style suggestions from code review
lambdageek Jun 21, 2024
7a337c1
BUGFIX: read DwFlags2 from the correct offset
lambdageek Jun 21, 2024
a7c8158
hide utility methods
lambdageek Jun 21, 2024
f4a3493
remove EEClass_1 struct
lambdageek Jun 21, 2024
10624c7
Merge remote-tracking branch 'origin/main' into cdac-wip
lambdageek Jun 21, 2024
65cc531
rename data descriptor members to remove prefixes
lambdageek Jun 21, 2024
d526087
cleanup the contract docs
lambdageek Jun 21, 2024
0a4112e
remove hungariant notation prefixes from data descriptors
lambdageek Jun 24, 2024
1071ca4
DAC: always set wNumVirtuals and wNumVtableSlots to 0
lambdageek Jun 25, 2024
6c5235c
Remove NumVirtuals and NumVtableSlots from Metadata.md
lambdageek Jun 27, 2024
95b728a
Merge remote-tracking branch 'origin/main' into cdac-wip
lambdageek Jun 28, 2024
6573e14
"untrusted" -> "non-validated"
lambdageek Jun 28, 2024
8596892
merge fixup
lambdageek Jun 28, 2024
6eabf42
remove #if 0
lambdageek Jun 28, 2024
4d3200d
cleanup
lambdageek Jun 28, 2024
2e66740
pull test target helpers out
lambdageek Jun 28, 2024
8533148
Add one FreeObjectMethodTable unit test
lambdageek Jul 1, 2024
77cf405
clean up the test helpers a bit
lambdageek Jul 2, 2024
f9bce4c
validate that a mock system object is a valid method table
lambdageek Jul 2, 2024
3721992
code review feedback and more tests:
lambdageek Jul 2, 2024
1af7c80
Update src/coreclr/gc/env/gcenv.object.h
lambdageek Jul 2, 2024
993ae1d
Update src/native/managed/cdacreader/src/Contracts/Metadata_1.MethodT…
lambdageek Jul 2, 2024
f04d880
Address code review feedback
lambdageek Jul 2, 2024
76859d1
move non-validated MethodTable handling to a separate class
lambdageek Jul 2, 2024
a12a407
clear up ComponentSize contract spec and impl
lambdageek Jul 2, 2024
9cf4c5a
rename Metadata -> RuntimeTypeSystem
lambdageek Jul 3, 2024
1814848
add validation failure test; change validation to throw InvalidOperat…
lambdageek Jul 3, 2024
89f98a3
Merge remote-tracking branch 'origin/main' into cdac-wip
lambdageek Jul 3, 2024
a0989fa
Update src/native/managed/cdacreader/src/Contracts/RuntimeTypeSystem_…
lambdageek Jul 3, 2024
617bf62
spellcheck
lambdageek Jul 3, 2024
815ff0d
Merge branch 'cdac-wip' of github.com:lambdageek/runtime into cdac-wip
lambdageek Jul 3, 2024
1ab4f08
Add a generic instance test
lambdageek Jul 3, 2024
ee3a362
add array instance test
lambdageek Jul 3, 2024
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
1 change: 1 addition & 0 deletions src/coreclr/debug/daccess/dacimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,7 @@ class ClrDataAccess

HRESULT GetThreadDataImpl(CLRDATA_ADDRESS threadAddr, struct DacpThreadData *threadData);
HRESULT GetThreadStoreDataImpl(struct DacpThreadStoreData *data);
HRESULT GetMethodTableDataImpl(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data);

BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord);
#ifndef TARGET_UNIX
Expand Down
52 changes: 49 additions & 3 deletions src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,14 @@ BOOL DacValidateMethodTable(PTR_MethodTable pMT, BOOL &bIsFree)
// In rare cases, we've seen the standard check above pass when it shouldn't.
// Insert additional/ad-hoc tests below.

// FIXME(cdac): ak - this check is trivially true - GetCl() runs in the DAC and synthesizes a token with a mdtTypeDef table
// so the check is always true.
#if 0
// Metadata token should look valid for a class
mdTypeDef td = pMT->GetCl();
if (td != mdTokenNil && TypeFromToken(td) != mdtTypeDef)
goto BadMethodTable;
#endif

// BaseSize should always be greater than 0 for valid objects (unless it's an interface)
// For strings, baseSize is not ptr-aligned
Expand Down Expand Up @@ -1765,12 +1769,55 @@ ClrDataAccess::GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData
return E_INVALIDARG;

SOSDacEnter();
if (m_cdacSos != NULL)
{
// Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC.
hr = m_cdacSos->GetMethodTableData(mt, MTData);
if (FAILED(hr))
{
hr = GetMethodTableDataImpl(mt, MTData);
}
#ifdef _DEBUG
else
{
// Assert that the data is the same as what we get from the DAC.
DacpMethodTableData mtDataLocal;
HRESULT hrLocal = GetMethodTableDataImpl(mt, &mtDataLocal);
_ASSERTE(hr == hrLocal);
_ASSERTE(MTData->BaseSize == mtDataLocal.BaseSize);
_ASSERTE(MTData->ComponentSize == mtDataLocal.ComponentSize);
_ASSERTE(MTData->bIsFree == mtDataLocal.bIsFree);
_ASSERTE(MTData->Module == mtDataLocal.Module);
_ASSERTE(MTData->Class == mtDataLocal.Class);
_ASSERTE(MTData->ParentMethodTable == mtDataLocal.ParentMethodTable);
_ASSERTE(MTData->wNumInterfaces == mtDataLocal.wNumInterfaces);
_ASSERTE(MTData->wNumMethods == mtDataLocal.wNumMethods);
_ASSERTE(MTData->wNumVtableSlots == mtDataLocal.wNumVtableSlots);
_ASSERTE(MTData->wNumVirtuals == mtDataLocal.wNumVirtuals);
_ASSERTE(MTData->cl == mtDataLocal.cl);
_ASSERTE(MTData->dwAttrClass = mtDataLocal.dwAttrClass);
_ASSERTE(MTData->bContainsPointers == mtDataLocal.bContainsPointers);
_ASSERTE(MTData->bIsShared == mtDataLocal.bIsShared);
_ASSERTE(MTData->bIsDynamic == mtDataLocal.bIsDynamic);
}
#endif
}
else
{
hr = GetMethodTableDataImpl (mt, MTData);
}
SOSDacLeave();
return hr;
}

HRESULT
ClrDataAccess::GetMethodTableDataImpl(CLRDATA_ADDRESS mt, struct DacpMethodTableData *MTData)
{
PTR_MethodTable pMT = PTR_MethodTable(TO_TADDR(mt));
BOOL bIsFree = FALSE;
if (!DacValidateMethodTable(pMT, bIsFree))
{
hr = E_INVALIDARG;
return E_INVALIDARG;
}
else
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
{
Expand All @@ -1797,8 +1844,7 @@ ClrDataAccess::GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData
}
}

SOSDacLeave();
return hr;
return S_OK;
}

HRESULT
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/debug/runtimeinfo/contractpointerdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
#include <stdint.h>

#include "threads.h"
#include "vars.hpp"

extern "C"
{

lambdageek marked this conversation as resolved.
Show resolved Hide resolved
// without an extern declaration, clang does not emit this global into the object file
extern const uintptr_t contractDescriptorPointerData[];

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/runtimeinfo/contracts.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// cdac-build-tool can take multiple "-c contract_file" arguments
// so to conditionally include contracts, put additional contracts in a separate file
{
"Metadata": 1,
"Thread": 1,
"SOSBreakingChangeVersion": 1 // example contract: "runtime exports an SOS breaking change version global"
}
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/runtimeinfo/datadescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "static_assert.h"

#include <sospriv.h>
#include "methodtable.h"
#include "threads.h"

// begin blob definition
Expand Down
29 changes: 29 additions & 0 deletions src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,34 @@ CDAC_TYPE_BEGIN(GCHandle)
CDAC_TYPE_SIZE(sizeof(OBJECTHANDLE))
CDAC_TYPE_END(GCHandle)

// Metadata

CDAC_TYPE_BEGIN(MethodTable)
CDAC_TYPE_INDETERMINATE(MethodTable)
CDAC_TYPE_FIELD(MethodTable, /*uint32*/, DwFlags, cdac_offsets<MethodTable>::m_dwFlags)
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
CDAC_TYPE_FIELD(MethodTable, /*uint32*/, BaseSize, cdac_offsets<MethodTable>::m_BaseSize)
CDAC_TYPE_FIELD(MethodTable, /*uint32*/, DwFlags2, cdac_offsets<MethodTable>::m_dwFlags2)
CDAC_TYPE_FIELD(MethodTable, /*nuint*/, EEClassOrCanonMT, cdac_offsets<MethodTable>::m_pEEClassOrCanonMT)
CDAC_TYPE_FIELD(MethodTable, /*pointer*/, Module, cdac_offsets<MethodTable>::m_pModule)
CDAC_TYPE_FIELD(MethodTable, /*pointer*/, AuxiliaryData, cdac_offsets<MethodTable>::m_pAuxiliaryData)
CDAC_TYPE_FIELD(MethodTable, /*pointer*/, ParentMethodTable, cdac_offsets<MethodTable>::m_pParentMethodTable)
CDAC_TYPE_FIELD(MethodTable, /*uint16*/, NumInterfaces, cdac_offsets<MethodTable>::m_wNumInterfaces)
CDAC_TYPE_FIELD(MethodTable, /*uint16*/, NumVirtuals, cdac_offsets<MethodTable>::m_wNumVirtuals)
CDAC_TYPE_END(MethodTable)

CDAC_TYPE_BEGIN(EEClass)
CDAC_TYPE_INDETERMINATE(EEClass)
CDAC_TYPE_FIELD(EEClass, /*pointer*/, MethodTable, cdac_offsets<EEClass>::m_pMethodTable)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumMethods, cdac_offsets<EEClass>::m_NumMethods)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumNonVirtualSlots, cdac_offsets<EEClass>::m_NumNonVirtualSlots)
CDAC_TYPE_FIELD(EEClass, /*uint32*/, DwAttrClass, cdac_offsets<EEClass>::m_dwAttrClass)
CDAC_TYPE_END(EEClass)

CDAC_TYPE_BEGIN(MethodTableAuxiliaryData)
CDAC_TYPE_INDETERMINATE(MethodTableAuxiliaryData)
CDAC_TYPE_FIELD(MethodTableAuxiliaryData, /*uint32*/, DwFlags, offsetof(MethodTableAuxiliaryData, m_dwFlags))
CDAC_TYPE_END(MethodTableAuxiliaryData)

CDAC_TYPES_END()

CDAC_GLOBALS_BEGIN()
Expand All @@ -138,6 +166,7 @@ CDAC_GLOBAL(FeatureEHFunclets, uint8, 1)
CDAC_GLOBAL(FeatureEHFunclets, uint8, 0)
#endif
CDAC_GLOBAL(SOSBreakingChangeVersion, uint8, SOS_BREAKING_CHANGE_VERSION)
CDAC_GLOBAL_POINTER(FreeObjectMethodTable, &::g_pFreeObjectMethodTable)
CDAC_GLOBALS_END()

#undef CDAC_BASELINE
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/cdacoffsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
//
// If the offset of some field F in class C must be provided to cDAC, but the field is private, the
// class C should declare cdac_offsets<T> as a friend:
//
// friend template<typename T> struct cdac_offsets;
//
// template<typename T> friend struct ::cdac_offsets;
//
// and provide a specialization cdac_offsets<C> with a constexpr size_t member providing the offset:
//
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/vm/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -1798,6 +1798,15 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
}
#endif // !DACCESS_COMPILE

template<typename T> friend struct ::cdac_offsets;
};

template<> struct ::cdac_offsets<EEClass>
{
static constexpr size_t m_pMethodTable = offsetof(EEClass, m_pMethodTable);
static constexpr size_t m_NumMethods = offsetof(EEClass, m_NumMethods);
static constexpr size_t m_NumNonVirtualSlots = offsetof(EEClass, m_NumNonVirtualSlots);
static constexpr size_t m_dwAttrClass = offsetof(EEClass, m_dwAttrClass);
};

// --------------------------------------------------------------------------------------------
Expand Down
17 changes: 16 additions & 1 deletion src/coreclr/vm/methodtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ struct DynamicStaticsInfo
// If it has, then we don't need to do anything
return false;
}

oldValFromInterlockedOp = InterlockedCompareExchangeT(pAddr, newVal | oldVal, oldVal);
} while(oldValFromInterlockedOp != oldVal);
return true;
Expand Down Expand Up @@ -3858,8 +3858,23 @@ public :
BOOL Validate ();

static void GetStaticsOffsets(StaticsOffsetType staticsOffsetType, bool fGenericsStatics, uint32_t *dwGCOffset, uint32_t *dwNonGCOffset);

template<typename T> friend struct ::cdac_offsets;
}; // class MethodTable

template<> struct ::cdac_offsets<MethodTable>
{
static constexpr size_t m_dwFlags = offsetof(MethodTable, m_dwFlags);
static constexpr size_t m_BaseSize = offsetof(MethodTable, m_BaseSize);
static constexpr size_t m_dwFlags2 = offsetof(MethodTable, m_dwFlags2);
static constexpr size_t m_pEEClassOrCanonMT = offsetof(MethodTable, m_pEEClass);
static constexpr size_t m_pModule = offsetof(MethodTable, m_pModule);
static constexpr size_t m_pAuxiliaryData = offsetof(MethodTable, m_pAuxiliaryData);
static constexpr size_t m_pParentMethodTable = offsetof(MethodTable, m_pParentMethodTable);
static constexpr size_t m_wNumInterfaces = offsetof(MethodTable, m_wNumInterfaces);
static constexpr size_t m_wNumVirtuals = offsetof(MethodTable, m_wNumVirtuals);
};

#ifndef CROSSBITNESS_COMPILE
static_assert_no_msg(sizeof(MethodTable) == SIZEOF__MethodTable_);
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/native/managed/cdacreader/src/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ internal static class Globals
internal const string GCThread = nameof(GCThread);

internal const string SOSBreakingChangeVersion = nameof(SOSBreakingChangeVersion);

internal const string FreeObjectMethodTable = nameof(FreeObjectMethodTable);
}
}
Loading
Loading