DebugInfo: Support debug_loc under fission
authorDavid Blaikie <dblaikie@gmail.com>
Tue, 25 Mar 2014 01:44:02 +0000 (01:44 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Tue, 25 Mar 2014 01:44:02 +0000 (01:44 +0000)
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

include/llvm/DebugInfo/DIContext.h
include/llvm/Support/Dwarf.h
lib/CodeGen/AsmPrinter/DIE.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.h
lib/DebugInfo/DWARFContext.cpp
lib/DebugInfo/DWARFContext.h
lib/DebugInfo/DWARFDebugLoc.cpp
lib/DebugInfo/DWARFDebugLoc.h
test/DebugInfo/X86/fission-ranges.ll
tools/llvm-dwarfdump/llvm-dwarfdump.cpp

index f04dc001f4b352b79b47dabe750e035e2d994093..69a4f8d1f6b8271912ce277f1bb5af7110d8a10a 100644 (file)
@@ -109,6 +109,7 @@ enum DIDumpType {
   DIDT_Line,
   DIDT_LineDwo,
   DIDT_Loc,
+  DIDT_LocDwo,
   DIDT_Ranges,
   DIDT_Pubnames,
   DIDT_Pubtypes,
index 7d434dcb12da4717060402ca6aa3a62bb586b4b4..876969906001f21422d53bd171f4602e004ba620 100644 (file)
@@ -771,6 +771,14 @@ enum Constants {
   DW_EH_PE_indirect = 0x80
 };
 
+enum LocationListEntry : unsigned char {
+  DW_LLE_end_of_list_entry,
+  DW_LLE_base_address_selection_entry,
+  DW_LLE_start_end_entry,
+  DW_LLE_start_length_entry,
+  DW_LLE_offset_pair_entry
+};
+
 enum ApplePropertyAttributes {
   // Apple Objective-C Property Attributes
   DW_APPLE_PROPERTY_readonly = 0x01,
index eb3a622ae7faeebcf983380c403f57631956e61f..34f070e0edbf905f1e2eab1a8ccc28c75a1809b3 100644 (file)
@@ -559,13 +559,15 @@ unsigned DIELocList::SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
 /// EmitValue - Emit label value.
 ///
 void DIELocList::EmitValue(AsmPrinter *AP, dwarf::Form Form) const {
+  DwarfDebug *DD = AP->getDwarfDebug();
   MCSymbol *Label = AP->GetTempSymbol("debug_loc", Index);
-  MCSymbol *DwarfDebugLocSectionSym = AP->getDwarfDebug()->getDebugLocSym();
 
-  if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
-    AP->EmitSectionOffset(Label, DwarfDebugLocSectionSym);
+  if (DD->useSplitDwarf())
+    AP->EmitLabelDifference(Label, DD->getDebugLocDWOSym(), 4);
+  else if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
+    AP->EmitSectionOffset(Label, DD->getDebugLocSym());
   else
-    AP->EmitLabelDifference(Label, DwarfDebugLocSectionSym, 4);
+    AP->EmitLabelDifference(Label, DD->getDebugLocSym(), 4);
 }
 
 #ifndef NDEBUG
index 792a9c48cdfc4a287d081435edc8a96d0bf3b2d4..a9ed9dbcb5ba392bcb41ac94d188e71c563597b9 100644 (file)
@@ -184,7 +184,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
 
   DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0;
   DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
-  DwarfAddrSectionSym = 0;
+  DwarfAddrSectionSym = DwarfDebugLocDWOSectionSym = 0;
   DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
   FunctionBeginSym = FunctionEndSym = 0;
   CurFn = 0;
@@ -1865,7 +1865,6 @@ void DwarfDebug::emitSectionLabels() {
 
   DwarfLineSectionSym =
       emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
-  emitSectionSym(Asm, TLOF.getDwarfLocSection());
   if (GenerateGnuPubSections) {
     DwarfGnuPubNamesSectionSym =
         emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection());
@@ -1883,12 +1882,13 @@ void DwarfDebug::emitSectionLabels() {
         emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
     DwarfAddrSectionSym =
         emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
-  }
+    DwarfDebugLocDWOSectionSym =
+        emitSectionSym(Asm, TLOF.getDwarfLocDWOSection(), "skel_loc");
+  } else
+    DwarfDebugLocSectionSym =
+        emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc");
   DwarfDebugRangeSectionSym =
       emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range");
-
-  DwarfDebugLocSectionSym =
-      emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc");
 }
 
 // Recursively emits a debug information entry.
@@ -2379,7 +2379,8 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
 void DwarfDebug::emitDebugLoc() {
   // Start the dwarf loc section.
   Asm->OutStreamer.SwitchSection(
-      Asm->getObjFileLowering().getDwarfLocSection());
+      useSplitDwarf() ? Asm->getObjFileLowering().getDwarfLocDWOSection()
+                      : Asm->getObjFileLowering().getDwarfLocSection());
   unsigned char Size = Asm->getDataLayout().getPointerSize();
   unsigned index = 0;
   for (const auto &DebugLoc : DotDebugLocEntries) {
@@ -2389,7 +2390,16 @@ void DwarfDebug::emitDebugLoc() {
       // compile unit. This is a hard coded 0 for low_pc when we're emitting
       // ranges, or the DW_AT_low_pc on the compile unit otherwise.
       const DwarfCompileUnit *CU = Entry.getCU();
-      if (CU->getRanges().size() == 1) {
+      if (useSplitDwarf()) {
+        // Just always use start_length for now - at least that's one address
+        // rather than two. We could get fancier and try to, say, reuse an
+        // address we know we've emitted elsewhere (the start of the function?
+        // The start of the CU or CU subrange that encloses this range?)
+        Asm->EmitInt8(dwarf::DW_LLE_start_length_entry);
+        unsigned idx = InfoHolder.getAddrPoolIndex(Entry.getBeginSym());
+        Asm->EmitULEB128(idx);
+        Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4);
+      } else if (CU->getRanges().size() == 1) {
         // Grab the begin symbol from the first range as our base.
         const MCSymbol *Base = CU->getRanges()[0].getStart();
         Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size);
@@ -2409,8 +2419,12 @@ void DwarfDebug::emitDebugLoc() {
       // Close the range.
       Asm->OutStreamer.EmitLabel(end);
     }
-    Asm->OutStreamer.EmitIntValue(0, Size);
-    Asm->OutStreamer.EmitIntValue(0, Size);
+    if (useSplitDwarf())
+      Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
+    else {
+      Asm->OutStreamer.EmitIntValue(0, Size);
+      Asm->OutStreamer.EmitIntValue(0, Size);
+    }
     ++index;
   }
 }
index 064c0fa7624b716798df6b4ea3f6a36eb259c608..0b0f0a8b7aadc00d2f550d7b21b014013508b4fb 100644 (file)
@@ -423,7 +423,7 @@ class DwarfDebug : public AsmPrinterHandler {
   MCSymbol *DwarfDebugLocSectionSym, *DwarfLineSectionSym, *DwarfAddrSectionSym;
   MCSymbol *FunctionBeginSym, *FunctionEndSym;
   MCSymbol *DwarfInfoDWOSectionSym, *DwarfAbbrevDWOSectionSym;
-  MCSymbol *DwarfStrDWOSectionSym;
+  MCSymbol *DwarfStrDWOSectionSym, *DwarfDebugLocDWOSectionSym;
   MCSymbol *DwarfGnuPubNamesSectionSym, *DwarfGnuPubTypesSectionSym;
 
   // As an optimization, there is no need to emit an entry in the directory
@@ -756,6 +756,9 @@ public:
   /// Returns the section symbol for the .debug_loc section.
   MCSymbol *getDebugLocSym() const { return DwarfDebugLocSectionSym; }
 
+  /// Returns the section symbol for the .debug_loc section.
+  MCSymbol *getDebugLocDWOSym() const { return DwarfDebugLocDWOSectionSym; }
+
   /// Returns the previous section that was emitted into.
   const MCSection *getPrevSection() const { return PrevSection; }
 
index 0afe6ef6e138cf1adb8deb41c0f783502ddad85c..60c5f6ab56d73b4e7893507deb8b64a50d662cc6 100644 (file)
@@ -96,6 +96,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
     getDebugLoc()->dump(OS);
   }
 
+  if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) {
+    OS << "\n.debug_loc.dwo contents:\n";
+    getDebugLocDWO()->dump(OS);
+  }
+
   if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
     OS << "\n.debug_frame contents:\n";
     getDebugFrame()->dump(OS);
@@ -237,6 +242,16 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() {
   return Loc.get();
 }
 
+const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() {
+  if (LocDWO)
+    return LocDWO.get();
+
+  DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0);
+  LocDWO.reset(new DWARFDebugLocDWO());
+  LocDWO->parse(LocData);
+  return LocDWO.get();
+}
+
 const DWARFDebugAranges *DWARFContext::getDebugAranges() {
   if (Aranges)
     return Aranges.get();
@@ -648,6 +663,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj)
             .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
             .Case("debug_info.dwo", &InfoDWOSection.Data)
             .Case("debug_abbrev.dwo", &AbbrevDWOSection)
