Home | History | Annotate | Download | only in DWARF
      1 //===-- HashedNameToDIE.h ---------------------------------------*- 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 #ifndef SymbolFileDWARF_HashedNameToDIE_h_
     11 #define SymbolFileDWARF_HashedNameToDIE_h_
     12 
     13 #include <vector>
     14 
     15 #include "DWARFDefines.h"
     16 #include "DWARFFormValue.h"
     17 
     18 #include "lldb/lldb-defines.h"
     19 #include "lldb/Core/dwarf.h"
     20 #include "lldb/Core/RegularExpression.h"
     21 #include "lldb/Core/MappedHash.h"
     22 
     23 
     24 class SymbolFileDWARF;
     25 class DWARFCompileUnit;
     26 class DWARFDebugInfoEntry;
     27 
     28 struct DWARFMappedHash
     29 {
     30     struct DIEInfo
     31     {
     32         dw_offset_t offset;  // The DIE offset
     33         dw_tag_t tag;
     34         uint32_t type_flags; // Any flags for this DIEInfo
     35         uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
     36 
     37         DIEInfo () :
     38             offset (DW_INVALID_OFFSET),
     39             tag (0),
     40             type_flags (0),
     41             qualified_name_hash (0)
     42         {
     43         }
     44 
     45         DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) :
     46             offset(o),
     47             tag (t),
     48             type_flags (f),
     49             qualified_name_hash (h)
     50         {
     51         }
     52 
     53         void
     54         Clear()
     55         {
     56             offset = DW_INVALID_OFFSET;
     57             tag = 0;
     58             type_flags = 0;
     59             qualified_name_hash = 0;
     60         }
     61     };
     62 
     63     typedef std::vector<DIEInfo> DIEInfoArray;
     64     typedef std::vector<uint32_t> DIEArray;
     65 
     66     static void
     67     ExtractDIEArray (const DIEInfoArray &die_info_array,
     68                      DIEArray &die_offsets)
     69     {
     70         const size_t count = die_info_array.size();
     71         for (size_t i=0; i<count; ++i)
     72         {
     73             die_offsets.push_back (die_info_array[i].offset);
     74         }
     75     }
     76 
     77     static void
     78     ExtractDIEArray (const DIEInfoArray &die_info_array,
     79                      const dw_tag_t tag,
     80                      DIEArray &die_offsets)
     81     {
     82         if (tag == 0)
     83         {
     84             ExtractDIEArray (die_info_array, die_offsets);
     85         }
     86         else
     87         {
     88             const size_t count = die_info_array.size();
     89             for (size_t i=0; i<count; ++i)
     90             {
     91                 const dw_tag_t die_tag = die_info_array[i].tag;
     92                 bool tag_matches = die_tag == 0 || tag == die_tag;
     93                 if (!tag_matches)
     94                 {
     95                     if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
     96                         tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
     97                 }
     98                 if (tag_matches)
     99                     die_offsets.push_back (die_info_array[i].offset);
    100             }
    101         }
    102     }
    103 
    104     static void
    105     ExtractDIEArray (const DIEInfoArray &die_info_array,
    106                      const dw_tag_t tag,
    107                      const uint32_t qualified_name_hash,
    108                      DIEArray &die_offsets)
    109     {
    110         if (tag == 0)
    111         {
    112             ExtractDIEArray (die_info_array, die_offsets);
    113         }
    114         else
    115         {
    116             const size_t count = die_info_array.size();
    117             for (size_t i=0; i<count; ++i)
    118             {
    119                 if (qualified_name_hash != die_info_array[i].qualified_name_hash)
    120                     continue;
    121                 const dw_tag_t die_tag = die_info_array[i].tag;
    122                 bool tag_matches = die_tag == 0 || tag == die_tag;
    123                 if (!tag_matches)
    124                 {
    125                     if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
    126                         tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
    127                 }
    128                 if (tag_matches)
    129                     die_offsets.push_back (die_info_array[i].offset);
    130             }
    131         }
    132     }
    133 
    134     enum AtomType
    135     {
    136         eAtomTypeNULL       = 0u,
    137         eAtomTypeDIEOffset  = 1u,   // DIE offset, check form for encoding
    138         eAtomTypeCUOffset   = 2u,   // DIE offset of the compiler unit header that contains the item in question
    139         eAtomTypeTag        = 3u,   // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
    140         eAtomTypeNameFlags  = 4u,   // Flags from enum NameFlags
    141         eAtomTypeTypeFlags  = 5u,   // Flags from enum TypeFlags,
    142         eAtomTypeQualNameHash = 6u  // A 32 bit hash of the full qualified name (since all hash entries are basename only)
    143                                     // For example a type like "std::vector<int>::iterator" would have a name of "iterator"
    144                                     // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull
    145                                     // in debug info for a type when we know the fully qualified name.
    146     };
    147 
    148     // Bit definitions for the eAtomTypeTypeFlags flags
    149     enum TypeFlags
    150     {
    151         // Always set for C++, only set for ObjC if this is the
    152         // @implementation for class
    153         eTypeFlagClassIsImplementation  = ( 1u << 1 )
    154     };
    155 
    156 
    157     static void
    158     ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
    159                                   bool return_implementation_only_if_available,
    160                                   DIEArray &die_offsets)
    161     {
    162         const size_t count = die_info_array.size();
    163         for (size_t i=0; i<count; ++i)
    164         {
    165             const dw_tag_t die_tag = die_info_array[i].tag;
    166             if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
    167             {
    168                 if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
    169                 {
    170                     if (return_implementation_only_if_available)
    171                     {
    172                         // We found the one true definiton for this class, so
    173                         // only return that
    174                         die_offsets.clear();
    175                         die_offsets.push_back (die_info_array[i].offset);
    176                         return;
    177                     }
    178                     else
    179                     {
    180                         // Put the one true definition as the first entry so it
    181                         // matches first
    182                         die_offsets.insert (die_offsets.begin(), die_info_array[i].offset);
    183                     }
    184                 }
    185                 else
    186                 {
    187                     die_offsets.push_back (die_info_array[i].offset);
    188                 }
    189             }
    190         }
    191     }
    192 
    193     static void
    194     ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
    195                               uint32_t type_flag_mask,
    196                               uint32_t type_flag_value,
    197                               DIEArray &die_offsets)
    198     {
    199         const size_t count = die_info_array.size();
    200         for (size_t i=0; i<count; ++i)
    201         {
    202             if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
    203                 die_offsets.push_back (die_info_array[i].offset);
    204         }
    205     }
    206 
    207     struct Atom
    208     {
    209         uint16_t type;
    210         dw_form_t form;
    211 
    212         Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) :
    213             type (t),
    214             form (f)
    215         {
    216         }
    217     };
    218 
    219     typedef std::vector<Atom> AtomArray;
    220 
    221     static uint32_t
    222     GetTypeFlags (SymbolFileDWARF *dwarf2Data,
    223                   const DWARFCompileUnit* cu,
    224                   const DWARFDebugInfoEntry* die);
    225 
    226 
    227     static const char *
    228     GetAtomTypeName (uint16_t atom)
    229     {
    230         switch (atom)
    231         {
    232             case eAtomTypeNULL:         return "NULL";
    233             case eAtomTypeDIEOffset:    return "die-offset";
    234             case eAtomTypeCUOffset:     return "cu-offset";
    235             case eAtomTypeTag:          return "die-tag";
    236             case eAtomTypeNameFlags:    return "name-flags";
    237             case eAtomTypeTypeFlags:    return "type-flags";
    238             case eAtomTypeQualNameHash: return "qualified-name-hash";
    239         }
    240         return "<invalid>";
    241     }
    242     struct Prologue
    243     {
    244         // DIE offset base so die offsets in hash_data can be CU relative
    245         dw_offset_t die_base_offset;
    246         AtomArray atoms;
    247         uint32_t atom_mask;
    248         size_t min_hash_data_byte_size;
    249         bool hash_data_has_fixed_byte_size;
    250 
    251         Prologue (dw_offset_t _die_base_offset = 0) :
    252             die_base_offset (_die_base_offset),
    253             atoms(),
    254             atom_mask (0),
    255             min_hash_data_byte_size(0),
    256             hash_data_has_fixed_byte_size(true)
    257         {
    258             // Define an array of DIE offsets by first defining an array,
    259             // and then define the atom type for the array, in this case
    260             // we have an array of DIE offsets
    261             AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
    262         }
    263 
    264         virtual ~Prologue()
    265         {
    266         }
    267 
    268         void
    269         ClearAtoms ()
    270         {
    271             hash_data_has_fixed_byte_size = true;
    272             min_hash_data_byte_size = 0;
    273             atom_mask = 0;
    274             atoms.clear();
    275         }
    276 
    277         bool
    278         ContainsAtom (AtomType atom_type) const
    279         {
    280             return (atom_mask & (1u << atom_type)) != 0;
    281         }
    282 
    283         virtual void
    284         Clear ()
    285         {
    286             die_base_offset = 0;
    287             ClearAtoms ();
    288         }
    289 
    290         void
    291         AppendAtom (AtomType type, dw_form_t form)
    292         {
    293             atoms.push_back (Atom(type, form));
    294             atom_mask |= 1u << type;
    295             switch (form)
    296             {
    297                 case DW_FORM_indirect:
    298                 case DW_FORM_exprloc:
    299                 case DW_FORM_flag_present:
    300                 case DW_FORM_ref_sig8:
    301                     assert (!"Unhandled atom form");
    302                     break;
    303 
    304                 case DW_FORM_string:
    305                 case DW_FORM_block:
    306                 case DW_FORM_block1:
    307                 case DW_FORM_sdata:
    308                 case DW_FORM_udata:
    309                 case DW_FORM_ref_udata:
    310                     hash_data_has_fixed_byte_size = false;
    311                     // Fall through to the cases below...
    312                 case DW_FORM_flag:
    313                 case DW_FORM_data1:
    314                 case DW_FORM_ref1:
    315                 case DW_FORM_sec_offset:
    316                     min_hash_data_byte_size += 1;
    317                     break;
    318 
    319                 case DW_FORM_block2:
    320                     hash_data_has_fixed_byte_size = false;
    321                     // Fall through to the cases below...
    322                 case DW_FORM_data2:
    323                 case DW_FORM_ref2:
    324                     min_hash_data_byte_size += 2;
    325                     break;
    326 
    327                 case DW_FORM_block4:
    328                     hash_data_has_fixed_byte_size = false;
    329                     // Fall through to the cases below...
    330                 case DW_FORM_data4:
    331                 case DW_FORM_ref4:
    332                 case DW_FORM_addr:
    333                 case DW_FORM_ref_addr:
    334                 case DW_FORM_strp:
    335                     min_hash_data_byte_size += 4;
    336                     break;
    337 
    338                 case DW_FORM_data8:
    339                 case DW_FORM_ref8:
    340                     min_hash_data_byte_size += 8;
    341                     break;
    342 
    343             }
    344         }
    345 
    346 //        void
    347 //        Dump (std::ostream* ostrm_ptr);
    348 
    349         lldb::offset_t
    350         Read (const lldb_private::DataExtractor &data,
    351               lldb::offset_t offset)
    352         {
    353             ClearAtoms ();
    354 
    355             die_base_offset = data.GetU32 (&offset);
    356 
    357             const uint32_t atom_count = data.GetU32 (&offset);
    358             if (atom_count == 0x00060003u)
    359             {
    360                 // Old format, deal with contents of old pre-release format
    361                 while (data.GetU32(&offset))
    362                     /* do nothing */;
    363 
    364                 // Hardcode to the only known value for now.
    365                 AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
    366             }
    367             else
    368             {
    369                 for (uint32_t i=0; i<atom_count; ++i)
    370                 {
    371                     AtomType type = (AtomType)data.GetU16 (&offset);
    372                     dw_form_t form = (dw_form_t)data.GetU16 (&offset);
    373                     AppendAtom (type, form);
    374                 }
    375             }
    376             return offset;
    377         }
    378 
    379 //        virtual void
    380 //        Write (BinaryStreamBuf &s);
    381 
    382         size_t
    383         GetByteSize () const
    384         {
    385             // Add an extra count to the atoms size for the zero termination Atom that gets
    386             // written to disk
    387             return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
    388         }
    389 
    390         size_t
    391         GetMinumumHashDataByteSize () const
    392         {
    393             return min_hash_data_byte_size;
    394         }
    395 
    396         bool
    397         HashDataHasFixedByteSize() const
    398         {
    399             return hash_data_has_fixed_byte_size;
    400         }
    401     };
    402 
    403     struct Header : public MappedHash::Header<Prologue>
    404     {
    405         Header (dw_offset_t _die_base_offset = 0)
    406         {
    407         }
    408 
    409         virtual
    410         ~Header()
    411         {
    412         }
    413 
    414         virtual size_t
    415         GetByteSize (const HeaderData &header_data)
    416         {
    417             return header_data.GetByteSize();
    418         }
    419 
    420         //        virtual void
    421         //        Dump (std::ostream* ostrm_ptr);
    422         //
    423         virtual lldb::offset_t
    424         Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
    425         {
    426             offset = MappedHash::Header<Prologue>::Read (data, offset);
    427             if (offset != UINT32_MAX)
    428             {
    429                 offset = header_data.Read (data, offset);
    430             }
    431             return offset;
    432         }
    433 
    434         bool
    435         Read (const lldb_private::DataExtractor &data,
    436               lldb::offset_t *offset_ptr,
    437               DIEInfo &hash_data) const
    438         {
    439             const size_t num_atoms = header_data.atoms.size();
    440             if (num_atoms == 0)
    441                 return false;
    442 
    443             for (size_t i=0; i<num_atoms; ++i)
    444             {
    445                 DWARFFormValue form_value (header_data.atoms[i].form);
    446 
    447                 if (!form_value.ExtractValue(data, offset_ptr, NULL))
    448                     return false;
    449 
    450                 switch (header_data.atoms[i].type)
    451                 {
    452                     case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
    453                         hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
    454                         break;
    455 
    456                     case eAtomTypeTag:          // DW_TAG value for the DIE
    457                         hash_data.tag = (dw_tag_t)form_value.Unsigned ();
    458 
    459                     case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
    460                         hash_data.type_flags = (uint32_t)form_value.Unsigned ();
    461                         break;
    462 
    463                     case eAtomTypeQualNameHash:    // Flags from enum TypeFlags
    464                         hash_data.qualified_name_hash = form_value.Unsigned ();
    465                         break;
    466 
    467                     default:
    468                         // We can always skip atomes we don't know about
    469                         break;
    470                 }
    471             }
    472             return true;
    473         }
    474 
    475         void
    476         Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
    477         {
    478             const size_t num_atoms = header_data.atoms.size();
    479             for (size_t i=0; i<num_atoms; ++i)
    480             {
    481                 if (i > 0)
    482                     strm.PutCString (", ");
    483 
    484                 DWARFFormValue form_value (header_data.atoms[i].form);
    485                 switch (header_data.atoms[i].type)
    486                 {
    487                     case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
    488                         strm.Printf ("{0x%8.8x}", hash_data.offset);
    489                         break;
    490 
    491                     case eAtomTypeTag:          // DW_TAG value for the DIE
    492                         {
    493                             const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
    494                             if (tag_cstr)
    495                                 strm.PutCString (tag_cstr);
    496                             else
    497                                 strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
    498                         }
    499                         break;
    500 
    501                     case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
    502                         strm.Printf ("0x%2.2x", hash_data.type_flags);
    503                         if (hash_data.type_flags)
    504                         {
    505                             strm.PutCString (" (");
    506                             if (hash_data.type_flags & eTypeFlagClassIsImplementation)
    507                                 strm.PutCString (" implementation");
    508                             strm.PutCString (" )");
    509                         }
    510                         break;
    511 
    512                     case eAtomTypeQualNameHash:    // Flags from enum TypeFlags
    513                         strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
    514                         break;
    515 
    516                     default:
    517                         strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
    518                         break;
    519                 }
    520             }
    521         }
    522     };
    523 
    524 //    class ExportTable
    525 //    {
    526 //    public:
    527 //        ExportTable ();
    528 //
    529 //        void
    530 //        AppendNames (DWARFDebugPubnamesSet &pubnames_set,
    531 //                     StringTable &string_table);
    532 //
    533 //        void
    534 //        AppendNamesEntry (SymbolFileDWARF *dwarf2Data,
    535 //                          const DWARFCompileUnit* cu,
    536 //                          const DWARFDebugInfoEntry* die,
    537 //                          StringTable &string_table);
    538 //
    539 //        void
    540 //        AppendTypesEntry (DWARFData *dwarf2Data,
    541 //                          const DWARFCompileUnit* cu,
    542 //                          const DWARFDebugInfoEntry* die,
    543 //                          StringTable &string_table);
    544 //
    545 //        size_t
    546 //        Save (BinaryStreamBuf &names_data, const StringTable &string_table);
    547 //
    548 //        void
    549 //        AppendName (const char *name,
    550 //                    uint32_t die_offset,
    551 //                    StringTable &string_table,
    552 //                    dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied
    553 //        void
    554 //        AppendType (const char *name,
    555 //                    uint32_t die_offset,
    556 //                    StringTable &string_table);
    557 //
    558 //
    559 //    protected:
    560 //        struct Entry
    561 //        {
    562 //            uint32_t hash;
    563 //            uint32_t str_offset;
    564 //            uint32_t die_offset;
    565 //        };
    566 //
    567 //        // Map uniqued .debug_str offset to the corresponding DIE offsets
    568 //        typedef std::map<uint32_t, DIEInfoArray> NameInfo;
    569 //        // Map a name hash to one or more name infos
    570 //        typedef std::map<uint32_t, NameInfo> BucketEntry;
    571 //
    572 //        static uint32_t
    573 //        GetByteSize (const NameInfo &name_info);
    574 //
    575 //        typedef std::vector<BucketEntry> BucketEntryColl;
    576 //        typedef std::vector<Entry> EntryColl;
    577 //        EntryColl m_entries;
    578 //
    579 //    };
    580 
    581 
    582     // A class for reading and using a saved hash table from a block of data
    583     // in memory
    584     class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray>
    585     {
    586     public:
    587 
    588         MemoryTable (lldb_private::DataExtractor &table_data,
    589                      const lldb_private::DataExtractor &string_table,
    590                      const char *name) :
    591             MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
    592             m_data (table_data),
    593             m_string_table (string_table),
    594             m_name (name)
    595         {
    596         }
    597 
    598         virtual
    599         ~MemoryTable ()
    600         {
    601         }
    602 
    603         virtual const char *
    604         GetStringForKeyType (KeyType key) const
    605         {
    606             // The key in the DWARF table is the .debug_str offset for the string
    607             return m_string_table.PeekCStr (key);
    608         }
    609 
    610         virtual bool
    611         ReadHashData (uint32_t hash_data_offset,
    612                       HashData &hash_data) const
    613         {
    614             lldb::offset_t offset = hash_data_offset;
    615             offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
    616             const uint32_t count = m_data.GetU32 (&offset);
    617             if (count > 0)
    618             {
    619                 hash_data.resize(count);
    620                 for (uint32_t i=0; i<count; ++i)
    621                 {
    622                     if (!m_header.Read(m_data, &offset, hash_data[i]))
    623                         return false;
    624                 }
    625             }
    626             else
    627                 hash_data.clear();
    628             return true;
    629         }
    630 
    631         virtual Result
    632         GetHashDataForName (const char *name,
    633                             lldb::offset_t* hash_data_offset_ptr,
    634                             Pair &pair) const
    635         {
    636             pair.key = m_data.GetU32 (hash_data_offset_ptr);
    637             pair.value.clear();
    638 
    639             // If the key is zero, this terminates our chain of HashData objects
    640             // for this hash value.
    641             if (pair.key == 0)
    642                 return eResultEndOfHashData;
    643 
    644             // There definitely should be a string for this string offset, if
    645             // there isn't, there is something wrong, return and error
    646             const char *strp_cstr = m_string_table.PeekCStr (pair.key);
    647             if (strp_cstr == NULL)
    648             {
    649                 *hash_data_offset_ptr = UINT32_MAX;
    650                 return eResultError;
    651             }
    652 
    653             const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
    654             const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
    655             if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
    656             {
    657                 // We have at least one HashData entry, and we have enough
    658                 // data to parse at leats "count" HashData enties.
    659 
    660                 // First make sure the entire C string matches...
    661                 const bool match = strcmp (name, strp_cstr) == 0;
    662 
    663                 if (!match && m_header.header_data.HashDataHasFixedByteSize())
    664                 {
    665                     // If the string doesn't match and we have fixed size data,
    666                     // we can just add the total byte size of all HashData objects
    667                     // to the hash data offset and be done...
    668                     *hash_data_offset_ptr += min_total_hash_data_size;
    669                 }
    670                 else
    671                 {
    672                     // If the string does match, or we don't have fixed size data
    673                     // then we need to read the hash data as a stream. If the
    674                     // string matches we also append all HashData objects to the
    675                     // value array.
    676                     for (uint32_t i=0; i<count; ++i)
    677                     {
    678                         DIEInfo die_info;
    679                         if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
    680                         {
    681                             // Only happend the HashData if the string matched...
    682                             if (match)
    683                                 pair.value.push_back (die_info);
    684                         }
    685                         else
    686                         {
    687                             // Something went wrong while reading the data
    688                             *hash_data_offset_ptr = UINT32_MAX;
    689                             return eResultError;
    690                         }
    691                     }
    692                 }
    693                 // Return the correct response depending on if the string matched
    694                 // or not...
    695                 if (match)
    696                     return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
    697                 else
    698                     return eResultKeyMismatch;  // The key doesn't match, this function will get called
    699                                                 // again for the next key/value or the key terminator
    700                                                 // which in our case is a zero .debug_str offset.
    701             }
    702             else
    703             {
    704                 *hash_data_offset_ptr = UINT32_MAX;
    705                 return eResultError;
    706             }
    707         }
    708 
    709         virtual Result
    710         AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
    711                                             lldb::offset_t* hash_data_offset_ptr,
    712                                             Pair &pair) const
    713         {
    714             pair.key = m_data.GetU32 (hash_data_offset_ptr);
    715             // If the key is zero, this terminates our chain of HashData objects
    716             // for this hash value.
    717             if (pair.key == 0)
    718                 return eResultEndOfHashData;
    719 
    720             // There definitely should be a string for this string offset, if
    721             // there isn't, there is something wrong, return and error
    722             const char *strp_cstr = m_string_table.PeekCStr (pair.key);
    723             if (strp_cstr == NULL)
    724                 return eResultError;
    725 
    726             const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
    727             const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
    728             if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
    729             {
    730                 const bool match = regex.Execute(strp_cstr);
    731 
    732                 if (!match && m_header.header_data.HashDataHasFixedByteSize())
    733                 {
    734                     // If the regex doesn't match and we have fixed size data,
    735                     // we can just add the total byte size of all HashData objects
    736                     // to the hash data offset and be done...
    737                     *hash_data_offset_ptr += min_total_hash_data_size;
    738                 }
    739                 else
    740                 {
    741                     // If the string does match, or we don't have fixed size data
    742                     // then we need to read the hash data as a stream. If the
    743                     // string matches we also append all HashData objects to the
    744                     // value array.
    745                     for (uint32_t i=0; i<count; ++i)
    746                     {
    747                         DIEInfo die_info;
    748                         if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
    749                         {
    750                             // Only happend the HashData if the string matched...
    751                             if (match)
    752                                 pair.value.push_back (die_info);
    753                         }
    754                         else
    755                         {
    756                             // Something went wrong while reading the data
    757                             *hash_data_offset_ptr = UINT32_MAX;
    758                             return eResultError;
    759                         }
    760                     }
    761                 }
    762                 // Return the correct response depending on if the string matched
    763                 // or not...
    764                 if (match)
    765                     return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
    766                 else
    767                     return eResultKeyMismatch;  // The key doesn't match, this function will get called
    768                                                 // again for the next key/value or the key terminator
    769                                                 // which in our case is a zero .debug_str offset.
    770             }
    771             else
    772             {
    773                 *hash_data_offset_ptr = UINT32_MAX;
    774                 return eResultError;
    775             }
    776         }
    777 
    778         size_t
    779         AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,
    780                                         DIEInfoArray &die_info_array) const
    781         {
    782             const uint32_t hash_count = m_header.hashes_count;
    783             Pair pair;
    784             for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
    785             {
    786                 lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
    787                 while (hash_data_offset != UINT32_MAX)
    788                 {
    789                     const lldb::offset_t prev_hash_data_offset = hash_data_offset;
    790                     Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
    791                     if (prev_hash_data_offset == hash_data_offset)
    792                         break;
    793 
    794                     // Check the result of getting our hash data
    795                     switch (hash_result)
    796                     {
    797                         case eResultKeyMatch:
    798                         case eResultKeyMismatch:
    799                             // Whether we matches or not, it doesn't matter, we
    800                             // keep looking.
    801                             break;
    802 
    803                         case eResultEndOfHashData:
    804                         case eResultError:
    805                             hash_data_offset = UINT32_MAX;
    806                             break;
    807                     }
    808                 }
    809             }
    810             die_info_array.swap (pair.value);
    811             return die_info_array.size();
    812         }
    813 
    814         size_t
    815         AppendAllDIEsInRange (const uint32_t die_offset_start,
    816                               const uint32_t die_offset_end,
    817                               DIEInfoArray &die_info_array) const
    818         {
    819             const uint32_t hash_count = m_header.hashes_count;
    820             for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
    821             {
    822                 bool done = false;
    823                 lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
    824                 while (!done && hash_data_offset != UINT32_MAX)
    825                 {
    826                     KeyType key = m_data.GetU32 (&hash_data_offset);
    827                     // If the key is zero, this terminates our chain of HashData objects
    828                     // for this hash value.
    829                     if (key == 0)
    830                         break;
    831 
    832                     const uint32_t count = m_data.GetU32 (&hash_data_offset);
    833                     for (uint32_t i=0; i<count; ++i)
    834                     {
    835                         DIEInfo die_info;
    836                         if (m_header.Read(m_data, &hash_data_offset, die_info))
    837                         {
    838                             if (die_info.offset == 0)
    839                                 done = true;
    840                             if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
    841                                 die_info_array.push_back(die_info);
    842                         }
    843                     }
    844                 }
    845             }
    846             return die_info_array.size();
    847         }
    848 
    849         size_t
    850         FindByName (const char *name, DIEArray &die_offsets)
    851         {
    852             DIEInfoArray die_info_array;
    853             if (FindByName(name, die_info_array))
    854                 DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
    855             return die_info_array.size();
    856         }
    857 
    858         size_t
    859         FindByNameAndTag (const char *name,
    860                           const dw_tag_t tag,
    861                           DIEArray &die_offsets)
    862         {
    863             DIEInfoArray die_info_array;
    864             if (FindByName(name, die_info_array))
    865                 DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
    866             return die_info_array.size();
    867         }
    868 
    869         size_t
    870         FindByNameAndTagAndQualifiedNameHash (const char *name,
    871                                               const dw_tag_t tag,
    872                                               const uint32_t qualified_name_hash,
    873                                               DIEArray &die_offsets)
    874         {
    875             DIEInfoArray die_info_array;
    876             if (FindByName(name, die_info_array))
    877                 DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
    878             return die_info_array.size();
    879         }
    880 
    881         size_t
    882         FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation)
    883         {
    884             DIEInfoArray die_info_array;
    885             if (FindByName(name, die_info_array))
    886             {
    887                 if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
    888                 {
    889                     // If we have two atoms, then we have the DIE offset and
    890                     // the type flags so we can find the objective C class
    891                     // efficiently.
    892                     DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
    893                                                                UINT32_MAX,
    894                                                                eTypeFlagClassIsImplementation,
    895                                                                die_offsets);
    896                 }
    897                 else
    898                 {
    899                     // We don't only want the one true definition, so try and see
    900                     // what we can find, and only return class or struct DIEs.
    901                     // If we do have the full implementation, then return it alone,
    902                     // else return all possible matches.
    903                     const bool return_implementation_only_if_available = true;
    904                     DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
    905                                                                    return_implementation_only_if_available,
    906                                                                    die_offsets);
    907                 }
    908             }
    909             return die_offsets.size();
    910         }
    911 
    912         size_t
    913         FindByName (const char *name, DIEInfoArray &die_info_array)
    914         {
    915             Pair kv_pair;
    916             size_t old_size = die_info_array.size();
    917             if (Find (name, kv_pair))
    918             {
    919                 die_info_array.swap(kv_pair.value);
    920                 return die_info_array.size() - old_size;
    921             }
    922             return 0;
    923         }
    924 
    925     protected:
    926         const lldb_private::DataExtractor &m_data;
    927         const lldb_private::DataExtractor &m_string_table;
    928         std::string m_name;
    929     };
    930 };
    931 
    932 
    933 #endif  // SymbolFileDWARF_HashedNameToDIE_h_
    934