HashedNameToDIE.h revision 36da2aa6dc5ad9994b638ed09eb81c44cc05540b
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        lldb::offset_t
310        Read (const lldb_private::DataExtractor &data,
311              lldb::offset_t offset)
312        {
313            ClearAtoms ();
314
315            die_base_offset = data.GetU32 (&offset);
316
317            const uint32_t atom_count = data.GetU32 (&offset);
318            if (atom_count == 0x00060003u)
319            {
320                // Old format, deal with contents of old pre-release format
321                while (data.GetU32(&offset))
322                    /* do nothing */;
323
324                // Hardcode to the only known value for now.
325                AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
326            }
327            else
328            {
329                for (uint32_t i=0; i<atom_count; ++i)
330                {
331                    AtomType type = (AtomType)data.GetU16 (&offset);
332                    dw_form_t form = (dw_form_t)data.GetU16 (&offset);
333                    AppendAtom (type, form);
334                }
335            }
336            return offset;
337        }
338
339//        virtual void
340//        Write (BinaryStreamBuf &s);
341
342        size_t
343        GetByteSize () const
344        {
345            // Add an extra count to the atoms size for the zero termination Atom that gets
346            // written to disk
347            return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
348        }
349
350        size_t
351        GetMinumumHashDataByteSize () const
352        {
353            return min_hash_data_byte_size;
354        }
355
356        bool
357        HashDataHasFixedByteSize() const
358        {
359            return hash_data_has_fixed_byte_size;
360        }
361    };
362
363    struct Header : public MappedHash::Header<Prologue>
364    {
365        Header (dw_offset_t _die_base_offset = 0)
366        {
367        }
368
369        virtual
370        ~Header()
371        {
372        }
373
374        virtual size_t
375        GetByteSize (const HeaderData &header_data)
376        {
377            return header_data.GetByteSize();
378        }
379
380        //        virtual void
381        //        Dump (std::ostream* ostrm_ptr);
382        //
383        virtual lldb::offset_t
384        Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
385        {
386            offset = MappedHash::Header<Prologue>::Read (data, offset);
387            if (offset != UINT32_MAX)
388            {
389                offset = header_data.Read (data, offset);
390            }
391            return offset;
392        }
393
394        bool
395        Read (const lldb_private::DataExtractor &data,
396              lldb::offset_t *offset_ptr,
397              DIEInfo &hash_data) const
398        {
399            const size_t num_atoms = header_data.atoms.size();
400            if (num_atoms == 0)
401                return false;
402
403            for (size_t i=0; i<num_atoms; ++i)
404            {
405                DWARFFormValue form_value (header_data.atoms[i].form);
406
407                if (!form_value.ExtractValue(data, offset_ptr, NULL))
408                    return false;
409
410                switch (header_data.atoms[i].type)
411                {
412                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
413                        hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
414                        break;
415
416                    case eAtomTypeTag:          // DW_TAG value for the DIE
417                        hash_data.tag = (dw_tag_t)form_value.Unsigned ();
418
419                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
420                        hash_data.type_flags = (uint32_t)form_value.Unsigned ();
421                        break;
422                    default:
423                        return false;
424                        break;
425                }
426            }
427            return true;
428        }
429
430        void
431        Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
432        {
433            const size_t num_atoms = header_data.atoms.size();
434            for (size_t i=0; i<num_atoms; ++i)
435            {
436                if (i > 0)
437                    strm.PutCString (", ");
438
439                DWARFFormValue form_value (header_data.atoms[i].form);
440                switch (header_data.atoms[i].type)
441                {
442                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
443                        strm.Printf ("{0x%8.8x}", hash_data.offset);
444                        break;
445
446                    case eAtomTypeTag:          // DW_TAG value for the DIE
447                        {
448                            const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
449                            if (tag_cstr)
450                                strm.PutCString (tag_cstr);
451                            else
452                                strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
453                        }
454                        break;
455
456                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
457                        strm.Printf ("0x%2.2x", hash_data.type_flags);
458                        if (hash_data.type_flags)
459                        {
460                            strm.PutCString (" (");
461                            if (hash_data.type_flags & eTypeFlagClassIsImplementation)
462                                strm.PutCString (" implementation");
463                            strm.PutCString (" )");
464                        }
465                        break;
466
467                    default:
468                        strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
469                        break;
470                }
471            }
472        }
473    };
474
475//    class ExportTable
476//    {
477//    public:
478//        ExportTable ();
479//
480//        void
481//        AppendNames (DWARFDebugPubnamesSet &pubnames_set,
482//                     StringTable &string_table);
483//
484//        void
485//        AppendNamesEntry (SymbolFileDWARF *dwarf2Data,
486//                          const DWARFCompileUnit* cu,
487//                          const DWARFDebugInfoEntry* die,
488//                          StringTable &string_table);
489//
490//        void
491//        AppendTypesEntry (DWARFData *dwarf2Data,
492//                          const DWARFCompileUnit* cu,
493//                          const DWARFDebugInfoEntry* die,
494//                          StringTable &string_table);
495//
496//        size_t
497//        Save (BinaryStreamBuf &names_data, const StringTable &string_table);
498//
499//        void
500//        AppendName (const char *name,
501//                    uint32_t die_offset,
502//                    StringTable &string_table,
503//                    dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied
504//        void
505//        AppendType (const char *name,
506//                    uint32_t die_offset,
507//                    StringTable &string_table);
508//
509//
510//    protected:
511//        struct Entry
512//        {
513//            uint32_t hash;
514//            uint32_t str_offset;
515//            uint32_t die_offset;
516//        };
517//
518//        // Map uniqued .debug_str offset to the corresponding DIE offsets
519//        typedef std::map<uint32_t, DIEInfoArray> NameInfo;
520//        // Map a name hash to one or more name infos
521//        typedef std::map<uint32_t, NameInfo> BucketEntry;
522//
523//        static uint32_t
524//        GetByteSize (const NameInfo &name_info);
525//
526//        typedef std::vector<BucketEntry> BucketEntryColl;
527//        typedef std::vector<Entry> EntryColl;
528//        EntryColl m_entries;
529//
530//    };
531
532
533    // A class for reading and using a saved hash table from a block of data
534    // in memory
535    class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray>
536    {
537    public:
538
539        MemoryTable (lldb_private::DataExtractor &table_data,
540                     const lldb_private::DataExtractor &string_table,
541                     const char *name) :
542            MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
543            m_data (table_data),
544            m_string_table (string_table),
545            m_name (name)
546        {
547        }
548
549        virtual
550        ~MemoryTable ()
551        {
552        }
553
554        virtual const char *
555        GetStringForKeyType (KeyType key) const
556        {
557            // The key in the DWARF table is the .debug_str offset for the string
558            return m_string_table.PeekCStr (key);
559        }
560
561        virtual Result
562        GetHashDataForName (const char *name,
563                            lldb::offset_t* hash_data_offset_ptr,
564                            Pair &pair) const
565        {
566            pair.key = m_data.GetU32 (hash_data_offset_ptr);
567            pair.value.clear();
568
569            // If the key is zero, this terminates our chain of HashData objects
570            // for this hash value.
571            if (pair.key == 0)
572                return eResultEndOfHashData;
573
574            // There definitely should be a string for this string offset, if
575            // there isn't, there is something wrong, return and error
576            const char *strp_cstr = m_string_table.PeekCStr (pair.key);
577            if (strp_cstr == NULL)
578            {
579                *hash_data_offset_ptr = UINT32_MAX;
580                return eResultError;
581            }
582
583            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
584            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
585            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
586            {
587                // We have at least one HashData entry, and we have enough
588                // data to parse at leats "count" HashData enties.
589
590                // First make sure the entire C string matches...
591                const bool match = strcmp (name, strp_cstr) == 0;
592
593                if (!match && m_header.header_data.HashDataHasFixedByteSize())
594                {
595                    // If the string doesn't match and we have fixed size data,
596                    // we can just add the total byte size of all HashData objects
597                    // to the hash data offset and be done...
598                    *hash_data_offset_ptr += min_total_hash_data_size;
599                }
600                else
601                {
602                    // If the string does match, or we don't have fixed size data
603                    // then we need to read the hash data as a stream. If the
604                    // string matches we also append all HashData objects to the
605                    // value array.
606                    for (uint32_t i=0; i<count; ++i)
607                    {
608                        DIEInfo die_info;
609                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
610                        {
611                            // Only happend the HashData if the string matched...
612                            if (match)
613                                pair.value.push_back (die_info);
614                        }
615                        else
616                        {
617                            // Something went wrong while reading the data
618                            *hash_data_offset_ptr = UINT32_MAX;
619                            return eResultError;
620                        }
621                    }
622                }
623                // Return the correct response depending on if the string matched
624                // or not...
625                if (match)
626                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
627                else
628                    return eResultKeyMismatch;  // The key doesn't match, this function will get called
629                                                // again for the next key/value or the key terminator
630                                                // which in our case is a zero .debug_str offset.
631            }
632            else
633            {
634                *hash_data_offset_ptr = UINT32_MAX;
635                return eResultError;
636            }
637        }
638
639        virtual Result
640        AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
641                                            lldb::offset_t* hash_data_offset_ptr,
642                                            Pair &pair) const
643        {
644            pair.key = m_data.GetU32 (hash_data_offset_ptr);
645            // If the key is zero, this terminates our chain of HashData objects
646            // for this hash value.
647            if (pair.key == 0)
648                return eResultEndOfHashData;
649
650            // There definitely should be a string for this string offset, if
651            // there isn't, there is something wrong, return and error
652            const char *strp_cstr = m_string_table.PeekCStr (pair.key);
653            if (strp_cstr == NULL)
654                return eResultError;
655
656            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
657            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
658            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
659            {
660                const bool match = regex.Execute(strp_cstr);
661
662                if (!match && m_header.header_data.HashDataHasFixedByteSize())
663                {
664                    // If the regex doesn't match and we have fixed size data,
665                    // we can just add the total byte size of all HashData objects
666                    // to the hash data offset and be done...
667                    *hash_data_offset_ptr += min_total_hash_data_size;
668                }
669                else
670                {
671                    // If the string does match, or we don't have fixed size data
672                    // then we need to read the hash data as a stream. If the
673                    // string matches we also append all HashData objects to the
674                    // value array.
675                    for (uint32_t i=0; i<count; ++i)
676                    {
677                        DIEInfo die_info;
678                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
679                        {
680                            // Only happend the HashData if the string matched...
681                            if (match)
682                                pair.value.push_back (die_info);
683                        }
684                        else
685                        {
686                            // Something went wrong while reading the data
687                            *hash_data_offset_ptr = UINT32_MAX;
688                            return eResultError;
689                        }
690                    }
691                }
692                // Return the correct response depending on if the string matched
693                // or not...
694                if (match)
695                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
696                else
697                    return eResultKeyMismatch;  // The key doesn't match, this function will get called
698                                                // again for the next key/value or the key terminator
699                                                // which in our case is a zero .debug_str offset.
700            }
701            else
702            {
703                *hash_data_offset_ptr = UINT32_MAX;
704                return eResultError;
705            }
706        }
707
708        size_t
709        AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,
710                                        DIEInfoArray &die_info_array) const
711        {
712            const uint32_t hash_count = m_header.hashes_count;
713            Pair pair;
714            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
715            {
716                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
717                while (hash_data_offset != UINT32_MAX)
718                {
719                    const lldb::offset_t prev_hash_data_offset = hash_data_offset;
720                    Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
721                    if (prev_hash_data_offset == hash_data_offset)
722                        break;
723
724                    // Check the result of getting our hash data
725                    switch (hash_result)
726                    {
727                        case eResultKeyMatch:
728                        case eResultKeyMismatch:
729                            // Whether we matches or not, it doesn't matter, we
730                            // keep looking.
731                            break;
732
733                        case eResultEndOfHashData:
734                        case eResultError:
735                            hash_data_offset = UINT32_MAX;
736                            break;
737                    }
738                }
739            }
740            die_info_array.swap (pair.value);
741            return die_info_array.size();
742        }
743
744        size_t
745        AppendAllDIEsInRange (const uint32_t die_offset_start,
746                              const uint32_t die_offset_end,
747                              DIEInfoArray &die_info_array) const
748        {
749            const uint32_t hash_count = m_header.hashes_count;
750            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
751            {
752                bool done = false;
753                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
754                while (!done && hash_data_offset != UINT32_MAX)
755                {
756                    KeyType key = m_data.GetU32 (&hash_data_offset);
757                    // If the key is zero, this terminates our chain of HashData objects
758                    // for this hash value.
759                    if (key == 0)
760                        break;
761
762                    const uint32_t count = m_data.GetU32 (&hash_data_offset);
763                    for (uint32_t i=0; i<count; ++i)
764                    {
765                        DIEInfo die_info;
766                        if (m_header.Read(m_data, &hash_data_offset, die_info))
767                        {
768                            if (die_info.offset == 0)
769                                done = true;
770                            if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
771                                die_info_array.push_back(die_info);
772                        }
773                    }
774                }
775            }
776            return die_info_array.size();
777        }
778
779        size_t
780        FindByName (const char *name, DIEArray &die_offsets)
781        {
782            DIEInfoArray die_info_array;
783            if (FindByName(name, die_info_array))
784                DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
785            return die_info_array.size();
786        }
787
788        size_t
789        FindByNameAndTag (const char *name,
790                          const dw_tag_t tag,
791                          DIEArray &die_offsets)
792        {
793            DIEInfoArray die_info_array;
794            if (FindByName(name, die_info_array))
795                DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
796            return die_info_array.size();
797        }
798
799        size_t
800        FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation)
801        {
802            DIEInfoArray die_info_array;
803            if (FindByName(name, die_info_array))
804            {
805                if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
806                {
807                    // If we have two atoms, then we have the DIE offset and
808                    // the type flags so we can find the objective C class
809                    // efficiently.
810                    DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
811                                                               UINT32_MAX,
812                                                               eTypeFlagClassIsImplementation,
813                                                               die_offsets);
814                }
815                else
816                {
817                    // We don't only want the one true definition, so try and see
818                    // what we can find, and only return class or struct DIEs.
819                    // If we do have the full implementation, then return it alone,
820                    // else return all possible matches.
821                    const bool return_implementation_only_if_available = true;
822                    DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
823                                                                   return_implementation_only_if_available,
824                                                                   die_offsets);
825                }
826            }
827            return die_offsets.size();
828        }
829
830        size_t
831        FindByName (const char *name, DIEInfoArray &die_info_array)
832        {
833            Pair kv_pair;
834            size_t old_size = die_info_array.size();
835            if (Find (name, kv_pair))
836            {
837                die_info_array.swap(kv_pair.value);
838                return die_info_array.size() - old_size;
839            }
840            return 0;
841        }
842
843    protected:
844        const lldb_private::DataExtractor &m_data;
845        const lldb_private::DataExtractor &m_string_table;
846        std::string m_name;
847    };
848};
849
850
851#endif  // SymbolFileDWARF_HashedNameToDIE_h_
852