1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
9 // Everything directly related to zapping of native code
12 // - All XXX infos: GC Info, EH Info, Unwind Info, ...
14 // ======================================================================================
20 #include "zapimport.h"
22 #include "zapinnerptr.h"
24 #ifdef FEATURE_READYTORUN_COMPILER
25 #include "zapreadytorun.h"
29 #include "rhcodeinfo.h"
31 #include "modulegcinfoencoder.h"
35 // The image layout algorithm
38 ZapVirtualSection * ZapImage::GetCodeSection(CodeType codeType)
43 return m_pHotCodeSection;
45 return m_pColdCodeSection;
47 return m_pCodeSection;
53 #if defined(WIN64EXCEPTIONS)
54 ZapVirtualSection * ZapImage::GetUnwindDataSection(CodeType codeType)
57 return m_pUnwindDataSection;
62 return m_pHotUnwindDataSection;
64 return m_pColdUnwindDataSection;
66 return m_pUnwindDataSection;
72 #endif // defined(WIN64EXCEPTIONS)
74 ZapVirtualSection * ZapImage::GetRuntimeFunctionSection(CodeType codeType)
79 return m_pHotRuntimeFunctionSection;
81 return m_pColdRuntimeFunctionSection;
83 return m_pRuntimeFunctionSection;
89 ZapVirtualSection * ZapImage::GetCodeMethodDescSection(CodeType codeType)
94 return m_pHotCodeMethodDescsSection;
96 return m_pCodeMethodDescsSection;
102 ZapVirtualSection* ZapImage::GetUnwindInfoLookupSection(CodeType codeType)
107 return m_pHotRuntimeFunctionLookupSection;
109 return m_pRuntimeFunctionLookupSection;
115 void ZapImage::GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end)
117 _ASSERTE(start && end);
121 *end = m_MethodCompilationOrder.GetCount();
127 *end = m_iUntrainedMethod;
131 *end = m_MethodCompilationOrder.GetCount();
134 *start = m_iUntrainedMethod;
135 *end = m_MethodCompilationOrder.GetCount();
141 void ZapImage::OutputCode(CodeType codeType)
143 // Note there are three codeTypes: ProfiledHot, Unprofiled and ProfiledCold
145 SectionMethodListGenerator map;
148 bool fCold = (codeType == ProfiledCold);
149 CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD;
150 BeginRegion(regionKind);
152 ZapVirtualSection * pCodeSection = GetCodeSection(codeType);
153 ZapVirtualSection * pRuntimeFunctionSection = GetRuntimeFunctionSection(codeType);
155 #if defined (WIN64EXCEPTIONS)
156 ZapVirtualSection * pUnwindDataSection = GetUnwindDataSection(codeType);
157 #endif // defined (WIN64EXCEPTIONS)
161 // We should start with empty code section
162 _ASSERTE(pRuntimeFunctionSection->GetNodeCount() == 0);
163 _ASSERTE(pCodeSection->GetNodeCount() == 0);
165 COUNT_T startMethod, endMethod;
166 #ifdef REDHAWK // TritonTBD
167 DWORD currentOffset = 0;
170 GetCodeCompilationRange(codeType, &startMethod, &endMethod);
172 DWORD dwStartMethodIndex = (codeType == Unprofiled) ? m_pHotRuntimeFunctionSection->GetNodeCount() : 0;
174 for (COUNT_T curMethod = startMethod; curMethod < endMethod; curMethod++)
176 ZapMethodHeader * pMethod = m_MethodCompilationOrder[curMethod];
178 ZapBlobWithRelocs * pCode = fCold ? pMethod->m_pColdCode : pMethod->m_pCode;
186 pMethod->m_methodIndex = dwStartMethodIndex + pRuntimeFunctionSection->GetNodeCount();
190 pMethod->m_methodIndex = (DWORD)-1;
193 //Count the method size for use by ZapUnwindInfoLookupTable
194 codeSize = AlignUp(codeSize, pCode->GetAlignment());
195 codeSize += pCode->GetSize();
197 pCodeSection->Place(pCode);
200 DWORD codeOffset = AlignUp(currentOffset, pCode->GetAlignment());
201 codeOffset = map.AlignToMethodStartGranularity(codeOffset);
202 map.NoticeMethod(codeOffset, pCode->GetSize());
203 currentOffset = codeOffset + pCode->GetSize();
206 ZapReloc * pRelocs = pCode->GetRelocs();
209 for (ZapReloc * pReloc = pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++)
211 ZapNode * pTarget = pReloc->m_pTargetNode;
213 ZapNodeType type = pTarget->GetType();
214 if (type == ZapNodeType_InnerPtr)
216 pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
217 type = pTarget->GetType();
222 case ZapNodeType_StubDispatchCell:
223 // Optimizations may create redundant references to the StubDispatchCell
224 if (!pTarget->IsPlaced())
226 m_pStubDispatchDataTable->PlaceStubDispatchCell((ZapImport *)pTarget);
229 case ZapNodeType_MethodEntryPoint:
230 pTarget = m_pMethodEntryPoints->CanDirectCall((ZapMethodEntryPoint *)pTarget, pMethod);
233 pReloc->m_pTargetNode = pTarget;
236 case ZapNodeType_Stub:
237 if (!pTarget->IsPlaced())
239 m_pStubsSection->Place(pTarget);
242 case ZapNodeType_HelperThunk:
243 if (!pTarget->IsPlaced())
245 // This should place the most frequently used JIT helpers first and together
246 m_pHelperTableSection->Place(pTarget);
249 case ZapNodeType_LazyHelperThunk:
250 if (!pTarget->IsPlaced())
252 ((ZapLazyHelperThunk *)pTarget)->Place(this);
255 case ZapNodeType_Import_ModuleHandle:
256 case ZapNodeType_Import_ClassHandle:
257 case ZapNodeType_Import_StringHandle:
258 case ZapNodeType_Import_Helper:
259 // Place all potentially eager imports
260 if (!pTarget->IsPlaced())
261 m_pImportTable->PlaceImport((ZapImport *)pTarget);
264 case ZapNodeType_ExternalMethodThunk:
265 if (!pTarget->IsPlaced())
266 m_pExternalMethodDataTable->PlaceExternalMethodThunk((ZapImport *)pTarget);
269 case ZapNodeType_ExternalMethodCell:
270 if (!pTarget->IsPlaced())
271 m_pExternalMethodDataTable->PlaceExternalMethodCell((ZapImport *)pTarget);
274 #ifdef FEATURE_READYTORUN_COMPILER
275 case ZapNodeType_DynamicHelperCell:
276 if (!pTarget->IsPlaced())
277 m_pDynamicHelperDataTable->PlaceDynamicHelperCell((ZapImport *)pTarget);
280 case ZapNodeType_IndirectHelperThunk:
281 if (!pTarget->IsPlaced())
282 m_pImportTable->PlaceIndirectHelperThunk(pTarget);
285 case ZapNodeType_RVAFieldData:
286 if (!pTarget->IsPlaced())
287 m_pReadOnlyDataSection->Place(pTarget);
291 case ZapNodeType_GenericSignature:
292 if (!pTarget->IsPlaced())
293 m_pImportTable->PlaceBlob((ZapBlob *)pTarget);
301 #if defined (WIN64EXCEPTIONS)
306 InlineSArray<ZapUnwindInfo *, 8> unwindInfos;
308 ZapUnwindInfo * pFragment;
310 // Go over all fragments and append their unwind infos in this section
311 for (pFragment = pMethod->m_pUnwindInfoFragments;
313 pFragment = pFragment->GetNextFragment())
315 ZapNode * pFragmentCode = pFragment->GetCode();
316 _ASSERTE(pFragmentCode == pMethod->m_pCode || pFragmentCode == pMethod->m_pColdCode);
318 if (pFragmentCode == pCode)
320 unwindInfos.Append(pFragment);
324 // The runtime function section must be ordered correctly relative to code layout
325 // in the image. Sort the unwind infos by their offset
326 _ASSERTE(unwindInfos.GetCount() > 0);
327 qsort(&unwindInfos[0], unwindInfos.GetCount(), sizeof(ZapUnwindInfo *), ZapUnwindInfo::CompareUnwindInfo);
329 // Set the initial unwind info for the hot and cold sections
332 _ASSERTE(pMethod->m_pColdUnwindInfo == NULL);
333 pMethod->m_pColdUnwindInfo = unwindInfos[0];
337 _ASSERTE(pMethod->m_pUnwindInfo == NULL);
338 pMethod->m_pUnwindInfo = unwindInfos[0];
341 for (COUNT_T iUnwindInfo = 0; iUnwindInfo < unwindInfos.GetCount(); iUnwindInfo++)
343 ZapUnwindInfo * pUnwindInfo = unwindInfos[iUnwindInfo];
344 pRuntimeFunctionSection->Place(pUnwindInfo);
346 ZapNode * pUnwindData = pUnwindInfo->GetUnwindData();
348 if (!pUnwindData->IsPlaced())
350 pUnwindDataSection->Place(pUnwindData);
354 #else // defined (WIN64EXCEPTIONS)
356 ZapUnwindInfo * pUnwindInfo;
359 // Chained unwind info
360 pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pUnwindInfo);
361 pMethod->m_pColdUnwindInfo = pUnwindInfo;
365 pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pGCInfo);
366 pMethod->m_pUnwindInfo = pUnwindInfo;
368 pRuntimeFunctionSection->Place(pUnwindInfo);
370 #endif // defined (WIN64EXCEPTIONS)
374 CorInfoIndirectCallReason reason;
375 BOOL direct = m_pPreloader->CanSkipMethodPreparation(NULL, pMethod->GetHandle(), &reason);
377 if (direct && pMethod->m_pFixupList != NULL)
379 reason = CORINFO_INDIRECT_CALL_FIXUPS;
385 m_stats->m_directMethods++;
389 m_stats->m_prestubMethods++;
390 m_stats->m_indirectMethodReasons[reason]++;
396 // Redhawk needs any trailing padding to be 0xcc
397 DWORD cbPad = AlignUp(currentOffset, sizeof(DWORD)) - currentOffset;
400 ZapBlob * pBlob = ZapBlob::NewBlob(this, NULL, cbPad);
401 memset(pBlob->GetData(), DEFAULT_CODE_BUFFER_INIT, cbPad);
402 pCodeSection->Place(pBlob);
403 currentOffset += cbPad;
406 map.Output(this, m_pCodeMgrSection, numMethods);
408 COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount();
410 if (nUnwindInfos != 0)
412 if (IsReadyToRunCompilation())
419 ZapVirtualSection * pCodeMethodDescSection = GetCodeMethodDescSection(codeType);
420 pCodeMethodDescSection->Place(new (GetHeap()) ZapCodeMethodDescs(startMethod, endMethod, nUnwindInfos));
422 ZapVirtualSection* pUnwindInfoLookupSection = GetUnwindInfoLookupSection(codeType);
423 pUnwindInfoLookupSection->Place(new (GetHeap()) ZapUnwindInfoLookupTable(pRuntimeFunctionSection, pCodeSection, codeSize));
427 m_pColdCodeMapSection->Place(new (GetHeap()) ZapColdCodeMap(pRuntimeFunctionSection));
432 EndRegion(regionKind);
435 void ZapImage::OutputCodeInfo(CodeType codeType)
437 CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD;
438 BeginRegion(regionKind);
440 for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
442 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
445 // We are either outputing the ProfiledHot methods
446 // or the unprofiled and cold methods
448 if ((pMethod->m_ProfilingDataFlags & (1 << ReadMethodCode)) != (codeType == ProfiledHot))
450 // Wrong kind so skip
454 if (pMethod->m_pROData != NULL)
455 m_pReadOnlyDataSection->Place(pMethod->m_pROData);
458 // Note: for Redhawk we place EH info via OutputEHInfo().
459 if (pMethod->m_pExceptionInfo != NULL)
461 ZapNode* pCode = pMethod->m_pCode;
462 m_pExceptionInfoLookupTable->PlaceExceptionInfoEntry(pCode, pMethod->m_pExceptionInfo);
466 if (pMethod->m_pFixupList != NULL && !IsReadyToRunCompilation())
467 pMethod->m_pFixupInfo = m_pImportTable->PlaceFixups(pMethod->m_pFixupList);
470 EndRegion(regionKind);
473 void ZapImage::OutputProfileData()
475 if (m_pInstrumentSection == NULL)
480 ZapProfileData * pPrevious = NULL;
482 for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
484 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
486 if (pMethod->m_pProfileData == NULL)
491 ZapProfileData * pHeader = new (GetHeap()) ZapProfileData(pMethod);
493 m_pInstrumentSection->Place(pHeader);
494 m_pInstrumentSection->Place(pMethod->m_pProfileData);
496 if (pPrevious != NULL)
498 pPrevious->SetNext(pHeader);
505 void ZapImage::OutputDebugInfo()
507 m_pDebugInfoTable->PrepareLayout();
508 for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
510 m_pDebugInfoTable->PlaceDebugInfo(m_MethodCompilationOrder[i]);
512 m_pDebugInfoTable->FinishLayout();
515 void ZapImage::OutputGCInfo()
524 static const MaskValue gcInfoSequence[] =
526 { (1 << CommonReadGCInfo) , (1 << CommonReadGCInfo) }, // c flag on, r flag don't care
527 { (1 << CommonReadGCInfo)|(1 << ReadGCInfo), (1 << ReadGCInfo) }, // r flag on, c flag off
528 { (1 << CommonReadGCInfo)|(1 << ReadGCInfo), 0 }, // both flags off
532 // Make three passes over the gc infos, emitting them in order of decreasing hotness,
533 // and for stuff that wasn't touched by anyone we put it in the cold section
534 for (const MaskValue *pMaskValue = gcInfoSequence; pMaskValue->mask; pMaskValue++)
536 for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
538 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
540 if ((pMethod->m_ProfilingDataFlags & pMaskValue->mask) != pMaskValue->value)
545 ZapGCInfo * pGCInfo = pMethod->m_pGCInfo;
547 // Given that GC Info can be interned it may have been placed already on
548 // this or a previous pass through the compiled methods. If it hasn't already
549 // been placed then we place it in the appropriate section.
550 if (!pGCInfo->IsPlaced())
552 // A) it was touched, and here they are placed in order of flags above
553 if (pMaskValue->value)
555 m_pHotTouchedGCSection->Place(pGCInfo);
557 // B) the method that it is attached to is in the trained section
558 else if (i<m_iUntrainedMethod)
560 m_pHotGCSection->Place(pGCInfo);
562 // C) it wasn't touched _and_ it is related to untrained code
565 m_pGCSection->Place(pGCInfo);
570 // Just after placing those touched in an IBC scenario, place those that
571 // should be prioritized regardless of the corresponding method's IBC information.
572 // (Currently, this is used to pack the gc info of IL stubs that cannot be directly tracked by IBC.)
573 if (pMaskValue->value == (1 << ReadGCInfo))
575 for (COUNT_T i = 0; i < m_PrioritizedGCInfo.GetCount(); i++)
577 ZapGCInfo * pGCInfo = m_PrioritizedGCInfo[i];
578 if (!pGCInfo->IsPlaced())
580 m_pHotGCSection->Place(pGCInfo);
587 ModuleGcInfoEncoder * pEncoder = GetGcInfoEncoder();
589 m_pUnwindInfoBlob = pEncoder->ConstructUnwindInfoBlob(this);
590 m_pCallsiteInfoBlob = pEncoder->ConstructCallsiteInfoBlob(this);
591 ZapBlob * pShortcutMap = pEncoder->ConstructDeltaShortcutMap(this);
593 // @TODO: we could fold this loop into ConstructMethodInfoBlob, but then we'd have to keep a separate
594 // list of method infos inside the ModuleGcInfoEncoder..
595 for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
597 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
598 pEncoder->EncodeMethodInfo(pMethod->m_pGCInfo);
600 ZapBlob * pMethodInfos = pEncoder->ConstructMethodInfoBlob(this);
602 for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
604 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
605 // At this point pMethod->m_pGCInfo is really a pointer that the encoder owns.
606 // We must pass it back to the encoder so it can encode it and pass back a proper ZapBlob *
607 pMethod->m_pGCInfo = pEncoder->FindMethodInfo(this, pMethod->m_pGCInfo);
610 m_pGCSection->Place(pShortcutMap);
611 m_pGCSection->Place(pMethodInfos);
612 if (m_pUnwindInfoBlob)
613 m_pGCSection->Place(m_pUnwindInfoBlob);
615 if (m_pCallsiteInfoBlob)
616 m_pGCSection->Place(m_pCallsiteInfoBlob);
619 // Create the method-number-to-gc-info table
621 UINT32 methodInfoSize = pMethodInfos->GetSize();
623 COUNT_T nMethods = m_MethodCompilationOrder.GetCount();
626 if (methodInfoSize <= 0x10000)
630 // Remember the element size for this map in the module header
631 m_moduleHeaderFlags |= ModuleHeader::SmallGCInfoListEntriesFlag;
635 SIZE_T tableSize = elemSize * nMethods;
636 ZapBlob * pMethodToGcInfoMap = ZapBlob::NewBlob(this, NULL, tableSize);
638 UINT16* pwTableEntries = (UINT16*) pMethodToGcInfoMap->GetData();
639 UINT32* pdwTableEntries = (UINT32*) pwTableEntries;
641 for (COUNT_T i = 0; i < nMethods; i++)
643 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
644 ZapGCInfo * pGCInfo = pMethod->m_pGCInfo;
647 if (pGCInfo->GetType() == ZapNodeType_InnerPtr)
649 uOffset = ((ZapInnerPtr*)pGCInfo)->GetOffset();
653 assert(ZapNodeType_Blob == pGCInfo->GetType());
654 assert(pGCInfo == pMethodInfos);
659 assert(uOffset <= 0xFFFF);
660 pwTableEntries[i] = uOffset;
664 pdwTableEntries[i] = uOffset;
668 m_pMethodToGCInfoMap->Place(pMethodToGcInfoMap);
673 // Place all ZapExceptionInfo blobs into the exception section, and form the lookup table that we'll
674 // use at runtime to find EH info for a given method.
675 void ZapImage::OutputEHInfo()
677 // For non-REDHAWK builds, we output EH info with the other per-method data in OutputCodeInfo().
679 // @TODO: consider emitting EH info in order of increasing hotness, like we do for GC info.
681 // Place EH info for every method that has EH.
682 for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
684 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
685 ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo;
687 if ((pEHInfo != NULL) && !pEHInfo->IsPlaced())
689 // We add relocs to the exception info here, at the last possible momement before placing
690 // them. That's because adding relocs changes the exception info, but prior to this we
691 // want to be able to use the data of the exception info as a hash key for interning.
692 AddRelocsForEHClauses(pEHInfo);
693 m_pExceptionSection->Place(pEHInfo);
697 // Get the offsets for each EH blob that we will emit.
698 MapSHash<ZapNode *, UINT32> ehinfoOffsets;
701 ehinfoSize = m_pExceptionSection->FillInNodeOffsetMap(&ehinfoOffsets);
703 // Chose a table entry size.
704 COUNT_T nMethods = m_MethodCompilationOrder.GetCount();
707 if (ehinfoSize <= 0x10000)
711 // Remember the element size for this map in the module header
712 m_moduleHeaderFlags |= ModuleHeader::SmallEHInfoListEntriesFlag;
716 SIZE_T tableSize = elemSize * nMethods;
717 SArray<BYTE> tableData(tableSize);
719 UINT16* pwTableEntries = (UINT16*)&tableData[0];
720 UINT32* pdwTableEntries = (UINT32*) pwTableEntries;
722 // Fill in the offset for each method that has EH info. For methods that have no
723 // EH info, we will use a sentinel offset of -1.
724 for (COUNT_T i = 0; i < nMethods; i++)
726 ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
727 ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo;
733 ehinfoOffsets.Lookup(pEHInfo, &uOffset);
734 assert(uOffset != -1); // Can't have a valid offset match the sentinel!
735 assert((4 == elemSize) || (uOffset <= 0xFFFF)); // Size must fit in 2 bytes if we're using hte small rep.
740 pwTableEntries[i] = uOffset;
744 pdwTableEntries[i] = uOffset;
748 m_pMethodToEHInfoMap->Place(ZapBlob::NewBlob(this, &tableData[0], tableSize));
753 // Add relocs for any EEType references in any typed EH clauses for the given EH Info.
754 void ZapImage::AddRelocsForEHClauses(ZapExceptionInfo * pExceptionInfo)
756 EE_ILEXCEPTION *pEHInfo = (EE_ILEXCEPTION *)pExceptionInfo->GetData();
757 _ASSERTE(pEHInfo != NULL);
759 // One set of relocs for the entire set of clauses. Size assuming that every clause has a token.
760 ZapReloc * pRelocs = (ZapReloc *)
761 new (GetHeap()) BYTE[sizeof(ZapReloc) * pEHInfo->EHCount() + sizeof(ZapRelocationType)];
763 DWORD relocIndex = 0;
765 // Add relocs for EEType references each typed clause.
766 for (int i = 0; i < pEHInfo->EHCount(); i++)
768 EE_ILEXCEPTION_CLAUSE *pClause = pEHInfo->EHClause(i);
770 if ((pClause->Flags == COR_ILEXCEPTION_CLAUSE_NONE) ||
771 (pClause->Flags == COR_ILEXCEPTION_CLAUSE_INDIRECT_TYPE_REFERENCE))
773 ZapNode *pEETypeNode = (ZapNode*)pClause->EETypeReference;
775 // @TODO: we're using a full pointer for each EEType reference in the EH clause. This will be
776 // 64bits on a 64bit system, though, which is twice as large as it needs to be. We should make
777 // these 32bit RVA's and compute the final address at runtime when we start supporting 64bit
778 // systems. See comments in ZapInfo::setEHinfo() for more details.
780 // N.B! If we move to RVAs, then the runtime structure that matches the EE_ILEXCEPTION struct
781 // needs to have a padding field removed. (The C++ compiler introduced 4 bytes of padding between
782 // 'DataSize' and 'Clauses' because 'Clauses' has a pointer field in it. This padding will
783 // disappear when we change the pointers to RVAs.)
784 pRelocs[relocIndex].m_type = IMAGE_REL_BASED_PTR;
785 pRelocs[relocIndex].m_pTargetNode = pEETypeNode;
786 pRelocs[relocIndex].m_offset = (BYTE*)pClause - (BYTE*)pEHInfo + offsetof(EE_ILEXCEPTION_CLAUSE, EETypeReference);
787 pExceptionInfo->ZeroPointer(pRelocs[relocIndex].m_offset);
792 // Did we end up with any relocs? If so, then add them to the blob.
796 C_ASSERT(offsetof(ZapReloc, m_type) == 0);
797 pRelocs[relocIndex].m_type = IMAGE_REL_INVALID;
799 pExceptionInfo->SetRelocs(pRelocs);
808 #if defined(_TARGET_X86_)
810 DWORD ZapCodeBlob::ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos)
812 void * pData = GetData();
813 SIZE_T size = GetSize();
814 DWORD dwAlignment = GetAlignment();
816 dwPos = AlignUp(dwPos, dwAlignment);
820 // Padding for straddler relocations.
823 // The maximum size of padding
824 const DWORD cbAdjustForDynamicBaseMax = 256;
826 // Find padding that gives us minimum number of straddlers
827 DWORD nMinStraddlers = MAXDWORD;
829 for (DWORD pad = 0; pad < cbAdjustForDynamicBaseMax; pad += dwAlignment)
831 COUNT_T nStraddlers = GetCountOfStraddlerRelocations(dwPos + pad);
832 if (nStraddlers < nMinStraddlers)
834 nMinStraddlers = nStraddlers;
837 // It won't get better than this.
838 if (nMinStraddlers == 0)
843 DWORD dwPaddedPos = dwPos + bestPad;
846 return dwPaddedPos + size;
847 #endif // _TARGET_X86_
850 template <DWORD alignment>
851 class ZapCodeBlobConst : public ZapCodeBlob
854 ZapCodeBlobConst(SIZE_T cbSize)
855 : ZapCodeBlob(cbSize)
860 virtual UINT GetAlignment()
865 static ZapCodeBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize)
867 S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapCodeBlobConst<alignment>)) + S_SIZE_T(cbSize);
868 if(cbAllocSize.IsOverflow())
869 ThrowHR(COR_E_OVERFLOW);
871 void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()];
873 ZapCodeBlob * pZapCodeBlob = new (pMemory) ZapCodeBlobConst<alignment>(cbSize);
876 memcpy((void*)(pZapCodeBlob + 1), pData, cbSize);
882 ZapCodeBlob * ZapCodeBlob::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment)
887 return ZapCodeBlobConst<1>::NewBlob(pWriter, pData, cbSize);
889 return ZapCodeBlobConst<2>::NewBlob(pWriter, pData, cbSize);
891 return ZapCodeBlobConst<4>::NewBlob(pWriter, pData, cbSize);
893 return ZapCodeBlobConst<8>::NewBlob(pWriter, pData, cbSize);
895 return ZapCodeBlobConst<16>::NewBlob(pWriter, pData, cbSize);
898 _ASSERTE(!"Requested alignment not supported");
906 // See function prototype for details on why this iterator is "partial"
907 BOOL ZapMethodHeader::PartialTargetMethodIterator::GetNext(CORINFO_METHOD_HANDLE *pHnd)
909 _ASSERTE(pHnd != NULL);
911 if (m_pCurReloc == NULL)
916 while (m_pCurReloc->m_type != IMAGE_REL_INVALID)
918 ZapNode * pTarget = m_pCurReloc->m_pTargetNode;
919 ZapNodeType type = pTarget->GetType();
923 if (type == ZapNodeType_InnerPtr)
925 pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
926 type = pTarget->GetType();
929 if (type == ZapNodeType_MethodEntryPoint)
931 *pHnd = ((ZapMethodEntryPoint *)pTarget)->GetHandle();
939 void ZapCodeMethodDescs::Save(ZapWriter * pZapWriter)
941 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
943 COUNT_T nUnwindInfos = 0;
945 for (COUNT_T curMethod = m_iStartMethod; curMethod < m_iEndMethod; curMethod++)
947 ZapMethodHeader * pMethod = pImage->m_MethodCompilationOrder[curMethod];
948 DWORD dwRVA = pImage->m_pPreloader->MapMethodHandle(pMethod->GetHandle());
950 if (pMethod->m_pExceptionInfo != NULL)
951 dwRVA |= HAS_EXCEPTION_INFO_MASK;
953 pImage->Write(&dwRVA, sizeof(dwRVA));
956 #ifdef WIN64EXCEPTIONS
957 ZapUnwindInfo * pFragment = pMethod->m_pUnwindInfoFragments;
958 while (pFragment != NULL)
960 if (pFragment != pMethod->m_pUnwindInfo && pFragment->GetCode() == pMethod->m_pCode)
963 pImage->Write(&dwRVA, sizeof(dwRVA));
967 pFragment = pFragment->GetNextFragment();
971 _ASSERTE(nUnwindInfos == m_nUnwindInfos);
975 // ZapMethodEntryPoint
978 void ZapMethodEntryPoint::Resolve(ZapImage * pImage)
980 DWORD rvaValue = pImage->m_pPreloader->MapMethodEntryPoint(GetHandle());
982 if (rvaValue == NULL)
985 pImage->GetCompileInfo()->GetMethodDef(GetHandle(), &token);
986 pImage->Error(token, S_OK, 0, W("MapMethodEntryPoint failed"));
995 ZapMethodEntryPoint * ZapMethodEntryPointTable::GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags)
997 ZapMethodEntryPoint * pMethodEntryPoint = m_entries.Lookup(MethodEntryPointKey(handle, accessFlags));
999 if (pMethodEntryPoint != NULL)
1000 return pMethodEntryPoint;
1004 m_pImage->GetCompileInfo()->GetMethodDef(handle, &token);
1007 pMethodEntryPoint = new (m_pImage->GetHeap()) ZapMethodEntryPoint(handle, accessFlags);
1008 m_entries.Add(pMethodEntryPoint);
1009 return pMethodEntryPoint;
1012 void ZapMethodEntryPointTable::Resolve()
1014 for (MethodEntryPointTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
1016 ZapMethodEntryPoint * pMethodEntryPoint = *i;
1018 // Skip unused entrypoints - they may be omitted in the image
1019 if (!pMethodEntryPoint->IsUsed())
1022 pMethodEntryPoint->Resolve(m_pImage);
1026 ZapNode * ZapMethodEntryPointTable::CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller)
1028 CORINFO_METHOD_HANDLE caller = pCaller->GetHandle();
1029 CORINFO_METHOD_HANDLE callee = pMethodEntryPoint->GetHandle();
1031 CorInfoIndirectCallReason reason;
1032 if (m_pImage->canIntraModuleDirectCall(caller, callee, &reason, pMethodEntryPoint->GetAccessFlags()))
1034 ZapNode * pCode = m_pImage->GetCompiledMethod(callee)->GetCode();
1036 pCode = m_pImage->GetInnerPtr(pCode, THUMB_CODE);
1037 #endif // _TARGET_ARM_
1042 if (!pMethodEntryPoint->IsUsed())
1044 // This method entry point is going to be used for indirect call.
1045 // Record this so that later we will assign it an RVA.
1046 pMethodEntryPoint->SetIsUsed();
1052 #ifdef WIN64EXCEPTIONS
1053 ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo)
1055 ZapGCInfo * pNode = m_blobs.Lookup(GCInfoKey(pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo));
1062 pNode = ZapGCInfo::NewGCInfo(m_pImage, pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo);
1067 ZapGCInfo * ZapGCInfo::NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo)
1069 S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapGCInfo)) + S_SIZE_T(cbGCInfo) + S_SIZE_T(cbUnwindInfo);
1070 if(cbAllocSize.IsOverflow())
1071 ThrowHR(COR_E_OVERFLOW);
1073 void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()];
1075 ZapGCInfo * pZapGCInfo = new (pMemory) ZapGCInfo(cbGCInfo, cbUnwindInfo);
1077 memcpy(pZapGCInfo->GetGCInfo(), pGCInfo, cbGCInfo);
1078 memcpy(pZapGCInfo->GetUnwindInfo(), pUnwindInfo, cbUnwindInfo);
1080 #if !defined(_TARGET_X86_)
1081 // Make sure the personality routine thunk is created
1082 pZapGCInfo->GetPersonalityRoutine(ZapImage::GetImage(pWriter));
1083 #endif // !defined(_TARGET_X86_)
1087 ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pBlob, SIZE_T cbBlob)
1089 ZapGCInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob));
1096 pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob);
1106 void ZapUnwindInfo::Save(ZapWriter * pZapWriter)
1108 T_RUNTIME_FUNCTION runtimeFunction;
1110 #if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
1111 RUNTIME_FUNCTION__SetBeginAddress(&runtimeFunction, GetStartAddress());
1112 runtimeFunction.UnwindData = m_pUnwindData->GetRVA();
1113 #elif defined(_TARGET_AMD64_)
1114 runtimeFunction.BeginAddress = GetStartAddress();
1115 runtimeFunction.EndAddress = GetEndAddress();
1116 ULONG unwindData = m_pUnwindData->GetRVA();
1117 if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info
1118 unwindData |= RUNTIME_FUNCTION_INDIRECT;
1119 runtimeFunction.UnwindData = unwindData;
1120 #elif defined(_TARGET_X86_)
1121 runtimeFunction.BeginAddress = GetStartAddress();
1122 ULONG unwindData = m_pUnwindData->GetRVA();
1123 if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info
1124 unwindData |= RUNTIME_FUNCTION_INDIRECT;
1125 runtimeFunction.UnwindData = unwindData;
1127 PORTABILITY_ASSERT("ZapUnwindInfo");
1130 pZapWriter->Write(&runtimeFunction, sizeof(runtimeFunction));
1133 #if defined(WIN64EXCEPTIONS)
1134 // Compare the unwind infos by their offset
1135 int __cdecl ZapUnwindInfo::CompareUnwindInfo(const void* a_, const void* b_)
1137 ZapUnwindInfo * a = *(ZapUnwindInfo **)a_;
1138 ZapUnwindInfo * b = *(ZapUnwindInfo **)b_;
1140 if (a->GetStartOffset() > b->GetStartOffset())
1142 _ASSERTE(a->GetStartOffset() >= b->GetEndOffset());
1146 if (a->GetStartOffset() < b->GetStartOffset())
1148 _ASSERTE(a->GetEndOffset() <= b->GetEndOffset());
1156 #if defined(_TARGET_AMD64_)
1158 UINT ZapUnwindData::GetAlignment()
1160 return sizeof(ULONG);
1163 DWORD ZapUnwindData::GetSize()
1165 DWORD dwSize = ZapBlob::GetSize();
1168 // Add space for personality routine, it must be 4-byte aligned.
1169 // Everything in the UNWIND_INFO has already had its size included in size
1170 dwSize = AlignUp(dwSize, sizeof(ULONG));
1172 dwSize += sizeof(ULONG);
1178 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1180 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1182 PVOID pData = GetData();
1183 DWORD dwSize = GetBlobSize();
1185 UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData;
1187 // Check whether the size is what we expect it to be
1188 _ASSERTE(dwSize == offsetof(UNWIND_INFO, UnwindCode) + pUnwindInfo->CountOfUnwindCodes * sizeof(UNWIND_CODE));
1190 pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER;
1193 pZapWriter->Write(pData, dwSize);
1196 DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD));
1198 pZapWriter->WritePad(dwPad);
1200 ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA();
1201 pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine));
1205 #elif defined(_TARGET_X86_)
1207 UINT ZapUnwindData::GetAlignment()
1209 return sizeof(BYTE);
1212 DWORD ZapUnwindData::GetSize()
1214 return ZapBlob::GetSize();
1217 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1219 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1221 PVOID pData = GetData();
1222 DWORD dwSize = GetBlobSize();
1224 pZapWriter->Write(pData, dwSize);
1227 #elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
1229 UINT ZapUnwindData::GetAlignment()
1231 return sizeof(ULONG);
1234 DWORD ZapUnwindData::GetSize()
1236 DWORD dwSize = ZapBlob::GetSize();
1238 // Add space for personality routine, it must be 4-byte aligned.
1239 // Everything in the UNWIND_INFO has already had its size included in size
1240 dwSize = AlignUp(dwSize, sizeof(ULONG));
1241 dwSize += sizeof(ULONG);
1246 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1248 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1250 PVOID pData = GetData();
1251 DWORD dwSize = GetBlobSize();
1253 UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData;
1255 // Set the 'X' bit to indicate that there is a personality routine associated with this method
1256 *(LONG *)pUnwindInfo |= (1<<20);
1258 pZapWriter->Write(pData, dwSize);
1260 DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD));
1262 pZapWriter->WritePad(dwPad);
1264 ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA();
1265 pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine));
1269 UINT ZapUnwindData::GetAlignment()
1271 PORTABILITY_ASSERT("ZapUnwindData::GetAlignment");
1272 return sizeof(ULONG);
1274 DWORD ZapUnwindData::GetSize()
1276 PORTABILITY_ASSERT("ZapUnwindData::GetSize");
1279 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1281 PORTABILITY_ASSERT("ZapUnwindData::Save");
1286 ZapNode * ZapUnwindData::GetPersonalityRoutine(ZapImage * pImage)
1288 // Use different personality routine pointer for filter funclets so that we can quickly tell at runtime
1289 // whether funclet is a filter.
1290 #ifdef FEATURE_READYTORUN_COMPILER
1291 if (IsReadyToRunCompilation())
1293 ReadyToRunHelper helperNum = IsFilterFunclet() ? READYTORUN_HELPER_PersonalityRoutineFilterFunclet : READYTORUN_HELPER_PersonalityRoutine;
1294 return pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helperNum);
1297 return pImage->GetHelperThunk(IsFilterFunclet() ? CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET : CORINFO_HELP_EE_PERSONALITY_ROUTINE);
1300 ZapUnwindData * ZapUnwindData::NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet)
1302 SIZE_T cbAllocSize = sizeof(ZapUnwindData) + cbSize;
1304 void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize];
1306 ZapUnwindData * pZapUnwindData = fIsFilterFunclet ?
1307 (new (pMemory) ZapFilterFuncletUnwindData(cbSize)) : (new (pMemory) ZapUnwindData(cbSize));
1309 memcpy((void*)(pZapUnwindData + 1), pData, cbSize);
1311 #if !defined(_TARGET_X86_)
1312 // Make sure the personality routine thunk is created
1313 pZapUnwindData->GetPersonalityRoutine(ZapImage::GetImage(pWriter));
1314 #endif // !defined(_TARGET_X86_)
1316 return pZapUnwindData;
1319 ZapUnwindData * ZapUnwindDataTable::GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet)
1321 ZapUnwindData * pNode = (ZapUnwindData *)m_blobs.Lookup(ZapUnwindDataKey(pBlob, cbBlob, fIsFilterFunclet));
1328 pNode = ZapUnwindData::NewUnwindData(m_pImage, pBlob, cbBlob, fIsFilterFunclet);
1332 #endif // WIN64EXCEPTIONS
1338 ZapDebugInfo * ZapDebugInfoTable::GetDebugInfo(PVOID pBlob, SIZE_T cbBlob)
1340 ZapDebugInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob));
1348 pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob);
1353 void ZapDebugInfoTable::PrepareLayout()
1358 // Make sure that the number of methods is odd number
1361 m_pTable = new (m_pImage->GetHeap()) ZapNode * [m_nCount];
1364 void ZapDebugInfoTable::PlaceDebugInfo(ZapMethodHeader * pMethod)
1366 // Place the debug info blob if it is not placed yet
1367 ZapBlob * pDebugInfo = pMethod->GetDebugInfo();
1368 if (pDebugInfo == NULL)
1373 if (!pDebugInfo->IsPlaced())
1375 m_pImage->m_pDebugSection->Place(pDebugInfo);
1379 IfFailThrow(m_pImage->GetCompileInfo()->GetMethodDef(pMethod->GetHandle(), &md));
1381 COUNT_T index = GetDebugRidEntryHash(md) % m_nCount;
1383 ZapNode * pHead = m_pTable[index];
1386 // The common case - single rid entry.
1387 m_pTable[index] = pMethod;
1391 // Create linked list of labelled entries if we do not have one yet
1392 if (pHead->GetType() != ZapNodeType_DebugInfoLabelledEntry)
1394 m_pTable[index] = new (m_pImage->GetHeap()) LabelledEntry((ZapMethodHeader *)pHead);
1397 // Insert the method at the end of the linked list
1398 LabelledEntry * pEntry = (LabelledEntry *)m_pTable[index];
1399 while (pEntry->m_pNext != NULL)
1400 pEntry = pEntry->m_pNext;
1402 pEntry->m_pNext = new (m_pImage->GetHeap()) LabelledEntry(pMethod);
1405 void ZapDebugInfoTable::FinishLayout()
1407 // Go over the table again and place all labelled entries
1408 for (COUNT_T i = 0; i < m_nCount; i++)
1410 ZapNode * pNode = m_pTable[i];
1412 if (pNode == NULL || pNode->GetType() != ZapNodeType_DebugInfoLabelledEntry)
1415 LabelledEntry * pEntry = (LabelledEntry *)pNode;
1417 while (pEntry != NULL)
1419 m_pImage->m_pDebugSection->Place(pEntry);
1420 pEntry = pEntry->m_pNext;
1425 void ZapDebugInfoTable::Save(ZapWriter * pZapWriter)
1427 for (COUNT_T i = 0; i < m_nCount; i++)
1429 CORCOMPILE_DEBUG_ENTRY entry = 0;
1431 ZapNode * pNode = m_pTable[i];
1435 if (pNode->GetType() == ZapNodeType_DebugInfoLabelledEntry)
1436 entry |= pNode->GetRVA() | CORCOMPILE_DEBUG_MULTIPLE_ENTRIES;
1438 entry = ((ZapMethodHeader *)pNode)->GetDebugInfo()->GetRVA();
1441 pZapWriter->Write(&entry, sizeof(entry));
1445 void ZapDebugInfoTable::LabelledEntry::Save(ZapWriter * pZapWriter)
1447 CORCOMPILE_DEBUG_LABELLED_ENTRY entry;
1449 entry.nativeCodeRVA = m_pMethod->GetCode()->GetRVA();
1450 entry.debugInfoOffset = m_pMethod->GetDebugInfo()->GetRVA();
1452 if (m_pNext != NULL)
1453 entry.debugInfoOffset |= CORCOMPILE_DEBUG_MULTIPLE_ENTRIES;
1455 pZapWriter->Write(&entry, sizeof(entry));
1461 void ZapProfileData::Save(ZapWriter * pZapWriter)
1463 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1465 CORCOMPILE_METHOD_PROFILE_LIST profileData;
1467 ZeroMemory(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST));
1469 if (m_pNext != NULL)
1470 pImage->WriteReloc(&profileData,
1471 offsetof(CORCOMPILE_METHOD_PROFILE_LIST, next),
1472 m_pNext, 0, IMAGE_REL_BASED_PTR);
1474 pZapWriter->Write(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST));
1478 // Zapping of ExeptionInfoTable
1479 ZapExceptionInfoLookupTable::ZapExceptionInfoLookupTable(ZapImage *pImage) : m_pImage(pImage)
1481 _ASSERTE(m_pImage->m_pExceptionSection != NULL);
1482 m_pImage->m_pExceptionSection->Place(this);
1485 void ZapExceptionInfoLookupTable::PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo)
1487 ExceptionInfoEntry entry;
1488 entry.m_pCode = pCode;
1489 entry.m_pExceptionInfo = pExceptionInfo;
1490 m_exceptionInfoEntries.Append(entry);
1491 m_pImage->m_pExceptionSection->Place(pExceptionInfo);
1494 DWORD ZapExceptionInfoLookupTable::GetSize()
1496 if (m_exceptionInfoEntries.GetCount() == 0)
1499 DWORD numExceptionInfoEntries = m_exceptionInfoEntries.GetCount();
1500 // 1 sentential entry at the end of the table.
1501 return (numExceptionInfoEntries + 1) * sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY);
1504 void ZapExceptionInfoLookupTable::Save(ZapWriter* pZapWriter)
1507 if(m_exceptionInfoEntries.GetCount() == 0)
1510 for(COUNT_T i = 0; i < m_exceptionInfoEntries.GetCount(); ++i)
1512 DWORD methodStartRVA = m_exceptionInfoEntries[i].m_pCode->GetRVA();
1514 ZapExceptionInfo* pExceptionInfo = m_exceptionInfoEntries[i].m_pExceptionInfo;
1516 CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY lookupEntry;
1518 lookupEntry.MethodStartRVA = methodStartRVA;
1519 lookupEntry.ExceptionInfoRVA = pExceptionInfo->GetRVA();
1521 pZapWriter->Write(&lookupEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY));
1524 // Make sure there are no gaps between 2 consecutive CORCOMPILE_EXCEPTION_CLAUSE
1525 // We use pointer arithmatic to calculate the number of EHClause for a method.
1528 ZapExceptionInfo* pPreviousExceptionInfo = m_exceptionInfoEntries[i-1].m_pExceptionInfo;
1529 DWORD size = pExceptionInfo->GetRVA() - pPreviousExceptionInfo->GetRVA();
1530 DWORD ehClauseSize = size % sizeof(CORCOMPILE_EXCEPTION_CLAUSE);
1531 CONSISTENCY_CHECK_MSG(ehClauseSize == 0, "There must be no gaps between 2 successive clause arrays, please check ZapExceptionInfo alignment");
1536 // write a sentinal entry.. this entry helps to find the number of EHClauses for the last entry
1537 CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY sentinalEntry;
1539 ExceptionInfoEntry lastEntry = m_exceptionInfoEntries[m_exceptionInfoEntries.GetCount() -1];
1541 ZapExceptionInfo* pLastExceptionInfo = lastEntry.m_pExceptionInfo;
1543 sentinalEntry.MethodStartRVA = (DWORD)-1;
1545 // points just after the end of the Exception table
1546 // the sentinal node m_pExceptionInfo pointer actually points to an invalid CORCOMPILE_EXCEPTION_CLAUSE
1547 // area. The lookup algorithm will never dereference the sentinal pointer, and hence this is safe
1548 sentinalEntry.ExceptionInfoRVA = pLastExceptionInfo->GetRVA() + pLastExceptionInfo->GetSize();
1550 pZapWriter->Write(&sentinalEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY));
1554 DWORD ZapUnwindInfoLookupTable::GetSize()
1556 // Sentinal entry at the end
1557 return (GetNumEntries() + 1) * sizeof (DWORD);
1560 void ZapUnwindInfoLookupTable::Save(ZapWriter* pZapWriter)
1562 ZapVirtualSection * pRuntimeFunctionSection = m_pRuntimeFunctionSection;
1564 // Create Lookup entries.
1565 // 1 lookup entry for each RUNTIME_FUNCTION_LOOKUP_STRIDE K of code.
1566 COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount();
1568 DWORD dwCodeSectionStartAddress = m_pCodeSection->GetRVA();
1570 DWORD nLookupEntries = 0;
1573 DWORD nTotalLookupEntries = GetNumEntries();
1575 // write out the first entry
1577 pZapWriter->Write(&entry, sizeof(DWORD));
1579 if (nLookupEntries == nTotalLookupEntries)
1582 for (COUNT_T i = 1; i < nUnwindInfos; ++i)
1584 ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)pRuntimeFunctionSection->GetNode(i);
1585 DWORD RelativePC = pUnwindInfo->GetStartAddress() - dwCodeSectionStartAddress;
1587 COUNT_T iCurrentIndex = RelativePC / RUNTIME_FUNCTION_LOOKUP_STRIDE;
1589 // Note that we should not be using pUnwindInfo->GetEndAddress() here. The binary search
1590 // in the VM that's accelerated by this table does not look at the EndAddress either, and
1591 // so not using EndAddress here assures consistency.
1592 COUNT_T iPreviousIndex = (RelativePC - 1)/ RUNTIME_FUNCTION_LOOKUP_STRIDE;
1594 while(iPreviousIndex >= nLookupEntries)
1597 pZapWriter->Write(&entry, sizeof(DWORD));
1599 if (nLookupEntries == nTotalLookupEntries)
1603 if (iCurrentIndex == nLookupEntries)
1606 pZapWriter->Write(&entry, sizeof(DWORD));
1608 if (nLookupEntries == nTotalLookupEntries)
1614 // There should always be one sentinel entry at the end. The sentinel entry will
1615 // be good to cover the rest of the section to account for extra padding.
1616 _ASSERTE(nLookupEntries <= nTotalLookupEntries);
1618 while (nLookupEntries <= nTotalLookupEntries)
1620 entry = nUnwindInfos - 1;
1621 pZapWriter->Write(&entry, sizeof (DWORD));
1626 DWORD ZapColdCodeMap::GetSize()
1628 return m_pRuntimeFunctionSection->GetNodeCount() * sizeof(CORCOMPILE_COLD_METHOD_ENTRY);
1631 void ZapColdCodeMap::Save(ZapWriter* pZapWriter)
1633 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1635 ZapNode * pPendingCode = NULL;
1636 COUNT_T curMethod = 0;
1638 COUNT_T nUnwindInfos = m_pRuntimeFunctionSection->GetNodeCount();
1639 for (COUNT_T i = 0; i < nUnwindInfos; ++i)
1641 CORCOMPILE_COLD_METHOD_ENTRY entry;
1643 ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)m_pRuntimeFunctionSection->GetNode(i);
1645 #ifdef WIN64EXCEPTIONS
1646 if (pUnwindInfo->GetCode() == pPendingCode)
1648 entry.mainFunctionEntryRVA = 0;
1649 entry.hotCodeSize = 0;
1654 pPendingCode = pUnwindInfo->GetCode();
1656 ZapMethodHeader * pMethod;
1660 pMethod = pImage->m_MethodCompilationOrder[curMethod];
1661 if (pMethod->m_pColdCode == pPendingCode)
1666 #ifdef WIN64EXCEPTIONS
1667 entry.mainFunctionEntryRVA = pMethod->m_pUnwindInfo->GetRVA();
1670 entry.hotCodeSize = pMethod->m_pCode->GetSize();
1673 pZapWriter->Write(&entry, sizeof(entry));
1677 DWORD ZapHelperThunk::GetSize()
1679 return (m_dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN;
1682 void ZapHelperThunk::Save(ZapWriter * pZapWriter)
1685 LOG((LF_ZAP, LL_INFO1000000, "Emitting JIT helper table entry for helper %3d (%s)\n",
1686 (USHORT) m_dwHelper, s_rgHelperNames[(USHORT) m_dwHelper]));
1689 // Save the index of the helper, the actual code for the thunk will be generated at runtime
1690 pZapWriter->Write(&m_dwHelper, sizeof(DWORD));
1692 DWORD pad = GetSize() - sizeof(DWORD);
1695 void * pPad = _alloca(pad);
1696 memset(pPad, DEFAULT_CODE_BUFFER_INIT, pad);
1697 pZapWriter->Write(pPad, pad);
1701 void ZapLazyHelperThunk::Place(ZapImage * pImage)
1703 m_pArg = pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE];
1705 m_pTarget = pImage->GetHelperThunk(m_dwHelper);
1707 pImage->m_pLazyHelperSection->Place(this);
1710 DWORD ZapLazyHelperThunk::GetSize()
1712 return SaveWorker(NULL);
1715 void ZapLazyHelperThunk::Save(ZapWriter * pZapWriter)
1717 SaveWorker(pZapWriter);
1720 DWORD ZapLazyHelperThunk::SaveWorker(ZapWriter * pZapWriter)
1722 ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1724 BYTE buffer[42]; // Buffer big enough to hold any reasonable helper thunk sequence
1727 #if defined(_TARGET_X86_)
1731 pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR);
1737 pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32);
1739 #elif defined(_TARGET_AMD64_)
1742 #ifdef UNIX_AMD64_ABI
1750 pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_REL32);
1756 pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32);
1758 #elif defined(_TARGET_ARM_)
1760 *(WORD *)(p + 0) = 0xf240;
1761 *(WORD *)(p + 2) = 1 << 8;
1763 *(WORD *)(p + 4) = 0xf2c0;
1764 *(WORD *)(p + 6) = 1 << 8;
1766 pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_THUMB_MOV32);
1770 *(WORD *)(p + 0) = 0xf000;
1771 *(WORD *)(p + 2) = 0xb800;
1773 pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_THUMB_BRANCH24);
1775 #elif defined(_TARGET_ARM64_)
1777 *(DWORD *)(p) =0x58000041;
1780 *(DWORD *)(p) = 0x14000000;
1782 pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_ARM64_BRANCH26);
1785 pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR);
1788 PORTABILITY_ASSERT("ZapLazyHelperThunk::Save");
1791 _ASSERTE(p - buffer <= sizeof(buffer));
1793 if (pZapWriter != NULL)
1794 pZapWriter->Write(&buffer, (int)(p - buffer));
1796 return (DWORD) (p - buffer);