Skip to content

Commit da68db3

Browse files
cjacekSquallATF
authored andcommitted
[LLD][COFF] Add support for x86_64 archives on ARM64X (llvm#128241)
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.
1 parent 1f6d9e4 commit da68db3

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

lld/COFF/InputFiles.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/LTO/LTO.h"
3030
#include "llvm/Object/Binary.h"
3131
#include "llvm/Object/COFF.h"
32+
#include "llvm/Object/COFFImportFile.h"
3233
#include "llvm/Support/Casting.h"
3334
#include "llvm/Support/Endian.h"
3435
#include "llvm/Support/Error.h"
@@ -122,6 +123,8 @@ ArchiveFile::ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m)
122123

123124
void ArchiveFile::parse() {
124125
COFFLinkerContext &ctx = symtab.ctx;
126+
SymbolTable *archiveSymtab = &symtab;
127+
125128
// Parse a MemoryBufferRef as an archive file.
126129
file = CHECK(Archive::create(mb), this);
127130

@@ -136,12 +139,50 @@ void ArchiveFile::parse() {
136139
// Read both EC and native symbols on ARM64X.
137140
if (!ctx.hybridSymtab)
138141
return;
142+
} else if (ctx.hybridSymtab) {
143+
// If the ECSYMBOLS section is missing in the archive, the archive could
144+
// be either a native-only ARM64 or x86_64 archive. Check the machine type
145+
// of the object containing a symbol to determine which symbol table to
146+
// use.
147+
Archive::symbol_iterator sym = file->symbol_begin();
148+
if (sym != file->symbol_end()) {
149+
MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN;
150+
Archive::Child child =
151+
CHECK(sym->getMember(),
152+
file->getFileName() +
153+
": could not get the buffer for a child of the archive");
154+
MemoryBufferRef mb = CHECK(
155+
child.getMemoryBufferRef(),
156+
file->getFileName() +
157+
": could not get the buffer for a child buffer of the archive");
158+
switch (identify_magic(mb.getBuffer())) {
159+
case file_magic::coff_object: {
160+
std::unique_ptr<COFFObjectFile> obj =
161+
CHECK(COFFObjectFile::create(mb),
162+
check(child.getName()) + ":" + ": not a valid COFF file");
163+
machine = MachineTypes(obj->getMachine());
164+
break;
165+
}
166+
case file_magic::coff_import_library:
167+
machine = MachineTypes(COFFImportFile(mb).getMachine());
168+
break;
169+
case file_magic::bitcode: {
170+
std::unique_ptr<lto::InputFile> obj =
171+
check(lto::InputFile::create(mb));
172+
machine = BitcodeFile::getMachineType(obj.get());
173+
break;
174+
}
175+
default:
176+
break;
177+
}
178+
archiveSymtab = &ctx.getSymtab(machine);
179+
}
139180
}
140181
}
141182

142183
// Read the symbol table to construct Lazy objects.
143184
for (const Archive::Symbol &sym : file->symbols())
144-
ctx.symtab.addLazyArchive(this, sym);
185+
archiveSymtab->addLazyArchive(this, sym);
145186
}
146187

147188
// Returns a buffer pointing to a member file containing a given symbol.

lld/test/COFF/arm64x-symtab.s

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows symref.s -o symref-aarch64.obj
88
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows symref.s -o symref-arm64ec.obj
99
// RUN: llvm-mc -filetype=obj -triple=x86_64-windows symref.s -o symref-x86_64.obj
10+
// RUN: llvm-as sym.ll -o sym.ll.obj
1011
// RUN: llvm-lib -machine:arm64x -out:sym.lib sym-aarch64.obj sym-arm64ec.obj
12+
// RUN: llvm-lib -machine:amd64 -out:sym-x86_64.lib sym-x86_64.obj
13+
// RUN: llvm-lib -machine:amd64 -out:sym-ll.lib sym.ll.obj
14+
// RUN: llvm-lib -machine:amd64 -out:sym-imp.lib -def:sym.def
15+
// RUN: llvm-lib -machine:arm64 -out:sym-aarch64.lib sym-aarch64.obj
1116

1217
// Check that native object files can't reference EC symbols.
1318

@@ -40,12 +45,49 @@
4045

4146
// RUN: lld-link -machine:arm64x -dll -noentry -out:out2.dll symref-aarch64.obj symref-arm64ec.obj sym.lib
4247

48+
// Check that EC object files can reference x86_64 library symbols.
49+
50+
// RUN: lld-link -machine:arm64x -dll -noentry -out:out3.dll symref-arm64ec.obj sym-x86_64.lib
51+
// RUN: lld-link -machine:arm64x -dll -noentry -out:out4.dll symref-arm64ec.obj sym-ll.lib
52+
// RUN: lld-link -machine:arm64x -dll -noentry -out:out5.dll symref-arm64ec.obj sym-imp.lib
53+
54+
// Check that native object files can't reference x86_64 library symbols.
55+
56+
// RUN: not lld-link -machine:arm64x -dll -noentry -out:err3.dll symref-aarch64.obj sym-x86_64.lib \
57+
// RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s
58+
59+
// Check that native object files can reference native library symbols.
60+
61+
// RUN: lld-link -machine:arm64x -dll -noentry -out:out6.dll symref-aarch64.obj sym-aarch64.lib
62+
63+
// Check that EC object files can't reference native ARM64 library symbols.
64+
65+
// RUN: not lld-link -machine:arm64x -dll -noentry -out:err4.dll symref-arm64ec.obj sym-aarch64.lib \
66+
// RUN: 2>&1 | FileCheck --check-prefix=UNDEFEC %s
67+
4368
#--- symref.s
4469
.data
4570
.rva sym
4671

72+
.text
73+
.globl __icall_helper_arm64ec
74+
__icall_helper_arm64ec:
75+
ret
76+
4777
#--- sym.s
4878
.data
4979
.globl sym
5080
sym:
5181
.word 0
82+
83+
#--- sym.ll
84+
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"
85+
target triple = "x86_64-unknown-windows-msvc19.33.0"
86+
87+
@sym = dso_local global i32 0, align 4
88+
89+
#--- sym.def
90+
LIBRARY test.dll
91+
EXPORTS
92+
Func
93+
sym

0 commit comments

Comments
 (0)