),
0);
- if (NO_SECURITY_OBJECT != hdrdecoder.GetSecurityObjectStackSlot() ||
- NO_GENERICS_INST_CONTEXT != hdrdecoder.GetGenericsInstContextStackSlot() ||
+ if (NO_GENERICS_INST_CONTEXT != hdrdecoder.GetGenericsInstContextStackSlot() ||
NO_GS_COOKIE == hdrdecoder.GetGSCookieStackSlot())
{
gcPrintf("Prolog size: ");
gcPrintf("%d\n", prologSize);
}
- gcPrintf("Security object: ");
- if (NO_SECURITY_OBJECT == hdrdecoder.GetSecurityObjectStackSlot())
- {
- gcPrintf("<none>\n");
- }
- else
- {
- INT32 ofs = hdrdecoder.GetSecurityObjectStackSlot();
- char sign = '+';
-
- if (ofs < 0)
- {
- sign = '-';
- ofs = -ofs;
- }
-
- gcPrintf("caller.sp%c%x\n", sign, ofs);
- }
-
gcPrintf("GS cookie: ");
if (NO_GS_COOKIE == hdrdecoder.GetGSCookieStackSlot())
{
m_NumCallSites = 0;
#endif
- m_SecurityObjectStackSlot = NO_SECURITY_OBJECT;
m_GSCookieStackSlot = NO_GS_COOKIE;
m_GSCookieValidRangeStart = 0;
_ASSERTE(sizeof(m_GSCookieValidRangeEnd) == sizeof(UINT32));
m_CodeLength = length;
}
-
-void GcInfoEncoder::SetSecurityObjectStackSlot( INT32 spOffset )
-{
- _ASSERTE( spOffset != NO_SECURITY_OBJECT );
-#if defined(TARGET_AMD64)
- _ASSERTE( spOffset < 0x10 && "The security object cannot reside in an input variable!" );
-#endif
- _ASSERTE( m_SecurityObjectStackSlot == NO_SECURITY_OBJECT || m_SecurityObjectStackSlot == spOffset );
-
- m_SecurityObjectStackSlot = spOffset;
-}
-
void GcInfoEncoder::SetPrologSize( UINT32 prologSize )
{
_ASSERTE(prologSize != 0);
///////////////////////////////////////////////////////////////////////
- UINT32 hasSecurityObject = (m_SecurityObjectStackSlot != NO_SECURITY_OBJECT);
UINT32 hasGSCookie = (m_GSCookieStackSlot != NO_GS_COOKIE);
UINT32 hasContextParamType = (m_GenericsInstContextStackSlot != NO_GENERICS_INST_CONTEXT);
UINT32 hasReversePInvokeFrame = (m_ReversePInvokeFrameSlot != NO_REVERSE_PINVOKE_FRAME);
- BOOL slimHeader = (!m_IsVarArg && !hasSecurityObject && !hasGSCookie && (m_PSPSymStackSlot == NO_PSP_SYM) &&
+ BOOL slimHeader = (!m_IsVarArg && !hasGSCookie && (m_PSPSymStackSlot == NO_PSP_SYM) &&
!hasContextParamType && (m_InterruptibleRanges.Count() == 0) && !hasReversePInvokeFrame &&
((m_StackBaseRegister == NO_STACK_BASE_REGISTER) || (NORMALIZE_STACK_BASE_REGISTER(m_StackBaseRegister) == 0))) &&
(m_SizeOfEditAndContinuePreservedArea == NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA) &&
{
GCINFO_WRITE(m_Info1, 1, 1, FlagsSize); // Fat encoding
GCINFO_WRITE(m_Info1, (m_IsVarArg ? 1 : 0), 1, FlagsSize);
- GCINFO_WRITE(m_Info1, (hasSecurityObject ? 1 : 0), 1, FlagsSize);
+ GCINFO_WRITE(m_Info1, 0 /* unused - was hasSecurityObject */, 1, FlagsSize);
GCINFO_WRITE(m_Info1, (hasGSCookie ? 1 : 0), 1, FlagsSize);
GCINFO_WRITE(m_Info1, ((m_PSPSymStackSlot != NO_PSP_SYM) ? 1 : 0), 1, FlagsSize);
GCINFO_WRITE(m_Info1, m_contextParamType, 2, FlagsSize);
GCINFO_WRITE_VARL_U(m_Info1, normPrologSize-1, NORM_PROLOG_SIZE_ENCBASE, ProEpilogSize);
GCINFO_WRITE_VARL_U(m_Info1, normEpilogSize, NORM_EPILOG_SIZE_ENCBASE, ProEpilogSize);
}
- else if (hasSecurityObject || hasContextParamType)
+ else if (hasContextParamType)
{
_ASSERTE(!slimHeader);
// Save the prolog size, to be used for determining when it is not safe
GCINFO_WRITE_VARL_U(m_Info1, normPrologSize-1, NORM_PROLOG_SIZE_ENCBASE, ProEpilogSize);
}
- // Encode the offset to the security object.
- if(hasSecurityObject)
- {
- _ASSERTE(!slimHeader);
-#ifdef _DEBUG
- LOG((LF_GCINFO, LL_INFO1000, "Security object at " FMT_STK "\n",
- DBG_STK(m_SecurityObjectStackSlot)
- ));
-#endif
-
- GCINFO_WRITE_VARL_S(m_Info1, NORMALIZE_STACK_SLOT(m_SecurityObjectStackSlot), SECURITY_OBJECT_STACK_SLOT_ENCBASE, SecObjSize);
- }
-
// Encode the offset to the GS cookie.
if(hasGSCookie)
{
bool doubleAlign; // is the stack double-aligned? locals addressed relative to ESP, and arguments relative to EBP
bool interruptible; // intr. at all times (excluding prolog/epilog), not just call sites
- bool securityCheck; // has a slot for security object
bool handlers; // has callable handlers
bool localloc; // uses localloc
bool editNcontinue; // has been compiled in EnC mode
enum GcInfoHeaderFlags
{
GC_INFO_IS_VARARG = 0x1,
- GC_INFO_HAS_SECURITY_OBJECT = 0x2,
+ // unused = 0x2, // was GC_INFO_HAS_SECURITY_OBJECT
GC_INFO_HAS_GS_COOKIE = 0x4,
GC_INFO_HAS_PSP_SYM = 0x8,
GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK = 0x30,
// Miscellaneous method information
//------------------------------------------------------------------------
- INT32 GetSecurityObjectStackSlot();
INT32 GetGSCookieStackSlot();
UINT32 GetGSCookieValidRangeStart();
UINT32 GetGSCookieValidRangeEnd();
#elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
bool m_HasTailCalls;
#endif // TARGET_AMD64
- INT32 m_SecurityObjectStackSlot;
INT32 m_GSCookieStackSlot;
INT32 m_ReversePInvokeFrameStackSlot;
UINT32 m_ValidRangeStart;
Fat Header for other cases:
- EncodingType[Fat]
- Flag: isVarArg,
- hasSecurityObject,
+ unused (was hasSecurityObject),
hasGSCookie,
hasPSPSymStackSlot,
hasGenericsInstContextStackSlot,
hasReversePInvokeFrame,
- ReturnKind (Fat: 4 bits)
- CodeLength
- - Prolog (if hasSecurityObject || hasGenericsInstContextStackSlot || hasGSCookie)
+ - Prolog (if hasGenericsInstContextStackSlot || hasGSCookie)
- Epilog (if hasGSCookie)
- SecurityObjectStackSlot (if any)
- GSCookieStackSlot (if any)
// Miscellaneous method information
//------------------------------------------------------------------------
- void SetSecurityObjectStackSlot( INT32 spOffset );
void SetPrologSize( UINT32 prologSize );
void SetGSCookieStackSlot( INT32 spOffsetGSCookie, UINT32 validRangeStart, UINT32 validRangeEnd );
void SetPSPSymStackSlot( INT32 spOffsetPSPSym );
#elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
bool m_HasTailCalls;
#endif // TARGET_AMD64
- INT32 m_SecurityObjectStackSlot;
INT32 m_GSCookieStackSlot;
UINT32 m_GSCookieValidRangeStart;
UINT32 m_GSCookieValidRangeEnd;
// Stack offsets must be 8-byte aligned, so we use this unaligned
// offset to represent that the method doesn't have a security object
-#define NO_SECURITY_OBJECT (-1)
#define NO_GS_COOKIE (-1)
#define NO_STACK_BASE_REGISTER (0xffffffff)
#define NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA (0xffffffff)
}
}
- void SetSecurityObjectStackSlot(INT32 spOffset)
- {
- m_gcInfoEncoder->SetSecurityObjectStackSlot(spOffset);
- if (m_doLogging)
- {
- printf("Set security object stack slot to %d.\n", spOffset);
- }
- }
-
void SetIsVarArg()
{
m_gcInfoEncoder->SetIsVarArg();
infoPtr->revPInvokeOffset = header.revPInvokeOffset;
infoPtr->doubleAlign = header.doubleAlign;
- infoPtr->securityCheck = header.security;
infoPtr->handlers = header.handlers;
infoPtr->localloc = header.localloc;
infoPtr->editNcontinue = header.editNcontinue;
// We do a "pop eax; jmp eax" to return from a fault or finally handler
const size_t END_FIN_POP_STACK = sizeof(TADDR);
-
-// The offset (in bytes) from EBP for the secutiy object on the stack
-inline size_t GetSecurityObjectOffset(hdrInfo * info)
-{
- LIMITED_METHOD_DAC_CONTRACT;
-
- _ASSERTE(info->securityCheck && info->ebpFrame);
-
- unsigned position = info->savedRegsCountExclFP +
- 1;
- return position * sizeof(TADDR);
-}
-
inline
size_t GetLocallocSPOffset(hdrInfo * info)
{
_ASSERTE(info->localloc && info->ebpFrame);
unsigned position = info->savedRegsCountExclFP +
- info->securityCheck +
1;
return position * sizeof(TADDR);
}
_ASSERTE((info->genericsContext || info->handlers) && info->ebpFrame);
unsigned position = info->savedRegsCountExclFP +
- info->securityCheck +
info->localloc +
1; // For CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG
return position * sizeof(TADDR);
/* @TODO: Check if we have grown out of space for locals, in the face of localloc */
_ASSERTE(!oldInfo.localloc && !newInfo.localloc);
- // Always reserve space for the securityCheck slot
- _ASSERTE(oldInfo.securityCheck && newInfo.securityCheck);
-
// @TODO: If nesting level grows above the MAX_EnC_HANDLER_NESTING_LEVEL,
// we should return EnC_NESTED_HANLDERS
_ASSERTE(oldInfo.handlers && newInfo.handlers);
TADDR callerSP = oldStackBase + oldFixedStackSize;
- // If the old code saved a security object, store the object's reference now.
- OBJECTREF securityObject = NULL;
- INT32 nOldSecurityObjectStackSlot = oldGcDecoder.GetSecurityObjectStackSlot();
- if (nOldSecurityObjectStackSlot != NO_SECURITY_OBJECT)
- {
- securityObject = ObjectToOBJECTREF(*PTR_PTR_Object(callerSP + nOldSecurityObjectStackSlot));
- }
-
#ifdef _DEBUG
// If the old method has a PSPSym, then its value should == FP for x64 and callerSP for arm64
INT32 nOldPspSymStackSlot = oldGcDecoder.GetPSPSymStackSlot();
#elif defined(TARGET_AMD64) || defined(TARGET_ARM64)
memset((void*)newStackBase, 0, newFixedStackSize - frameHeaderSize);
- // On AMD64/ARM64, after zeroing out the stack, restore the security object and PSPSym...
-
- // There is no relationship we can guarantee between the old code having a security
- // object and the new code having a security object. If the new code does have a
- // security object, then we copy over the old security object's reference if there
- // was one (else we copy over NULL, which is fine). If the new code doesn't have a
- // security object, we do nothing.
- INT32 nNewSecurityObjectStackSlot = newGcDecoder.GetSecurityObjectStackSlot();
- if (nNewSecurityObjectStackSlot != NO_SECURITY_OBJECT)
- {
- *PTR_PTR_Object(callerSP + nNewSecurityObjectStackSlot) = OBJECTREFToObject(securityObject);
- }
-
// Restore PSPSym for the new function. Its value should be set to our new FP. But
// first, we gotta find PSPSym's location on the stack
INT32 nNewPspSymStackSlot = newGcDecoder.GetPSPSymStackSlot();
if (pUnwindInfo != NULL)
{
- pUnwindInfo->securityObjectOffset = 0;
- if (info->securityCheck)
- {
- _ASSERTE(info->ebpFrame);
- SIZE_T securityObjectOffset = (GetSecurityObjectOffset(info) / sizeof(void*));
- _ASSERTE(securityObjectOffset != 0);
- pUnwindInfo->securityObjectOffset = DWORD(securityObjectOffset);
- }
-
pUnwindInfo->fUseEbpAsFrameReg = info->ebpFrame;
pUnwindInfo->fUseEbp = ((info->savedRegMask & RM_EBP) != 0);
}
}
m_IsVarArg = headerFlags & GC_INFO_IS_VARARG;
- int hasSecurityObject = headerFlags & GC_INFO_HAS_SECURITY_OBJECT;
int hasGSCookie = headerFlags & GC_INFO_HAS_GS_COOKIE;
int hasPSPSym = headerFlags & GC_INFO_HAS_PSP_SYM;
int hasGenericsInstContext = (headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE;
m_ValidRangeEnd = (UINT32) DENORMALIZE_CODE_OFFSET(normCodeLength - normEpilogSize);
_ASSERTE(m_ValidRangeStart < m_ValidRangeEnd);
}
- else if (hasSecurityObject || hasGenericsInstContext)
+ else if (hasGenericsInstContext)
{
// Decode prolog information
UINT32 normPrologSize = (UINT32) m_Reader.DecodeVarLengthUnsigned(NORM_PROLOG_SIZE_ENCBASE) + 1;
return;
}
- // Decode the offset to the security object.
- if(hasSecurityObject)
- {
- m_SecurityObjectStackSlot = (INT32) DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(SECURITY_OBJECT_STACK_SLOT_ENCBASE));
- }
- else
- {
- m_SecurityObjectStackSlot = NO_SECURITY_OBJECT;
- }
-
- remainingFlags &= ~DECODE_SECURITY_OBJECT;
- if (remainingFlags == 0)
- {
- // Bail, if we've decoded enough,
- return;
- }
-
// Decode the offset to the GS cookie.
if(hasGSCookie)
{
}
}
-INT32 GcInfoDecoder::GetSecurityObjectStackSlot()
-{
- _ASSERTE( m_Flags & DECODE_SECURITY_OBJECT );
- return m_SecurityObjectStackSlot;
-}
-
INT32 GcInfoDecoder::GetGSCookieStackSlot()
{
_ASSERTE( m_Flags & DECODE_GS_COOKIE );
ULONG RBPOffset;
ULONG RSPOffsetFromUnwindInfo;
#else // !TARGET_AMD64
- size_t securityObjectOffset; // offset of SecurityObject. 0 if there is no security object
BOOL fUseEbp; // Is EBP modified by the method - either for a frame-pointer or for a scratch-register?
BOOL fUseEbpAsFrameReg; // use EBP as the frame pointer?
#endif // !TARGET_AMD64
UINT_PTR IP;
#if !defined(TARGET_AMD64)
WORD ESPOffset:15; // stack offset (frame size + pending arguments + etc)
- WORD securityObjectOffset:3;// offset of SecurityObject. 0 if there is no security object
WORD fUseEbp:1; // For ESP methods, is EBP touched at all?
WORD fUseEbpAsFrameReg:1; // use EBP as the frame register?
- WORD argSize:11; // size of args pushed on stack
+ WORD argSize:15; // size of args pushed on stack
#else // TARGET_AMD64
DWORD RSPOffset;
DWORD RBPOffset;
this->ESPOffset = SPOffset;
this->argSize = argSize;
- this->securityObjectOffset = (WORD)pUnwindInfo->securityObjectOffset;
- _ASSERTE(this->securityObjectOffset == pUnwindInfo->securityObjectOffset);
-
this->fUseEbp = pUnwindInfo->fUseEbp;
this->fUseEbpAsFrameReg = pUnwindInfo->fUseEbpAsFrameReg;
_ASSERTE(!fUseEbpAsFrameReg || fUseEbp);
#endif // !TARGET_X86 && !TARGET_AMD64
}
- inline BOOL HasSecurityObject()
- {
- LIMITED_METHOD_CONTRACT;
-
-#if defined(TARGET_X86)
- return securityObjectOffset != 0;
-#else // !TARGET_X86
- // On AMD64 we don't save anything by grabbing the security object before it is needed. This is because
- // we need to crack the GC info in order to find the security object, and to unwind we only need to
- // crack the unwind info.
- return FALSE;
-#endif // !TARGET_X86
- }
-
inline BOOL IsSafeToUseCache()
{
LIMITED_METHOD_CONTRACT;
#if defined(TARGET_AMD64)
RBPOffset = pCacheEntry->RBPOffset;
#else // !TARGET_AMD64
- securityObjectOffset = pCacheEntry->securityObjectOffset;
fUseEbp = pCacheEntry->fUseEbp;
fUseEbpAsFrameReg = pCacheEntry->fUseEbpAsFrameReg;
#endif // !TARGET_AMD64