From: Tobias Edler von Koch Date: Thu, 13 Apr 2017 16:24:14 +0000 (+0000) Subject: LTO: Pass SF_Executable flag through to InputFile::Symbol X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7f80f1bbf58b26d2cf7f267f895c7b3ce177d0e8;p=llvm LTO: Pass SF_Executable flag through to InputFile::Symbol Summary: The linker needs to be able to determine whether a symbol is text or data to handle the case of a common being overridden by a strong definition in an archive. If the archive contains a text member of the same name as the common, that function is discarded. However, if the archive contains a data member of the same name, that strong definition overrides the common. This is a behavior of ld.bfd, which the Qualcomm linker also supports in LTO. Here's a test case to illustrate: #### cat > 1.c << \! int blah; ! cat > 2.c << \! int blah() { return 0; } ! cat > 3.c << \! int blah = 20; ! clang -c 1.c clang -c 2.c clang -c 3.c ar cr lib.a 2.o 3.o ld 1.o lib.a -t #### The correct output is: 1.o (lib.a)3.o Thanks to Shankar Easwaran and Hemant Kulkarni for the test case! Reviewers: mehdi_amini, rafael, pcc, davide Reviewed By: pcc Subscribers: davide, llvm-commits, inglorion Differential Revision: https://reviews.llvm.org/D31901 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300205 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h index 693568f5b9a..8c083947b84 100644 --- a/include/llvm/LTO/LTO.h +++ b/include/llvm/LTO/LTO.h @@ -126,6 +126,7 @@ public: using irsymtab::Symbol::getCommonSize; using irsymtab::Symbol::getCommonAlignment; using irsymtab::Symbol::getCOFFWeakExternalFallback; + using irsymtab::Symbol::isExecutable; }; /// A range over the symbols in this InputFile. diff --git a/include/llvm/Object/IRSymtab.h b/include/llvm/Object/IRSymtab.h index 7ce6fa50e6d..98ef3ffcc97 100644 --- a/include/llvm/Object/IRSymtab.h +++ b/include/llvm/Object/IRSymtab.h @@ -92,6 +92,7 @@ struct Symbol { FB_global, FB_format_specific, FB_unnamed_addr, + FB_executable, }; /// The index into the Uncommon table, or -1 if this symbol does not have an @@ -166,6 +167,7 @@ struct Symbol { bool isGlobal() const { return (Flags >> S::FB_global) & 1; } bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; } bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; } + bool isExecutable() const { return (Flags >> S::FB_executable) & 1; } uint64_t getCommonSize() const { assert(isCommon()); diff --git a/lib/Object/IRSymtab.cpp b/lib/Object/IRSymtab.cpp index 1ef2c4bb730..f78b84b388a 100644 --- a/lib/Object/IRSymtab.cpp +++ b/lib/Object/IRSymtab.cpp @@ -125,6 +125,8 @@ Error Builder::addSymbol(ModuleSymbolTable::Symbol Msym) { Sym.Flags |= 1 << storage::Symbol::FB_global; if (Flags & object::BasicSymbolRef::SF_FormatSpecific) Sym.Flags |= 1 << storage::Symbol::FB_format_specific; + if (Flags & object::BasicSymbolRef::SF_Executable) + Sym.Flags |= 1 << storage::Symbol::FB_executable; Sym.ComdatIndex = -1; auto *GV = Msym.dyn_cast(); diff --git a/test/LTO/Resolution/X86/symtab.ll b/test/LTO/Resolution/X86/symtab.ll index 48eb198fb1c..e2729ac918a 100644 --- a/test/LTO/Resolution/X86/symtab.ll +++ b/test/LTO/Resolution/X86/symtab.ll @@ -11,37 +11,42 @@ source_filename = "src.c" !0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}} !llvm.module.flags = !{ !0 } -; CHECK: H------ _g1 +; CHECK: D------X _fun +define i32 @fun() { + ret i32 0 +} + +; CHECK: H------- _g1 @g1 = hidden global i32 0 -; CHECK: P------ _g2 +; CHECK: P------- _g2 @g2 = protected global i32 0 -; CHECK: D------ _g3 +; CHECK: D------- _g3 @g3 = global i32 0 -; CHECK: DU----- _g4 +; CHECK: DU------ _g4 @g4 = external global i32 -; CHECK: D--W--- _g5 +; CHECK: D--W---- _g5 @g5 = weak global i32 0 -; CHECK: D--W-O- _g6 +; CHECK: D--W-O-- _g6 @g6 = linkonce_odr unnamed_addr global i32 0 -; CHECK: D-----T _g7 +; CHECK: D-----T- _g7 @g7 = thread_local global i32 0 -; CHECK: D-C---- _g8 +; CHECK: D-C----- _g8 ; CHECK-NEXT: size 4 align 8 @g8 = common global i32 0, align 8 -; CHECK: D------ _g9 +; CHECK: D------- _g9 ; CHECK-NEXT: comdat g9 $g9 = comdat any @g9 = global i32 0, comdat -; CHECK: D--WI-- _g10 +; CHECK: D--WI--- _g10 ; CHECK-NEXT: comdat g9 ; CHECK-NEXT: fallback _g9 @g10 = weak alias i32, i32* @g9 diff --git a/tools/llvm-lto2/llvm-lto2.cpp b/tools/llvm-lto2/llvm-lto2.cpp index 52ba669279c..7a8d4055338 100644 --- a/tools/llvm-lto2/llvm-lto2.cpp +++ b/tools/llvm-lto2/llvm-lto2.cpp @@ -317,18 +317,19 @@ static int dumpSymtab(int argc, char **argv) { PrintBool('I', Sym.isIndirect()); PrintBool('O', Sym.canBeOmittedFromSymbolTable()); PrintBool('T', Sym.isTLS()); + PrintBool('X', Sym.isExecutable()); outs() << ' ' << Sym.getName() << '\n'; if (Sym.isCommon()) - outs() << " size " << Sym.getCommonSize() << " align " + outs() << " size " << Sym.getCommonSize() << " align " << Sym.getCommonAlignment() << '\n'; int Comdat = Sym.getComdatIndex(); if (Comdat != -1) - outs() << " comdat " << ComdatTable[Comdat] << '\n'; + outs() << " comdat " << ComdatTable[Comdat] << '\n'; if (Sym.isWeak() && Sym.isIndirect()) - outs() << " fallback " << Sym.getCOFFWeakExternalFallback() << '\n'; + outs() << " fallback " << Sym.getCOFFWeakExternalFallback() << '\n'; } outs() << '\n';