DWARF: Generate the address lookup table from the DIE tree if .debug_aranges is not...
authorBenjamin Kramer <benny.kra@googlemail.com>
Wed, 14 Sep 2011 20:52:27 +0000 (20:52 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Wed, 14 Sep 2011 20:52:27 +0000 (20:52 +0000)
Ported from LLDB.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139732 91177308-0d34-0410-b5e6-96231b3b80d8

lib/DebugInfo/DWARFCompileUnit.cpp
lib/DebugInfo/DWARFCompileUnit.h
lib/DebugInfo/DWARFContext.cpp
lib/DebugInfo/DWARFDebugAranges.cpp
lib/DebugInfo/DWARFDebugAranges.h
lib/DebugInfo/DWARFDebugInfoEntry.cpp
lib/DebugInfo/DWARFDebugInfoEntry.h

index 224ae925c2ed30f254db7166db94d304e39f934e..d535df05d3b5bb29d7db3b10b5c10ae9a94d3a2f 100644 (file)
@@ -200,3 +200,40 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
   setDIERelations();
   return DieArray.size();
 }
+
+void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) {
+  if (DieArray.size() > 1) {
+    // std::vectors never get any smaller when resized to a smaller size,
+    // or when clear() or erase() are called, the size will report that it
+    // is smaller, but the memory allocated remains intact (call capacity()
+    // to see this). So we need to create a temporary vector and swap the
+    // contents which will cause just the internal pointers to be swapped
+    // so that when "tmp_array" goes out of scope, it will destroy the
+    // contents.
+
+    // Save at least the compile unit DIE
+    std::vector<DWARFDebugInfoEntryMinimal> tmpArray;
+    DieArray.swap(tmpArray);
+    if (keep_compile_unit_die)
+      DieArray.push_back(tmpArray.front());
+  }
+}
+
+void
+DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
+                                         bool clear_dies_if_already_not_parsed){
+  // This function is usually called if there in no .debug_aranges section
+  // in order to produce a compile unit level set of address ranges that
+  // is accurate. If the DIEs weren't parsed, then we don't want all dies for
+  // all compile units to stay loaded when they weren't needed. So we can end
+  // up parsing the DWARF and then throwing them all away to keep memory usage
+  // down.
+  const bool clear_dies = extractDIEsIfNeeded(false) > 1;
+
+  DieArray[0].buildAddressRangeTable(this, debug_aranges);
+
+  // Keep memory down by clearing DIEs if this generate function
+  // caused them to be parsed.
+  if (clear_dies)
+    clearDIEs(true);
+}
index 0c082ad33782ce1bae5d9690962f2057bce23db4..378b6ced8cfe0fa26eef211b3cd25ba36f02b1e3 100644 (file)
@@ -91,6 +91,11 @@ public:
       DieArray.reserve(getDebugInfoSize() / 14);
     DieArray.push_back(die);
   }
+
+  void clearDIEs(bool keep_compile_unit_die);
+
+  void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
+                              bool clear_dies_if_already_not_parsed);
 };
 
 }
index c034bb369638fa4356724840712671612413c307..3359ae3b900ded9b074c49a2f1a554db70f9af79 100644 (file)
@@ -46,6 +46,8 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() {
 
   Aranges.reset(new DWARFDebugAranges());
   Aranges->extract(arangesData);
+  if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs.
+    Aranges->generate(this);
   return Aranges.get();
 }
 
index b116f8f7d89eb93fe92636896b3060b088ae9461..5053e19b71c98f32faa4859ba4ec949b40431cd1 100644 (file)
@@ -83,6 +83,19 @@ bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) {
   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);
+    }
+  }
+  return !isEmpty();
+}
+
 void DWARFDebugAranges::dump(raw_ostream &OS) const {
   const uint32_t num_ranges = getNumRanges();
   for (uint32_t i = 0; i < num_ranges; ++i) {
index 8fe70e4aa453f916c2d6356da4185ef0b0aa1f04..12afb60beb4098c4c64db08b908c4b9ab2c28889 100644 (file)
@@ -64,6 +64,7 @@ public:
   bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const;
   bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const;
   bool extract(DataExtractor debug_aranges_data);
+  bool generate(DWARFContext *ctx);
 
   // Use append range multiple times and then call sort
   void appendRange(uint32_t cu_offset, uint64_t low_pc, uint64_t high_pc);
index 627fad5afce6f4897caf5deee67ef14a8381bf38..0bf8b69611fd443b557e241a9a42902271d5dc4d 100644 (file)
@@ -397,7 +397,8 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
 }
 
 uint64_t
-DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(const DWARFCompileUnit* cu,
+DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
+                                                  const DWARFCompileUnit* cu,
                                                   const uint16_t attr,
                                                   uint64_t fail_value) const {
   DWARFFormValue form_value;
@@ -405,3 +406,26 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(const DWARFCompileUnit*
       return form_value.getReference(cu);
   return fail_value;
 }
+
+void
+DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu,
+                                               DWARFDebugAranges *debug_aranges)
+                                                   const {
+  if (AbbrevDecl) {
+    uint16_t tag = AbbrevDecl->getTag();
+    if (tag == DW_TAG_subprogram) {
+      uint64_t hi_pc = -1ULL;
+      uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
+      if (lo_pc != -1ULL)
+        hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
+      if (hi_pc != -1ULL)
+        debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc);
+    }
+
+    const DWARFDebugInfoEntryMinimal *child = getFirstChild();
+    while (child) {
+      child->buildAddressRangeTable(cu, debug_aranges);
+      child = child->getSibling();
+    }
+  }
+}
index 5e7b89b5a6e848f15a1b5cc60555f285102b0eb7..aff2e855672914e1f1913a154cd9c7e8e5c2c742 100644 (file)
@@ -15,6 +15,7 @@
 
 namespace llvm {
 
+class DWARFDebugAranges;
 class DWARFCompileUnit;
 class DWARFContext;
 class DWARFFormValue;
@@ -124,6 +125,9 @@ public:
   int64_t getAttributeValueAsSigned(const DWARFCompileUnit* cu,
                                     const uint16_t attr,
                                     int64_t fail_value) const;
+
+  void buildAddressRangeTable(const DWARFCompileUnit *cu,
+                              DWARFDebugAranges *debug_aranges) const;
 };
 
 }