llvm.org GIT mirror llvm / b13d54f
DebugInfo: Support debug_loc under fission Implement debug_loc.dwo, as well as llvm-dwarfdump support for dumping this section. Outlined in the DWARF5 spec and http://gcc.gnu.org/wiki/DebugFission the debug_loc.dwo section has more variation than the standard debug_loc, allowing 3 different forms of entry (plus the end of list entry). GCC seems to, and Clang certainly, only use one form, so I've just implemented dumping support for that for now. It wasn't immediately obvious that there was a good refactoring to share the implementation of dumping support between debug_loc and debug_loc.dwo, so they're separate for now - ideas welcome or I may come back to it at some point. As per a comment in the code, we could choose different forms that may reduce the number of debug_addr entries we emit, but that will require further study. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204697 91177308-0d34-0410-b5e6-96231b3b80d8 David Blaikie 6 years ago
11 changed file(s) with 172 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
108108 DIDT_Line,
109109 DIDT_LineDwo,
110110 DIDT_Loc,
111 DIDT_LocDwo,
111112 DIDT_Ranges,
112113 DIDT_Pubnames,
113114 DIDT_Pubtypes,
770770 DW_EH_PE_indirect = 0x80
771771 };
772772
773 enum LocationListEntry : unsigned char {
774 DW_LLE_end_of_list_entry,
775 DW_LLE_base_address_selection_entry,
776 DW_LLE_start_end_entry,
777 DW_LLE_start_length_entry,
778 DW_LLE_offset_pair_entry
779 };
780
773781 enum ApplePropertyAttributes {
774782 // Apple Objective-C Property Attributes
775783 DW_APPLE_PROPERTY_readonly = 0x01,
558558 /// EmitValue - Emit label value.
559559 ///
560560 void DIELocList::EmitValue(AsmPrinter *AP, dwarf::Form Form) const {
561 DwarfDebug *DD = AP->getDwarfDebug();
561562 MCSymbol *Label = AP->GetTempSymbol("debug_loc", Index);
562 MCSymbol *DwarfDebugLocSectionSym = AP->getDwarfDebug()->getDebugLocSym();
563
564 if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
565 AP->EmitSectionOffset(Label, DwarfDebugLocSectionSym);
563
564 if (DD->useSplitDwarf())
565 AP->EmitLabelDifference(Label, DD->getDebugLocDWOSym(), 4);
566 else if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
567 AP->EmitSectionOffset(Label, DD->getDebugLocSym());
566568 else
567 AP->EmitLabelDifference(Label, DwarfDebugLocSectionSym, 4);
569 AP->EmitLabelDifference(Label, DD->getDebugLocSym(), 4);
568570 }
569571
570572 #ifndef NDEBUG
183183
184184 DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0;
185185 DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
186 DwarfAddrSectionSym = 0;
186 DwarfAddrSectionSym = DwarfDebugLocDWOSectionSym = 0;
187187 DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
188188 FunctionBeginSym = FunctionEndSym = 0;
189189 CurFn = 0;
18641864
18651865 DwarfLineSectionSym =
18661866 emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
1867 emitSectionSym(Asm, TLOF.getDwarfLocSection());
18681867 if (GenerateGnuPubSections) {
18691868 DwarfGnuPubNamesSectionSym =
18701869 emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection());
18821881 emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
18831882 DwarfAddrSectionSym =
18841883 emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
1885 }
1884 DwarfDebugLocDWOSectionSym =
1885 emitSectionSym(Asm, TLOF.getDwarfLocDWOSection(), "skel_loc");
1886 } else
1887 DwarfDebugLocSectionSym =
1888 emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc");
18861889 DwarfDebugRangeSectionSym =
18871890 emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range");
1888
1889 DwarfDebugLocSectionSym =
1890 emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc");
18911891 }
18921892
18931893 // Recursively emits a debug information entry.
23782378 void DwarfDebug::emitDebugLoc() {
23792379 // Start the dwarf loc section.
23802380 Asm->OutStreamer.SwitchSection(
2381 Asm->getObjFileLowering().getDwarfLocSection());
2381 useSplitDwarf() ? Asm->getObjFileLowering().getDwarfLocDWOSection()
2382 : Asm->getObjFileLowering().getDwarfLocSection());
23822383 unsigned char Size = Asm->getDataLayout().getPointerSize();
23832384 unsigned index = 0;
23842385 for (const auto &DebugLoc : DotDebugLocEntries) {
23882389 // compile unit. This is a hard coded 0 for low_pc when we're emitting
23892390 // ranges, or the DW_AT_low_pc on the compile unit otherwise.
23902391 const DwarfCompileUnit *CU = Entry.getCU();
2391 if (CU->getRanges().size() == 1) {
2392 if (useSplitDwarf()) {
2393 // Just always use start_length for now - at least that's one address
2394 // rather than two. We could get fancier and try to, say, reuse an
2395 // address we know we've emitted elsewhere (the start of the function?
2396 // The start of the CU or CU subrange that encloses this range?)
2397 Asm->EmitInt8(dwarf::DW_LLE_start_length_entry);
2398 unsigned idx = InfoHolder.getAddrPoolIndex(Entry.getBeginSym());
2399 Asm->EmitULEB128(idx);
2400 Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4);
2401 } else if (CU->getRanges().size() == 1) {
23922402 // Grab the begin symbol from the first range as our base.
23932403 const MCSymbol *Base = CU->getRanges()[0].getStart();
23942404 Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size);
24082418 // Close the range.
24092419 Asm->OutStreamer.EmitLabel(end);
24102420 }
2411 Asm->OutStreamer.EmitIntValue(0, Size);
2412 Asm->OutStreamer.EmitIntValue(0, Size);
2421 if (useSplitDwarf())
2422 Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
2423 else {
2424 Asm->OutStreamer.EmitIntValue(0, Size);
2425 Asm->OutStreamer.EmitIntValue(0, Size);
2426 }
24132427 ++index;
24142428 }
24152429 }
422422 MCSymbol *DwarfDebugLocSectionSym, *DwarfLineSectionSym, *DwarfAddrSectionSym;
423423 MCSymbol *FunctionBeginSym, *FunctionEndSym;
424424 MCSymbol *DwarfInfoDWOSectionSym, *DwarfAbbrevDWOSectionSym;
425 MCSymbol *DwarfStrDWOSectionSym;
425 MCSymbol *DwarfStrDWOSectionSym, *DwarfDebugLocDWOSectionSym;
426426 MCSymbol *DwarfGnuPubNamesSectionSym, *DwarfGnuPubTypesSectionSym;
427427
428428 // As an optimization, there is no need to emit an entry in the directory
755755 /// Returns the section symbol for the .debug_loc section.
756756 MCSymbol *getDebugLocSym() const { return DwarfDebugLocSectionSym; }
757757
758 /// Returns the section symbol for the .debug_loc section.
759 MCSymbol *getDebugLocDWOSym() const { return DwarfDebugLocDWOSectionSym; }
760
758761 /// Returns the previous section that was emitted into.
759762 const MCSection *getPrevSection() const { return PrevSection; }
760763
9595 getDebugLoc()->dump(OS);
9696 }
9797
98 if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) {
99 OS << "\n.debug_loc.dwo contents:\n";
100 getDebugLocDWO()->dump(OS);
101 }
102
98103 if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
99104 OS << "\n.debug_frame contents:\n";
100105 getDebugFrame()->dump(OS);
234239 if (getNumCompileUnits())
235240 Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize());
236241 return Loc.get();
242 }
243
244 const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() {
245 if (LocDWO)
246 return LocDWO.get();
247
248 DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0);
249 LocDWO.reset(new DWARFDebugLocDWO());
250 LocDWO->parse(LocData);
251 return LocDWO.get();
237252 }
238253
239254 const DWARFDebugAranges *DWARFContext::getDebugAranges() {
647662 .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
648663 .Case("debug_info.dwo", &InfoDWOSection.Data)
649664 .Case("debug_abbrev.dwo", &AbbrevDWOSection)
665 .Case("debug_loc.dwo", &LocDWOSection.Data)
650666 .Case("debug_line.dwo", &LineDWOSection.Data)
651667 .Case("debug_str.dwo", &StringDWOSection)
652668 .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
4141 CUVector DWOCUs;
4242 TUVector DWOTUs;
4343 std::unique_ptr AbbrevDWO;
44 std::unique_ptr LocDWO;
4445
4546 DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION;
4647 DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION;
146147
147148 /// Get a pointer to the parsed dwo abbreviations object.
148149 const DWARFDebugAbbrev *getDebugAbbrevDWO();
150
151 /// Get a pointer to the parsed DebugLoc object.
152 const DWARFDebugLocDWO *getDebugLocDWO();
149153
150154 /// Get a pointer to the parsed DebugAranges object.
151155 const DWARFDebugAranges *getDebugAranges();
172176 virtual const TypeSectionMap &getTypesSections() = 0;
173177 virtual StringRef getAbbrevSection() = 0;
174178 virtual const Section &getLocSection() = 0;
179 virtual const Section &getLocDWOSection() = 0;
175180 virtual StringRef getARangeSection() = 0;
176181 virtual StringRef getDebugFrameSection() = 0;
177182 virtual const Section &getLineSection() = 0;
215220 TypeSectionMap TypesSections;
216221 StringRef AbbrevSection;
217222 Section LocSection;
223 Section LocDWOSection;
218224 StringRef ARangeSection;
219225 StringRef DebugFrameSection;
220226 Section LineSection;
245251 const TypeSectionMap &getTypesSections() override { return TypesSections; }
246252 StringRef getAbbrevSection() override { return AbbrevSection; }
247253 const Section &getLocSection() override { return LocSection; }
254 const Section &getLocDWOSection() override { return LocDWOSection; }
248255 StringRef getARangeSection() override { return ARangeSection; }
249256 StringRef getDebugFrameSection() override { return DebugFrameSection; }
250257 const Section &getLineSection() override { return LineSection; }
1010 #include "llvm/Support/Compiler.h"
1111 #include "llvm/Support/Format.h"
1212 #include "llvm/Support/raw_ostream.h"
13 #include "llvm/Support/Dwarf.h"
1314
1415 using namespace llvm;
1516
7374 if (data.isValidOffset(Offset))
7475 llvm::errs() << "error: failed to consume entire .debug_loc section\n";
7576 }
77
78 void DWARFDebugLocDWO::parse(DataExtractor data) {
79 uint32_t Offset = 0;
80 while (data.isValidOffset(Offset)) {
81 Locations.resize(Locations.size() + 1);
82 LocationList &Loc = Locations.back();
83 Loc.Offset = Offset;
84 dwarf::LocationListEntry Kind;
85 while ((Kind = static_cast(
86 data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list_entry) {
87
88 if (Kind != dwarf::DW_LLE_start_length_entry) {
89 llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
90 << " not implemented\n";
91 return;
92 }
93
94 Entry E;
95
96 E.Start = data.getULEB128(&Offset);
97 E.Length = data.getU32(&Offset);
98
99 unsigned Bytes = data.getU16(&Offset);
100 // A single location description describing the location of the object...
101 StringRef str = data.getData().substr(Offset, Bytes);
102 Offset += Bytes;
103 E.Loc.resize(str.size());
104 std::copy(str.begin(), str.end(), E.Loc.begin());
105
106 Loc.Entries.push_back(std::move(E));
107 }
108 }
109 }
110
111 void DWARFDebugLocDWO::dump(raw_ostream &OS) const {
112 for (const LocationList &L : Locations) {
113 OS << format("0x%8.8x: ", L.Offset);
114 const unsigned Indent = 12;
115 for (const Entry &E : L.Entries) {
116 if (&E != L.Entries.begin())
117 OS.indent(Indent);
118 OS << "Beginning address index: " << E.Start << '\n';
119 OS.indent(Indent) << " Length: " << E.Length << '\n';
120 OS.indent(Indent) << " Location description: ";
121 for (unsigned char Loc : E.Loc)
122 OS << format("%2.2x ", Loc);
123 OS << "\n\n";
124 }
125 }
126 }
127
5454 /// specified address size to interpret the address ranges.
5555 void parse(DataExtractor data, unsigned AddressSize);
5656 };
57
58 class DWARFDebugLocDWO {
59 struct Entry {
60 uint64_t Start;
61 uint32_t Length;
62 SmallVector Loc;
63 };
64
65 struct LocationList {
66 unsigned Offset;
67 SmallVector Entries;
68 };
69
70 typedef SmallVector LocationLists;
71
72 LocationLists Locations;
73
74 public:
75 void parse(DataExtractor data);
76 void dump(raw_ostream &OS) const;
77 };
5778 }
5879
5980 #endif
0 ; RUN: llc -split-dwarf=Enable -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t
1 ; RUN: llvm-dwarfdump -debug-dump=info.dwo %t | FileCheck %s
2 ; RUN: llvm-objdump -r %t | FileCheck --check-prefix=RELA %s
1 ; RUN: llvm-dwarfdump %t | FileCheck %s
2 ; RUN: llvm-objdump -h %t | FileCheck --check-prefix=HDR %s
33
4 ; CHECK: .debug_info.dwo contents:
5 ; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[A:0x[0-9a-z]*]])
6 ; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[E:0x[0-9a-z]*]])
7 ; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[B:0x[0-9a-z]*]])
8 ; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[D:0x[0-9a-z]*]])
49 ; CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x000000a0)
10 ; CHECK: .debug_loc contents:
11 ; CHECK-NOT: Beginning address offset
12 ; CHECK: .debug_loc.dwo contents:
13
14 ; Don't assume these locations are entirely correct - feel free to update them
15 ; if they've changed due to a bugfix, change in register allocation, etc.
16
17 ; CHECK: [[A]]: Beginning address index: 2
18 ; CHECK-NEXT: Length: 199
19 ; CHECK-NEXT: Location description: 10 00
20 ; CHECK-NEXT: {{^$}}
21 ; CHECK-NEXT: Beginning address index: 3
22 ; CHECK-NEXT: Length: 23
23 ; CHECK-NEXT: Location description: 50 93 04
24 ; CHECK: [[E]]: Beginning address index: 4
25 ; CHECK-NEXT: Length: 21
26 ; CHECK-NEXT: Location description: 50 93 04
27 ; CHECK: [[B]]: Beginning address index: 5
28 ; CHECK-NEXT: Length: 19
29 ; CHECK-NEXT: Location description: 50 93 04
30 ; CHECK: [[D]]: Beginning address index: 6
31 ; CHECK-NEXT: Length: 23
32 ; CHECK-NEXT: Location description: 50 93 04
533
634 ; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo)
7 ; FIXME: There should be no relocations in .dwo sections at all, but for now there are debug_loc relocs here.
8 ; RELA: RELOCATION RECORDS FOR [.rela.debug_info.dwo]
9 ; RELA-NOT: R_X86_64_32 .debug_ranges
10 ; RELA: RELOCATION RECORDS FOR
35 ; HDR-NOT: .rela.{{.*}}.dwo
1136
1237 ; From the code:
1338
6565 clEnumValN(DIDT_Line, "line", ".debug_line"),
6666 clEnumValN(DIDT_LineDwo, "line.dwo", ".debug_line.dwo"),
6767 clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
68 clEnumValN(DIDT_LocDwo, "loc.dwo", ".debug_loc.dwo"),
6869 clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
6970 clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
7071 clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),