Home | History | Annotate | Download | only in DWARF
      1 //===-- DWARFDebugPubnames.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 "DWARFDebugPubnames.h"
     11 
     12 #include "lldb/Core/Stream.h"
     13 #include "lldb/Core/Timer.h"
     14 
     15 #include "DWARFDebugInfo.h"
     16 #include "DWARFDIECollection.h"
     17 #include "DWARFFormValue.h"
     18 #include "DWARFCompileUnit.h"
     19 #include "LogChannelDWARF.h"
     20 #include "SymbolFileDWARF.h"
     21 
     22 
     23 using namespace lldb;
     24 using namespace lldb_private;
     25 
     26 DWARFDebugPubnames::DWARFDebugPubnames() :
     27     m_sets()
     28 {
     29 }
     30 
     31 bool
     32 DWARFDebugPubnames::Extract(const DataExtractor& data)
     33 {
     34     Timer scoped_timer (__PRETTY_FUNCTION__,
     35                         "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
     36                         (uint64_t)data.GetByteSize());
     37     Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
     38     if (log)
     39         log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")", (uint64_t)data.GetByteSize());
     40 
     41     if (data.ValidOffset(0))
     42     {
     43         lldb::offset_t offset = 0;
     44 
     45         DWARFDebugPubnamesSet set;
     46         while (data.ValidOffset(offset))
     47         {
     48             if (set.Extract(data, &offset))
     49             {
     50                 m_sets.push_back(set);
     51                 offset = set.GetOffsetOfNextEntry();
     52             }
     53             else
     54                 break;
     55         }
     56         if (log)
     57             Dump (log);
     58         return true;
     59     }
     60     return false;
     61 }
     62 
     63 
     64 bool
     65 DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
     66 {
     67     Timer scoped_timer (__PRETTY_FUNCTION__,
     68                         "DWARFDebugPubnames::GeneratePubnames (data = %p)",
     69                         dwarf2Data);
     70 
     71     Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
     72     if (log)
     73         log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data);
     74 
     75     m_sets.clear();
     76     DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
     77     if (debug_info)
     78     {
     79 
     80         const DataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
     81 
     82         uint32_t cu_idx = 0;
     83         const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
     84         for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
     85         {
     86 
     87             DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
     88 
     89             const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize());
     90 
     91             bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
     92 
     93             DWARFDIECollection dies;
     94             const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) +
     95                                      cu->AppendDIEsWithTag (DW_TAG_variable, dies);
     96 
     97             dw_offset_t cu_offset = cu->GetOffset();
     98             DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
     99 
    100             size_t die_idx;
    101             for (die_idx = 0; die_idx < die_count; ++die_idx)
    102             {
    103                 const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
    104                 DWARFDebugInfoEntry::Attributes attributes;
    105                 const char *name = NULL;
    106                 const char *mangled = NULL;
    107                 bool add_die = false;
    108                 const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes);
    109                 if (num_attributes > 0)
    110                 {
    111                     uint32_t i;
    112 
    113                     dw_tag_t tag = die->Tag();
    114 
    115                     for (i=0; i<num_attributes; ++i)
    116                     {
    117                         dw_attr_t attr = attributes.AttributeAtIndex(i);
    118                         DWARFFormValue form_value;
    119                         switch (attr)
    120                         {
    121                         case DW_AT_name:
    122                             if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
    123                                 name = form_value.AsCString(debug_str);
    124                             break;
    125 
    126                         case DW_AT_MIPS_linkage_name:
    127                         case DW_AT_linkage_name:
    128                             if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
    129                                 mangled = form_value.AsCString(debug_str);
    130                             break;
    131 
    132                         case DW_AT_low_pc:
    133                         case DW_AT_ranges:
    134                         case DW_AT_entry_pc:
    135                             if (tag == DW_TAG_subprogram)
    136                                 add_die = true;
    137                             break;
    138 
    139                         case DW_AT_location:
    140                             if (tag == DW_TAG_variable)
    141                             {
    142                                 const DWARFDebugInfoEntry* parent_die = die->GetParent();
    143                                 while ( parent_die != NULL )
    144                                 {
    145                                     switch (parent_die->Tag())
    146                                     {
    147                                     case DW_TAG_subprogram:
    148                                     case DW_TAG_lexical_block:
    149                                     case DW_TAG_inlined_subroutine:
    150                                         // Even if this is a function level static, we don't add it. We could theoretically
    151                                         // add these if we wanted to by introspecting into the DW_AT_location and seeing
    152                                         // if the location describes a hard coded address, but we don't want the performance
    153                                         // penalty of that right now.
    154                                         add_die = false;
    155 //                                      if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
    156 //                                      {
    157 //                                          // If we have valid block data, then we have location expression bytes
    158 //                                          // that are fixed (not a location list).
    159 //                                          const uint8_t *block_data = form_value.BlockData();
    160 //                                          if (block_data)
    161 //                                          {
    162 //                                              uint32_t block_length = form_value.Unsigned();
    163 //                                              if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
    164 //                                              {
    165 //                                                  if (block_data[0] == DW_OP_addr)
    166 //                                                      add_die = true;
    167 //                                              }
    168 //                                          }
    169 //                                      }
    170                                         parent_die = NULL;  // Terminate the while loop.
    171                                         break;
    172 
    173                                     case DW_TAG_compile_unit:
    174                                         add_die = true;
    175                                         parent_die = NULL;  // Terminate the while loop.
    176                                         break;
    177 
    178                                     default:
    179                                         parent_die = parent_die->GetParent();   // Keep going in the while loop.
    180                                         break;
    181                                     }
    182                                 }
    183                             }
    184                             break;
    185                         }
    186                     }
    187                 }
    188 
    189                 if (add_die && (name || mangled))
    190                 {
    191                     pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name);
    192                 }
    193             }
    194 
    195             if (pubnames_set.NumDescriptors() > 0)
    196             {
    197                 m_sets.push_back(pubnames_set);
    198             }
    199 
    200             // Keep memory down by clearing DIEs if this generate function
    201             // caused them to be parsed
    202             if (clear_dies)
    203                 cu->ClearDIEs (true);
    204         }
    205     }
    206     if (m_sets.empty())
    207         return false;
    208     if (log)
    209         Dump (log);
    210     return true;
    211 }
    212 
    213 bool
    214 DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
    215 {
    216     m_sets.clear();
    217     DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
    218     if (debug_info)
    219     {
    220         uint32_t cu_idx = 0;
    221         const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
    222         for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
    223         {
    224             DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
    225             DWARFDIECollection dies;
    226             const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies);
    227             dw_offset_t cu_offset = cu->GetOffset();
    228             DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
    229 
    230             size_t die_idx;
    231             for (die_idx = 0; die_idx < die_count; ++die_idx)
    232             {
    233                 const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
    234                 const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL);
    235 
    236                 if (name)
    237                 {
    238                     pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name);
    239                 }
    240             }
    241 
    242             if (pubnames_set.NumDescriptors() > 0)
    243             {
    244                 m_sets.push_back(pubnames_set);
    245             }
    246         }
    247     }
    248     return !m_sets.empty();
    249 }
    250 
    251 void
    252 DWARFDebugPubnames::Dump(Log *s) const
    253 {
    254     if (m_sets.empty())
    255         s->PutCString("< EMPTY >\n");
    256     else
    257     {
    258         const_iterator pos;
    259         const_iterator end = m_sets.end();
    260 
    261         for (pos = m_sets.begin(); pos != end; ++pos)
    262             (*pos).Dump(s);
    263     }
    264 }
    265 
    266 bool
    267 DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const
    268 {
    269     const_iterator pos;
    270     const_iterator end = m_sets.end();
    271 
    272     die_offsets.clear();
    273 
    274     for (pos = m_sets.begin(); pos != end; ++pos)
    275     {
    276         (*pos).Find(name, ignore_case, die_offsets);
    277     }
    278 
    279     return !die_offsets.empty();
    280 }
    281 
    282 bool
    283 DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const
    284 {
    285     const_iterator pos;
    286     const_iterator end = m_sets.end();
    287 
    288     die_offsets.clear();
    289 
    290     for (pos = m_sets.begin(); pos != end; ++pos)
    291     {
    292         (*pos).Find(regex, die_offsets);
    293     }
    294 
    295     return !die_offsets.empty();
    296 }
    297