mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
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) llvm-svn: 349207
This commit is contained in:
parent
cc880fb6ed
commit
831e5b558b
@ -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<DwarfCompileUnit>(
|
||||
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<DwarfCompileUnit>(
|
||||
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<DwarfCompileUnit> 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);
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
||||
if (!S)
|
||||
return;
|
||||
|
||||
Asm->OutStreamer->SwitchSection(S);
|
||||
TheU->emitHeader(UseOffsets);
|
||||
|
||||
Asm->emitDwarfDIE(Die);
|
||||
Asm->emitDwarfDIE(TheU->getUnitDie());
|
||||
}
|
||||
|
||||
// Compute the size and offset for each DIE.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user