diff options
| author | Greg Clayton <gclayton@apple.com> | 2014-03-14 23:36:38 +0000 | 
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2014-03-14 23:36:38 +0000 | 
| commit | 26c1fe356801a966945e858b699cd7b1e85c83af (patch) | |
| tree | 493678d6464275a1d949685e78bb3c7a9850d76e | |
| parent | e3b5c99fde0dfb7c0f691b7023903bc56962a901 (diff) | |
| download | bcm5719-llvm-26c1fe356801a966945e858b699cd7b1e85c83af.tar.gz bcm5719-llvm-26c1fe356801a966945e858b699cd7b1e85c83af.zip  | |
Parse DW_AT_ranges for compile units on Darwin when .debug_aranges is not available for the current compile unit.
<rdar://problem/16321434> 
llvm-svn: 203985
6 files changed, 77 insertions, 15 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index c63def1dc20..b2e64ad9f8c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -361,18 +361,43 @@ DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)  void  DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, -                                          DWARFDebugAranges* debug_aranges, -                                          bool clear_dies_if_already_not_parsed) +                                          DWARFDebugAranges* debug_aranges)  {      // 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. +    // is accurate. +     +    // First get the compile unit DIE only and check if it has a DW_AT_ranges +    const DWARFDebugInfoEntry* die = GetCompileUnitDIEOnly(); +     +    const dw_offset_t cu_offset = GetOffset(); +    if (die) +    { +        DWARFDebugRanges::RangeList ranges; +        const size_t num_ranges = die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false); +        if (num_ranges > 0) +        { +            // This compile unit has DW_AT_ranges, assume this is correct if it +            // is present since clang no longer makes .debug_aranges by default +            // and it emits DW_AT_ranges for DW_TAG_compile_units. GCC also does +            // this with recent GCC builds. +            for (size_t i=0; i<num_ranges; ++i) +            { +                const DWARFDebugRanges::RangeList::Entry &range = ranges.GetEntryRef(i); +                debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd()); +            } +             +            return; // We got all of our ranges from the DW_AT_ranges attribute +        } +    } +    // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF +     +    // 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; -    const DWARFDebugInfoEntry* die = DIE(); +    die = DIE();      if (die)          die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges); @@ -397,7 +422,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,                      for (uint32_t idx=0; idx<num_ranges; ++idx)                      {                          const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx); -                        debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); +                        debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());                          printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());                      }                  } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 35597f38942..ed1894b8a9f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -54,8 +54,7 @@ public:      dw_addr_t   GetBaseAddress() const { return m_base_addr; }      void        ClearDIEs(bool keep_compile_unit_die);      void        BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, -                                        DWARFDebugAranges* debug_aranges, -                                        bool clear_dies_if_already_not_parsed); +                                        DWARFDebugAranges* debug_aranges);      void      SetBaseAddress(dw_addr_t base_addr) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index 4f77bff86bd..be60321fb4e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -93,14 +93,13 @@ DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data)      DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();      if (debug_info)      { -        const bool clear_dies_if_already_not_parsed = true;          uint32_t cu_idx = 0;          const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();          for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)          {              DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);              if (cu) -                cu->BuildAddressRangeTable(dwarf2Data, this, clear_dies_if_already_not_parsed); +                cu->BuildAddressRangeTable(dwarf2Data, this);          }      }      return !IsEmpty(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index d4db12c17a4..b37bad9e5fb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -79,7 +79,6 @@ DWARFDebugInfo::GetCompileUnitAranges ()          // Manually build arange data for everything that wasn't in the .debug_aranges table.          bool printed = false;          const size_t num_compile_units = GetNumCompileUnits(); -        const bool clear_dies_if_already_not_parsed = true;          for (size_t idx = 0; idx < num_compile_units; ++idx)          {              DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx); @@ -94,7 +93,7 @@ DWARFDebugInfo::GetCompileUnitAranges ()                                       m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());                      printed = true;                  } -                cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed); +                cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get());              }          } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 37741eb1da9..856a7fa7a2f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -1485,6 +1485,40 @@ DWARFDebugInfoEntry::GetAttributeAddressRange      hi_pc = fail_value;      return false;  } + +size_t +DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF* dwarf2Data, +                                               const DWARFCompileUnit* cu, +                                               DWARFDebugRanges::RangeList &ranges, +                                               bool check_hi_lo_pc) const +{ +    ranges.Clear(); +     +    dw_offset_t ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); +    if (ranges_offset != DW_INVALID_OFFSET) +    { +        dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); +        if (debug_ranges_offset != DW_INVALID_OFFSET) +        { +            DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges(); +             +            debug_ranges->FindRanges(debug_ranges_offset, ranges); +            ranges.Slide (cu->GetBaseAddress()); +        } +    } +    else if (check_hi_lo_pc) +    { +        dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; +        dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; +        if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) +        { +            if (lo_pc < hi_pc) +                ranges.Append(DWARFDebugRanges::RangeList::Entry(lo_pc, hi_pc - lo_pc)); +        } +    } +    return ranges.GetSize(); +} +  //----------------------------------------------------------------------  // GetAttributeValueAsLocation  // diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index f7405755528..68020d6952c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -209,7 +209,13 @@ public:                      dw_addr_t& lo_pc,                      dw_addr_t& hi_pc,                      uint64_t fail_value) const; - +     +    size_t      GetAttributeAddressRanges ( +                    SymbolFileDWARF* dwarf2Data, +                    const DWARFCompileUnit* cu, +                    DWARFDebugRanges::RangeList &ranges, +                    bool check_hi_lo_pc) const; +          dw_offset_t GetAttributeValueAsLocation(                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu,  | 

