1254721Semaste//===-- HashedNameToDIE.h ---------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#ifndef SymbolFileDWARF_HashedNameToDIE_h_
11254721Semaste#define SymbolFileDWARF_HashedNameToDIE_h_
12254721Semaste
13254721Semaste#include <vector>
14254721Semaste
15254721Semaste#include "DWARFDefines.h"
16254721Semaste#include "DWARFFormValue.h"
17254721Semaste
18254721Semaste#include "lldb/lldb-defines.h"
19254721Semaste#include "lldb/Core/dwarf.h"
20254721Semaste#include "lldb/Core/RegularExpression.h"
21254721Semaste#include "lldb/Core/MappedHash.h"
22254721Semaste
23254721Semaste
24254721Semasteclass SymbolFileDWARF;
25254721Semasteclass DWARFCompileUnit;
26254721Semasteclass DWARFDebugInfoEntry;
27254721Semaste
28254721Semastestruct DWARFMappedHash
29254721Semaste{
30254721Semaste    struct DIEInfo
31254721Semaste    {
32254721Semaste        dw_offset_t offset;  // The DIE offset
33254721Semaste        dw_tag_t tag;
34254721Semaste        uint32_t type_flags; // Any flags for this DIEInfo
35254721Semaste        uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
36254721Semaste
37254721Semaste        DIEInfo () :
38254721Semaste            offset (DW_INVALID_OFFSET),
39254721Semaste            tag (0),
40254721Semaste            type_flags (0),
41254721Semaste            qualified_name_hash (0)
42254721Semaste        {
43254721Semaste        }
44254721Semaste
45254721Semaste        DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) :
46254721Semaste            offset(o),
47254721Semaste            tag (t),
48254721Semaste            type_flags (f),
49254721Semaste            qualified_name_hash (h)
50254721Semaste        {
51254721Semaste        }
52254721Semaste
53254721Semaste        void
54254721Semaste        Clear()
55254721Semaste        {
56254721Semaste            offset = DW_INVALID_OFFSET;
57254721Semaste            tag = 0;
58254721Semaste            type_flags = 0;
59254721Semaste            qualified_name_hash = 0;
60254721Semaste        }
61254721Semaste    };
62254721Semaste
63254721Semaste    typedef std::vector<DIEInfo> DIEInfoArray;
64254721Semaste    typedef std::vector<uint32_t> DIEArray;
65254721Semaste
66254721Semaste    static void
67254721Semaste    ExtractDIEArray (const DIEInfoArray &die_info_array,
68254721Semaste                     DIEArray &die_offsets)
69254721Semaste    {
70254721Semaste        const size_t count = die_info_array.size();
71254721Semaste        for (size_t i=0; i<count; ++i)
72254721Semaste        {
73254721Semaste            die_offsets.push_back (die_info_array[i].offset);
74254721Semaste        }
75254721Semaste    }
76254721Semaste
77254721Semaste    static void
78254721Semaste    ExtractDIEArray (const DIEInfoArray &die_info_array,
79254721Semaste                     const dw_tag_t tag,
80254721Semaste                     DIEArray &die_offsets)
81254721Semaste    {
82254721Semaste        if (tag == 0)
83254721Semaste        {
84254721Semaste            ExtractDIEArray (die_info_array, die_offsets);
85254721Semaste        }
86254721Semaste        else
87254721Semaste        {
88254721Semaste            const size_t count = die_info_array.size();
89254721Semaste            for (size_t i=0; i<count; ++i)
90254721Semaste            {
91254721Semaste                const dw_tag_t die_tag = die_info_array[i].tag;
92254721Semaste                bool tag_matches = die_tag == 0 || tag == die_tag;
93254721Semaste                if (!tag_matches)
94254721Semaste                {
95254721Semaste                    if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
96254721Semaste                        tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
97254721Semaste                }
98254721Semaste                if (tag_matches)
99254721Semaste                    die_offsets.push_back (die_info_array[i].offset);
100254721Semaste            }
101254721Semaste        }
102254721Semaste    }
103254721Semaste
104254721Semaste    static void
105254721Semaste    ExtractDIEArray (const DIEInfoArray &die_info_array,
106254721Semaste                     const dw_tag_t tag,
107254721Semaste                     const uint32_t qualified_name_hash,
108254721Semaste                     DIEArray &die_offsets)
109254721Semaste    {
110254721Semaste        if (tag == 0)
111254721Semaste        {
112254721Semaste            ExtractDIEArray (die_info_array, die_offsets);
113254721Semaste        }
114254721Semaste        else
115254721Semaste        {
116254721Semaste            const size_t count = die_info_array.size();
117254721Semaste            for (size_t i=0; i<count; ++i)
118254721Semaste            {
119254721Semaste                if (qualified_name_hash != die_info_array[i].qualified_name_hash)
120254721Semaste                    continue;
121254721Semaste                const dw_tag_t die_tag = die_info_array[i].tag;
122254721Semaste                bool tag_matches = die_tag == 0 || tag == die_tag;
123254721Semaste                if (!tag_matches)
124254721Semaste                {
125254721Semaste                    if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
126254721Semaste                        tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
127254721Semaste                }
128254721Semaste                if (tag_matches)
129254721Semaste                    die_offsets.push_back (die_info_array[i].offset);
130254721Semaste            }
131254721Semaste        }
132254721Semaste    }
133254721Semaste
134254721Semaste    enum AtomType
135254721Semaste    {
136254721Semaste        eAtomTypeNULL       = 0u,
137254721Semaste        eAtomTypeDIEOffset  = 1u,   // DIE offset, check form for encoding
138254721Semaste        eAtomTypeCUOffset   = 2u,   // DIE offset of the compiler unit header that contains the item in question
139254721Semaste        eAtomTypeTag        = 3u,   // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
140254721Semaste        eAtomTypeNameFlags  = 4u,   // Flags from enum NameFlags
141254721Semaste        eAtomTypeTypeFlags  = 5u,   // Flags from enum TypeFlags,
142254721Semaste        eAtomTypeQualNameHash = 6u  // A 32 bit hash of the full qualified name (since all hash entries are basename only)
143254721Semaste                                    // For example a type like "std::vector<int>::iterator" would have a name of "iterator"
144254721Semaste                                    // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull
145254721Semaste                                    // in debug info for a type when we know the fully qualified name.
146254721Semaste    };
147254721Semaste
148254721Semaste    // Bit definitions for the eAtomTypeTypeFlags flags
149254721Semaste    enum TypeFlags
150254721Semaste    {
151254721Semaste        // Always set for C++, only set for ObjC if this is the
152254721Semaste        // @implementation for class
153254721Semaste        eTypeFlagClassIsImplementation  = ( 1u << 1 )
154254721Semaste    };
155254721Semaste
156254721Semaste
157254721Semaste    static void
158254721Semaste    ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
159254721Semaste                                  bool return_implementation_only_if_available,
160254721Semaste                                  DIEArray &die_offsets)
161254721Semaste    {
162254721Semaste        const size_t count = die_info_array.size();
163254721Semaste        for (size_t i=0; i<count; ++i)
164254721Semaste        {
165254721Semaste            const dw_tag_t die_tag = die_info_array[i].tag;
166254721Semaste            if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
167254721Semaste            {
168254721Semaste                if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
169254721Semaste                {
170254721Semaste                    if (return_implementation_only_if_available)
171254721Semaste                    {
172254721Semaste                        // We found the one true definiton for this class, so
173254721Semaste                        // only return that
174254721Semaste                        die_offsets.clear();
175254721Semaste                        die_offsets.push_back (die_info_array[i].offset);
176254721Semaste                        return;
177254721Semaste                    }
178254721Semaste                    else
179254721Semaste                    {
180254721Semaste                        // Put the one true definition as the first entry so it
181254721Semaste                        // matches first
182254721Semaste                        die_offsets.insert (die_offsets.begin(), die_info_array[i].offset);
183254721Semaste                    }
184254721Semaste                }
185254721Semaste                else
186254721Semaste                {
187254721Semaste                    die_offsets.push_back (die_info_array[i].offset);
188254721Semaste                }
189254721Semaste            }
190254721Semaste        }
191254721Semaste    }
192254721Semaste
193254721Semaste    static void
194254721Semaste    ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
195254721Semaste                              uint32_t type_flag_mask,
196254721Semaste                              uint32_t type_flag_value,
197254721Semaste                              DIEArray &die_offsets)
198254721Semaste    {
199254721Semaste        const size_t count = die_info_array.size();
200254721Semaste        for (size_t i=0; i<count; ++i)
201254721Semaste        {
202254721Semaste            if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
203254721Semaste                die_offsets.push_back (die_info_array[i].offset);
204254721Semaste        }
205254721Semaste    }
206254721Semaste
207254721Semaste    struct Atom
208254721Semaste    {
209254721Semaste        uint16_t type;
210254721Semaste        dw_form_t form;
211254721Semaste
212254721Semaste        Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) :
213254721Semaste            type (t),
214254721Semaste            form (f)
215254721Semaste        {
216254721Semaste        }
217254721Semaste    };
218254721Semaste
219254721Semaste    typedef std::vector<Atom> AtomArray;
220254721Semaste
221254721Semaste    static uint32_t
222254721Semaste    GetTypeFlags (SymbolFileDWARF *dwarf2Data,
223254721Semaste                  const DWARFCompileUnit* cu,
224254721Semaste                  const DWARFDebugInfoEntry* die);
225254721Semaste
226254721Semaste
227254721Semaste    static const char *
228254721Semaste    GetAtomTypeName (uint16_t atom)
229254721Semaste    {
230254721Semaste        switch (atom)
231254721Semaste        {
232254721Semaste            case eAtomTypeNULL:         return "NULL";
233254721Semaste            case eAtomTypeDIEOffset:    return "die-offset";
234254721Semaste            case eAtomTypeCUOffset:     return "cu-offset";
235254721Semaste            case eAtomTypeTag:          return "die-tag";
236254721Semaste            case eAtomTypeNameFlags:    return "name-flags";
237254721Semaste            case eAtomTypeTypeFlags:    return "type-flags";
238254721Semaste            case eAtomTypeQualNameHash: return "qualified-name-hash";
239254721Semaste        }
240254721Semaste        return "<invalid>";
241254721Semaste    }
242254721Semaste    struct Prologue
243254721Semaste    {
244254721Semaste        // DIE offset base so die offsets in hash_data can be CU relative
245254721Semaste        dw_offset_t die_base_offset;
246254721Semaste        AtomArray atoms;
247254721Semaste        uint32_t atom_mask;
248254721Semaste        size_t min_hash_data_byte_size;
249254721Semaste        bool hash_data_has_fixed_byte_size;
250254721Semaste
251254721Semaste        Prologue (dw_offset_t _die_base_offset = 0) :
252254721Semaste            die_base_offset (_die_base_offset),
253254721Semaste            atoms(),
254254721Semaste            atom_mask (0),
255254721Semaste            min_hash_data_byte_size(0),
256254721Semaste            hash_data_has_fixed_byte_size(true)
257254721Semaste        {
258254721Semaste            // Define an array of DIE offsets by first defining an array,
259254721Semaste            // and then define the atom type for the array, in this case
260254721Semaste            // we have an array of DIE offsets
261254721Semaste            AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
262254721Semaste        }
263254721Semaste
264254721Semaste        virtual ~Prologue()
265254721Semaste        {
266254721Semaste        }
267254721Semaste
268254721Semaste        void
269254721Semaste        ClearAtoms ()
270254721Semaste        {
271254721Semaste            hash_data_has_fixed_byte_size = true;
272254721Semaste            min_hash_data_byte_size = 0;
273254721Semaste            atom_mask = 0;
274254721Semaste            atoms.clear();
275254721Semaste        }
276254721Semaste
277254721Semaste        bool
278254721Semaste        ContainsAtom (AtomType atom_type) const
279254721Semaste        {
280254721Semaste            return (atom_mask & (1u << atom_type)) != 0;
281254721Semaste        }
282254721Semaste
283254721Semaste        virtual void
284254721Semaste        Clear ()
285254721Semaste        {
286254721Semaste            die_base_offset = 0;
287254721Semaste            ClearAtoms ();
288254721Semaste        }
289254721Semaste
290254721Semaste        void
291254721Semaste        AppendAtom (AtomType type, dw_form_t form)
292254721Semaste        {
293254721Semaste            atoms.push_back (Atom(type, form));
294254721Semaste            atom_mask |= 1u << type;
295254721Semaste            switch (form)
296254721Semaste            {
297254721Semaste                case DW_FORM_indirect:
298254721Semaste                case DW_FORM_exprloc:
299254721Semaste                case DW_FORM_flag_present:
300254721Semaste                case DW_FORM_ref_sig8:
301254721Semaste                    assert (!"Unhandled atom form");
302254721Semaste                    break;
303254721Semaste
304254721Semaste                case DW_FORM_string:
305254721Semaste                case DW_FORM_block:
306254721Semaste                case DW_FORM_block1:
307254721Semaste                case DW_FORM_sdata:
308254721Semaste                case DW_FORM_udata:
309254721Semaste                case DW_FORM_ref_udata:
310254721Semaste                    hash_data_has_fixed_byte_size = false;
311254721Semaste                    // Fall through to the cases below...
312254721Semaste                case DW_FORM_flag:
313254721Semaste                case DW_FORM_data1:
314254721Semaste                case DW_FORM_ref1:
315254721Semaste                case DW_FORM_sec_offset:
316254721Semaste                    min_hash_data_byte_size += 1;
317254721Semaste                    break;
318254721Semaste
319254721Semaste                case DW_FORM_block2:
320254721Semaste                    hash_data_has_fixed_byte_size = false;
321254721Semaste                    // Fall through to the cases below...
322254721Semaste                case DW_FORM_data2:
323254721Semaste                case DW_FORM_ref2:
324254721Semaste                    min_hash_data_byte_size += 2;
325254721Semaste                    break;
326254721Semaste
327254721Semaste                case DW_FORM_block4:
328254721Semaste                    hash_data_has_fixed_byte_size = false;
329254721Semaste                    // Fall through to the cases below...
330254721Semaste                case DW_FORM_data4:
331254721Semaste                case DW_FORM_ref4:
332254721Semaste                case DW_FORM_addr:
333254721Semaste                case DW_FORM_ref_addr:
334254721Semaste                case DW_FORM_strp:
335254721Semaste                    min_hash_data_byte_size += 4;
336254721Semaste                    break;
337254721Semaste
338254721Semaste                case DW_FORM_data8:
339254721Semaste                case DW_FORM_ref8:
340254721Semaste                    min_hash_data_byte_size += 8;
341254721Semaste                    break;
342254721Semaste
343254721Semaste            }
344254721Semaste        }
345254721Semaste
346254721Semaste//        void
347254721Semaste//        Dump (std::ostream* ostrm_ptr);
348254721Semaste
349254721Semaste        lldb::offset_t
350254721Semaste        Read (const lldb_private::DataExtractor &data,
351254721Semaste              lldb::offset_t offset)
352254721Semaste        {
353254721Semaste            ClearAtoms ();
354254721Semaste
355254721Semaste            die_base_offset = data.GetU32 (&offset);
356254721Semaste
357254721Semaste            const uint32_t atom_count = data.GetU32 (&offset);
358254721Semaste            if (atom_count == 0x00060003u)
359254721Semaste            {
360254721Semaste                // Old format, deal with contents of old pre-release format
361254721Semaste                while (data.GetU32(&offset))
362254721Semaste                    /* do nothing */;
363254721Semaste
364254721Semaste                // Hardcode to the only known value for now.
365254721Semaste                AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
366254721Semaste            }
367254721Semaste            else
368254721Semaste            {
369254721Semaste                for (uint32_t i=0; i<atom_count; ++i)
370254721Semaste                {
371254721Semaste                    AtomType type = (AtomType)data.GetU16 (&offset);
372254721Semaste                    dw_form_t form = (dw_form_t)data.GetU16 (&offset);
373254721Semaste                    AppendAtom (type, form);
374254721Semaste                }
375254721Semaste            }
376254721Semaste            return offset;
377254721Semaste        }
378254721Semaste
379254721Semaste//        virtual void
380254721Semaste//        Write (BinaryStreamBuf &s);
381254721Semaste
382254721Semaste        size_t
383254721Semaste        GetByteSize () const
384254721Semaste        {
385254721Semaste            // Add an extra count to the atoms size for the zero termination Atom that gets
386254721Semaste            // written to disk
387254721Semaste            return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
388254721Semaste        }
389254721Semaste
390254721Semaste        size_t
391254721Semaste        GetMinumumHashDataByteSize () const
392254721Semaste        {
393254721Semaste            return min_hash_data_byte_size;
394254721Semaste        }
395254721Semaste
396254721Semaste        bool
397254721Semaste        HashDataHasFixedByteSize() const
398254721Semaste        {
399254721Semaste            return hash_data_has_fixed_byte_size;
400254721Semaste        }
401254721Semaste    };
402254721Semaste
403254721Semaste    struct Header : public MappedHash::Header<Prologue>
404254721Semaste    {
405254721Semaste        Header (dw_offset_t _die_base_offset = 0)
406254721Semaste        {
407254721Semaste        }
408254721Semaste
409254721Semaste        virtual
410254721Semaste        ~Header()
411254721Semaste        {
412254721Semaste        }
413254721Semaste
414254721Semaste        virtual size_t
415254721Semaste        GetByteSize (const HeaderData &header_data)
416254721Semaste        {
417254721Semaste            return header_data.GetByteSize();
418254721Semaste        }
419254721Semaste
420254721Semaste        //        virtual void
421254721Semaste        //        Dump (std::ostream* ostrm_ptr);
422254721Semaste        //
423254721Semaste        virtual lldb::offset_t
424254721Semaste        Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
425254721Semaste        {
426254721Semaste            offset = MappedHash::Header<Prologue>::Read (data, offset);
427254721Semaste            if (offset != UINT32_MAX)
428254721Semaste            {
429254721Semaste                offset = header_data.Read (data, offset);
430254721Semaste            }
431254721Semaste            return offset;
432254721Semaste        }
433254721Semaste
434254721Semaste        bool
435263363Semaste        Read (const lldb_private::DWARFDataExtractor &data,
436254721Semaste              lldb::offset_t *offset_ptr,
437254721Semaste              DIEInfo &hash_data) const
438254721Semaste        {
439254721Semaste            const size_t num_atoms = header_data.atoms.size();
440254721Semaste            if (num_atoms == 0)
441254721Semaste                return false;
442254721Semaste
443254721Semaste            for (size_t i=0; i<num_atoms; ++i)
444254721Semaste            {
445254721Semaste                DWARFFormValue form_value (header_data.atoms[i].form);
446254721Semaste
447254721Semaste                if (!form_value.ExtractValue(data, offset_ptr, NULL))
448254721Semaste                    return false;
449254721Semaste
450254721Semaste                switch (header_data.atoms[i].type)
451254721Semaste                {
452254721Semaste                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
453254721Semaste                        hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
454254721Semaste                        break;
455254721Semaste
456254721Semaste                    case eAtomTypeTag:          // DW_TAG value for the DIE
457254721Semaste                        hash_data.tag = (dw_tag_t)form_value.Unsigned ();
458254721Semaste
459254721Semaste                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
460254721Semaste                        hash_data.type_flags = (uint32_t)form_value.Unsigned ();
461254721Semaste                        break;
462254721Semaste
463254721Semaste                    case eAtomTypeQualNameHash:    // Flags from enum TypeFlags
464254721Semaste                        hash_data.qualified_name_hash = form_value.Unsigned ();
465254721Semaste                        break;
466254721Semaste
467254721Semaste                    default:
468254721Semaste                        // We can always skip atomes we don't know about
469254721Semaste                        break;
470254721Semaste                }
471254721Semaste            }
472254721Semaste            return true;
473254721Semaste        }
474254721Semaste
475254721Semaste        void
476254721Semaste        Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
477254721Semaste        {
478254721Semaste            const size_t num_atoms = header_data.atoms.size();
479254721Semaste            for (size_t i=0; i<num_atoms; ++i)
480254721Semaste            {
481254721Semaste                if (i > 0)
482254721Semaste                    strm.PutCString (", ");
483254721Semaste
484254721Semaste                DWARFFormValue form_value (header_data.atoms[i].form);
485254721Semaste                switch (header_data.atoms[i].type)
486254721Semaste                {
487254721Semaste                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
488254721Semaste                        strm.Printf ("{0x%8.8x}", hash_data.offset);
489254721Semaste                        break;
490254721Semaste
491254721Semaste                    case eAtomTypeTag:          // DW_TAG value for the DIE
492254721Semaste                        {
493254721Semaste                            const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
494254721Semaste                            if (tag_cstr)
495254721Semaste                                strm.PutCString (tag_cstr);
496254721Semaste                            else
497254721Semaste                                strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
498254721Semaste                        }
499254721Semaste                        break;
500254721Semaste
501254721Semaste                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
502254721Semaste                        strm.Printf ("0x%2.2x", hash_data.type_flags);
503254721Semaste                        if (hash_data.type_flags)
504254721Semaste                        {
505254721Semaste                            strm.PutCString (" (");
506254721Semaste                            if (hash_data.type_flags & eTypeFlagClassIsImplementation)
507254721Semaste                                strm.PutCString (" implementation");
508254721Semaste                            strm.PutCString (" )");
509254721Semaste                        }
510254721Semaste                        break;
511254721Semaste
512254721Semaste                    case eAtomTypeQualNameHash:    // Flags from enum TypeFlags
513254721Semaste                        strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
514254721Semaste                        break;
515254721Semaste
516254721Semaste                    default:
517254721Semaste                        strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
518254721Semaste                        break;
519254721Semaste                }
520254721Semaste            }
521254721Semaste        }
522254721Semaste    };
523254721Semaste
524254721Semaste//    class ExportTable
525254721Semaste//    {
526254721Semaste//    public:
527254721Semaste//        ExportTable ();
528254721Semaste//
529254721Semaste//        void
530254721Semaste//        AppendNames (DWARFDebugPubnamesSet &pubnames_set,
531254721Semaste//                     StringTable &string_table);
532254721Semaste//
533254721Semaste//        void
534254721Semaste//        AppendNamesEntry (SymbolFileDWARF *dwarf2Data,
535254721Semaste//                          const DWARFCompileUnit* cu,
536254721Semaste//                          const DWARFDebugInfoEntry* die,
537254721Semaste//                          StringTable &string_table);
538254721Semaste//
539254721Semaste//        void
540254721Semaste//        AppendTypesEntry (DWARFData *dwarf2Data,
541254721Semaste//                          const DWARFCompileUnit* cu,
542254721Semaste//                          const DWARFDebugInfoEntry* die,
543254721Semaste//                          StringTable &string_table);
544254721Semaste//
545254721Semaste//        size_t
546254721Semaste//        Save (BinaryStreamBuf &names_data, const StringTable &string_table);
547254721Semaste//
548254721Semaste//        void
549254721Semaste//        AppendName (const char *name,
550254721Semaste//                    uint32_t die_offset,
551254721Semaste//                    StringTable &string_table,
552254721Semaste//                    dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied
553254721Semaste//        void
554254721Semaste//        AppendType (const char *name,
555254721Semaste//                    uint32_t die_offset,
556254721Semaste//                    StringTable &string_table);
557254721Semaste//
558254721Semaste//
559254721Semaste//    protected:
560254721Semaste//        struct Entry
561254721Semaste//        {
562254721Semaste//            uint32_t hash;
563254721Semaste//            uint32_t str_offset;
564254721Semaste//            uint32_t die_offset;
565254721Semaste//        };
566254721Semaste//
567254721Semaste//        // Map uniqued .debug_str offset to the corresponding DIE offsets
568254721Semaste//        typedef std::map<uint32_t, DIEInfoArray> NameInfo;
569254721Semaste//        // Map a name hash to one or more name infos
570254721Semaste//        typedef std::map<uint32_t, NameInfo> BucketEntry;
571254721Semaste//
572254721Semaste//        static uint32_t
573254721Semaste//        GetByteSize (const NameInfo &name_info);
574254721Semaste//
575254721Semaste//        typedef std::vector<BucketEntry> BucketEntryColl;
576254721Semaste//        typedef std::vector<Entry> EntryColl;
577254721Semaste//        EntryColl m_entries;
578254721Semaste//
579254721Semaste//    };
580254721Semaste
581254721Semaste
582254721Semaste    // A class for reading and using a saved hash table from a block of data
583254721Semaste    // in memory
584254721Semaste    class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray>
585254721Semaste    {
586254721Semaste    public:
587254721Semaste
588263363Semaste        MemoryTable (lldb_private::DWARFDataExtractor &table_data,
589263363Semaste                     const lldb_private::DWARFDataExtractor &string_table,
590254721Semaste                     const char *name) :
591254721Semaste            MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
592254721Semaste            m_data (table_data),
593254721Semaste            m_string_table (string_table),
594254721Semaste            m_name (name)
595254721Semaste        {
596254721Semaste        }
597254721Semaste
598254721Semaste        virtual
599254721Semaste        ~MemoryTable ()
600254721Semaste        {
601254721Semaste        }
602254721Semaste
603254721Semaste        virtual const char *
604254721Semaste        GetStringForKeyType (KeyType key) const
605254721Semaste        {
606254721Semaste            // The key in the DWARF table is the .debug_str offset for the string
607254721Semaste            return m_string_table.PeekCStr (key);
608254721Semaste        }
609254721Semaste
610254721Semaste        virtual bool
611254721Semaste        ReadHashData (uint32_t hash_data_offset,
612254721Semaste                      HashData &hash_data) const
613254721Semaste        {
614254721Semaste            lldb::offset_t offset = hash_data_offset;
615254721Semaste            offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
616254721Semaste            const uint32_t count = m_data.GetU32 (&offset);
617254721Semaste            if (count > 0)
618254721Semaste            {
619254721Semaste                hash_data.resize(count);
620254721Semaste                for (uint32_t i=0; i<count; ++i)
621254721Semaste                {
622254721Semaste                    if (!m_header.Read(m_data, &offset, hash_data[i]))
623254721Semaste                        return false;
624254721Semaste                }
625254721Semaste            }
626254721Semaste            else
627254721Semaste                hash_data.clear();
628254721Semaste            return true;
629254721Semaste        }
630254721Semaste
631254721Semaste        virtual Result
632254721Semaste        GetHashDataForName (const char *name,
633254721Semaste                            lldb::offset_t* hash_data_offset_ptr,
634254721Semaste                            Pair &pair) const
635254721Semaste        {
636254721Semaste            pair.key = m_data.GetU32 (hash_data_offset_ptr);
637254721Semaste            pair.value.clear();
638254721Semaste
639254721Semaste            // If the key is zero, this terminates our chain of HashData objects
640254721Semaste            // for this hash value.
641254721Semaste            if (pair.key == 0)
642254721Semaste                return eResultEndOfHashData;
643254721Semaste
644254721Semaste            // There definitely should be a string for this string offset, if
645254721Semaste            // there isn't, there is something wrong, return and error
646254721Semaste            const char *strp_cstr = m_string_table.PeekCStr (pair.key);
647254721Semaste            if (strp_cstr == NULL)
648254721Semaste            {
649254721Semaste                *hash_data_offset_ptr = UINT32_MAX;
650254721Semaste                return eResultError;
651254721Semaste            }
652254721Semaste
653254721Semaste            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
654254721Semaste            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
655254721Semaste            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
656254721Semaste            {
657254721Semaste                // We have at least one HashData entry, and we have enough
658254721Semaste                // data to parse at leats "count" HashData enties.
659254721Semaste
660254721Semaste                // First make sure the entire C string matches...
661254721Semaste                const bool match = strcmp (name, strp_cstr) == 0;
662254721Semaste
663254721Semaste                if (!match && m_header.header_data.HashDataHasFixedByteSize())
664254721Semaste                {
665254721Semaste                    // If the string doesn't match and we have fixed size data,
666254721Semaste                    // we can just add the total byte size of all HashData objects
667254721Semaste                    // to the hash data offset and be done...
668254721Semaste                    *hash_data_offset_ptr += min_total_hash_data_size;
669254721Semaste                }
670254721Semaste                else
671254721Semaste                {
672254721Semaste                    // If the string does match, or we don't have fixed size data
673254721Semaste                    // then we need to read the hash data as a stream. If the
674254721Semaste                    // string matches we also append all HashData objects to the
675254721Semaste                    // value array.
676254721Semaste                    for (uint32_t i=0; i<count; ++i)
677254721Semaste                    {
678254721Semaste                        DIEInfo die_info;
679254721Semaste                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
680254721Semaste                        {
681254721Semaste                            // Only happend the HashData if the string matched...
682254721Semaste                            if (match)
683254721Semaste                                pair.value.push_back (die_info);
684254721Semaste                        }
685254721Semaste                        else
686254721Semaste                        {
687254721Semaste                            // Something went wrong while reading the data
688254721Semaste                            *hash_data_offset_ptr = UINT32_MAX;
689254721Semaste                            return eResultError;
690254721Semaste                        }
691254721Semaste                    }
692254721Semaste                }
693254721Semaste                // Return the correct response depending on if the string matched
694254721Semaste                // or not...
695254721Semaste                if (match)
696254721Semaste                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
697254721Semaste                else
698254721Semaste                    return eResultKeyMismatch;  // The key doesn't match, this function will get called
699254721Semaste                                                // again for the next key/value or the key terminator
700254721Semaste                                                // which in our case is a zero .debug_str offset.
701254721Semaste            }
702254721Semaste            else
703254721Semaste            {
704254721Semaste                *hash_data_offset_ptr = UINT32_MAX;
705254721Semaste                return eResultError;
706254721Semaste            }
707254721Semaste        }
708254721Semaste
709254721Semaste        virtual Result
710254721Semaste        AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
711254721Semaste                                            lldb::offset_t* hash_data_offset_ptr,
712254721Semaste                                            Pair &pair) const
713254721Semaste        {
714254721Semaste            pair.key = m_data.GetU32 (hash_data_offset_ptr);
715254721Semaste            // If the key is zero, this terminates our chain of HashData objects
716254721Semaste            // for this hash value.
717254721Semaste            if (pair.key == 0)
718254721Semaste                return eResultEndOfHashData;
719254721Semaste
720254721Semaste            // There definitely should be a string for this string offset, if
721254721Semaste            // there isn't, there is something wrong, return and error
722254721Semaste            const char *strp_cstr = m_string_table.PeekCStr (pair.key);
723254721Semaste            if (strp_cstr == NULL)
724254721Semaste                return eResultError;
725254721Semaste
726254721Semaste            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
727254721Semaste            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
728254721Semaste            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
729254721Semaste            {
730254721Semaste                const bool match = regex.Execute(strp_cstr);
731254721Semaste
732254721Semaste                if (!match && m_header.header_data.HashDataHasFixedByteSize())
733254721Semaste                {
734254721Semaste                    // If the regex doesn't match and we have fixed size data,
735254721Semaste                    // we can just add the total byte size of all HashData objects
736254721Semaste                    // to the hash data offset and be done...
737254721Semaste                    *hash_data_offset_ptr += min_total_hash_data_size;
738254721Semaste                }
739254721Semaste                else
740254721Semaste                {
741254721Semaste                    // If the string does match, or we don't have fixed size data
742254721Semaste                    // then we need to read the hash data as a stream. If the
743254721Semaste                    // string matches we also append all HashData objects to the
744254721Semaste                    // value array.
745254721Semaste                    for (uint32_t i=0; i<count; ++i)
746254721Semaste                    {
747254721Semaste                        DIEInfo die_info;
748254721Semaste                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
749254721Semaste                        {
750254721Semaste                            // Only happend the HashData if the string matched...
751254721Semaste                            if (match)
752254721Semaste                                pair.value.push_back (die_info);
753254721Semaste                        }
754254721Semaste                        else
755254721Semaste                        {
756254721Semaste                            // Something went wrong while reading the data
757254721Semaste                            *hash_data_offset_ptr = UINT32_MAX;
758254721Semaste                            return eResultError;
759254721Semaste                        }
760254721Semaste                    }
761254721Semaste                }
762254721Semaste                // Return the correct response depending on if the string matched
763254721Semaste                // or not...
764254721Semaste                if (match)
765254721Semaste                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
766254721Semaste                else
767254721Semaste                    return eResultKeyMismatch;  // The key doesn't match, this function will get called
768254721Semaste                                                // again for the next key/value or the key terminator
769254721Semaste                                                // which in our case is a zero .debug_str offset.
770254721Semaste            }
771254721Semaste            else
772254721Semaste            {
773254721Semaste                *hash_data_offset_ptr = UINT32_MAX;
774254721Semaste                return eResultError;
775254721Semaste            }
776254721Semaste        }
777254721Semaste
778254721Semaste        size_t
779254721Semaste        AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,
780254721Semaste                                        DIEInfoArray &die_info_array) const
781254721Semaste        {
782254721Semaste            const uint32_t hash_count = m_header.hashes_count;
783254721Semaste            Pair pair;
784254721Semaste            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
785254721Semaste            {
786254721Semaste                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
787254721Semaste                while (hash_data_offset != UINT32_MAX)
788254721Semaste                {
789254721Semaste                    const lldb::offset_t prev_hash_data_offset = hash_data_offset;
790254721Semaste                    Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
791254721Semaste                    if (prev_hash_data_offset == hash_data_offset)
792254721Semaste                        break;
793254721Semaste
794254721Semaste                    // Check the result of getting our hash data
795254721Semaste                    switch (hash_result)
796254721Semaste                    {
797254721Semaste                        case eResultKeyMatch:
798254721Semaste                        case eResultKeyMismatch:
799254721Semaste                            // Whether we matches or not, it doesn't matter, we
800254721Semaste                            // keep looking.
801254721Semaste                            break;
802254721Semaste
803254721Semaste                        case eResultEndOfHashData:
804254721Semaste                        case eResultError:
805254721Semaste                            hash_data_offset = UINT32_MAX;
806254721Semaste                            break;
807254721Semaste                    }
808254721Semaste                }
809254721Semaste            }
810254721Semaste            die_info_array.swap (pair.value);
811254721Semaste            return die_info_array.size();
812254721Semaste        }
813254721Semaste
814254721Semaste        size_t
815254721Semaste        AppendAllDIEsInRange (const uint32_t die_offset_start,
816254721Semaste                              const uint32_t die_offset_end,
817254721Semaste                              DIEInfoArray &die_info_array) const
818254721Semaste        {
819254721Semaste            const uint32_t hash_count = m_header.hashes_count;
820254721Semaste            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
821254721Semaste            {
822254721Semaste                bool done = false;
823254721Semaste                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
824254721Semaste                while (!done && hash_data_offset != UINT32_MAX)
825254721Semaste                {
826254721Semaste                    KeyType key = m_data.GetU32 (&hash_data_offset);
827254721Semaste                    // If the key is zero, this terminates our chain of HashData objects
828254721Semaste                    // for this hash value.
829254721Semaste                    if (key == 0)
830254721Semaste                        break;
831254721Semaste
832254721Semaste                    const uint32_t count = m_data.GetU32 (&hash_data_offset);
833254721Semaste                    for (uint32_t i=0; i<count; ++i)
834254721Semaste                    {
835254721Semaste                        DIEInfo die_info;
836254721Semaste                        if (m_header.Read(m_data, &hash_data_offset, die_info))
837254721Semaste                        {
838254721Semaste                            if (die_info.offset == 0)
839254721Semaste                                done = true;
840254721Semaste                            if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
841254721Semaste                                die_info_array.push_back(die_info);
842254721Semaste                        }
843254721Semaste                    }
844254721Semaste                }
845254721Semaste            }
846254721Semaste            return die_info_array.size();
847254721Semaste        }
848254721Semaste
849254721Semaste        size_t
850254721Semaste        FindByName (const char *name, DIEArray &die_offsets)
851254721Semaste        {
852254721Semaste            DIEInfoArray die_info_array;
853254721Semaste            if (FindByName(name, die_info_array))
854254721Semaste                DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
855254721Semaste            return die_info_array.size();
856254721Semaste        }
857254721Semaste
858254721Semaste        size_t
859254721Semaste        FindByNameAndTag (const char *name,
860254721Semaste                          const dw_tag_t tag,
861254721Semaste                          DIEArray &die_offsets)
862254721Semaste        {
863254721Semaste            DIEInfoArray die_info_array;
864254721Semaste            if (FindByName(name, die_info_array))
865254721Semaste                DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
866254721Semaste            return die_info_array.size();
867254721Semaste        }
868254721Semaste
869254721Semaste        size_t
870254721Semaste        FindByNameAndTagAndQualifiedNameHash (const char *name,
871254721Semaste                                              const dw_tag_t tag,
872254721Semaste                                              const uint32_t qualified_name_hash,
873254721Semaste                                              DIEArray &die_offsets)
874254721Semaste        {
875254721Semaste            DIEInfoArray die_info_array;
876254721Semaste            if (FindByName(name, die_info_array))
877254721Semaste                DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
878254721Semaste            return die_info_array.size();
879254721Semaste        }
880254721Semaste
881254721Semaste        size_t
882254721Semaste        FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation)
883254721Semaste        {
884254721Semaste            DIEInfoArray die_info_array;
885254721Semaste            if (FindByName(name, die_info_array))
886254721Semaste            {
887254721Semaste                if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
888254721Semaste                {
889254721Semaste                    // If we have two atoms, then we have the DIE offset and
890254721Semaste                    // the type flags so we can find the objective C class
891254721Semaste                    // efficiently.
892254721Semaste                    DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
893254721Semaste                                                               UINT32_MAX,
894254721Semaste                                                               eTypeFlagClassIsImplementation,
895254721Semaste                                                               die_offsets);
896254721Semaste                }
897254721Semaste                else
898254721Semaste                {
899254721Semaste                    // We don't only want the one true definition, so try and see
900254721Semaste                    // what we can find, and only return class or struct DIEs.
901254721Semaste                    // If we do have the full implementation, then return it alone,
902254721Semaste                    // else return all possible matches.
903254721Semaste                    const bool return_implementation_only_if_available = true;
904254721Semaste                    DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
905254721Semaste                                                                   return_implementation_only_if_available,
906254721Semaste                                                                   die_offsets);
907254721Semaste                }
908254721Semaste            }
909254721Semaste            return die_offsets.size();
910254721Semaste        }
911254721Semaste
912254721Semaste        size_t
913254721Semaste        FindByName (const char *name, DIEInfoArray &die_info_array)
914254721Semaste        {
915254721Semaste            Pair kv_pair;
916254721Semaste            size_t old_size = die_info_array.size();
917254721Semaste            if (Find (name, kv_pair))
918254721Semaste            {
919254721Semaste                die_info_array.swap(kv_pair.value);
920254721Semaste                return die_info_array.size() - old_size;
921254721Semaste            }
922254721Semaste            return 0;
923254721Semaste        }
924254721Semaste
925254721Semaste    protected:
926263363Semaste        const lldb_private::DWARFDataExtractor &m_data;
927263363Semaste        const lldb_private::DWARFDataExtractor &m_string_table;
928254721Semaste        std::string m_name;
929254721Semaste    };
930254721Semaste};
931254721Semaste
932254721Semaste
933254721Semaste#endif  // SymbolFileDWARF_HashedNameToDIE_h_
934