diff --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h index 2c5f6415e5d4b..f45b754384ef9 100644 --- a/lld/COFF/COFFLinkerContext.h +++ b/lld/COFF/COFFLinkerContext.h @@ -50,6 +50,14 @@ class COFFLinkerContext : public CommonLinkerContext { f(symtab); } + // Invoke the specified callback for each active symbol table, + // skipping the native symbol table on pure ARM64EC targets. + void forEachActiveSymtab(std::function f) { + if (symtab.ctx.config.machine == ARM64X) + f(*hybridSymtab); + f(symtab); + } + std::vector objFileInstances; std::map pdbInputFileInstances; std::vector importFileInstances; diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index ff2bc40932c04..01752cdc6a9da 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -580,7 +580,7 @@ void SectionChunk::getBaserels(std::vector *res) { // to match the value in the EC load config, which is expected to be // a relocatable pointer to the __chpe_metadata symbol. COFFLinkerContext &ctx = file->symtab.ctx; - if (ctx.hybridSymtab && ctx.hybridSymtab->loadConfigSym && + if (ctx.config.machine == ARM64X && ctx.hybridSymtab->loadConfigSym && ctx.hybridSymtab->loadConfigSym->getChunk() == this && ctx.symtab.loadConfigSym && ctx.hybridSymtab->loadConfigSize >= diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index 0440507b71756..c327da28ce138 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -560,7 +560,8 @@ class TailMergeChunkARM64 : public NonSectionCodeChunk { memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64)); applyArm64Addr(buf + 44, desc->getRVA(), rva + 44, 12); applyArm64Imm(buf + 48, desc->getRVA() & 0xfff, 0); - applyArm64Branch26(buf + 52, helper->getRVA() - rva - 52); + if (helper) + applyArm64Branch26(buf + 52, helper->getRVA() - rva - 52); } Chunk *desc = nullptr; @@ -781,6 +782,7 @@ void IdataContents::create(COFFLinkerContext &ctx) { // ordinal values to the table. size_t base = lookups.size(); Chunk *lookupsTerminator = nullptr, *addressesTerminator = nullptr; + uint32_t nativeOnly = 0; for (DefinedImportData *s : syms) { uint16_t ord = s->getOrdinal(); HintNameChunk *hintChunk = nullptr; @@ -806,8 +808,8 @@ void IdataContents::create(COFFLinkerContext &ctx) { // the native terminator, they will be ignored in the native view. // In the EC view, they should act as terminators, so emit ZEROFILL // relocations overriding them. - if (ctx.hybridSymtab && !lookupsTerminator && s->file->isEC() && - !s->file->hybridFile) { + if (ctx.config.machine == ARM64X && !lookupsTerminator && + s->file->isEC() && !s->file->hybridFile) { lookupsTerminator = lookupsChunk; addressesTerminator = addressesChunk; lookupsChunk = make(ctx); @@ -841,6 +843,7 @@ void IdataContents::create(COFFLinkerContext &ctx) { // Fill the auxiliary IAT with null chunks for native-only imports. auxIat.push_back(make(ctx)); auxIatCopy.push_back(make(ctx)); + ++nativeOnly; } } // Terminate with null values. @@ -862,18 +865,15 @@ void IdataContents::create(COFFLinkerContext &ctx) { // Create the import table header. dllNames.push_back(make(syms[0]->getDLLName())); auto *dir = make(dllNames.back()); - dir->lookupTab = lookups[base]; - dir->addressTab = addresses[base]; - dirs.push_back(dir); - if (ctx.hybridSymtab) { - // If native-only imports exist, they will appear as a prefix to all - // imports. Emit ARM64X relocations to skip them in the EC view. - uint32_t nativeOnly = - llvm::find_if(syms, - [](DefinedImportData *s) { return s->file->isEC(); }) - - syms.begin(); - if (nativeOnly) { + if (ctx.hybridSymtab && nativeOnly) { + if (ctx.config.machine != ARM64X) + // On pure ARM64EC targets, skip native-only imports in the import + // directory. + base += nativeOnly; + else if (nativeOnly) { + // If native-only imports exist, they will appear as a prefix to all + // imports. Emit ARM64X relocations to skip them in the EC view. ctx.dynamicRelocs->add( IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0, Arm64XRelocVal( @@ -886,6 +886,10 @@ void IdataContents::create(COFFLinkerContext &ctx) { nativeOnly * sizeof(uint64_t)); } } + + dir->lookupTab = lookups[base]; + dir->addressTab = addresses[base]; + dirs.push_back(dir); } // Add null terminator. dirs.push_back(make(sizeof(ImportDirectoryTableEntry), 4)); @@ -922,21 +926,25 @@ void DelayLoadContents::create() { size_t base = addresses.size(); ctx.forEachSymtab([&](SymbolTable &symtab) { - if (ctx.hybridSymtab && symtab.isEC()) { - // For hybrid images, emit null-terminated native import entries - // followed by null-terminated EC entries. If a view is missing imports - // for a given module, only terminators are emitted. Emit ARM64X - // relocations to skip native entries in the EC view. - ctx.dynamicRelocs->add( - IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0, - Arm64XRelocVal(dir, offsetof(delay_import_directory_table_entry, - DelayImportAddressTable)), - (addresses.size() - base) * sizeof(uint64_t)); - ctx.dynamicRelocs->add( - IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0, - Arm64XRelocVal(dir, offsetof(delay_import_directory_table_entry, - DelayImportNameTable)), - (addresses.size() - base) * sizeof(uint64_t)); + if (symtab.isEC()) { + if (ctx.config.machine == ARM64X) { + // For hybrid images, emit null-terminated native import entries + // followed by null-terminated EC entries. If a view is missing + // imports for a given module, only terminators are emitted. Emit + // ARM64X relocations to skip native entries in the EC view. + ctx.dynamicRelocs->add( + IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0, + Arm64XRelocVal(dir, offsetof(delay_import_directory_table_entry, + DelayImportAddressTable)), + (addresses.size() - base) * sizeof(uint64_t)); + ctx.dynamicRelocs->add( + IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0, + Arm64XRelocVal(dir, offsetof(delay_import_directory_table_entry, + DelayImportNameTable)), + (addresses.size() - base) * sizeof(uint64_t)); + } else { + base = addresses.size(); + } } Chunk *tm = nullptr; @@ -981,7 +989,7 @@ void DelayLoadContents::create() { chunk = make(s->file); auxIatCopy.push_back(chunk); s->file->auxImpCopySym->setLocation(chunk); - } else if (ctx.hybridSymtab) { + } else if (ctx.config.machine == ARM64X) { // Fill the auxiliary IAT with null chunks for native imports. auxIat.push_back(make(ctx)); auxIatCopy.push_back(make(ctx)); @@ -995,6 +1003,10 @@ void DelayLoadContents::create() { symtab.addSynthetic(tmName, tm); } + // Skip terminators on pure ARM64EC target if there are no native imports. + if (!tm && !symtab.isEC() && ctx.config.machine != ARM64X) + return; + // Terminate with null values. addresses.push_back(make(ctx, 8)); names.push_back(make(ctx, 8)); @@ -1024,7 +1036,7 @@ void DelayLoadContents::create() { } Chunk *DelayLoadContents::newTailMergeChunk(SymbolTable &symtab, Chunk *dir) { - auto helper = cast(symtab.delayLoadHelper); + auto helper = cast_or_null(symtab.delayLoadHelper); switch (symtab.machine) { case AMD64: case ARM64EC: diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 4c296da35d667..7250fdc86719f 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -190,7 +190,6 @@ static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) { case ARM64: return mt == ARM64 || mt == ARM64X; case ARM64EC: - return isArm64EC(mt) || mt == AMD64; case ARM64X: return isAnyArm64(mt) || mt == AMD64; case IMAGE_FILE_MACHINE_UNKNOWN: @@ -499,7 +498,7 @@ void LinkerDriver::parseDirectives(InputFile *file) { case OPT_entry: if (!arg->getValue()[0]) Fatal(ctx) << "missing entry point symbol name"; - ctx.forEachSymtab([&](SymbolTable &symtab) { + ctx.forEachActiveSymtab([&](SymbolTable &symtab) { symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true); }); break; @@ -657,9 +656,13 @@ void LinkerDriver::setMachine(MachineTypes machine) { ctx.config.machine = machine; - if (machine != ARM64X) { + if (!isArm64EC(machine)) { ctx.symtab.machine = machine; } else { + // Set up a hybrid symbol table on ARM64EC/ARM64X. This is primarily useful + // on ARM64X, where both the native and EC symbol tables are meaningful. + // However, since ARM64EC can include native object files, we also need to + // support a hybrid symbol table there. ctx.symtab.machine = ARM64EC; ctx.hybridSymtab.emplace(ctx, ARM64); } @@ -979,7 +982,7 @@ void LinkerDriver::createImportLibrary(bool asLib) { }; getExports(ctx.symtab, exports); - if (ctx.hybridSymtab) + if (ctx.config.machine == ARM64X) getExports(*ctx.hybridSymtab, nativeExports); std::string libName = getImportName(asLib); @@ -1383,13 +1386,13 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) { return; if (ctx.symtab.hadExplicitExports || - (ctx.hybridSymtab && ctx.hybridSymtab->hadExplicitExports)) + (ctx.config.machine == ARM64X && ctx.hybridSymtab->hadExplicitExports)) return; if (args.hasArg(OPT_exclude_all_symbols)) return; } - ctx.forEachSymtab([&](SymbolTable &symtab) { + ctx.forEachActiveSymtab([&](SymbolTable &symtab) { AutoExporter exporter(symtab, excludedSymbols); for (auto *arg : args.filtered(OPT_wholearchive_file)) @@ -2305,7 +2308,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { if (auto *arg = args.getLastArg(OPT_deffile)) { // parseModuleDefs mutates Config object. ctx.symtab.parseModuleDefs(arg->getValue()); - if (ctx.hybridSymtab) { + if (ctx.config.machine == ARM64X) { // MSVC ignores the /defArm64Native argument on non-ARM64X targets. // It is also ignored if the /def option is not specified. if (auto *arg = args.getLastArg(OPT_defarm64native)) @@ -2332,7 +2335,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { } // Handle /entry and /dll - ctx.forEachSymtab([&](SymbolTable &symtab) { + ctx.forEachActiveSymtab([&](SymbolTable &symtab) { llvm::TimeTraceScope timeScope("Entry point"); if (auto *arg = args.getLastArg(OPT_entry)) { if (!arg->getValue()[0]) @@ -2364,7 +2367,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { llvm::TimeTraceScope timeScope("Delay load"); for (auto *arg : args.filtered(OPT_delayload)) { config->delayLoads.insert(StringRef(arg->getValue()).lower()); - ctx.forEachSymtab([&](SymbolTable &symtab) { + ctx.forEachActiveSymtab([&](SymbolTable &symtab) { if (symtab.machine == I386) { symtab.delayLoadHelper = symtab.addGCRoot("___delayLoadHelper2@8"); } else { @@ -2538,7 +2541,9 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { u->setWeakAlias(symtab.addUndefined(to)); } } + }); + ctx.forEachActiveSymtab([&](SymbolTable &symtab) { // If any inputs are bitcode files, the LTO code generator may create // references to library functions that are not explicit in the bitcode // file's symbol table. If any of those library functions are defined in @@ -2568,7 +2573,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // Handle /includeglob for (StringRef pat : args::getStrings(args, OPT_incl_glob)) - ctx.forEachSymtab( + ctx.forEachActiveSymtab( [&](SymbolTable &symtab) { symtab.addUndefinedGlob(pat); }); // Create wrapped symbols for -wrap option. @@ -2685,12 +2690,12 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // need to create a .lib file. In MinGW mode, we only do that when the // -implib option is given explicitly, for compatibility with GNU ld. if (config->dll || !ctx.symtab.exports.empty() || - (ctx.hybridSymtab && !ctx.hybridSymtab->exports.empty())) { + (ctx.config.machine == ARM64X && !ctx.hybridSymtab->exports.empty())) { llvm::TimeTraceScope timeScope("Create .lib exports"); - ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); }); + ctx.forEachActiveSymtab([](SymbolTable &symtab) { symtab.fixupExports(); }); if (!config->noimplib && (!config->mingw || !config->implib.empty())) createImportLibrary(/*asLib=*/false); - ctx.forEachSymtab( + ctx.forEachActiveSymtab( [](SymbolTable &symtab) { symtab.assignExportOrdinals(); }); } @@ -2756,7 +2761,8 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { if (ctx.symtab.isEC()) ctx.symtab.initializeECThunks(); - ctx.forEachSymtab([](SymbolTable &symtab) { symtab.initializeLoadConfig(); }); + ctx.forEachActiveSymtab( + [](SymbolTable &symtab) { symtab.initializeLoadConfig(); }); // Identify unreferenced COMDAT sections. if (config->doGC) { diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 7fb42bb681939..e10b6419b5ad5 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -137,10 +137,8 @@ void ArchiveFile::parse() { ctx.symtab.addLazyArchive(this, sym); // Read both EC and native symbols on ARM64X. - if (!ctx.hybridSymtab) - return; archiveSymtab = &*ctx.hybridSymtab; - } else if (ctx.hybridSymtab) { + } else { // If the ECSYMBOLS section is missing in the archive, the archive could // be either a native-only ARM64 or x86_64 archive. Check the machine type // of the object containing a symbol to determine which symbol table to diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 8fb0ee4e890d6..d6f771284aa83 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -551,7 +551,7 @@ void SymbolTable::initializeLoadConfig() { Warn(ctx) << "EC version of '_load_config_used' is missing"; return; } - if (ctx.hybridSymtab) { + if (ctx.config.machine == ARM64X) { Warn(ctx) << "native version of '_load_config_used' is missing for " "ARM64X target"; return; diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index f3cf4902e6ecf..db6133e20a037 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1374,7 +1374,7 @@ void Writer::createExportTable() { } } } - ctx.forEachSymtab([&](SymbolTable &symtab) { + ctx.forEachActiveSymtab([&](SymbolTable &symtab) { if (symtab.edataStart) { if (symtab.hadExplicitExports) Warn(ctx) << "literal .edata sections override exports"; @@ -1776,7 +1776,8 @@ template void Writer::writeHeader() { assert(coffHeaderOffset == buf - buffer->getBufferStart()); auto *coff = reinterpret_cast(buf); buf += sizeof(*coff); - SymbolTable &symtab = ctx.hybridSymtab ? *ctx.hybridSymtab : ctx.symtab; + SymbolTable &symtab = + ctx.config.machine == ARM64X ? *ctx.hybridSymtab : ctx.symtab; coff->Machine = symtab.isEC() ? AMD64 : symtab.machine; coff->NumberOfSections = ctx.outputSections.size(); coff->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; @@ -2433,7 +2434,7 @@ void Writer::setECSymbols() { return a.first->getRVA() < b.first->getRVA(); }); - ChunkRange &chpePdata = ctx.hybridSymtab ? hybridPdata : pdata; + ChunkRange &chpePdata = ctx.config.machine == ARM64X ? hybridPdata : pdata; Symbol *rfeTableSym = ctx.symtab.findUnderscore("__arm64x_extra_rfe_table"); replaceSymbol(rfeTableSym, "__arm64x_extra_rfe_table", chpePdata.first); @@ -2478,7 +2479,7 @@ void Writer::setECSymbols() { delayIdata.getAuxIatCopy().empty() ? nullptr : delayIdata.getAuxIatCopy().front()); - if (ctx.hybridSymtab) { + if (ctx.config.machine == ARM64X) { // For the hybrid image, set the alternate entry point to the EC entry // point. In the hybrid view, it is swapped to the native entry point // using ARM64X relocations. @@ -2868,7 +2869,7 @@ void Writer::fixTlsAlignment() { } void Writer::prepareLoadConfig() { - ctx.forEachSymtab([&](SymbolTable &symtab) { + ctx.forEachActiveSymtab([&](SymbolTable &symtab) { if (!symtab.loadConfigSym) return; @@ -2928,7 +2929,7 @@ void Writer::prepareLoadConfig(SymbolTable &symtab, T *loadConfig) { IF_CONTAINS(CHPEMetadataPointer) { // On ARM64X, only the EC version of the load config contains // CHPEMetadataPointer. Copy its value to the native load config. - if (ctx.hybridSymtab && !symtab.isEC() && + if (ctx.config.machine == ARM64X && !symtab.isEC() && ctx.symtab.loadConfigSize >= offsetof(T, CHPEMetadataPointer) + sizeof(T::CHPEMetadataPointer)) { OutputSection *sec = diff --git a/lld/test/COFF/arm64ec-entry-mangle.test b/lld/test/COFF/arm64ec-entry-mangle.test index 6db16ef218dc8..1f029077ba51d 100644 --- a/lld/test/COFF/arm64ec-entry-mangle.test +++ b/lld/test/COFF/arm64ec-entry-mangle.test @@ -97,7 +97,7 @@ RUN: not lld-link -machine:arm64ec -dll -out:test.dll demangled-func.obj loadcon RUN: "-entry:#func" 2>&1 | FileCheck -check-prefix=FUNC-NOT-FOUND %s RUN: not lld-link -machine:arm64ec -dll -out:test.dll demangled-func.obj loadconfig-arm64ec.obj \ RUN: -noentry "-export:#func" 2>&1 | FileCheck -check-prefix=FUNC-NOT-FOUND %s -FUNC-NOT-FOUND: undefined symbol: #func +FUNC-NOT-FOUND: undefined symbol: #func (EC symbol) Verify that the linker recognizes the demangled x86_64 _DllMainCRTStartup. RUN: lld-link -machine:arm64ec -dll -out:test.dll x64-dll-main.obj loadconfig-arm64ec.obj diff --git a/lld/test/COFF/arm64ec-hybmp.s b/lld/test/COFF/arm64ec-hybmp.s index 5fc24d4250704..670ee3926ab5c 100644 --- a/lld/test/COFF/arm64ec-hybmp.s +++ b/lld/test/COFF/arm64ec-hybmp.s @@ -62,7 +62,7 @@ thunk: // RUN: llvm-mc -filetype=obj -triple=arm64ec-windows undef-func.s -o undef-func.obj // RUN: not lld-link -machine:arm64ec -dll -noentry -out:test.dll undef-func.obj 2>&1 | FileCheck -check-prefix=UNDEF-FUNC %s -// UNDEF-FUNC: error: undefined symbol: func +// UNDEF-FUNC: error: undefined symbol: func (EC symbol) #--- undef-thunk.s .section .text,"xr",discard,func @@ -79,7 +79,7 @@ func: // RUN: llvm-mc -filetype=obj -triple=arm64ec-windows undef-thunk.s -o undef-thunk.obj // RUN: not lld-link -machine:arm64ec -dll -noentry -out:test.dll undef-thunk.obj 2>&1 | FileCheck -check-prefix=UNDEF-THUNK %s -// UNDEF-THUNK: error: undefined symbol: thunk +// UNDEF-THUNK: error: undefined symbol: thunk (EC symbol) #--- invalid-type.s .section .text,"xr",discard,func diff --git a/lld/test/COFF/arm64ec-lib.test b/lld/test/COFF/arm64ec-lib.test index 8698a5ceccbe7..1e6fa60209d94 100644 --- a/lld/test/COFF/arm64ec-lib.test +++ b/lld/test/COFF/arm64ec-lib.test @@ -29,11 +29,13 @@ RUN: lld-link -machine:arm64ec -dll -noentry -out:test2.dll symref-arm64ec.obj s Verify that both native and EC symbols can be referenced in a hybrid target. RUN: lld-link -machine:arm64x -dll -noentry -out:test3.dll symref-arm64ec.obj nsymref-aarch64.obj sym-arm64ec.lib \ RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj +RUN: lld-link -machine:arm64ec -dll -noentry -out:test3ec.dll symref-arm64ec.obj nsymref-aarch64.obj sym-arm64ec.lib \ +RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj Ensure that an EC symbol is not resolved using a regular symbol map. RUN: not lld-link -machine:arm64ec -dll -noentry -out:test-err.dll nsymref-arm64ec.obj sym-arm64ec.lib loadconfig-arm64ec.obj 2>&1 |\ RUN: FileCheck --check-prefix=ERR %s -ERR: error: undefined symbol: nsym +ERR: error: undefined symbol: nsym (EC symbol) Verify that a library symbol can be referenced, even if its name conflicts with an anti-dependency alias. RUN: lld-link -machine:arm64ec -dll -noentry -out:ref-alias-1.dll ref-alias.obj func.lib loadconfig-arm64ec.obj diff --git a/lld/test/COFF/arm64ec-patchable-thunks.test b/lld/test/COFF/arm64ec-patchable-thunks.test index 1e1ff1f7f2ee4..593405775ba87 100644 --- a/lld/test/COFF/arm64ec-patchable-thunks.test +++ b/lld/test/COFF/arm64ec-patchable-thunks.test @@ -57,7 +57,7 @@ RUN: llvm-readobj --coff-load-config test3.dll | FileCheck -check-prefix=PATCH-C RUN: not lld-link -out:test4.dll -machine:arm64ec test-sec.obj loadconfig-arm64ec.obj -dll -noentry 2>&1 | FileCheck --check-prefix=ERR %s -ERR: error: undefined symbol: EXP+#patchable_func +ERR: error: undefined symbol: EXP+#patchable_func (EC symbol) RUN: lld-link -out:testx.dll -machine:arm64x arm64ec-patchable.obj test-sec.obj \ diff --git a/lld/test/COFF/arm64ec-range-thunks.s b/lld/test/COFF/arm64ec-range-thunks.s index dcfa6365b4e3a..955e19c30c2ae 100644 --- a/lld/test/COFF/arm64ec-range-thunks.s +++ b/lld/test/COFF/arm64ec-range-thunks.s @@ -79,7 +79,11 @@ # RUN: -out:testx2.dll -verbose 2>&1 | FileCheck -check-prefix=VERBOSEX %s # VERBOSEX: Added 5 thunks with margin {{.*}} in 1 passes +# RUN: lld-link -machine:arm64ec -noentry -dll funcs-arm64ec.obj funcs-aarch64.obj loadconfig-arm64.obj loadconfig-arm64ec.obj \ +# RUN: -out:testx2ec.dll -verbose 2>&1 | FileCheck -check-prefix=VERBOSEX %s + # RUN: llvm-objdump -d testx2.dll | FileCheck --check-prefix=DISASMX %s +# RUN: llvm-objdump -d testx2ec.dll | FileCheck --check-prefix=DISASMX %s # DISASMX: Disassembly of section .code1: # DISASMX-EMPTY: @@ -126,6 +130,7 @@ # DISASMX-NEXT: 180016010: d61f0200 br x16 # RUN: llvm-readobj --coff-load-config testx2.dll | FileCheck --check-prefix=LOADCFGX2 %s +# RUN: llvm-readobj --coff-load-config testx2ec.dll | FileCheck --check-prefix=LOADCFGX2 %s # LOADCFGX2: CodeMap [ # LOADCFGX2-NEXT: 0x4000 - 0x4014 ARM64EC diff --git a/lld/test/COFF/arm64ec.test b/lld/test/COFF/arm64ec.test index 75288e97e598d..ea92689250063 100644 --- a/lld/test/COFF/arm64ec.test +++ b/lld/test/COFF/arm64ec.test @@ -35,14 +35,15 @@ RUN: llvm-readobj --file-headers test.dll | FileCheck -check-prefix=ARM64X-HEADE RUN: llvm-readobj --hex-dump=.data test.dll | FileCheck -check-prefix=ARM64X-DATA %s ARM64X-DATA: 03030303 01010101 02020202 +RUN: lld-link -out:test.dll -machine:arm64ec x86_64-data-sym.obj arm64-data-sym.obj \ +RUN: arm64ec-data-sym.obj arm64x-resource.obj -dll -noentry +RUN: llvm-readobj --file-headers test.dll | FileCheck -check-prefix=ARM64EC-HEADER %s +RUN: llvm-readobj --hex-dump=.data test.dll | FileCheck -check-prefix=ARM64X-DATA %s + RUN: not lld-link -out:test.dll -machine:arm64 arm64-data-sym.obj arm64ec-data-sym.obj \ RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT1 %s INCOMPAT1: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec conflicts with arm64 -RUN: not lld-link -out:test.dll -machine:arm64ec arm64ec-data-sym.obj arm64-data-sym.obj \ -RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT2 %s -INCOMPAT2: lld-link: error: arm64-data-sym.obj: machine type arm64 conflicts with arm64ec - RUN: not lld-link -out:test.dll -machine:arm64 arm64-data-sym.obj x86_64-data-sym.obj \ RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT3 %s INCOMPAT3: lld-link: error: x86_64-data-sym.obj: machine type x64 conflicts with arm64 diff --git a/lld/test/COFF/arm64x-altnames.s b/lld/test/COFF/arm64x-altnames.s index 43a3f89db9a03..db348f85b6b00 100644 --- a/lld/test/COFF/arm64x-altnames.s +++ b/lld/test/COFF/arm64x-altnames.s @@ -10,6 +10,8 @@ // RUN: not lld-link -out:out.dll -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj -alternatename:sym=altsym \ // RUN: 2>&1 | FileCheck --check-prefix=ERR-NATIVE %s +// RUN: not lld-link -out:out.dll -machine:arm64ec -dll -noentry test-arm64.obj test-arm64ec.obj -alternatename:sym=altsym \ +// RUN: 2>&1 | FileCheck --check-prefix=ERR-NATIVE %s // ERR-NATIVE-NOT: test-arm64ec.obj // ERR-NATIVE: lld-link: error: undefined symbol: sym (native symbol) @@ -20,9 +22,13 @@ // RUN: not lld-link -out:out.dll -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj drectve-arm64ec.obj \ // RUN: 2>&1 | FileCheck --check-prefix=ERR-NATIVE %s +// RUN: not lld-link -out:out.dll -machine:arm64ec -dll -noentry test-arm64.obj test-arm64ec.obj drectve-arm64ec.obj \ +// RUN: 2>&1 | FileCheck --check-prefix=ERR-NATIVE %s // RUN: not lld-link -out:out.dll -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj drectve-arm64.obj \ // RUN: 2>&1 | FileCheck --check-prefix=ERR-EC %s +// RUN: not lld-link -out:out.dll -machine:arm64ec -dll -noentry test-arm64.obj test-arm64ec.obj drectve-arm64.obj \ +// RUN: 2>&1 | FileCheck --check-prefix=ERR-EC %s // ERR-EC-NOT: test-arm64.obj // ERR-EC: lld-link: error: undefined symbol: sym (EC symbol) diff --git a/lld/test/COFF/arm64x-buildid.s b/lld/test/COFF/arm64x-buildid.s index 99f50073eaa69..857bcae2c0566 100644 --- a/lld/test/COFF/arm64x-buildid.s +++ b/lld/test/COFF/arm64x-buildid.s @@ -6,6 +6,9 @@ # RUN: llvm-readobj --hex-dump=.test %t.dll | FileCheck %s # CHECK: 0x180003000 3c100000 3c100000 +# RUN: lld-link -machine:arm64ec -dll -noentry %t-arm64.obj %t-arm64ec.obj -debug -build-id -Brepro -out:%t-ec.dll +# RUN: llvm-readobj --hex-dump=.test %t-ec.dll | FileCheck %s + .section .test,"dr" .rva __buildid diff --git a/lld/test/COFF/arm64x-comm.s b/lld/test/COFF/arm64x-comm.s index 830e3d3fdaaa1..b950af5b70a44 100644 --- a/lld/test/COFF/arm64x-comm.s +++ b/lld/test/COFF/arm64x-comm.s @@ -8,6 +8,9 @@ // RUN: llvm-readobj --hex-dump=.test %t.dll | FileCheck %s // CHECK: 0x180004000 10200000 18200000 20200000 28200000 +// RUN: lld-link -machine:arm64ec -lldmingw -dll -noentry -out:%t-ec.dll %t-arm64.obj %t-arm64ec.obj +// RUN: llvm-readobj --hex-dump=.test %t-ec.dll | FileCheck %s + .data .word 0 diff --git a/lld/test/COFF/arm64x-crt-sec.s b/lld/test/COFF/arm64x-crt-sec.s index 5be70a1845f12..45141ec238aea 100644 --- a/lld/test/COFF/arm64x-crt-sec.s +++ b/lld/test/COFF/arm64x-crt-sec.s @@ -17,6 +17,9 @@ // RUN: lld-link -out:out3.dll -machine:arm64x -dll -noentry crt2-amd64.obj crt1-arm64ec.obj crt2-arm64.obj crt1-arm64.obj // RUN: llvm-readobj --hex-dump=.CRT out3.dll | FileCheck %s +// RUN: lld-link -out:out4.dll -machine:arm64ec -dll -noentry crt2-amd64.obj crt1-arm64ec.obj crt2-arm64.obj crt1-arm64.obj +// RUN: llvm-readobj --hex-dump=.CRT out4.dll | FileCheck %s + // CHECK: 0x180002000 01000000 00000000 02000000 00000000 // CHECK-NEXT: 0x180002010 03000000 00000000 11000000 00000000 // CHECK-NEXT: 0x180002020 12000000 00000000 13000000 00000000 diff --git a/lld/test/COFF/arm64x-ctors-sec.s b/lld/test/COFF/arm64x-ctors-sec.s index 283d5f045260d..3295b3f20b8b2 100644 --- a/lld/test/COFF/arm64x-ctors-sec.s +++ b/lld/test/COFF/arm64x-ctors-sec.s @@ -22,6 +22,10 @@ // RUN: ctor2-arm64.obj ctor1-arm64ec.obj ctor2-amd64.obj ctor1-arm64.obj // RUN: llvm-readobj --hex-dump=.rdata --hex-dump=.test out3.dll | FileCheck %s +// RUN: lld-link -out:out4.dll -machine:arm64ec -lldmingw -dll -noentry test-arm64.obj test-arm64ec.obj \ +// RUN: ctor2-arm64.obj ctor1-arm64ec.obj ctor2-amd64.obj ctor1-arm64.obj +// RUN: llvm-readobj --hex-dump=.rdata --hex-dump=.test out4.dll | FileCheck %s + // CHECK: Hex dump of section '.rdata': // CHECK-NEXT: 0x180001000 ffffffff ffffffff 01000000 00000000 // CHECK-NEXT: 0x180001010 02000000 00000000 03000000 00000000 diff --git a/lld/test/COFF/arm64x-guardcf.s b/lld/test/COFF/arm64x-guardcf.s index 750bf0b3862c5..9d307bde276e1 100644 --- a/lld/test/COFF/arm64x-guardcf.s +++ b/lld/test/COFF/arm64x-guardcf.s @@ -16,7 +16,7 @@ // RUN: lld-link -dll -noentry -machine:arm64x func-gfids-arm64.obj func-gfids-arm64ec.obj func-amd64.obj -guard:cf -out:out.dll \ // RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj -// RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefix=LOADCFG %s +// RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefixes=LOADCFG,LOADCFGX %s // LOADCFG: LoadConfig [ // LOADCFG: GuardCFFunctionCount: 3 @@ -31,28 +31,36 @@ // LOADCFG-NEXT: 0x180002000 // LOADCFG-NEXT: 0x180003000 // LOADCFG-NEXT: ] -// LOADCFG: HybridObject { -// LOADCFG: LoadConfig [ -// LOADCFG: GuardCFFunctionCount: 3 -// LOADCFG-NEXT: GuardFlags [ (0x10500) -// LOADCFG-NEXT: CF_FUNCTION_TABLE_PRESENT (0x400) -// LOADCFG-NEXT: CF_INSTRUMENTED (0x100) -// LOADCFG-NEXT: CF_LONGJUMP_TABLE_PRESENT (0x10000) -// LOADCFG-NEXT: ] -// LOADCFG: ] -// LOADCFG: GuardFidTable [ -// LOADCFG-NEXT: 0x180001000 -// LOADCFG-NEXT: 0x180002000 -// LOADCFG-NEXT: 0x180003000 -// LOADCFG-NEXT: ] -// LOADCFG: ] +// LOADCFGX: HybridObject { +// LOADCFGX: LoadConfig [ +// LOADCFGX: GuardCFFunctionCount: 3 +// LOADCFG-NEXTX: GuardFlags [ (0x10500) +// LOADCFG-NEXTX: CF_FUNCTION_TABLE_PRESENT (0x400) +// LOADCFG-NEXTX: CF_INSTRUMENTED (0x100) +// LOADCFG-NEXTX: CF_LONGJUMP_TABLE_PRESENT (0x10000) +// LOADCFG-NEXTX: ] +// LOADCFGX: ] +// LOADCFGX: GuardFidTable [ +// LOADCFG-NEXTX: 0x180001000 +// LOADCFG-NEXTX: 0x180002000 +// LOADCFG-NEXTX: 0x180003000 +// LOADCFG-NEXTX: ] +// LOADCFGX: ] + +// RUN: lld-link -dll -noentry -machine:arm64ec func-gfids-arm64.obj func-gfids-arm64ec.obj func-amd64.obj -guard:cf -out:out-ec.dll \ +// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj +// RUN: llvm-readobj --coff-load-config out-ec.dll | FileCheck --check-prefix=LOADCFG %s // Check that exports from both views are present in CF guard tables. // RUN: lld-link -dll -noentry -machine:arm64x func-exp-arm64.obj func-exp-arm64ec.obj -guard:cf -out:out-exp.dll \ // RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj -// RUN: llvm-readobj --coff-load-config out-exp.dll | FileCheck --check-prefix=LOADCFG %s +// RUN: llvm-readobj --coff-load-config out-exp.dll | FileCheck --check-prefixes=LOADCFG,LOADCFGX %s + +// RUN: lld-link -dll -noentry -machine:arm64ec func-exp-arm64.obj func-exp-arm64ec.obj -guard:cf -out:out-exp-ec.dll \ +// RUN: loadconfig-arm64ec.obj loadconfig-arm64.obj +// RUN: llvm-readobj --coff-load-config out-exp-ec.dll | FileCheck --check-prefixes=LOADCFG %s // Check that entry points from both views are present in CF guard tables. diff --git a/lld/test/COFF/arm64x-import.test b/lld/test/COFF/arm64x-import.test index 7441c71d87710..612b5f9b71de1 100644 --- a/lld/test/COFF/arm64x-import.test +++ b/lld/test/COFF/arm64x-import.test @@ -56,7 +56,7 @@ DISASM-12T-NEXT: 180002040: d65f03c0 ret DISASM-12T-NEXT: ... DISASM-12T-NEXT: 180003000: ff 25 fa 0f 00 00 jmpq *0xffa(%rip) # 0x180004000 -RUN: llvm-readobj --coff-imports test-12-thunks.dll | FileCheck --check-prefix=IMPORTS-12 %s +RUN: llvm-readobj --coff-imports test-12-thunks.dll | FileCheck --check-prefixes=IMPORTS-12,IMPORTS-12-EC %s IMPORTS-12: Import { IMPORTS-12-NEXT: Name: test.dll IMPORTS-12-NEXT: ImportLookupTableRVA: 0x5348 @@ -65,13 +65,13 @@ IMPORTS-12-NEXT: Symbol: func1 (0) IMPORTS-12-NEXT: Symbol: func2 (0) IMPORTS-12-NEXT: } IMPORTS-12-NEXT: HybridObject { -IMPORTS-12: Import { -IMPORTS-12-NEXT: Name: test.dll -IMPORTS-12-NEXT: ImportLookupTableRVA: 0x5348 -IMPORTS-12-NEXT: ImportAddressTableRVA: 0x4000 -IMPORTS-12-NEXT: Symbol: func1 (0) -IMPORTS-12-NEXT: Symbol: func2 (0) -IMPORTS-12-NEXT: } +IMPORTS-12-EC: Import { +IMPORTS-12-EC-NEXT: Name: test.dll +IMPORTS-12-EC-NEXT: ImportLookupTableRVA: 0x5348 +IMPORTS-12-EC-NEXT: ImportAddressTableRVA: 0x4000 +IMPORTS-12-EC-NEXT: Symbol: func1 (0) +IMPORTS-12-EC-NEXT: Symbol: func2 (0) +IMPORTS-12-EC-NEXT:} IMPORTS-12-NEXT: } RUN: llvm-readobj --hex-dump=.test test-12-thunks.dll | FileCheck --check-prefix=FUNC-12-THUNKS %s @@ -81,6 +81,13 @@ FUNC-12-THUNKS-NEXT: 0x180009010 08600000 08400000 RUN: llvm-readobj --hex-dump=.testa test-12-thunks.dll | FileCheck --check-prefix=FUNC-12-THUNKSA %s FUNC-12-THUNKSA: 0x18000a000 00400000 08400000 00100000 +RUN: lld-link -machine:arm64ec -dll -noentry -out:test-12-thunks-ec.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: icall.obj func12-thunks-arm64ec.obj func12-thunks-arm64.obj imp-arm64ec.lib imp-arm64.lib +RUN: llvm-objdump -d test-12-thunks-ec.dll | FileCheck --check-prefix=DISASM-12T %s +RUN: llvm-readobj --hex-dump=.test test-12-thunks-ec.dll | FileCheck --check-prefix=FUNC-12-THUNKS %s +RUN: llvm-readobj --hex-dump=.testa test-12-thunks-ec.dll | FileCheck --check-prefix=FUNC-12-THUNKSA %s +RUN: llvm-readobj --coff-imports test-12-thunks-ec.dll | FileCheck --check-prefix=IMPORTS-12-EC %s + # If the ordinals of named imports don't match, use the EC value. @@ -146,7 +153,7 @@ IMPORTS-ORD2-NEXT: } RUN: lld-link -machine:arm64x -dll -noentry -out:test2.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ RUN: icall.obj func12-arm64ec.obj func123-arm64.obj imp-arm64x.lib -RUN: llvm-readobj --coff-imports test2.dll | FileCheck --check-prefix=IMPORTS-123-12 %s +RUN: llvm-readobj --coff-imports test2.dll | FileCheck --check-prefixes=IMPORTS-123-12,IMPORTS-123-12-EC %s IMPORTS-123-12: Import { IMPORTS-123-12-NEXT: Name: test.dll IMPORTS-123-12-NEXT: ImportLookupTableRVA: 0x3338 @@ -156,13 +163,13 @@ IMPORTS-123-12-NEXT: Symbol: func1 (0) IMPORTS-123-12-NEXT: Symbol: func2 (0) IMPORTS-123-12-NEXT: } IMPORTS-123-12-NEXT: HybridObject { -IMPORTS-123-12: Import { -IMPORTS-123-12-NEXT: Name: test.dll -IMPORTS-123-12-NEXT: ImportLookupTableRVA: 0x3340 -IMPORTS-123-12-NEXT: ImportAddressTableRVA: 0x2008 -IMPORTS-123-12-NEXT: Symbol: func1 (0) -IMPORTS-123-12-NEXT: Symbol: func2 (0) -IMPORTS-123-12-NEXT: } +IMPORTS-123-12-EC: Import { +IMPORTS-123-12-EC-NEXT: Name: test.dll +IMPORTS-123-12-EC-NEXT: ImportLookupTableRVA: 0x3340 +IMPORTS-123-12-EC-NEXT: ImportAddressTableRVA: 0x2008 +IMPORTS-123-12-EC-NEXT: Symbol: func1 (0) +IMPORTS-123-12-EC-NEXT: Symbol: func2 (0) +IMPORTS-123-12-EC-NEXT:} IMPORTS-123-12-NEXT: } RUN: llvm-readobj --hex-dump=.test test2.dll | FileCheck --check-prefix=TEST-123-12 %s @@ -175,13 +182,20 @@ RUN: llvm-readobj --hex-dump=.rdata test2.dll | FileCheck --check-prefix=TEST-12 TEST-123-12AUX: 0x180004000 00000000 00000000 08100080 01000000 TEST-123-12AUX-NEXT: 0x180004010 1c100080 01000000 00000000 00000000 +RUN: lld-link -machine:arm64ec -dll -noentry -out:test2-ec.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: icall.obj func12-arm64ec.obj func123-arm64.obj imp-arm64x.lib +RUN: llvm-readobj --coff-imports test2-ec.dll | FileCheck --check-prefix=IMPORTS-123-12-EC %s +RUN: llvm-readobj --hex-dump=.test test2-ec.dll | FileCheck --check-prefix=TEST-123-12 %s +RUN: llvm-readobj --hex-dump=.testa test2-ec.dll | FileCheck --check-prefix=TEST-123-12A %s +RUN: llvm-readobj --hex-dump=.rdata test2-ec.dll | FileCheck --check-prefix=TEST-123-12AUX %s + # Link to the imported func1 and func2 from both native and EC code, and func3 from EC code. RUN: lld-link -machine:arm64x -dll -noentry -out:func-12-123.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ RUN: icall.obj func123-arm64ec.obj func12-arm64.obj imp-arm64x.lib -RUN: llvm-readobj --coff-imports func-12-123.dll | FileCheck --check-prefix=IMPORTS-12-123 %s +RUN: llvm-readobj --coff-imports func-12-123.dll | FileCheck --check-prefixes=IMPORTS-12-123,IMPORTS-12-123-EC %s IMPORTS-12-123: Import { IMPORTS-12-123-NEXT: Name: test.dll IMPORTS-12-123-NEXT: ImportLookupTableRVA: 0x3338 @@ -190,14 +204,14 @@ IMPORTS-12-123-NEXT: Symbol: func1 (0) IMPORTS-12-123-NEXT: Symbol: func2 (0) IMPORTS-12-123-NEXT: } IMPORTS-12-123-NEXT: HybridObject { -IMPORTS-12-123: Import { -IMPORTS-12-123-NEXT: Name: test.dll -IMPORTS-12-123-NEXT: ImportLookupTableRVA: 0x3338 -IMPORTS-12-123-NEXT: ImportAddressTableRVA: 0x2000 -IMPORTS-12-123-NEXT: Symbol: func1 (0) -IMPORTS-12-123-NEXT: Symbol: func2 (0) -IMPORTS-12-123-NEXT: Symbol: func3 (0) -IMPORTS-12-123-NEXT: } +IMPORTS-12-123-EC: Import { +IMPORTS-12-123-EC-NEXT: Name: test.dll +IMPORTS-12-123-EC-NEXT: ImportLookupTableRVA: 0x3338 +IMPORTS-12-123-EC-NEXT: ImportAddressTableRVA: 0x2000 +IMPORTS-12-123-EC-NEXT: Symbol: func1 (0) +IMPORTS-12-123-EC-NEXT: Symbol: func2 (0) +IMPORTS-12-123-EC-NEXT: Symbol: func3 (0) +IMPORTS-12-123-EC-NEXT:} IMPORTS-12-123-NEXT: } RUN: llvm-readobj --hex-dump=.test func-12-123.dll | FileCheck --check-prefix=TEST-12-123 %s @@ -211,6 +225,12 @@ RUN: llvm-readobj --hex-dump=.rdata func-12-123.dll | FileCheck --check-prefix=T TEST-12-123AUX: 0x180004000 08100080 01000000 1c100080 01000000 TEST-12-123AUX-NEXT: 0x180004010 30100080 01000000 00000000 00000000 +RUN: lld-link -machine:arm64ec -dll -noentry -out:func-12-123-ec.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: icall.obj func123-arm64ec.obj func12-arm64.obj imp-arm64x.lib +RUN: llvm-readobj --coff-imports func-12-123-ec.dll | FileCheck --check-prefix=IMPORTS-12-123-EC %s +RUN: llvm-readobj --hex-dump=.test func-12-123-ec.dll | FileCheck --check-prefix=TEST-12-123 %s +RUN: llvm-readobj --hex-dump=.testa func-12-123-ec.dll | FileCheck --check-prefix=TEST-12-123A %s +RUN: llvm-readobj --hex-dump=.rdata func-12-123-ec.dll | FileCheck --check-prefix=TEST-12-123AUX %s # Link to the imported func2 and func3 from both native and EC code, func4 from native code, # and func1 from EC code. @@ -218,7 +238,7 @@ TEST-12-123AUX-NEXT: 0x180004010 30100080 01000000 00000000 00000000 RUN: lld-link -machine:arm64x -dll -noentry -out:test-234-123.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ RUN: icall.obj func123-arm64ec.obj func234-arm64.obj imp-arm64x.lib -RUN: llvm-readobj --coff-imports test-234-123.dll | FileCheck --check-prefix=IMPORTS-234-123 %s +RUN: llvm-readobj --coff-imports test-234-123.dll | FileCheck --check-prefixes=IMPORTS-234-123,IMPORTS-234-123-EC %s IMPORTS-234-123: Import { IMPORTS-234-123-NEXT: Name: test.dll IMPORTS-234-123-NEXT: ImportLookupTableRVA: 0x3338 @@ -228,14 +248,14 @@ IMPORTS-234-123-NEXT: Symbol: func2 (0) IMPORTS-234-123-NEXT: Symbol: func3 (0) IMPORTS-234-123-NEXT: } IMPORTS-234-123-NEXT: HybridObject { -IMPORTS-234-123: Import { -IMPORTS-234-123-NEXT: Name: test.dll -IMPORTS-234-123-NEXT: ImportLookupTableRVA: 0x3340 -IMPORTS-234-123-NEXT: ImportAddressTableRVA: 0x2008 -IMPORTS-234-123-NEXT: Symbol: func2 (0) -IMPORTS-234-123-NEXT: Symbol: func3 (0) -IMPORTS-234-123-NEXT: Symbol: func1 (0) -IMPORTS-234-123-NEXT: } +IMPORTS-234-123-EC: Import { +IMPORTS-234-123-EC-NEXT: Name: test.dll +IMPORTS-234-123-EC-NEXT: ImportLookupTableRVA: 0x3340 +IMPORTS-234-123-EC-NEXT: ImportAddressTableRVA: 0x2008 +IMPORTS-234-123-EC-NEXT: Symbol: func2 (0) +IMPORTS-234-123-EC-NEXT: Symbol: func3 (0) +IMPORTS-234-123-EC-NEXT: Symbol: func1 (0) +IMPORTS-234-123-EC-NEXT:} IMPORTS-234-123-NEXT: } RUN: llvm-readobj --hex-dump=.test test-234-123.dll | FileCheck --check-prefix=TEST-234-123 %s @@ -245,13 +265,19 @@ TEST-234-123-NEXT: 0x180007010 10400000 1020000 RUN: llvm-readobj --hex-dump=.testa test-234-123.dll | FileCheck --check-prefix=TEST-234-123A %s TEST-234-123A: 0x180008000 08200000 10200000 00200000 +RUN: lld-link -machine:arm64ec -dll -noentry -out:test-234-123-ec.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: icall.obj func123-arm64ec.obj func234-arm64.obj imp-arm64x.lib +RUN: llvm-readobj --coff-imports test-234-123-ec.dll | FileCheck --check-prefix=IMPORTS-234-123-EC %s +RUN: llvm-readobj --hex-dump=.test test-234-123-ec.dll | FileCheck --check-prefix=TEST-234-123 %s +RUN: llvm-readobj --hex-dump=.testa test-234-123-ec.dll | FileCheck --check-prefix=TEST-234-123A %s + # Link to the imported func3 and func4 from native code, and func1 and func2 from EC code. RUN: lld-link -machine:arm64x -dll -noentry -out:test-34-12.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ RUN: icall.obj func12o-arm64ec.obj func34o-arm64.obj imp-arm64x.lib imp2.lib -RUN: llvm-readobj --coff-imports test-34-12.dll | FileCheck --check-prefix=IMPORTS-34-12 %s +RUN: llvm-readobj --coff-imports test-34-12.dll | FileCheck --check-prefixes=IMPORTS-34-12,IMPORTS-34-12-EC %s IMPORTS-34-12: Import { IMPORTS-34-12-NEXT: Name: test.dll IMPORTS-34-12-NEXT: ImportLookupTableRVA: 0x3350 @@ -266,19 +292,19 @@ IMPORTS-34-12-NEXT: ImportAddressTableRVA: 0x2028 IMPORTS-34-12-NEXT: Symbol: otherfunc (0) IMPORTS-34-12-NEXT: } IMPORTS-34-12-NEXT: HybridObject { -IMPORTS-34-12: Import { -IMPORTS-34-12-NEXT: Name: test.dll -IMPORTS-34-12-NEXT: ImportLookupTableRVA: 0x3360 -IMPORTS-34-12-NEXT: ImportAddressTableRVA: 0x2010 -IMPORTS-34-12-NEXT: Symbol: func1 (0) -IMPORTS-34-12-NEXT: Symbol: func2 (0) -IMPORTS-34-12-NEXT: } -IMPORTS-34-12-NEXT: Import { -IMPORTS-34-12-NEXT: Name: test2.dll -IMPORTS-34-12-NEXT: ImportLookupTableRVA: 0x3378 -IMPORTS-34-12-NEXT: ImportAddressTableRVA: 0x2028 -IMPORTS-34-12-NEXT: Symbol: otherfunc (0) -IMPORTS-34-12-NEXT: } +IMPORTS-34-12-EC: Import { +IMPORTS-34-12-EC-NEXT: Name: test.dll +IMPORTS-34-12-EC-NEXT: ImportLookupTableRVA: 0x3360 +IMPORTS-34-12-EC-NEXT: ImportAddressTableRVA: 0x2010 +IMPORTS-34-12-EC-NEXT: Symbol: func1 (0) +IMPORTS-34-12-EC-NEXT: Symbol: func2 (0) +IMPORTS-34-12-EC-NEXT:} +IMPORTS-34-12-EC-NEXT:Import { +IMPORTS-34-12-EC-NEXT: Name: test2.dll +IMPORTS-34-12-EC-NEXT: ImportLookupTableRVA: 0x3378 +IMPORTS-34-12-EC-NEXT: ImportAddressTableRVA: 0x2028 +IMPORTS-34-12-EC-NEXT: Symbol: otherfunc (0) +IMPORTS-34-12-EC-NEXT:} IMPORTS-34-12-NEXT: } RUN: llvm-readobj --hex-dump=.test test-34-12.dll | FileCheck --check-prefix=TEST-23-12 %s @@ -288,6 +314,12 @@ TEST-23-12-NEXT: 0x180007010 28400000 28200000 RUN: llvm-readobj --hex-dump=.testa test-34-12.dll | FileCheck --check-prefix=TEST-23-12A %s TEST-23-12A: 0x180008000 00200000 08200000 28200000 +RUN: lld-link -machine:arm64ec -dll -noentry -out:test-34-12-ec.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: icall.obj func12o-arm64ec.obj func34o-arm64.obj imp-arm64x.lib imp2.lib +RUN: llvm-readobj --coff-imports test-34-12-ec.dll | FileCheck --check-prefix=IMPORTS-34-12-EC %s +RUN: llvm-readobj --hex-dump=.test test-34-12-ec.dll | FileCheck --check-prefix=TEST-23-12 %s +RUN: llvm-readobj --hex-dump=.testa test-34-12-ec.dll | FileCheck --check-prefix=TEST-23-12A %s + # Link only to imported EC functions, with no native imports. @@ -335,7 +367,7 @@ IMPORTS-EC12-NEXT: } RUN: lld-link -machine:arm64x -dll -noentry -out:test-n12.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ RUN: func12-arm64.obj imp-arm64x.lib -RUN: llvm-readobj --coff-imports test-n12.dll | FileCheck --check-prefix=IMPORTS-N12 %s +RUN: llvm-readobj --coff-imports test-n12.dll | FileCheck --check-prefixes=IMPORTS-N12,IMPORTS-N12-EC %s IMPORTS-N12: Arch: aarch64 IMPORTS-N12-NEXT: AddressSize: 64bit @@ -347,16 +379,20 @@ IMPORTS-N12-NEXT: Symbol: func1 (0) IMPORTS-N12-NEXT: Symbol: func2 (0) IMPORTS-N12-NEXT: } IMPORTS-N12-NEXT: HybridObject { -IMPORTS-N12-NEXT: Format: COFF-ARM64EC -IMPORTS-N12-NEXT: Arch: aarch64 -IMPORTS-N12-NEXT: AddressSize: 64bit -IMPORTS-N12-NEXT: Import { -IMPORTS-N12-NEXT: Name: test.dll -IMPORTS-N12-NEXT: ImportLookupTableRVA: 0x2340 -IMPORTS-N12-NEXT: ImportAddressTableRVA: 0x1010 -IMPORTS-N12-NEXT: } +IMPORTS-N12-EC: Format: COFF-ARM64EC +IMPORTS-N12-EC-NEXT: Arch: aarch64 +IMPORTS-N12-EC-NEXT: AddressSize: 64bit +IMPORTS-N12-EC-NEXT: Import { +IMPORTS-N12-EC-NEXT: Name: test.dll +IMPORTS-N12-EC-NEXT: ImportLookupTableRVA: 0x2340 +IMPORTS-N12-EC-NEXT: ImportAddressTableRVA: 0x1010 +IMPORTS-N12-EC-NEXT: } IMPORTS-N12-NEXT: } +RUN: lld-link -machine:arm64ec -dll -noentry -out:test-n12-ec.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: func12-arm64.obj imp-arm64x.lib +RUN: llvm-readobj --coff-imports test-n12-ec.dll | FileCheck --check-prefix=IMPORTS-N12-EC %s + RUN: lld-link -machine:arm64x -dll -noentry -out:test-dup.dll loadconfig-arm64.obj loadconfig-arm64ec.obj icall.obj \ RUN: func12-arm64ec.obj func34-arm64.obj dup.lib diff --git a/lld/test/COFF/arm64x-symtab.s b/lld/test/COFF/arm64x-symtab.s index c634f8a6ed4c5..176e81a23be16 100644 --- a/lld/test/COFF/arm64x-symtab.s +++ b/lld/test/COFF/arm64x-symtab.s @@ -18,6 +18,8 @@ // RUN: not lld-link -machine:arm64x -dll -noentry -out:err1.dll symref-aarch64.obj sym-arm64ec.obj \ // RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s +// RUN: not lld-link -machine:arm64ec -dll -noentry -out:err1.dll symref-aarch64.obj sym-arm64ec.obj \ +// RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s // UNDEF: lld-link: error: undefined symbol: sym (native symbol) // UNDEF-NEXT: >>> referenced by symref-aarch64.obj:(.data) @@ -25,25 +27,34 @@ // RUN: not lld-link -machine:arm64x -dll -noentry -out:out.dll symref-arm64ec.obj sym-aarch64.obj \ // RUN: 2>&1 | FileCheck --check-prefix=UNDEFEC %s +// RUN: not lld-link -machine:arm64ec -dll -noentry -out:out.dll symref-arm64ec.obj sym-aarch64.obj \ +// RUN: 2>&1 | FileCheck --check-prefix=UNDEFEC %s // UNDEFEC: lld-link: error: undefined symbol: sym (EC symbol) // UNDEFEC-NEXT: >>> referenced by symref-arm64ec.obj:(.data) // RUN: not lld-link -machine:arm64x -dll -noentry -out:out.dll symref-x86_64.obj sym-aarch64.obj \ // RUN: 2>&1 | FileCheck --check-prefix=UNDEFX86 %s +// RUN: not lld-link -machine:arm64ec -dll -noentry -out:out.dll symref-x86_64.obj sym-aarch64.obj \ +// RUN: 2>&1 | FileCheck --check-prefix=UNDEFX86 %s // UNDEFX86: lld-link: error: undefined symbol: sym (EC symbol) // UNDEFX86-NEXT: >>> referenced by symref-x86_64.obj:(.data) // RUN: not lld-link -machine:arm64x -dll -noentry -out:err2.dll symref-aarch64.obj sym-x86_64.obj \ // RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s +// RUN: not lld-link -machine:arm64ec -dll -noentry -out:err2.dll symref-aarch64.obj sym-x86_64.obj \ +// RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s // Check that ARM64X target can have the same symbol names in both native and EC namespaces. // RUN: lld-link -machine:arm64x -dll -noentry -out:out.dll symref-aarch64.obj sym-aarch64.obj \ // RUN: symref-arm64ec.obj sym-x86_64.obj +// RUN: lld-link -machine:arm64ec -dll -noentry -out:out.dll symref-aarch64.obj sym-aarch64.obj \ +// RUN: symref-arm64ec.obj sym-x86_64.obj // Check that ARM64X target can reference both native and EC symbols from an archive. // RUN: lld-link -machine:arm64x -dll -noentry -out:out2.dll symref-aarch64.obj symref-arm64ec.obj sym.lib +// RUN: lld-link -machine:arm64ec -dll -noentry -out:out2.dll symref-aarch64.obj symref-arm64ec.obj sym.lib // Check that EC object files can reference x86_64 library symbols. @@ -55,15 +66,20 @@ // RUN: not lld-link -machine:arm64x -dll -noentry -out:err3.dll symref-aarch64.obj sym-x86_64.lib \ // RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s +// RUN: not lld-link -machine:arm64ec -dll -noentry -out:err3.dll symref-aarch64.obj sym-x86_64.lib \ +// RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s // Check that native object files can reference native library symbols. // RUN: lld-link -machine:arm64x -dll -noentry -out:out6.dll symref-aarch64.obj sym-aarch64.lib +// RUN: lld-link -machine:arm64ec -dll -noentry -out:out6.dll symref-aarch64.obj sym-aarch64.lib // Check that EC object files can't reference native ARM64 library symbols. // RUN: not lld-link -machine:arm64x -dll -noentry -out:err4.dll symref-arm64ec.obj sym-aarch64.lib \ // RUN: 2>&1 | FileCheck --check-prefix=UNDEFEC %s +// RUN: not lld-link -machine:arm64ec -dll -noentry -out:err4.dll symref-arm64ec.obj sym-aarch64.lib \ +// RUN: 2>&1 | FileCheck --check-prefix=UNDEFEC %s #--- symref.s .data diff --git a/lld/test/COFF/arm64x-wrap.s b/lld/test/COFF/arm64x-wrap.s index 4f600e38f7a83..5530bc47c884e 100644 --- a/lld/test/COFF/arm64x-wrap.s +++ b/lld/test/COFF/arm64x-wrap.s @@ -15,6 +15,10 @@ // CHECK: 0x180004000 02000000 02000000 01000000 02000000 // CHECK: 0x180004010 02000000 01000000 +// RUN: lld-link -machine:arm64ec -dll -noentry test-arm64.obj test-arm64ec.obj other-arm64.obj other-arm64ec.obj \ +// RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -out:out-ec.dll -wrap:sym -wrap:nosuchsym +// RUN: llvm-readobj --hex-dump=.test out-ec.dll | FileCheck %s + #--- test.s .section .test,"dr" .word sym diff --git a/lld/test/COFF/autoimport-arm64ec-data.test b/lld/test/COFF/autoimport-arm64ec-data.test index 1f22ca4917557..52e64d6020a83 100644 --- a/lld/test/COFF/autoimport-arm64ec-data.test +++ b/lld/test/COFF/autoimport-arm64ec-data.test @@ -12,7 +12,7 @@ RUN: llvm-objdump -s out.dll | FileCheck --check-prefix=CONTENTS %s IMPORTS: Import { IMPORTS-NEXT: Name: test.dll -IMPORTS-NEXT: ImportLookupTableRVA: 0x40E0 +IMPORTS-NEXT: ImportLookupTableRVA: 0x4100 IMPORTS-NEXT: ImportAddressTableRVA: 0x3000 IMPORTS-NEXT: Symbol: variable (0) IMPORTS-NEXT: }