Skip to content

Commit a750de6

Browse files
committed
[lld][ELF] Error when deplibs adds new input file after LTO
Parsing the new input file's symbols might invalidate LTO codegen, but the semantics of deplibs require them to be parsed. Accordingly, report an error unless the file had already been added to the link. Fixes #56070
1 parent 7d1b6b2 commit a750de6

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

lld/ELF/Driver.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2966,6 +2966,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
29662966
// With this the symbol table should be complete. After this, no new names
29672967
// except a few linker-synthesized ones will be added to the symbol table.
29682968
const size_t numObjsBeforeLTO = ctx.objectFiles.size();
2969+
const size_t numInputFilesBeforeLTO = ctx.driver.files.size();
29692970
compileBitcodeFiles<ELFT>(skipLinkedOutput);
29702971

29712972
// Symbol resolution finished. Report backward reference problems,
@@ -2990,6 +2991,20 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
29902991
for (const DuplicateSymbol &d : ctx.duplicates)
29912992
reportDuplicate(*d.sym, d.file, d.section, d.value);
29922993

2994+
// ELF dependent libraries may have introduced new input files after LTO has
2995+
// completed. This is an error if the file hadn't already been parsed, since
2996+
// it's no longer legal to change the symbol table by parsing it.
2997+
auto newInputFiles = ArrayRef(ctx.driver.files).slice(numInputFilesBeforeLTO);
2998+
if (!newInputFiles.empty()) {
2999+
DenseSet<StringRef> oldFilenames;
3000+
for (InputFile *f :
3001+
ArrayRef(ctx.driver.files).slice(0, numInputFilesBeforeLTO))
3002+
oldFilenames.insert(f->getName());
3003+
for (InputFile *newFile : newInputFiles)
3004+
if (!oldFilenames.contains(newFile->getName()))
3005+
error("input file '" + newFile->getName() + "' added after LTO");
3006+
}
3007+
29933008
// Handle --exclude-libs again because lto.tmp may reference additional
29943009
// libcalls symbols defined in an excluded archive. This may override
29953010
// versionId set by scanVersionScript().

lld/test/ELF/deplibs-lto.s

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# REQUIRES: x86
2+
3+
# RUN: rm -rf %t && split-file %s %t && cd %t
4+
# RUN: llvm-mc -filetype=obj -triple=aarch64 -o deplibs.o deplibs.s
5+
# RUN: llvm-mc -filetype=obj -triple=aarch64 -o foo.o foo.s
6+
# RUN: llvm-as -o lto.o lto.ll
7+
# RUN: llvm-ar rc libdeplibs.a deplibs.o
8+
# RUN: llvm-ar rc libfoo.a foo.o
9+
10+
## LTO emits a libcall (`__aarch64_ldadd4_relax`) that is resolved using a
11+
## library (libdeplibc.a) that contains a `.deplibs` section pointing to a file
12+
## not yet added to the link.
13+
14+
# RUN: not ld.lld lto.o -u a -L. -ldeplibs 2>&1 | FileCheck %s
15+
# CHECK: error: input file 'foo.o' added after LTO
16+
17+
## Including the file before LTO prevents the issue.
18+
19+
# RUN: ld.lld lto.o -u a -L. -ldeplibs -lfoo
20+
21+
#--- foo.s
22+
.global foo
23+
foo:
24+
#--- deplibs.s
25+
.global __aarch64_ldadd4_relax
26+
__aarch64_ldadd4_relax:
27+
b foo
28+
.section ".deplibs","MS",@llvm_dependent_libraries,1
29+
.asciz "foo"
30+
#--- lto.ll
31+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
32+
target triple = "aarch64"
33+
34+
define void @a(i32* nocapture %0) #0 {
35+
%2 = atomicrmw add i32* %0, i32 1 monotonic, align 4
36+
ret void
37+
}
38+
39+
attributes #0 = { "target-features"="+outline-atomics" }

0 commit comments

Comments
 (0)