+            .Case("debug_loc.dwo", &LocDWOSection.Data)
             .Case("debug_line.dwo", &LineDWOSection.Data)
             .Case("debug_str.dwo", &StringDWOSection)
             .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
index a3bae7927376f685c434707e485a214fb8aeb03a..ad6841ae9e31c54458ffde66df7b0f441d355401 100644 (file)
@@ -42,6 +42,7 @@ class DWARFContext : public DIContext {
   CUVector DWOCUs;
   TUVector DWOTUs;
   std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
+  std::unique_ptr<DWARFDebugLocDWO> LocDWO;
 
   DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION;
   DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION;
@@ -148,6 +149,9 @@ public:
   /// Get a pointer to the parsed dwo abbreviations object.
   const DWARFDebugAbbrev *getDebugAbbrevDWO();
 
+  /// Get a pointer to the parsed DebugLoc object.
+  const DWARFDebugLocDWO *getDebugLocDWO();
+
   /// Get a pointer to the parsed DebugAranges object.
   const DWARFDebugAranges *getDebugAranges();
 
@@ -173,6 +177,7 @@ public:
   virtual const TypeSectionMap &getTypesSections() = 0;
   virtual StringRef getAbbrevSection() = 0;
   virtual const Section &getLocSection() = 0;
+  virtual const Section &getLocDWOSection() = 0;
   virtual StringRef getARangeSection() = 0;
   virtual StringRef getDebugFrameSection() = 0;
   virtual const Section &getLineSection() = 0;
@@ -216,6 +221,7 @@ class DWARFContextInMemory : public DWARFContext {
   TypeSectionMap TypesSections;
   StringRef AbbrevSection;
   Section LocSection;
+  Section LocDWOSection;
   StringRef ARangeSection;
   StringRef DebugFrameSection;
   Section LineSection;
@@ -246,6 +252,7 @@ public:
   const TypeSectionMap &getTypesSections() override { return TypesSections; }
   StringRef getAbbrevSection() override { return AbbrevSection; }
   const Section &getLocSection() override { return LocSection; }
+  const Section &getLocDWOSection() override { return LocDWOSection; }
   StringRef getARangeSection() override { return ARangeSection; }
   StringRef getDebugFrameSection() override { return DebugFrameSection; }
   const Section &getLineSection() override { return LineSection; }
index 5f0ff0240da61ab6be1339af972899f2c5aef748..e4aa5dcce27e808b4429804535db25987f3089a5 100644 (file)
@@ -11,6 +11,7 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Dwarf.h"
 
 using namespace llvm;
 
@@ -74,3 +75,54 @@ void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) {
   if (data.isValidOffset(Offset))
     llvm::errs() << "error: failed to consume entire .debug_loc section\n";
 }
+
+void DWARFDebugLocDWO::parse(DataExtractor data) {
+  uint32_t Offset = 0;
+  while (data.isValidOffset(Offset)) {
+    Locations.resize(Locations.size() + 1);
+    LocationList &Loc = Locations.back();
+    Loc.Offset = Offset;
+    dwarf::LocationListEntry Kind;
+    while ((Kind = static_cast<dwarf::LocationListEntry>(
+                data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list_entry) {
+
+      if (Kind != dwarf::DW_LLE_start_length_entry) {
+        llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
+                     << " not implemented\n";
+        return;
+      }
+
+      Entry E;
+
+      E.Start = data.getULEB128(&Offset);
+      E.Length = data.getU32(&Offset);
+
+      unsigned Bytes = data.getU16(&Offset);
+      // A single location description describing the location of the object...
+      StringRef str = data.getData().substr(Offset, Bytes);
+      Offset += Bytes;
+      E.Loc.resize(str.size());
+      std::copy(str.begin(), str.end(), E.Loc.begin());
+
+      Loc.Entries.push_back(std::move(E));
+    }
+  }
+}
+
+void DWARFDebugLocDWO::dump(raw_ostream &OS) const {
+  for (const LocationList &L : Locations) {
+    OS << format("0x%8.8x: ", L.Offset);
+    const unsigned Indent = 12;
+    for (const Entry &E : L.Entries) {
+      if (&E != L.Entries.begin())
+        OS.indent(Indent);
+      OS << "Beginning address index: " << E.Start << '\n';
+      OS.indent(Indent) << "                 Length: " << E.Length << '\n';
+      OS.indent(Indent) << "   Location description: ";
+      for (unsigned char Loc : E.Loc)
+        OS << format("%2.2x ", Loc);
+      OS << "\n\n";
+    }
+  }
+}
+
index d31aaaa127377172d48eeac51509e97d584c44c4..663acbb42f8d3922b93616dfa04d51e4816650c5 100644 (file)
@@ -55,6 +55,27 @@ public:
   /// specified address size to interpret the address ranges.
   void parse(DataExtractor data, unsigned AddressSize);
 };
+
+class DWARFDebugLocDWO {
+  struct Entry {
+    uint64_t Start;
+    uint32_t Length;
+    SmallVector<unsigned char, 4> Loc;
+  };
+
+  struct LocationList {
+    unsigned Offset;
+    SmallVector<Entry, 2> Entries;
+  };
+
+  typedef SmallVector<LocationList, 4> LocationLists;
+
+  LocationLists Locations;
+
+public:
+  void parse(DataExtractor data);
+  void dump(raw_ostream &OS) const;
+};
 }
 
 #endif
index b95038bacc1462c35ac7981887736ea046ecad43..a48896f5a55043aa6a0ceec59aad73db6a0ba459 100644 (file)
@@ -1,14 +1,39 @@
 ; RUN: llc -split-dwarf=Enable -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t
-; RUN: llvm-dwarfdump -debug-dump=info.dwo %t | FileCheck %s
-; RUN: llvm-objdump -r %t | FileCheck --check-prefix=RELA %s
-
+; RUN: llvm-dwarfdump %t | FileCheck %s
+; RUN: llvm-objdump -h %t | FileCheck --check-prefix=HDR %s
+
+; CHECK: .debug_info.dwo contents:
+; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[A:0x[0-9a-z]*]])
+; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[E:0x[0-9a-z]*]])
+; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[B:0x[0-9a-z]*]])
+; CHECK: DW_AT_location [DW_FORM_sec_offset]   ([[D:0x[0-9a-z]*]])
 ; CHECK: DW_AT_ranges [DW_FORM_sec_offset]   (0x000000a0)
