From: David Blaikie Date: Fri, 14 Dec 2018 22:44:46 +0000 (+0000) Subject: DebugInfo: Avoid using split DWARF when the split unit would be empty. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b4b260e17979210464c395ee00e6c985f305a16e;p=llvm DebugInfo: Avoid using split DWARF when the split unit would be empty. In ThinLTO many split CUs may be effectively empty because of the lack of support for cross-unit references in split DWARF. Using a split unit in those cases is just a waste/overhead - and turned out to be one contributor to a significant symbolizer performance issue when global variable debug info was being imported (see r348416 for the primary fix) due to symbolizers seeing CUs with no ranges, assuming there might still be addresses covered and walking into the split CU to see if there are any ranges (when that split CU was in a DWP file, that meant loading the DWP and its index, the index was extra large because of all these fractured/empty CUs... and so was very expensive to load). (the 3rd fix which will follow, is to assume that a CU with no ranges is empty rather than merely missing its CU level range data - and to not walk into its DIEs (split or otherwise) in search of address information that is generally not present) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349207 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 774f7d1df4e..5fc8d0622a4 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -568,25 +568,10 @@ void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const { U.addFlag(D, dwarf::DW_AT_GNU_pubnames); } -// Create new DwarfCompileUnit for the given metadata node with tag -// DW_TAG_compile_unit. -DwarfCompileUnit & -DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { - if (auto *CU = CUMap.lookup(DIUnit)) - return *CU; - StringRef FN = DIUnit->getFilename(); - CompilationDir = DIUnit->getDirectory(); - - auto OwnedUnit = llvm::make_unique( - InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); - DwarfCompileUnit &NewCU = *OwnedUnit; +void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, + DwarfCompileUnit &NewCU) { DIE &Die = NewCU.getUnitDie(); - InfoHolder.addUnit(std::move(OwnedUnit)); - if (useSplitDwarf()) { - NewCU.setSkeleton(constructSkeletonCU(NewCU)); - NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, - Asm->TM.Options.MCOptions.SplitDwarfFile); - } + StringRef FN = DIUnit->getFilename(); for (auto *IE : DIUnit->getImportedEntities()) NewCU.addImportedEntity(IE); @@ -640,11 +625,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { dwarf::DW_FORM_data1, RVer); } - if (useSplitDwarf()) - NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); - else - NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); - if (DIUnit->getDWOId()) { // This CU is either a clang module DWO or a skeleton CU. NewCU.addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, @@ -654,9 +634,31 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, DIUnit->getSplitDebugFilename()); } +} +// Create new DwarfCompileUnit for the given metadata node with tag +// DW_TAG_compile_unit. +DwarfCompileUnit & +DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { + if (auto *CU = CUMap.lookup(DIUnit)) + return *CU; + + CompilationDir = DIUnit->getDirectory(); + + auto OwnedUnit = llvm::make_unique( + InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + InfoHolder.addUnit(std::move(OwnedUnit)); + + if (useSplitDwarf()) { + NewCU.setSkeleton(constructSkeletonCU(NewCU)); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); + } else { + finishUnitAttributes(DIUnit, NewCU); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); + } CUMap.insert({DIUnit, &NewCU}); - CUDieMap.insert({&Die, &NewCU}); + CUDieMap.insert({&NewCU.getUnitDie(), &NewCU}); return NewCU; } @@ -851,7 +853,12 @@ void DwarfDebug::finalizeModuleInfo() { // If we're splitting the dwarf out now that we've got the entire // CU then add the dwo id to it. auto *SkCU = TheCU.getSkeleton(); - if (useSplitDwarf()) { + if (useSplitDwarf() && !empty(TheCU.getUnitDie().children())) { + finishUnitAttributes(TheCU.getCUNode(), TheCU); + TheCU.addString(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); + SkCU->addString(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); // Emit a unique identifier for this CU. uint64_t ID = DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie()); @@ -870,6 +877,8 @@ void DwarfDebug::finalizeModuleInfo() { SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, Sym, Sym); } + } else if (SkCU) { + finishUnitAttributes(SkCU->getCUNode(), *SkCU); } // If we have code split among multiple sections or non-contiguous @@ -882,7 +891,9 @@ void DwarfDebug::finalizeModuleInfo() { // We don't keep track of which addresses are used in which CU so this // is a bit pessimistic under LTO. - if (!AddrPool.isEmpty()) + if (!AddrPool.isEmpty() && + (getDwarfVersion() >= 5 || + (SkCU && !empty(TheCU.getUnitDie().children())))) U.addAddrTableBase(); if (unsigned NumRanges = TheCU.getRanges().size()) { @@ -2483,8 +2494,6 @@ void DwarfDebug::emitDebugMacinfo() { void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, std::unique_ptr NewU) { - NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name, - Asm->TM.Options.MCOptions.SplitDwarfFile); if (!CompilationDir.empty()) NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index c73d442af2f..56aac676ed5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -540,6 +540,8 @@ class DwarfDebug : public DebugHandlerBase { /// Create new DwarfCompileUnit for the given metadata node with tag /// DW_TAG_compile_unit. DwarfCompileUnit &getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit); + void finishUnitAttributes(const DICompileUnit *DIUnit, + DwarfCompileUnit &NewCU); /// Construct imported_module or imported_declaration DIE. void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/lib/CodeGen/AsmPrinter/DwarfFile.cpp index 4e410bb49be..0bfa1d46008 100644 --- a/lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -39,13 +39,14 @@ void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) { if (TheU->getCUNode()->isDebugDirectivesOnly()) return; - DIE &Die = TheU->getUnitDie(); - MCSection *USection = TheU->getSection(); - Asm->OutStreamer->SwitchSection(USection); + MCSection *S = TheU->getSection(); - TheU->emitHeader(UseOffsets); + if (!S) + return; - Asm->emitDwarfDIE(Die); + Asm->OutStreamer->SwitchSection(S); + TheU->emitHeader(UseOffsets); + Asm->emitDwarfDIE(TheU->getUnitDie()); } // Compute the size and offset for each DIE. diff --git a/test/DebugInfo/X86/fission-cu.ll b/test/DebugInfo/X86/fission-cu.ll index 1551bedc981..95669b6dd59 100644 --- a/test/DebugInfo/X86/fission-cu.ll +++ b/test/DebugInfo/X86/fission-cu.ll @@ -25,18 +25,18 @@ source_filename = "test/DebugInfo/X86/fission-cu.ll" ; CHECK: Abbrev table for offset: 0x00000000 ; CHECK: [1] DW_TAG_compile_unit DW_CHILDREN_no ; CHECK: DW_AT_stmt_list DW_FORM_sec_offset -; CHECK: DW_AT_GNU_dwo_name DW_FORM_strp ; CHECK: DW_AT_comp_dir DW_FORM_strp +; CHECK: DW_AT_GNU_dwo_name DW_FORM_strp ; CHECK: DW_AT_GNU_dwo_id DW_FORM_data8 ; Check that we're using the right forms. ; CHECK: .debug_abbrev.dwo contents: ; CHECK: Abbrev table for offset: 0x00000000 ; CHECK: [1] DW_TAG_compile_unit DW_CHILDREN_yes -; CHECK: DW_AT_GNU_dwo_name DW_FORM_GNU_str_index ; CHECK: DW_AT_producer DW_FORM_GNU_str_index ; CHECK: DW_AT_language DW_FORM_data2 ; CHECK: DW_AT_name DW_FORM_GNU_str_index +; CHECK: DW_AT_GNU_dwo_name DW_FORM_GNU_str_index ; CHECK-NOT: DW_AT_low_pc ; CHECK-NOT: DW_AT_stmt_list ; CHECK-NOT: DW_AT_comp_dir @@ -58,48 +58,48 @@ source_filename = "test/DebugInfo/X86/fission-cu.ll" ; CHECK: .debug_info contents: ; CHECK: DW_TAG_compile_unit ; CHECK-NEXT: DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) -; CHECK-NEXT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000000] = "baz.dwo") -; CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000008] = "/usr/local/google/home/echristo/tmp") +; CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000000] = "/usr/local/google/home/echristo/tmp") +; CHECK-NEXT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000024] = "baz.dwo") ; CHECK-NEXT: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x1f1f859683d49324) ; Check that the rest of the compile units have information. ; CHECK: .debug_info.dwo contents: ; CHECK: DW_TAG_compile_unit -; CHECK: DW_AT_GNU_dwo_name [DW_FORM_GNU_str_index] ( indexed (00000000) string = "baz.dwo") -; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] ( indexed (00000001) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)") +; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] ( indexed (00000002) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)") ; CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99) -; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000002) string = "baz.c") +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000003) string = "baz.c") +; CHECK: DW_AT_GNU_dwo_name [DW_FORM_GNU_str_index] ( indexed (00000004) string = "baz.dwo") ; CHECK-NOT: DW_AT_low_pc ; CHECK-NOT: DW_AT_stmt_list ; CHECK-NOT: DW_AT_comp_dir ; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x1f1f859683d49324) ; CHECK: DW_TAG_variable -; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000003) string = "a") +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000000) string = "a") ; CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[0-9a-f]*}} => {[[TYPE:0x[0-9a-f]*]]} ; CHECK: DW_AT_external [DW_FORM_flag_present] (true) ; CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01) ; CHECK: DW_AT_decl_line [DW_FORM_data1] (1) ; CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0) ; CHECK: [[TYPE]]: DW_TAG_base_type -; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000004) string = "int") +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000001) string = "int") ; CHECK: .debug_str contents: -; CHECK: 0x00000000: "baz.dwo" -; CHECK: 0x00000008: "/usr/local/google/home/echristo/tmp" +; CHECK: 0x00000000: "/usr/local/google/home/echristo/tmp" +; CHECK: 0x00000024: "baz.dwo" ; CHECK: .debug_str.dwo contents: -; CHECK: 0x00000000: "baz.dwo" -; CHECK: 0x00000008: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)" -; CHECK: 0x0000003d: "baz.c" -; CHECK: 0x00000043: "a" -; CHECK: 0x00000045: "int" +; CHECK: 0x00000000: "a" +; CHECK: 0x00000002: "int" +; CHECK: 0x00000006: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)" +; CHECK: 0x0000003b: "baz.c" +; CHECK: 0x00000041: "baz.dwo" ; CHECK: .debug_str_offsets.dwo contents: ; CHECK: 0x00000000: 00000000 -; CHECK: 0x00000004: 00000008 -; CHECK: 0x00000008: 0000003d -; CHECK: 0x0000000c: 00000043 -; CHECK: 0x00000010: 00000045 +; CHECK: 0x00000004: 00000002 +; CHECK: 0x00000008: 00000006 +; CHECK: 0x0000000c: 0000003b +; CHECK: 0x00000010: 00000041 ; Object file checks ; For x86-64-linux we should have this set of relocations for the debug info section diff --git a/test/DebugInfo/X86/fission-ranges.ll b/test/DebugInfo/X86/fission-ranges.ll index 5883d2b0c40..1a1dc22870a 100644 --- a/test/DebugInfo/X86/fission-ranges.ll +++ b/test/DebugInfo/X86/fission-ranges.ll @@ -8,8 +8,8 @@ ; CHECK: .debug_info contents: ; CHECK: DW_TAG_compile_unit ; CHECK-NEXT: DW_AT_stmt_list -; CHECK-NEXT: DW_AT_GNU_dwo_name ; CHECK-NEXT: DW_AT_comp_dir +; CHECK-NEXT: DW_AT_GNU_dwo_name ; CHECK-NEXT: DW_AT_GNU_dwo_id ; CHECK-NEXT: DW_AT_GNU_ranges_base ; CHECK-NEXT: DW_AT_GNU_addr_base [DW_FORM_sec_offset] (0x00000000) diff --git a/test/DebugInfo/X86/string-offsets-table-order.ll b/test/DebugInfo/X86/string-offsets-table-order.ll index 79c0ffcaa3e..1378b134659 100644 --- a/test/DebugInfo/X86/string-offsets-table-order.ll +++ b/test/DebugInfo/X86/string-offsets-table-order.ll @@ -13,11 +13,11 @@ ; CHECK: .debug_info contents: ; CHECK: DW_TAG_compile_unit -; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string = "X3") +; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000000) string = "X3") ; CHECK: DW_TAG_compile_unit -; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000002) string = "X2") +; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string = "X2") ; CHECK: DW_TAG_compile_unit -; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000003) string = "X1") +; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000002) string = "X1") ; CHECK: .debug_info.dwo contents: ; CHECK: .debug_str contents: @@ -27,10 +27,10 @@ ; CHECK: .debug_str_offsets contents: ; CHECK: Format = DWARF32, Version = 5 -; CHECK-NEXT: 00000000 "foo.dwo" ; CHECK-NEXT: [[X3]] "X3" ; CHECK-NEXT: [[X2]] "X2" ; CHECK-NEXT: [[X1]] "X1" +; CHECK-NEXT: "foo.dwo" ; CHECK-EMPTY: diff --git a/test/DebugInfo/X86/string-offsets-table.ll b/test/DebugInfo/X86/string-offsets-table.ll index b0615106de4..ae7797a3055 100644 --- a/test/DebugInfo/X86/string-offsets-table.ll +++ b/test/DebugInfo/X86/string-offsets-table.ll @@ -59,8 +59,8 @@ ; SPLIT: DW_TAG_compile_unit ; SPLIT-NOT: {{DW_TAG|contents:}} ; SPLIT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008) -; SPLIT: DW_AT_GNU_dwo_name [DW_FORM_strx1] ( indexed (00000000) string = "foo.dwo") -; SPLIT: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string = "/home/test") +; SPLIT: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000000) string = "/home/test") +; SPLIT: DW_AT_GNU_dwo_name [DW_FORM_strx1] ( indexed (00000001) string = "foo.dwo") ; Check for the split CU in .debug_info.dwo. ; SPLIT: .debug_info.dwo contents: @@ -73,18 +73,18 @@ ; SPLIT-NOT: contents: ; SPLIT: DW_TAG_enumerator ; SPLIT-NOT: {{DW_TAG|NULL}} -; SPLIT: DW_AT_name [DW_FORM_strx1] ( indexed (00000004) string = "a") +; SPLIT: DW_AT_name [DW_FORM_strx1] ( indexed (00000001) string = "a") ; SPLIT-NOT: contents: ; SPLIT: DW_TAG_enumerator ; SPLIT-NOT: {{DW_TAG|NULL}} -; SPLIT: DW_AT_name [DW_FORM_strx1] ( indexed (00000005) string = "b") +; SPLIT: DW_AT_name [DW_FORM_strx1] ( indexed (00000002) string = "b") ; ; Extract the string offsets referenced in the main file by the skeleton unit. ; SPLIT: .debug_str contents: -; SPLIT-NEXT: 0x00000000: "foo.dwo" -; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]: "/home/test" -; SPLIT-NEXT: 0x[[STRING3SPLIT:[0-9a-f]*]]: "E" -; SPLIT-NEXT: 0x[[STRING4SPLIT:[0-9a-f]*]]: "glob" +; SPLIT-NEXT: 0x[[STRHOMETESTSPLIT:[0-9a-f]*]]: "/home/test" +; SPLIT-NEXT: 0x[[STRESPLIT:[0-9a-f]*]]: "E" +; SPLIT-NEXT: 0x[[STRGLOBSPLIT:[0-9a-f]*]]: "glob" +; SPLIT-NEXT: 0x[[STRFOODWOSPLIT:[0-9a-f]*]]: "foo.dwo" ; ; Extract the string offsets referenced in the .dwo file by the split unit. ; SPLIT: .debug_str.dwo contents: @@ -98,8 +98,8 @@ ; referenced by the debug info. ; SPLIT: .debug_str_offsets contents: ; SPLIT-NEXT: 0x00000000: Contribution size = 12, Format = DWARF32, Version = 5 -; SPLIT-NEXT: 0x00000008: 00000000 "foo.dwo" -; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]] "/home/test" +; SPLIT-NEXT: 0x00000008: [[STRHOMETESTSPLIT]] "/home/test" +; SPLIT-NEXT: 0x0000000c: [[STRFOODWOSPLIT]] "foo.dwo" ; SPLIT-EMPTY: ; SPLIT: .debug_str_offsets.dwo contents: