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