summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h393
1 files changed, 393 insertions, 0 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index 67ccda7cf62..909f6aaeb3e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -13,6 +13,7 @@
#include <vector>
#include "lldb/lldb-defines.h"
#include "lldb/Core/dwarf.h"
+#include "lldb/Core/RegularExpression.h"
class SymbolFileDWARF;
@@ -267,4 +268,396 @@ public:
};
};
+#include "lldb/Core/MappedHash.h"
+
+struct DWARFMappedHash
+{
+ typedef std::vector<uint32_t> DIEArray;
+
+ enum AtomType
+ {
+ eAtomTypeNULL = 0u,
+ eAtomTypeHashString = 1u, // String value for hash, use DW_FORM_strp (preferred) or DW_FORM_string
+ eAtomTypeHashLength = 2u, // Length of data for the previous string refered by the last eAtomTypeHashString atom
+ eAtomTypeArraySize = 3u, // A count that specifies a number of atoms that follow this entry, the next atom defines what the atom type for the array is
+ eAtomTypeDIEOffset = 4u, // DIE offset, check form for encoding. If DW_FORM_ref1,2,4,8 or DW_FORM_ref_udata, then this value is added to the prologue
+ eAtomTypeTag = 5u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
+ eAtomTypeNameFlags = 6u, // Flags from enum NameFlags
+ eAtomTypeTypeFlags = 7u, // Flags from enum TypeFlags
+ };
+
+ struct Atom
+ {
+ uint16_t type;
+ dw_form_t form;
+
+ Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) :
+ type (t),
+ form (f)
+ {
+ }
+ };
+
+ typedef std::vector<Atom> AtomArray;
+
+
+ static const char *
+ GetAtomTypeName (uint16_t atom)
+ {
+ switch (atom)
+ {
+ case eAtomTypeNULL: return "NULL";
+ case eAtomTypeHashString: return "hash-string";
+ case eAtomTypeHashLength: return "hash-data-length";
+ case eAtomTypeArraySize: return "array-size";
+ case eAtomTypeDIEOffset: return "die-offset";
+ case eAtomTypeTag: return "die-tag";
+ case eAtomTypeNameFlags: return "name-flags";
+ case eAtomTypeTypeFlags: return "type-flags";
+ }
+ return "<invalid>";
+ }
+ struct Prologue
+ {
+ // DIE offset base so die offsets in hash_data can be CU relative
+ dw_offset_t die_base_offset;
+ AtomArray atoms;
+
+ Prologue (dw_offset_t _die_base_offset = 0) :
+ die_base_offset (_die_base_offset)
+ {
+ // Define an array of DIE offsets by first defining an array,
+ // and then define the atom type for the array, in this case
+ // we have an array of DIE offsets
+ atoms.push_back (Atom(eAtomTypeArraySize, DW_FORM_data4));
+ atoms.push_back (Atom(eAtomTypeDIEOffset, DW_FORM_data4));
+ }
+
+ virtual ~Prologue()
+ {
+ }
+
+ virtual void
+ Clear ()
+ {
+ die_base_offset = 0;
+ atoms.clear();
+ }
+
+// void
+// Dump (std::ostream* ostrm_ptr);
+
+ uint32_t
+ Read (const lldb_private::DataExtractor &data, uint32_t offset)
+ {
+ die_base_offset = data.GetU32 (&offset);
+ Atom atom;
+ while (offset != UINT32_MAX)
+ {
+ atom.type = data.GetU16 (&offset);
+ atom.form = data.GetU16 (&offset);
+ if (atom.type == eAtomTypeNULL)
+ break;
+ atoms.push_back(atom);
+ }
+ return offset;
+ }
+
+// virtual void
+// Write (BinaryStreamBuf &s);
+
+ size_t
+ GetByteSize () const
+ {
+ // Add an extra count to the atoms size for the zero termination Atom that gets
+ // written to disk
+ return sizeof(die_base_offset) + ((atoms.size() + 1) * sizeof(Atom));
+ }
+ };
+
+ struct Header : public MappedHash::Header<Prologue>
+ {
+ Header (dw_offset_t _die_base_offset = 0)
+ {
+ }
+
+ virtual
+ ~Header()
+ {
+ }
+
+ virtual size_t
+ GetByteSize (const HeaderData &header_data)
+ {
+ return header_data.GetByteSize();
+ }
+
+
+ // virtual void
+ // Dump (std::ostream* ostrm_ptr);
+ //
+ virtual uint32_t
+ Read (lldb_private::DataExtractor &data, uint32_t offset)
+ {
+ offset = MappedHash::Header<Prologue>::Read (data, offset);
+ if (offset != UINT32_MAX)
+ {
+ offset = header_data.Read (data, offset);
+ }
+ return offset;
+ }
+ //
+ // virtual void
+ // Write (BinaryStreamBuf &s);
+ };
+
+// class ExportTable
+// {
+// public:
+// ExportTable ();
+//
+// void
+// AppendNames (DWARFDebugPubnamesSet &pubnames_set,
+// StringTable &string_table);
+//
+// void
+// AppendNamesEntry (SymbolFileDWARF *dwarf2Data,
+// const DWARFCompileUnit* cu,
+// const DWARFDebugInfoEntry* die,
+// StringTable &string_table);
+//
+// void
+// AppendTypesEntry (DWARFData *dwarf2Data,
+// const DWARFCompileUnit* cu,
+// const DWARFDebugInfoEntry* die,
+// StringTable &string_table);
+//
+// size_t
+// Save (BinaryStreamBuf &names_data, const StringTable &string_table);
+//
+// void
+// AppendName (const char *name,
+// uint32_t die_offset,
+// StringTable &string_table,
+// dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied
+// void
+// AppendType (const char *name,
+// uint32_t die_offset,
+// StringTable &string_table);
+//
+//
+// protected:
+// struct Entry
+// {
+// uint32_t hash;
+// uint32_t str_offset;
+// uint32_t die_offset;
+// };
+//
+// // Map uniqued .debug_str offset to the corresponding DIE offsets
+// typedef std::map<uint32_t, DIEArray> NameInfo;
+// // Map a name hash to one or more name infos
+// typedef std::map<uint32_t, NameInfo> BucketEntry;
+//
+// static uint32_t
+// GetByteSize (const NameInfo &name_info);
+//
+// typedef std::vector<BucketEntry> BucketEntryColl;
+// typedef std::vector<Entry> EntryColl;
+// EntryColl m_entries;
+//
+// };
+
+
+ // A class for reading and using a saved hash table from a block of data
+ // in memory
+ class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEArray>
+ {
+ public:
+
+ MemoryTable (lldb_private::DataExtractor &table_data,
+ const lldb_private::DataExtractor &string_table,
+ bool is_apple_names) :
+ MappedHash::MemoryTable<uint32_t, Header, DIEArray> (table_data),
+ m_data (table_data),
+ m_string_table (string_table),
+ m_is_apple_names (is_apple_names)
+ {
+ }
+
+ virtual
+ ~MemoryTable ()
+ {
+ }
+
+ virtual const char *
+ GetStringForKeyType (KeyType key) const
+ {
+ // The key in the DWARF table is the .debug_str offset for the string
+ return m_string_table.PeekCStr (key);
+ }
+
+ virtual Result
+ GetHashDataForName (const char *name,
+ uint32_t* hash_data_offset_ptr,
+ Pair &pair) const
+ {
+ pair.key = m_data.GetU32 (hash_data_offset_ptr);
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (pair.key == 0)
+ return eResultEndOfHashData;
+
+ // There definitely should be a string for this string offset, if
+ // there isn't, there is something wrong, return and error
+ const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+ if (strp_cstr == NULL)
+ return eResultError;
+
+ const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+ const uint32_t data_size = count * sizeof(uint32_t);
+ if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, data_size))
+ {
+ if (strcmp (name, strp_cstr) == 0)
+ {
+ pair.value.clear();
+ for (uint32_t i=0; i<count; ++i)
+ pair.value.push_back (m_data.GetU32 (hash_data_offset_ptr));
+ return eResultKeyMatch;
+ }
+ else
+ {
+ // Skip the data so we are ready to parse another HashData
+ // for this hash value
+ *hash_data_offset_ptr += data_size;
+ // The key doesn't match
+ return eResultKeyMismatch;
+ }
+ }
+ else
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+ }
+
+ virtual Result
+ AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
+ uint32_t* hash_data_offset_ptr,
+ Pair &pair) const
+ {
+ pair.key = m_data.GetU32 (hash_data_offset_ptr);
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (pair.key == 0)
+ return eResultEndOfHashData;
+
+ // There definitely should be a string for this string offset, if
+ // there isn't, there is something wrong, return and error
+ const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+ if (strp_cstr == NULL)
+ return eResultError;
+
+ const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+ const uint32_t data_size = count * sizeof(uint32_t);
+ if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, data_size))
+ {
+ if (regex.Execute(strp_cstr))
+ {
+ for (uint32_t i=0; i<count; ++i)
+ pair.value.push_back (m_data.GetU32 (hash_data_offset_ptr));
+ return eResultKeyMatch;
+ }
+ else
+ {
+ // Skip the data so we are ready to parse another HashData
+ // for this hash value
+ *hash_data_offset_ptr += data_size;
+ // The key doesn't match
+ return eResultKeyMismatch;
+ }
+ }
+ else
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+ }
+
+ size_t
+ AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,
+ DIEArray &die_offsets) const
+ {
+ const uint32_t hash_count = m_header.hashes_count;
+ Pair pair;
+ for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+ {
+ uint32_t hash_data_offset = GetHashDataOffset (offset_idx);
+ while (hash_data_offset != UINT32_MAX)
+ {
+ const uint32_t prev_hash_data_offset = hash_data_offset;
+ Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
+ if (prev_hash_data_offset == hash_data_offset)
+ break;
+
+ // Check the result of getting our hash data
+ switch (hash_result)
+ {
+ case eResultKeyMatch:
+ case eResultKeyMismatch:
+ // Whether we matches or not, it doesn't matter, we
+ // keep looking.
+ break;
+
+ case eResultEndOfHashData:
+ case eResultError:
+ hash_data_offset = UINT32_MAX;
+ break;
+ }
+ }
+ }
+ die_offsets.swap (pair.value);
+ return die_offsets.size();
+ }
+
+ size_t
+ AppendAllDIEsInRange (const uint32_t die_offset_start,
+ const uint32_t die_offset_end,
+ DIEArray &die_offsets) const
+ {
+ const uint32_t hash_count = m_header.hashes_count;
+ for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+ {
+ bool done = false;
+ uint32_t hash_data_offset = GetHashDataOffset (offset_idx);
+ while (!done && hash_data_offset != UINT32_MAX)
+ {
+ KeyType key = m_data.GetU32 (&hash_data_offset);
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (key == 0)
+ break;
+
+ const uint32_t count = m_data.GetU32 (&hash_data_offset);
+ for (uint32_t i=0; i<count; ++i)
+ {
+ uint32_t die_offset = m_data.GetU32 (&hash_data_offset);
+ if (die_offset == 0)
+ done = true;
+ if (die_offset_start <= die_offset && die_offset < die_offset_end)
+ die_offsets.push_back(die_offset);
+ }
+ }
+ }
+ return die_offsets.size();
+ }
+
+ protected:
+ const lldb_private::DataExtractor &m_data;
+ const lldb_private::DataExtractor &m_string_table;
+ bool m_is_apple_names; // true => .apple_names, false => .apple_types
+ };
+};
+
+
#endif // SymbolFileDWARF_HashedNameToDIE_h_
OpenPOWER on IntegriCloud