//------------------------------------------------------------------------ // Compiler::unwindEmitFuncHelper: Report the unwind information to the VM for a // given main function or funclet, for either the hot or cold section. // // Arguments: // func - The main function or funclet to reserve unwind info for. // pHotCode - Pointer to the beginning of the memory with the function and funclet hot code. // pColdCode - Pointer to the beginning of the memory with the function and funclet cold code. // Ignored if 'isHotCode' is true. // isHotCode - 'true' to report the hot section, 'false' to report the cold section. // void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode) { UNATIVE_OFFSET startOffset; UNATIVE_OFFSET endOffset; DWORD unwindCodeBytes; BYTE* pUnwindBlock; if (isHotCode) { if (func->startLoc == nullptr) { startOffset = 0; } else { startOffset = func->startLoc->CodeOffset(genEmitter); } if (func->endLoc == nullptr) { endOffset = info.compNativeCodeSize; } else { endOffset = func->endLoc->CodeOffset(genEmitter); } unwindCodeBytes = sizeof(func->unwindCodes) - func->unwindCodeSlot; #ifdef DEBUG UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *) (&func->unwindCodes[func->unwindCodeSlot]); DWORD unwindCodeBytesSpecified = offsetof(UNWIND_INFO, UnwindCode) + pUnwindInfo->CountOfUnwindCodes * sizeof(UNWIND_CODE); // This is what the unwind codes themselves say; it better match what we tell the VM. assert(unwindCodeBytes == unwindCodeBytesSpecified); #endif // DEBUG pUnwindBlock = &func->unwindCodes[func->unwindCodeSlot]; } else { assert(fgFirstColdBlock != nullptr); assert(func->funKind == FUNC_ROOT); // No splitting of funclets. if (func->coldStartLoc == nullptr) { startOffset = 0; } else { startOffset = func->coldStartLoc->CodeOffset(genEmitter); } if (func->coldEndLoc == nullptr) { endOffset = info.compNativeCodeSize; } else { endOffset = func->coldEndLoc->CodeOffset(genEmitter); } unwindCodeBytes = 0; // The VM handles creating chained unwind info, and requires this to be zero. pUnwindBlock = nullptr; } #ifdef DEBUG if (opts.dspUnwind) { DumpUnwindInfo(isHotCode, startOffset, endOffset, (const UNWIND_INFO * const)pUnwindBlock); } #endif // DEBUG // Adjust for cold or hot code: // 1. The VM doesn't want the cold code pointer unless this is cold code. // 2. The startOffset and endOffset need to be from the base of the hot section for hot code // and from the base of the cold section for cold code if (isHotCode) { assert(endOffset <= info.compTotalHotCodeSize); pColdCode = nullptr; } else { assert(startOffset >= info.compTotalHotCodeSize); startOffset -= info.compTotalHotCodeSize; endOffset -= info.compTotalHotCodeSize; } eeAllocUnwindInfo((BYTE*)pHotCode, (BYTE*)pColdCode, startOffset, endOffset, unwindCodeBytes, pUnwindBlock, (CorJitFuncKind)func->funKind); }
void Compiler::unwindEmitFuncCFI(FuncInfoDsc* func, void* pHotCode, void* pColdCode) { UNATIVE_OFFSET startOffset; UNATIVE_OFFSET endOffset; DWORD unwindCodeBytes = 0; BYTE* pUnwindBlock = nullptr; if (func->startLoc == nullptr) { startOffset = 0; } else { startOffset = func->startLoc->CodeOffset(genEmitter); } if (func->endLoc == nullptr) { endOffset = info.compNativeCodeSize; } else { endOffset = func->endLoc->CodeOffset(genEmitter); } DWORD size = (DWORD)func->cfiCodes->size(); if (size > 0) { unwindCodeBytes = size * sizeof(CFI_CODE); pUnwindBlock = (BYTE*)&(*func->cfiCodes)[0]; } #ifdef DEBUG if (opts.dspUnwind) { DumpCfiInfo(true /*isHotCode*/, startOffset, endOffset, unwindCodeBytes, (const CFI_CODE* const)pUnwindBlock); } #endif // DEBUG assert(endOffset <= info.compTotalHotCodeSize); eeAllocUnwindInfo((BYTE*)pHotCode, nullptr /* pColdCode */, startOffset, endOffset, unwindCodeBytes, pUnwindBlock, (CorJitFuncKind)func->funKind); if (pColdCode != nullptr) { assert(fgFirstColdBlock != nullptr); assert(func->funKind == FUNC_ROOT); // No splitting of funclets. unwindCodeBytes = 0; pUnwindBlock = nullptr; if (func->coldStartLoc == nullptr) { startOffset = 0; } else { startOffset = func->coldStartLoc->CodeOffset(genEmitter); } if (func->coldEndLoc == nullptr) { endOffset = info.compNativeCodeSize; } else { endOffset = func->coldEndLoc->CodeOffset(genEmitter); } #ifdef DEBUG if (opts.dspUnwind) { DumpCfiInfo(false /*isHotCode*/, startOffset, endOffset, unwindCodeBytes, (const CFI_CODE* const)pUnwindBlock); } #endif // DEBUG assert(startOffset >= info.compTotalHotCodeSize); startOffset -= info.compTotalHotCodeSize; endOffset -= info.compTotalHotCodeSize; eeAllocUnwindInfo((BYTE*)pHotCode, (BYTE*)pColdCode, startOffset, endOffset, unwindCodeBytes, pUnwindBlock, (CorJitFuncKind)func->funKind); } }