// will return exact size which will match the size returned by Emit unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses) { if (ehCount == 0) return(0); unsigned smallSize = COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount); if (smallSize > COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)); for (unsigned i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&clauses[i]; if (fatClause->GetTryOffset() > 0xFFFF || fatClause->GetTryLength() > 0xFF || fatClause->GetHandlerOffset() > 0xFFFF || fatClause->GetHandlerLength() > 0xFF) { return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)); } } return smallSize; }
// This method computes the same result as COR_ILMETHOD_SECT_EH::Size(...) but // does so in a way that detects overflow if the number of exception clauses is // too great (in which case an OOM exception is thrown). We do this rather than // modifying COR_ILMETHOD_SECT_EH::Size because that routine is published in the // SDK and can't take breaking changes and because the overflow support (and // exception mechanism) we're using is only available to the VM. UINT32 ExceptionHandlingSize(unsigned uNumExceptions, COR_ILMETHOD_SECT_EH_CLAUSE_FAT* pClauses) { STANDARD_VM_CONTRACT; if (uNumExceptions == 0) return 0; // Speculatively compute the size for the slim version of the header. S_UINT32 uSmallSize = S_UINT32(sizeof(COR_ILMETHOD_SECT_EH_SMALL)) + (S_UINT32(sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL)) * (S_UINT32(uNumExceptions - 1))); if (uSmallSize.IsOverflow()) COMPlusThrowOM(); if (uSmallSize.Value() > COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) goto FatCase; // Check whether any of the clauses won't fit in the slim case. for (UINT32 i = 0; i < uNumExceptions; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_FAT* pFatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&pClauses[i]; if (pFatClause->GetTryOffset() > 0xFFFF || pFatClause->GetTryLength() > 0xFF || pFatClause->GetHandlerOffset() > 0xFFFF || pFatClause->GetHandlerLength() > 0xFF) { goto FatCase; } } _ASSERTE(uSmallSize.Value() == COR_ILMETHOD_SECT_EH::Size(uNumExceptions, pClauses)); return uSmallSize.Value(); FatCase: S_UINT32 uFatSize = S_UINT32(sizeof(COR_ILMETHOD_SECT_EH_FAT)) + (S_UINT32(sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)) * (S_UINT32(uNumExceptions - 1))); if (uFatSize.IsOverflow()) COMPlusThrowOM(); _ASSERTE(uFatSize.Value() == COR_ILMETHOD_SECT_EH::Size(uNumExceptions, pClauses)); return uFatSize.Value(); }
/* static */ IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) { if (((COR_ILMETHOD_SECT_EH *)pSectEH)->IsFat()) return(&(((COR_ILMETHOD_SECT_EH *)pSectEH)->Fat.Clauses[idx])); COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)buff; COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx]; // mask to remove sign extension - cast just wouldn't work fatClause->SetFlags((CorExceptionFlag)(smallClause->GetFlags()&0x0000ffff)); fatClause->SetClassToken(smallClause->GetClassToken()); fatClause->SetTryOffset(smallClause->GetTryOffset()); fatClause->SetTryLength(smallClause->GetTryLength()); fatClause->SetHandlerLength(smallClause->GetHandlerLength()); fatClause->SetHandlerOffset(smallClause->GetHandlerOffset()); return(buff); }
// emit the section (best format); unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, BOOL moreSections, BYTE* outBuff, ULONG* ehTypeOffsets) { if (size == 0) return(0); _ASSERTE((((size_t) outBuff) & 3) == 0); // header is dword aligned BYTE* origBuff = outBuff; if (ehCount <= 0) return 0; // Initialize the ehTypeOffsets array. if (ehTypeOffsets) { for (unsigned int i = 0; i < ehCount; i++) ehTypeOffsets[i] = (ULONG) -1; } if (COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount) < COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) { COR_ILMETHOD_SECT_EH_SMALL* EHSect = (COR_ILMETHOD_SECT_EH_SMALL*) outBuff; unsigned i; for (i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&clauses[i]; if (fatClause->GetTryOffset() > 0xFFFF || fatClause->GetTryLength() > 0xFF || fatClause->GetHandlerOffset() > 0xFFFF || fatClause->GetHandlerLength() > 0xFF) { break; // fall through and generate as FAT } _ASSERTE((fatClause->GetFlags() & ~0xFFFF) == 0); _ASSERTE((fatClause->GetTryOffset() & ~0xFFFF) == 0); _ASSERTE((fatClause->GetTryLength() & ~0xFF) == 0); _ASSERTE((fatClause->GetHandlerOffset() & ~0xFFFF) == 0); _ASSERTE((fatClause->GetHandlerLength() & ~0xFF) == 0); COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&EHSect->Clauses[i]; smallClause->SetFlags((CorExceptionFlag) fatClause->GetFlags()); smallClause->SetTryOffset(fatClause->GetTryOffset()); smallClause->SetTryLength(fatClause->GetTryLength()); smallClause->SetHandlerOffset(fatClause->GetHandlerOffset()); smallClause->SetHandlerLength(fatClause->GetHandlerLength()); smallClause->SetClassToken(fatClause->GetClassToken()); } if (i >= ehCount) { // if actually got through all the clauses and they are small enough EHSect->Kind = CorILMethod_Sect_EHTable; if (moreSections) EHSect->Kind |= CorILMethod_Sect_MoreSects; EHSect->DataSize = EHSect->Size(ehCount); EHSect->Reserved = 0; _ASSERTE(EHSect->DataSize == EHSect->Size(ehCount)); // make sure didn't overflow outBuff = (BYTE*) &EHSect->Clauses[ehCount]; // Set the offsets for the exception type tokens. if (ehTypeOffsets) { for (i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&EHSect->Clauses[i]; if (smallClause->GetFlags() == COR_ILEXCEPTION_CLAUSE_NONE) { _ASSERTE(! IsNilToken(smallClause->GetClassToken())); ehTypeOffsets[i] = (ULONG)((BYTE *)&smallClause->ClassToken - origBuff); } } } return(size); } } // either total size too big or one of constituent elements too big (eg. offset or length) COR_ILMETHOD_SECT_EH_FAT* EHSect = (COR_ILMETHOD_SECT_EH_FAT*) outBuff; EHSect->SetKind(CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat); if (moreSections) EHSect->SetKind(EHSect->GetKind() | CorILMethod_Sect_MoreSects); EHSect->SetDataSize(EHSect->Size(ehCount)); memcpy(EHSect->Clauses, clauses, ehCount * sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT)); outBuff = (BYTE*) &EHSect->Clauses[ehCount]; _ASSERTE(&origBuff[size] == outBuff); // Set the offsets for the exception type tokens. if (ehTypeOffsets) { for (unsigned int i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&EHSect->Clauses[i]; if (fatClause->GetFlags() == COR_ILEXCEPTION_CLAUSE_NONE) { _ASSERTE(! IsNilToken(fatClause->GetClassToken())); ehTypeOffsets[i] = (ULONG)((BYTE *)&fatClause->ClassToken - origBuff); } } } return(size); }