@@ -221,6 +221,7 @@ class Writer {
221221 uint16_t type, int margin);
222222 bool createThunks (OutputSection *os, int margin);
223223 bool verifyRanges (const std::vector<Chunk *> chunks);
224+ void createECCodeMap ();
224225 void finalizeAddresses ();
225226 void removeEmptySections ();
226227 void assignOutputSectionIndices ();
@@ -229,6 +230,7 @@ class Writer {
229230 template <typename PEHeaderTy> void writeHeader ();
230231 void createSEHTable ();
231232 void createRuntimePseudoRelocs ();
233+ void createECChunks ();
232234 void insertCtorDtorSymbols ();
233235 void markSymbolsWithRelocations (ObjFile *file, SymbolRVASet &usedSymbols);
234236 void createGuardCFTables ();
@@ -271,6 +273,7 @@ class Writer {
271273 std::map<PartialSectionKey, PartialSection *> partialSections;
272274 std::vector<char > strtab;
273275 std::vector<llvm::object::coff_symbol16> outputSymtab;
276+ std::vector<ECCodeMapEntry> codeMap;
274277 IdataContents idata;
275278 Chunk *importTableStart = nullptr ;
276279 uint64_t importTableSize = 0 ;
@@ -528,6 +531,53 @@ bool Writer::createThunks(OutputSection *os, int margin) {
528531 return addressesChanged;
529532}
530533
534+ // Create a code map for CHPE metadata.
535+ void Writer::createECCodeMap () {
536+ if (!isArm64EC (ctx.config .machine ))
537+ return ;
538+
539+ // Clear the map in case we were're recomputing the map after adding
540+ // a range extension thunk.
541+ codeMap.clear ();
542+
543+ std::optional<chpe_range_type> lastType;
544+ Chunk *first, *last;
545+
546+ auto closeRange = [&]() {
547+ if (lastType) {
548+ codeMap.push_back ({first, last, *lastType});
549+ lastType.reset ();
550+ }
551+ };
552+
553+ for (OutputSection *sec : ctx.outputSections ) {
554+ if (!sec->isCodeSection ()) {
555+ closeRange ();
556+ continue ;
557+ }
558+
559+ for (Chunk *c : sec->chunks ) {
560+ // Skip empty section chunks. MSVC does not seem to do that and
561+ // generates empty code ranges in some cases.
562+ if (isa<SectionChunk>(c) && !c->getSize ())
563+ continue ;
564+
565+ std::optional<chpe_range_type> chunkType = c->getArm64ECRangeType ();
566+ if (chunkType != lastType) {
567+ closeRange ();
568+ first = c;
569+ lastType = chunkType;
570+ }
571+ last = c;
572+ }
573+ }
574+
575+ closeRange ();
576+
577+ Symbol *tableCountSym = ctx.symtab .findUnderscore (" __hybrid_code_map_count" );
578+ cast<DefinedAbsolute>(tableCountSym)->setVA (codeMap.size ());
579+ }
580+
531581// Verify that all relocations are in range, with no extra margin requirements.
532582bool Writer::verifyRanges (const std::vector<Chunk *> chunks) {
533583 for (Chunk *c : chunks) {
@@ -1077,6 +1127,9 @@ void Writer::createMiscChunks() {
10771127 if (config->guardCF != GuardCFLevel::Off)
10781128 createGuardCFTables ();
10791129
1130+ if (isArm64EC (config->machine ))
1131+ createECChunks ();
1132+
10801133 if (config->autoImport )
10811134 createRuntimePseudoRelocs ();
10821135
@@ -1402,6 +1455,10 @@ void Writer::assignAddresses() {
14021455 llvm::TimeTraceScope timeScope (" Assign addresses" );
14031456 Configuration *config = &ctx.config ;
14041457
1458+ // We need to create EC code map so that ECCodeMapChunk knows its size.
1459+ // We do it here to make sure that we account for range extension chunks.
1460+ createECCodeMap ();
1461+
14051462 sizeOfHeaders = dosStubSize + sizeof (PEMagic) + sizeof (coff_file_header) +
14061463 sizeof (data_directory) * numberOfDataDirectory +
14071464 sizeof (coff_section) * ctx.outputSections .size ();
@@ -1937,6 +1994,15 @@ void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
19371994 cast<DefinedAbsolute>(c)->setVA (tableChunk->getSize () / (hasFlag ? 5 : 4 ));
19381995}
19391996
1997+ // Create CHPE metadata chunks.
1998+ void Writer::createECChunks () {
1999+ auto codeMapChunk = make<ECCodeMapChunk>(codeMap);
2000+ rdataSec->addChunk (codeMapChunk);
2001+ Symbol *codeMapSym = ctx.symtab .findUnderscore (" __hybrid_code_map" );
2002+ replaceSymbol<DefinedSynthetic>(codeMapSym, codeMapSym->getName (),
2003+ codeMapChunk);
2004+ }
2005+
19402006// MinGW specific. Gather all relocations that are imported from a DLL even
19412007// though the code didn't expect it to, produce the table that the runtime
19422008// uses for fixing them up, and provide the synthetic symbols that the
0 commit comments