[llvm-commits] [PATCH] [DebugInfo] Generate address ranges for compile units even if .debug_aranges is present.

Alexey Samsonov samsonov at google.com
Tue Nov 13 06:24:09 PST 2012


Hi echristo, bkramer,

This is a long-standing issue of libDebugInfo. Even if the object file contains
.debug_aranges section, we can't assume that it contains the full set of address ranges
for all functions: it's often the case that ranges are present only for small set of
specific compile units (e.g. assembler sources).

Previously some clients of libDebugInfo were not affected by this bug, and some
(llvm-symbolizer) explicitly didn't provide .debug_aranges sections to DebugInfo.
Now that object file is scanned inside DebugInfo it would be ugly to introduce
such a difference.

Testing:
I plan to
(a) enable llvm-symbolizer for running ThreadSanitizer output tests - it can help to
diagnose many problems quick.
(b) implement a few "integration" tests: compile simple ll sources with debug metadata into
object files with ELF and then run llvm-dwarfdump/llvm-symbolizer on them to see if
debug info is restored correctly. This deserves separate commits.

http://llvm-reviews.chandlerc.com/D116

Files:
  lib/DebugInfo/DWARFContext.cpp
  lib/DebugInfo/DWARFDebugAranges.cpp
  lib/DebugInfo/DWARFDebugAranges.h

Index: lib/DebugInfo/DWARFContext.cpp
===================================================================
--- lib/DebugInfo/DWARFContext.cpp
+++ lib/DebugInfo/DWARFContext.cpp
@@ -91,8 +91,10 @@
 
   Aranges.reset(new DWARFDebugAranges());
   Aranges->extract(arangesData);
-  if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs.
-    Aranges->generate(this);
+  // Generate aranges from DIEs: even if .debug_aranges section is present,
+  // it may describe only a small subset of compilation units, so we need to
+  // manually build aranges for the rest of them.
+  Aranges->generate(this);
   return Aranges.get();
 }
 
Index: lib/DebugInfo/DWARFDebugAranges.cpp
===================================================================
--- lib/DebugInfo/DWARFDebugAranges.cpp
+++ lib/DebugInfo/DWARFDebugAranges.cpp
@@ -26,34 +26,40 @@
   class CountArangeDescriptors {
   public:
     CountArangeDescriptors(uint32_t &count_ref) : Count(count_ref) {}
-    void operator()(const DWARFDebugArangeSet &set) {
-      Count += set.getNumDescriptors();
+    void operator()(const DWARFDebugArangeSet &Set) {
+      Count += Set.getNumDescriptors();
     }
     uint32_t &Count;
   };
 
   class AddArangeDescriptors {
   public:
-    AddArangeDescriptors(DWARFDebugAranges::RangeColl &ranges)
-      : RangeCollection(ranges) {}
-    void operator()(const DWARFDebugArangeSet& set) {
-      const DWARFDebugArangeSet::Descriptor* arange_desc_ptr;
-      DWARFDebugAranges::Range range;
-      range.Offset = set.getCompileUnitDIEOffset();
-
-      for (uint32_t i=0; (arange_desc_ptr = set.getDescriptor(i)) != NULL; ++i){
-        range.LoPC = arange_desc_ptr->Address;
-        range.Length = arange_desc_ptr->Length;
+    AddArangeDescriptors(DWARFDebugAranges::RangeColl &Ranges,
+                         DWARFDebugAranges::ParsedCUOffsetColl &CUOffsets)
+      : RangeCollection(Ranges),
+        CUOffsetCollection(CUOffsets) {}
+    void operator()(const DWARFDebugArangeSet &Set) {
+      DWARFDebugAranges::Range Range;
+      Range.Offset = Set.getCompileUnitDIEOffset();
+      CUOffsetCollection.insert(Range.Offset);
+
+      for (uint32_t i = 0, n = Set.getNumDescriptors(); i < n; ++i) {
+        const DWARFDebugArangeSet::Descriptor *ArangeDescPtr =
+            Set.getDescriptor(i);
+        Range.LoPC = ArangeDescPtr->Address;
+        Range.Length = ArangeDescPtr->Length;
 
         // Insert each item in increasing address order so binary searching
         // can later be done!
-        DWARFDebugAranges::RangeColl::iterator insert_pos =
+        DWARFDebugAranges::RangeColl::iterator InsertPos =
           std::lower_bound(RangeCollection.begin(), RangeCollection.end(),
-                           range, RangeLessThan);
-        RangeCollection.insert(insert_pos, range);
+                           Range, RangeLessThan);
+        RangeCollection.insert(InsertPos, Range);
       }
+
     }
-    DWARFDebugAranges::RangeColl& RangeCollection;
+    DWARFDebugAranges::RangeColl &RangeCollection;
+    DWARFDebugAranges::ParsedCUOffsetColl &CUOffsetCollection;
   };
 }
 
@@ -75,21 +81,24 @@
 
     if (count > 0) {
       Aranges.reserve(count);
-      AddArangeDescriptors range_adder(Aranges);
+      AddArangeDescriptors range_adder(Aranges, ParsedCUOffsets);
       std::for_each(sets.begin(), sets.end(), range_adder);
     }
   }
   return false;
 }
 
 bool DWARFDebugAranges::generate(DWARFContext *ctx) {
-  clear();
   if (ctx) {
     const uint32_t num_compile_units = ctx->getNumCompileUnits();
     for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
-      DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx);
-      if (cu)
-        cu->buildAddressRangeTable(this, true);
+      if (DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx)) {
+        uint32_t CUOffset = cu->getOffset();
+        if (ParsedCUOffsets.count(CUOffset) == 0) {
+          cu->buildAddressRangeTable(this, true);
+          ParsedCUOffsets.insert(CUOffset);
+        }
+      }
     }
   }
   sort(true, /* overlap size */ 0);
Index: lib/DebugInfo/DWARFDebugAranges.h
===================================================================
--- lib/DebugInfo/DWARFDebugAranges.h
+++ lib/DebugInfo/DWARFDebugAranges.h
@@ -11,6 +11,7 @@
 #define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
 
 #include "DWARFDebugArangeSet.h"
+#include "llvm/ADT/DenseSet.h"
 #include <list>
 
 namespace llvm {
@@ -60,7 +61,10 @@
     uint32_t Offset; // Offset of the compile unit or die
   };
 
-  void clear() { Aranges.clear(); }
+  void clear() {
+    Aranges.clear();
+    ParsedCUOffsets.clear();
+  }
   bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const;
   bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const;
   bool extract(DataExtractor debug_aranges_data);
@@ -88,9 +92,11 @@
 
   typedef std::vector<Range>              RangeColl;
   typedef RangeColl::const_iterator       RangeCollIterator;
+  typedef DenseSet<uint32_t>              ParsedCUOffsetColl;
 
 private:
   RangeColl Aranges;
+  ParsedCUOffsetColl ParsedCUOffsets;
 };
 
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D116.1.patch
Type: text/x-patch
Size: 5106 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121113/e173aa19/attachment.bin>


More information about the llvm-commits mailing list