in src/InstrumentationEngine/CorHeaders.cpp [135:220]
unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount,
__in_ecount(ehCount) const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
bool moreSections, __inout_ecount_opt(size) BYTE* outBuff,
__out_ecount(ehCount) ULONG* ehTypeOffsets)
{
HRESULT hr = S_OK;
if (size == 0 || outBuff == nullptr)
return 0;
ASSERT ((((size_t) outBuff) & 3) == 0); // header is dword aligned
const BYTE* origBuff = outBuff;
if (ehCount == 0 || clauses == nullptr)
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++) {
if (clauses[i].TryOffset > 0xFFFF ||
clauses[i].TryLength > 0xFF ||
clauses[i].HandlerOffset > 0xFFFF ||
clauses[i].HandlerLength > 0xFF) {
break; // fall through and generate as FAT
}
ASSERT ((clauses[i].Flags & ~0xFFFF) == 0);
ASSERT ((clauses[i].TryOffset & ~0xFFFF) == 0);
ASSERT ((clauses[i].TryLength & ~0xFF) == 0);
ASSERT ((clauses[i].HandlerOffset & ~0xFFFF) == 0);
ASSERT ((clauses[i].HandlerLength & ~0xFF) == 0);
EHSect->Clauses[i].Flags = (CorExceptionFlag) clauses[i].Flags;
EHSect->Clauses[i].TryOffset = (WORD) clauses[i].TryOffset;
EHSect->Clauses[i].TryLength = (WORD) clauses[i].TryLength;
EHSect->Clauses[i].HandlerOffset = (WORD) clauses[i].HandlerOffset;
EHSect->Clauses[i].HandlerLength = (WORD) clauses[i].HandlerLength;
EHSect->Clauses[i].ClassToken = clauses[i].ClassToken;
}
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;
ASSERT (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 (unsigned int j = 0; j < ehCount; j++) {
if (EHSect->Clauses[j].Flags == COR_ILEXCEPTION_CLAUSE_NONE)
{
ehTypeOffsets[j] = (ULONG)((BYTE *)&EHSect->Clauses[j].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->Kind = CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat;
if (moreSections)
EHSect->Kind |= CorILMethod_Sect_MoreSects;
EHSect->DataSize = EHSect->Size(ehCount);
IfFailRetErrno(memcpy_s(EHSect->Clauses, ehCount * sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT), clauses, ehCount * sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)));
outBuff = (BYTE*) &EHSect->Clauses[ehCount];
ASSERT (&origBuff[size] == outBuff);
// Set the offsets for the exception type tokens.
if (ehTypeOffsets)
{
for (unsigned int i = 0; i < ehCount; i++) {
if (EHSect->Clauses[i].Flags == COR_ILEXCEPTION_CLAUSE_NONE)
{
ehTypeOffsets[i] = (ULONG)((BYTE *)&EHSect->Clauses[i].ClassToken - origBuff);
}
}
}
return(size);
}