[lld] b0ac68c - [ELF] Prevent internalizing used comdat symbol

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 1 21:14:55 PST 2021


Author: Igor Kudrin
Date: 2021-12-02T12:10:06+07:00
New Revision: b0ac68ccb72909e047c86e6ee7e036d278be28ff

URL: https://github.com/llvm/llvm-project/commit/b0ac68ccb72909e047c86e6ee7e036d278be28ff
DIFF: https://github.com/llvm/llvm-project/commit/b0ac68ccb72909e047c86e6ee7e036d278be28ff.diff

LOG: [ELF] Prevent internalizing used comdat symbol

When a comdat symbol is defined in both bitcode and regular object
files, which are contained in the same archive, the linker could lose
the flag that the symbol is used in the regular object file and allow
LTO to internalize it, which led to "error: undefined symbol".

The issue was introduced in D79300.

Differential Revision: https://reviews.llvm.org/D114801

Added: 
    lld/test/ELF/lto/comdat-mixed-archive.test

Modified: 
    lld/ELF/InputFiles.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 040f71478547c..5becc2d2ed81e 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1145,9 +1145,12 @@ template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
       if ((sym->symbolKind == Symbol::LazyArchiveKind &&
            !cast<ArchiveFile>(sym->file)->parsed) ||
           (sym->symbolKind == Symbol::LazyObjectKind &&
-           cast<LazyObjFile>(sym->file)->extracted))
+           cast<LazyObjFile>(sym->file)->extracted)) {
         sym->replace(und);
-      else
+        // Prevent LTO from internalizing the symbol in case there is a
+        // reference to this symbol from this file.
+        sym->isUsedInRegularObj = true;
+      } else
         sym->resolve(und);
       continue;
     }

diff  --git a/lld/test/ELF/lto/comdat-mixed-archive.test b/lld/test/ELF/lto/comdat-mixed-archive.test
new file mode 100644
index 0000000000000..98cba1ff93c9e
--- /dev/null
+++ b/lld/test/ELF/lto/comdat-mixed-archive.test
@@ -0,0 +1,74 @@
+REQUIRES: x86
+
+;; This checks a case when an archive contains a bitcode and a regular object
+;; files, and a comdat symbol is defined and used in both of them. Previously,
+;; lld could lose the flag that the symbol is used in a regular object file
+;; which led to the LTO backend internalizing the symbol and the linker
+;; reporting an "undefined symbol" error.
+
+;; In this test, group "foo" in "obj.o" is rejected in favor of "bc.bc" but we
+;; need to prevent LTO from internalizing "foo" as there is still a reference
+;; from outside the group in "obj.o".
+
+RUN: rm -rf %t.dir
+RUN: split-file %s %t.dir
+RUN: cd %t.dir
+
+RUN: llvm-mc -filetype=obj -triple=x86_64 start.s -o start.o
+RUN: llvm-mc -filetype=obj -triple=x86_64 obj.s -o obj.o
+RUN: llvm-as bc.ll -o bc.bc
+RUN: llvm-nm bc.bc --no-sort | FileCheck %s --check-prefix=BCSYM
+RUN: llvm-ar rc lib.a obj.o bc.bc
+RUN: ld.lld start.o lib.a -y foo -y bar -o /dev/null | FileCheck %s --check-prefix=TRACE
+
+;; "bar" should be encountered before "foo" so that it triggers the loading of
+;; "obj.o" while "foo" is still lazy.
+BCSYM:      U bar
+BCSYM-NEXT: W foo
+
+;; Check that the symbols are handled in the expected order.
+TRACE:      lib.a: lazy definition of foo
+TRACE-NEXT: lib.a: lazy definition of bar
+TRACE-NEXT: lib.a(bc.bc): reference to bar
+TRACE-NEXT: lib.a(obj.o): reference to foo
+TRACE-NEXT: lib.a(obj.o): definition of bar
+TRACE-NEXT: lib.a(bc.bc): definition of foo
+TRACE-NEXT: <internal>: reference to foo
+;; The definition of "foo" is visible outside the LTO result.
+TRACE-NEXT: lto.tmp: definition of foo
+TRACE-NEXT: lto.tmp: reference to bar
+
+;--- start.s
+  .global _start, baz
+_start:
+  call baz
+
+;--- obj.s
+  .weak foo
+  .global bar
+
+  .section .text.foo,"axG", at progbits,foo,comdat
+foo:
+  ret
+
+  .section .text.bar,"ax", at progbits
+bar:
+  call foo
+
+;--- bc.ll
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+
+declare void @bar()
+
+define linkonce_odr void @foo() comdat {
+  ret void
+}
+
+define void @baz() {
+  call void @foo()
+  call void @bar()
+  ret void
+}


        


More information about the llvm-commits mailing list