diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 2272963e43c5..a4757b1b4056 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -450,8 +450,10 @@ void BitcodeFile::parse(DenseSet &ComdatGroups) { continue; if (!(Flags & BasicSymbolRef::SF_Global)) continue; - if (Flags & BasicSymbolRef::SF_FormatSpecific) + if (GV->hasAppendingLinkage()) { + ExtraKeeps.push_back(GV->getName().copy(Alloc)); continue; + } uint8_t Visibility = getGvVisibility(GV); SmallString<64> Name; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 48fe27d31f2d..94d0a3767603 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -185,9 +185,17 @@ public: static bool classof(const InputFile *F); void parse(llvm::DenseSet &ComdatGroups); ArrayRef getSymbols() { return SymbolBodies; } + ArrayRef getExtraKeeps() { return ExtraKeeps; } private: std::vector SymbolBodies; + // Some symbols like llvm.global_ctors are internal to the IR and so + // don't show up in SymbolBodies, but must be kept when creating the + // combined LTO module. We track them here. + // We currently use a different Module for creating SymbolBody's vs when + // we are creating the combined LTO module, and so we can't store IR + // pointers directly and must rely on the IR names. + std::vector ExtraKeeps; llvm::BumpPtrAllocator Alloc; llvm::StringSaver Saver{Alloc}; }; diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index a5a88a09b484..cdff124b6920 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -155,6 +155,11 @@ static void addBitcodeFile(IRMover &Mover, BitcodeFile &F, assert(GV); Keep.push_back(GV); } + for (StringRef S : F.getExtraKeeps()) { + GlobalValue *GV = M->getNamedValue(S); + assert(GV); + Keep.push_back(GV); + } Mover.move(std::move(M), Keep, [](GlobalValue &, IRMover::ValueAdder) {}); } diff --git a/lld/test/ELF/lto/ctors.ll b/lld/test/ELF/lto/ctors.ll new file mode 100644 index 000000000000..629e503f474a --- /dev/null +++ b/lld/test/ELF/lto/ctors.ll @@ -0,0 +1,15 @@ +; REQUIRES: x86 +; RUN: llvm-as %s -o %t.o +; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared +; RUN: llvm-readobj -sections %t.so | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }] +define void @ctor() { + ret void +} + +; The llvm.global_ctors should end up producing constructors. +; CHECK: Name: .ctors