Index: lld/trunk/ELF/InputFiles.h =================================================================== --- lld/trunk/ELF/InputFiles.h +++ lld/trunk/ELF/InputFiles.h @@ -185,9 +185,17 @@ 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}; }; Index: lld/trunk/ELF/InputFiles.cpp =================================================================== --- lld/trunk/ELF/InputFiles.cpp +++ lld/trunk/ELF/InputFiles.cpp @@ -450,8 +450,10 @@ 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; Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -155,6 +155,11 @@ 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) {}); } Index: lld/trunk/test/ELF/lto/ctors.ll =================================================================== --- lld/trunk/test/ELF/lto/ctors.ll +++ lld/trunk/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