Home | History | Annotate | Download | only in DWARF
      1 //===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "DWARFDebugAranges.h"
     11 
     12 #include <assert.h>
     13 #include <stdio.h>
     14 
     15 #include <algorithm>
     16 
     17 #include "lldb/Core/Log.h"
     18 #include "lldb/Core/Stream.h"
     19 #include "lldb/Core/Timer.h"
     20 
     21 #include "LogChannelDWARF.h"
     22 #include "SymbolFileDWARF.h"
     23 #include "DWARFDebugInfo.h"
     24 #include "DWARFCompileUnit.h"
     25 
     26 using namespace lldb;
     27 using namespace lldb_private;
     28 
     29 //----------------------------------------------------------------------
     30 // Constructor
     31 //----------------------------------------------------------------------
     32 DWARFDebugAranges::DWARFDebugAranges() :
     33     m_aranges()
     34 {
     35 }
     36 
     37 //----------------------------------------------------------------------
     38 // CountArangeDescriptors
     39 //----------------------------------------------------------------------
     40 class CountArangeDescriptors
     41 {
     42 public:
     43     CountArangeDescriptors (uint32_t& count_ref) : count(count_ref)
     44     {
     45 //      printf("constructor CountArangeDescriptors()\n");
     46     }
     47     void operator() (const DWARFDebugArangeSet& set)
     48     {
     49         count += set.NumDescriptors();
     50     }
     51     uint32_t& count;
     52 };
     53 
     54 
     55 //----------------------------------------------------------------------
     56 // Extract
     57 //----------------------------------------------------------------------
     58 bool
     59 DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data)
     60 {
     61     if (debug_aranges_data.ValidOffset(0))
     62     {
     63         lldb::offset_t offset = 0;
     64 
     65         DWARFDebugArangeSet set;
     66         Range range;
     67         while (set.Extract(debug_aranges_data, &offset))
     68         {
     69             const uint32_t num_descriptors = set.NumDescriptors();
     70             if (num_descriptors > 0)
     71             {
     72                 const dw_offset_t cu_offset = set.GetCompileUnitDIEOffset();
     73 
     74                 for (uint32_t i=0; i<num_descriptors; ++i)
     75                 {
     76                     const DWARFDebugArangeSet::Descriptor &descriptor = set.GetDescriptorRef(i);
     77                     m_aranges.Append(RangeToDIE::Entry (descriptor.address, descriptor.length, cu_offset));
     78                 }
     79             }
     80             set.Clear();
     81         }
     82     }
     83     return false;
     84 }
     85 
     86 //----------------------------------------------------------------------
     87 // Generate
     88 //----------------------------------------------------------------------
     89 bool
     90 DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data)
     91 {
     92     Clear();
     93     DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
     94     if (debug_info)
     95     {
     96         const bool clear_dies_if_already_not_parsed = true;
     97         uint32_t cu_idx = 0;
     98         const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
     99         for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
    100         {
    101             DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
    102             if (cu)
    103                 cu->BuildAddressRangeTable(dwarf2Data, this, clear_dies_if_already_not_parsed);
    104         }
    105     }
    106     return !IsEmpty();
    107 }
    108 
    109 
    110 void
    111 DWARFDebugAranges::Dump (Log *log) const
    112 {
    113     if (log == NULL)
    114         return;
    115 
    116     const size_t num_entries = m_aranges.GetSize();
    117     for (size_t i=0; i<num_entries; ++i)
    118     {
    119         const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i);
    120         if (entry)
    121             log->Printf ("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")",
    122                          entry->data,
    123                          entry->GetRangeBase(),
    124                          entry->GetRangeEnd());
    125     }
    126 }
    127 
    128 void
    129 DWARFDebugAranges::AppendRange (dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc)
    130 {
    131     if (high_pc > low_pc)
    132         m_aranges.Append(RangeToDIE::Entry (low_pc, high_pc - low_pc, offset));
    133 }
    134 
    135 void
    136 DWARFDebugAranges::Sort (bool minimize)
    137 {
    138     Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
    139                        __PRETTY_FUNCTION__, this);
    140 
    141     Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
    142     size_t orig_arange_size = 0;
    143     if (log)
    144     {
    145         orig_arange_size = m_aranges.GetSize();
    146         log->Printf ("DWARFDebugAranges::Sort(minimize = %u) with %" PRIu64 " entries", minimize, (uint64_t)orig_arange_size);
    147     }
    148 
    149     m_aranges.Sort();
    150     m_aranges.CombineConsecutiveEntriesWithEqualData();
    151 
    152     if (log)
    153     {
    154         if (minimize)
    155         {
    156             const size_t new_arange_size = m_aranges.GetSize();
    157             const size_t delta = orig_arange_size - new_arange_size;
    158             log->Printf ("DWARFDebugAranges::Sort() %" PRIu64 " entries after minimizing (%" PRIu64 " entries combined for %" PRIu64 " bytes saved)",
    159                          (uint64_t)new_arange_size,
    160                          (uint64_t)delta,
    161                          (uint64_t)delta * sizeof(Range));
    162         }
    163         Dump (log);
    164     }
    165 }
    166 
    167 //----------------------------------------------------------------------
    168 // FindAddress
    169 //----------------------------------------------------------------------
    170 dw_offset_t
    171 DWARFDebugAranges::FindAddress(dw_addr_t address) const
    172 {
    173     const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address);
    174     if (entry)
    175         return entry->data;
    176     return DW_INVALID_OFFSET;
    177 }
    178