Skip to content

Commit

Permalink
Implement support for BEGIN/END_ILLINK_FEATURE_SWITCH in CoreLib/EE i…
Browse files Browse the repository at this point in the history
…nterface validation (dotnet#106151)
  • Loading branch information
jkoritzinsky authored Aug 9, 2024
1 parent 8ca4759 commit 8fe777f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
84 changes: 80 additions & 4 deletions src/coreclr/vm/binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "clrvarargs.h"
#include "sigbuilder.h"
#include "olevariant.h"
#include "configuration.h"

//
// Retrieve structures from ID.
Expand Down Expand Up @@ -553,6 +554,31 @@ const CoreLibBinder::OffsetAndSizeCheck CoreLibBinder::OffsetsAndSizes[] =
#include "corelib.h"
};

namespace
{
bool FeatureSwitchDisabled(LPCWSTR featureSwitch, bool enabledValue, bool defaultValue)
{
// If we don't have a feature switch, treat the switch as enabled.
return featureSwitch != nullptr &&
Configuration::GetKnobBooleanValue(featureSwitch, defaultValue) != enabledValue;
}

bool IsTrimmed(LPCSTR nameSpace, LPCSTR className)
{
bool isInDisabledFeatureSwitch = false;
#define BEGIN_ILLINK_FEATURE_SWITCH(s, e, d) isInDisabledFeatureSwitch = FeatureSwitchDisabled(W(#s), e, d);
#define END_ILLINK_FEATURE_SWITCH() isInDisabledFeatureSwitch = false;
#define DEFINE_CLASS_U(ns, stringName, unmanagedType) \
if (strcmp(nameSpace, g_ ## ns ## NS) == 0 \
&& strcmp(className, #stringName) == 0) \
return isInDisabledFeatureSwitch;

#include "corelib.h"

return false;
}
}

//
// check the basic consistency between CoreLib and VM
//
Expand All @@ -561,13 +587,18 @@ void CoreLibBinder::Check()
STANDARD_VM_CONTRACT;

MethodTable * pMT = NULL;
bool currentTypeTrimmed = false;

for (unsigned i = 0; i < ARRAY_SIZE(OffsetsAndSizes); i++)
{
const OffsetAndSizeCheck * p = OffsetsAndSizes + i;

if (p->className != NULL)
{
currentTypeTrimmed = IsTrimmed(p->classNameSpace, p->className);
if (currentTypeTrimmed)
continue;

pMT = ClassLoader::LoadTypeByNameThrowing(GetModule()->GetAssembly(), p->classNameSpace, p->className).AsMethodTable();

if (p->expectedClassSize == sizeof(NoClass))
Expand All @@ -586,7 +617,7 @@ void CoreLibBinder::Check()
"man: 0x%x, unman: 0x%x, Name: %s\n", size, expectedsize, pMT->GetDebugClassName()));
}
else
if (p->fieldName != NULL)
if (p->fieldName != NULL && !currentTypeTrimmed)
{
// This assert will fire if there is DEFINE_FIELD_U macro without preceding DEFINE_CLASS_U macro in corelib.h
_ASSERTE(pMT != NULL);
Expand Down Expand Up @@ -896,6 +927,51 @@ static void FCallCheckSignature(MethodDesc* pMD, PCODE pImpl)
}
#endif // CHECK_FCALL_SIGNATURE

namespace
{
bool IsTrimmed(BinderClassID classId)
{
LPCWSTR featureSwitch = nullptr;
bool enabledValue = true;
bool defaultValue = true;
#define DEFINE_CLASS(i,n,s) if (classId == CLASS__ ## i) \
return FeatureSwitchDisabled(featureSwitch, enabledValue, defaultValue);
#define BEGIN_ILLINK_FEATURE_SWITCH(s, e, d) featureSwitch = W(#s); enabledValue = e; defaultValue = d;
#define END_ILLINK_FEATURE_SWITCH() featureSwitch = nullptr;
#include "corelib.h"

return false;
}

bool IsTrimmed(BinderMethodID methodId)
{
LPCWSTR featureSwitch = nullptr;
bool enabledValue = true;
bool defaultValue = true;
#define DEFINE_METHOD(c,i,s,g) if (methodId == METHOD__ ## c ## __ ## i) \
return FeatureSwitchDisabled(featureSwitch, enabledValue, defaultValue);
#define BEGIN_ILLINK_FEATURE_SWITCH(s, e, d) featureSwitch = W(#s); enabledValue = e; defaultValue = d;
#define END_ILLINK_FEATURE_SWITCH() featureSwitch = nullptr;
#include "corelib.h"

return false;
}

extern bool IsTrimmed(BinderFieldID fieldId)
{
LPCWSTR featureSwitch = nullptr;
bool enabledValue = true;
bool defaultValue = true;
#define DEFINE_FIELD(c,i,s) if (fieldId == FIELD__ ## c ## __ ## i) \
return FeatureSwitchDisabled(featureSwitch, enabledValue, defaultValue);
#define BEGIN_ILLINK_FEATURE_SWITCH(s, e, d) featureSwitch = W(#s); enabledValue = e; defaultValue = d;
#define END_ILLINK_FEATURE_SWITCH() featureSwitch = nullptr;
#include "corelib.h"

return false;
}
}

//
// extended check of consistency between CoreLib and VM:
// - verifies that all references from CoreLib to VM are present
Expand All @@ -922,7 +998,7 @@ void CoreLibBinder::CheckExtended()
{
if (CoreLibBinder::GetClassName(cID) != NULL) // Allow for CorSigElement entries with no classes
{
if (NULL == CoreLibBinder::GetClass(cID))
if (!IsTrimmed(cID) && NULL == CoreLibBinder::GetClass(cID))
{
fError = true;
}
Expand All @@ -946,7 +1022,7 @@ void CoreLibBinder::CheckExtended()
BinderClassID cID = m_methodDescriptions[mID-1].classID;
EX_TRY
{
if (NULL == CoreLibBinder::GetMethod(mID))
if (!IsTrimmed(mID) && NULL == CoreLibBinder::GetMethod(mID))
{
fError = true;
}
Expand All @@ -969,7 +1045,7 @@ void CoreLibBinder::CheckExtended()
BinderClassID cID = m_fieldDescriptions[fID-1].classID;
EX_TRY
{
if (NULL == CoreLibBinder::GetField(fID))
if (!IsTrimmed(fID) && NULL == CoreLibBinder::GetField(fID))
{
fError = true;
}
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ DEFINE_METHOD(CLASS, GET_METHODS, GetMethods,
DEFINE_METHOD(CLASS, INVOKE_MEMBER, InvokeMember, IM_Str_BindingFlags_Binder_Obj_ArrObj_ArrParameterModifier_CultureInfo_ArrStr_RetObj)
DEFINE_METHOD(CLASS, GET_METHOD_BASE, GetMethodBase, SM_RuntimeType_RuntimeMethodHandleInternal_RetMethodBase)
DEFINE_METHOD(CLASS, GET_FIELD_INFO, GetFieldInfo, SM_RuntimeType_IRuntimeFieldInfo_RetFieldInfo)
DEFINE_METHOD(CLASS, GET_PROPERTY_INFO, GetPropertyInfo, SM_RuntimeType_Int_RetPropertyInfo)

#ifdef FEATURE_COMINTEROP
DEFINE_METHOD(CLASS, FORWARD_CALL_TO_INVOKE, ForwardCallToInvokeMember, IM_Str_BindingFlags_Obj_ArrObj_ArrBool_ArrInt_ArrType_Type_RetObj)
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/metasig.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ DEFINE_METASIG(SM(IntPtr_RetStr, I, s))
DEFINE_METASIG(SM(IntPtr_RetBool, I, F))
DEFINE_METASIG_T(SM(RuntimeType_RuntimeMethodHandleInternal_RetMethodBase, C(CLASS) g(METHOD_HANDLE_INTERNAL), C(METHOD_BASE) ))
DEFINE_METASIG_T(SM(RuntimeType_IRuntimeFieldInfo_RetFieldInfo, C(CLASS) C(I_RT_FIELD_INFO), C(FIELD_INFO) ))
DEFINE_METASIG_T(SM(RuntimeType_Int_RetPropertyInfo, C(CLASS) i, C(PROPERTY_INFO) ))
DEFINE_METASIG(SM(Char_Bool_Bool_RetByte, u F F, b))
DEFINE_METASIG(SM(Byte_RetChar, b, u))
DEFINE_METASIG(SM(Str_Bool_Bool_RefInt_RetIntPtr, s F F r(i), I))
Expand Down

0 comments on commit 8fe777f

Please sign in to comment.