Skip to content

[LLD][COFF] Add support for x86_64 archives on ARM64X #128241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion lld/COFF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);

Expand All @@ -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<COFFObjectFile> 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<lto::InputFile> 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.
Expand Down
42 changes: 42 additions & 0 deletions lld/test/COFF/arm64x-symtab.s
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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
Loading