+; CHECK: .debug_loc contents:
+; CHECK-NOT: Beginning address offset
+; CHECK: .debug_loc.dwo contents:
+
+; Don't assume these locations are entirely correct - feel free to update them
+; if they've changed due to a bugfix, change in register allocation, etc.
+
+; CHECK: [[A]]: Beginning address index: 2
+; CHECK-NEXT:                    Length: 199
+; CHECK-NEXT:      Location description: 10 00
+; CHECK-NEXT: {{^$}}
+; CHECK-NEXT:   Beginning address index: 3
+; CHECK-NEXT:                    Length: 23
+; CHECK-NEXT:      Location description: 50 93 04
+; CHECK: [[E]]: Beginning address index: 4
+; CHECK-NEXT:                    Length: 21
+; CHECK-NEXT:      Location description: 50 93 04
+; CHECK: [[B]]: Beginning address index: 5
+; CHECK-NEXT:                    Length: 19
+; CHECK-NEXT:      Location description: 50 93 04
+; CHECK: [[D]]: Beginning address index: 6
+; CHECK-NEXT:                    Length: 23
+; CHECK-NEXT:      Location description: 50 93 04
 
 ; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo)
-; FIXME: There should be no relocations in .dwo sections at all, but for now there are debug_loc relocs here.
-; RELA: RELOCATION RECORDS FOR [.rela.debug_info.dwo]
-; RELA-NOT: R_X86_64_32 .debug_ranges
-; RELA: RELOCATION RECORDS FOR
+; HDR-NOT: .rela.{{.*}}.dwo
 
 ; From the code:
 
index f019e9e9a98dca325820665188db9091e549216f..f4a9ae8bef0e3b3931a51ba2e0369553ac5fc5d1 100644 (file)
@@ -66,6 +66,7 @@ DumpType("debug-dump", cl::init(DIDT_All),
         clEnumValN(DIDT_Line, "line", ".debug_line"),
         clEnumValN(DIDT_LineDwo, "line.dwo", ".debug_line.dwo"),
         clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
+        clEnumValN(DIDT_LocDwo, "loc.dwo", ".debug_loc.dwo"),
         clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
         clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
         clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),