diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 7b105fb4c17a2..bb9f1407b51f7 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -29,6 +29,7 @@ #include "llvm/LTO/LTO.h" #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/COFFImportFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -122,6 +123,8 @@ ArchiveFile::ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m) void ArchiveFile::parse() { COFFLinkerContext &ctx = symtab.ctx; + SymbolTable *archiveSymtab = &symtab; + // Parse a MemoryBufferRef as an archive file. file = CHECK(Archive::create(mb), this); @@ -136,12 +139,50 @@ void ArchiveFile::parse() { // Read both EC and native symbols on ARM64X. if (!ctx.hybridSymtab) return; + } else if (ctx.hybridSymtab) { + // 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 + // use. + Archive::symbol_iterator sym = file->symbol_begin(); + if (sym != file->symbol_end()) { + MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN; + Archive::Child child = + CHECK(sym->getMember(), + file->getFileName() + + ": could not get the buffer for a child of the archive"); + MemoryBufferRef mb = CHECK( + child.getMemoryBufferRef(), + file->getFileName() + + ": could not get the buffer for a child buffer of the archive"); + switch (identify_magic(mb.getBuffer())) { + case file_magic::coff_object: { + std::unique_ptr obj = + CHECK(COFFObjectFile::create(mb), + check(child.getName()) + ":" + ": not a valid COFF file"); + machine = MachineTypes(obj->getMachine()); + break; + } + case file_magic::coff_import_library: + machine = MachineTypes(COFFImportFile(mb).getMachine()); + break; + case file_magic::bitcode: { + std::unique_ptr obj = + check(lto::InputFile::create(mb)); + machine = BitcodeFile::getMachineType(obj.get()); + break; + } + default: + break; + } + archiveSymtab = &ctx.getSymtab(machine); + } } } // Read the symbol table to construct Lazy objects. for (const Archive::Symbol &sym : file->symbols()) - ctx.symtab.addLazyArchive(this, sym); + archiveSymtab->addLazyArchive(this, sym); } // Returns a buffer pointing to a member file containing a given symbol. diff --git a/lld/test/COFF/arm64x-symtab.s b/lld/test/COFF/arm64x-symtab.s index 2b269dde61f61..16d78b2acc49f 100644 --- a/lld/test/COFF/arm64x-symtab.s +++ b/lld/test/COFF/arm64x-symtab.s @@ -7,7 +7,12 @@ // RUN: llvm-mc -filetype=obj -triple=aarch64-windows symref.s -o symref-aarch64.obj // RUN: llvm-mc -filetype=obj -triple=arm64ec-windows symref.s -o symref-arm64ec.obj // RUN: llvm-mc -filetype=obj -triple=x86_64-windows symref.s -o symref-x86_64.obj +// RUN: llvm-as sym.ll -o sym.ll.obj // RUN: llvm-lib -machine:arm64x -out:sym.lib sym-aarch64.obj sym-arm64ec.obj +// RUN: llvm-lib -machine:amd64 -out:sym-x86_64.lib sym-x86_64.obj +// RUN: llvm-lib -machine:amd64 -out:sym-ll.lib sym.ll.obj +// RUN: llvm-lib -machine:amd64 -out:sym-imp.lib -def:sym.def +// RUN: llvm-lib -machine:arm64 -out:sym-aarch64.lib sym-aarch64.obj // Check that native object files can't reference EC symbols. @@ -40,12 +45,49 @@ // RUN: lld-link -machine:arm64x -dll -noentry -out:out2.dll symref-aarch64.obj symref-arm64ec.obj sym.lib +// Check that EC object files can reference x86_64 library symbols. + +// RUN: lld-link -machine:arm64x -dll -noentry -out:out3.dll symref-arm64ec.obj sym-x86_64.lib +// RUN: lld-link -machine:arm64x -dll -noentry -out:out4.dll symref-arm64ec.obj sym-ll.lib +// RUN: lld-link -machine:arm64x -dll -noentry -out:out5.dll symref-arm64ec.obj sym-imp.lib + +// Check that native object files can't reference x86_64 library symbols. + +// 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 + +// 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 + +// 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 + #--- symref.s .data .rva sym + .text + .globl __icall_helper_arm64ec +__icall_helper_arm64ec: + ret + #--- sym.s .data .globl sym sym: .word 0 + +#--- sym.ll +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-windows-msvc19.33.0" + +@sym = dso_local global i32 0, align 4 + +#--- sym.def +LIBRARY test.dll +EXPORTS + Func + sym