Index: llvm/trunk/test/LTO/Resolution/X86/symtab.ll =================================================================== --- llvm/trunk/test/LTO/Resolution/X86/symtab.ll +++ llvm/trunk/test/LTO/Resolution/X86/symtab.ll @@ -0,0 +1,47 @@ +; RUN: llvm-as -o %t %s +; RUN: llvm-lto2 dump-symtab %t | FileCheck %s + +target triple = "i686-pc-windows-msvc18.0.0" +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" + +; CHECK: source filename: src.c +source_filename = "src.c" + +; CHECK: linker opts (COFF only): /include:foo +!0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}} +!llvm.module.flags = !{ !0 } + +; CHECK: H------ _g1 +@g1 = hidden global i32 0 + +; CHECK: P------ _g2 +@g2 = protected global i32 0 + +; CHECK: D------ _g3 +@g3 = global i32 0 + +; CHECK: DU----- _g4 +@g4 = external global i32 + +; CHECK: D--W--- _g5 +@g5 = weak global i32 0 + +; CHECK: D--W-O- _g6 +@g6 = linkonce_odr unnamed_addr global i32 0 + +; CHECK: D-----T _g7 +@g7 = thread_local global i32 0 + +; CHECK: D-C---- _g8 +; CHECK-NEXT: size 4 align 8 +@g8 = common global i32 0, align 8 + +; CHECK: D------ _g9 +; CHECK-NEXT: comdat g9 +$g9 = comdat any +@g9 = global i32 0, comdat + +; CHECK: D--WI-- _g10 +; CHECK-NEXT: comdat g9 +; CHECK-NEXT: fallback _g9 +@g10 = weak alias i32, i32* @g9 Index: llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp =================================================================== --- llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp +++ llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp @@ -127,7 +127,7 @@ } static int usage() { - errs() << "Available subcommands: run\n"; + errs() << "Available subcommands: dump-symtab run\n"; return 1; } @@ -287,6 +287,56 @@ return 0; } +static int dumpSymtab(int argc, char **argv) { + for (StringRef F : make_range(argv + 1, argv + argc)) { + std::unique_ptr MB = check(MemoryBuffer::getFile(F), F); + std::unique_ptr Input = + check(InputFile::create(MB->getMemBufferRef()), F); + + outs() << "source filename: " << Input->getSourceFileName() << '\n'; + outs() << "linker opts (COFF only): " << Input->getCOFFLinkerOpts() << '\n'; + + std::vector ComdatTable = Input->getComdatTable(); + for (const InputFile::Symbol &Sym : Input->symbols()) { + switch (Sym.getVisibility()) { + case GlobalValue::HiddenVisibility: + outs() << 'H'; + break; + case GlobalValue::ProtectedVisibility: + outs() << 'P'; + break; + case GlobalValue::DefaultVisibility: + outs() << 'D'; + break; + } + + auto PrintBool = [&](char C, bool B) { outs() << (B ? C : '-'); }; + PrintBool('U', Sym.isUndefined()); + PrintBool('C', Sym.isCommon()); + PrintBool('W', Sym.isWeak()); + PrintBool('I', Sym.isIndirect()); + PrintBool('O', Sym.canBeOmittedFromSymbolTable()); + PrintBool('T', Sym.isTLS()); + outs() << ' ' << Sym.getName() << '\n'; + + if (Sym.isCommon()) + outs() << " size " << Sym.getCommonSize() << " align " + << Sym.getCommonAlignment() << '\n'; + + int Comdat = Sym.getComdatIndex(); + if (Comdat != -1) + outs() << " comdat " << ComdatTable[Comdat] << '\n'; + + if (Sym.isWeak() && Sym.isIndirect()) + outs() << " fallback " << Sym.getCOFFWeakExternalFallback() << '\n'; + } + + outs() << '\n'; + } + + return 0; +} + int main(int argc, char **argv) { InitializeAllTargets(); InitializeAllTargetMCs(); @@ -302,6 +352,8 @@ StringRef Subcommand = argv[1]; // Ensure that argv[0] is correct after adjusting argv/argc. argv[1] = argv[0]; + if (Subcommand == "dump-symtab") + return dumpSymtab(argc - 1, argv + 1); if (Subcommand == "run") return run(argc - 1, argv + 1); return usage();