@@ -560,7 +560,8 @@ class TailMergeChunkARM64 : public NonSectionCodeChunk {
560560 memcpy (buf, tailMergeARM64, sizeof (tailMergeARM64));
561561 applyArm64Addr (buf + 44 , desc->getRVA (), rva + 44 , 12 );
562562 applyArm64Imm (buf + 48 , desc->getRVA () & 0xfff , 0 );
563- applyArm64Branch26 (buf + 52 , helper->getRVA () - rva - 52 );
563+ if (helper)
564+ applyArm64Branch26 (buf + 52 , helper->getRVA () - rva - 52 );
564565 }
565566
566567 Chunk *desc = nullptr ;
@@ -781,6 +782,7 @@ void IdataContents::create(COFFLinkerContext &ctx) {
781782 // ordinal values to the table.
782783 size_t base = lookups.size ();
783784 Chunk *lookupsTerminator = nullptr , *addressesTerminator = nullptr ;
785+ uint32_t nativeOnly = 0 ;
784786 for (DefinedImportData *s : syms) {
785787 uint16_t ord = s->getOrdinal ();
786788 HintNameChunk *hintChunk = nullptr ;
@@ -806,8 +808,8 @@ void IdataContents::create(COFFLinkerContext &ctx) {
806808 // the native terminator, they will be ignored in the native view.
807809 // In the EC view, they should act as terminators, so emit ZEROFILL
808810 // relocations overriding them.
809- if (ctx.hybridSymtab && !lookupsTerminator && s-> file -> isEC () &&
810- !s->file ->hybridFile ) {
811+ if (ctx.config . machine == ARM64X && !lookupsTerminator &&
812+ s-> file -> isEC () && !s->file ->hybridFile ) {
811813 lookupsTerminator = lookupsChunk;
812814 addressesTerminator = addressesChunk;
813815 lookupsChunk = make<NullChunk>(ctx);
@@ -841,6 +843,7 @@ void IdataContents::create(COFFLinkerContext &ctx) {
841843 // Fill the auxiliary IAT with null chunks for native-only imports.
842844 auxIat.push_back (make<NullChunk>(ctx));
843845 auxIatCopy.push_back (make<NullChunk>(ctx));
846+ ++nativeOnly;
844847 }
845848 }
846849 // Terminate with null values.
@@ -862,18 +865,15 @@ void IdataContents::create(COFFLinkerContext &ctx) {
862865 // Create the import table header.
863866 dllNames.push_back (make<StringChunk>(syms[0 ]->getDLLName ()));
864867 auto *dir = make<ImportDirectoryChunk>(dllNames.back ());
865- dir->lookupTab = lookups[base];
866- dir->addressTab = addresses[base];
867- dirs.push_back (dir);
868868
869- if (ctx.hybridSymtab ) {
870- // If native-only imports exist, they will appear as a prefix to all
871- // imports. Emit ARM64X relocations to skip them in the EC view.
872- uint32_t nativeOnly =
873- llvm::find_if (syms,
874- [](DefinedImportData *s ) { return s-> file -> isEC (); }) -
875- syms. begin ();
876- if (nativeOnly) {
869+ if (ctx.hybridSymtab && nativeOnly ) {
870+ if (ctx. config . machine != ARM64X)
871+ // On pure ARM64EC targets, skip native-only imports in the import
872+ // directory.
873+ base += nativeOnly;
874+ else if (nativeOnly ) {
875+ // If native-only imports exist, they will appear as a prefix to all
876+ // imports. Emit ARM64X relocations to skip them in the EC view.
877877 ctx.dynamicRelocs ->add (
878878 IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0 ,
879879 Arm64XRelocVal (
@@ -886,6 +886,10 @@ void IdataContents::create(COFFLinkerContext &ctx) {
886886 nativeOnly * sizeof (uint64_t ));
887887 }
888888 }
889+
890+ dir->lookupTab = lookups[base];
891+ dir->addressTab = addresses[base];
892+ dirs.push_back (dir);
889893 }
890894 // Add null terminator.
891895 dirs.push_back (make<NullChunk>(sizeof (ImportDirectoryTableEntry), 4 ));
@@ -922,21 +926,25 @@ void DelayLoadContents::create() {
922926
923927 size_t base = addresses.size ();
924928 ctx.forEachSymtab ([&](SymbolTable &symtab) {
925- if (ctx.hybridSymtab && symtab.isEC ()) {
926- // For hybrid images, emit null-terminated native import entries
927- // followed by null-terminated EC entries. If a view is missing imports
928- // for a given module, only terminators are emitted. Emit ARM64X
929- // relocations to skip native entries in the EC view.
930- ctx.dynamicRelocs ->add (
931- IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0 ,
932- Arm64XRelocVal (dir, offsetof (delay_import_directory_table_entry,
933- DelayImportAddressTable)),
934- (addresses.size () - base) * sizeof (uint64_t ));
935- ctx.dynamicRelocs ->add (
936- IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0 ,
937- Arm64XRelocVal (dir, offsetof (delay_import_directory_table_entry,
938- DelayImportNameTable)),
939- (addresses.size () - base) * sizeof (uint64_t ));
929+ if (symtab.isEC ()) {
930+ if (ctx.config .machine == ARM64X) {
931+ // For hybrid images, emit null-terminated native import entries
932+ // followed by null-terminated EC entries. If a view is missing
933+ // imports for a given module, only terminators are emitted. Emit
934+ // ARM64X relocations to skip native entries in the EC view.
935+ ctx.dynamicRelocs ->add (
936+ IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0 ,
937+ Arm64XRelocVal (dir, offsetof (delay_import_directory_table_entry,
938+ DelayImportAddressTable)),
939+ (addresses.size () - base) * sizeof (uint64_t ));
940+ ctx.dynamicRelocs ->add (
941+ IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0 ,
942+ Arm64XRelocVal (dir, offsetof (delay_import_directory_table_entry,
943+ DelayImportNameTable)),
944+ (addresses.size () - base) * sizeof (uint64_t ));
945+ } else {
946+ base = addresses.size ();
947+ }
940948 }
941949
942950 Chunk *tm = nullptr ;
@@ -981,7 +989,7 @@ void DelayLoadContents::create() {
981989 chunk = make<AuxImportChunk>(s->file );
982990 auxIatCopy.push_back (chunk);
983991 s->file ->auxImpCopySym ->setLocation (chunk);
984- } else if (ctx.hybridSymtab ) {
992+ } else if (ctx.config . machine == ARM64X ) {
985993 // Fill the auxiliary IAT with null chunks for native imports.
986994 auxIat.push_back (make<NullChunk>(ctx));
987995 auxIatCopy.push_back (make<NullChunk>(ctx));
@@ -995,6 +1003,10 @@ void DelayLoadContents::create() {
9951003 symtab.addSynthetic (tmName, tm);
9961004 }
9971005
1006+ // Skip terminators on pure ARM64EC target if there are no native imports.
1007+ if (!tm && !symtab.isEC () && ctx.config .machine != ARM64X)
1008+ return ;
1009+
9981010 // Terminate with null values.
9991011 addresses.push_back (make<NullChunk>(ctx, 8 ));
10001012 names.push_back (make<NullChunk>(ctx, 8 ));
@@ -1024,7 +1036,7 @@ void DelayLoadContents::create() {
10241036}
10251037
10261038Chunk *DelayLoadContents::newTailMergeChunk (SymbolTable &symtab, Chunk *dir) {
1027- auto helper = cast <Defined>(symtab.delayLoadHelper );
1039+ auto helper = cast_or_null <Defined>(symtab.delayLoadHelper );
10281040 switch (symtab.machine ) {
10291041 case AMD64:
10301042 case ARM64EC:
0 commit comments