[Lldb-commits] [lldb] r141130 - /lldb/trunk/include/lldb/Core/MappedHash.h
Greg Clayton
gclayton at apple.com
Tue Oct 4 15:56:44 PDT 2011
Author: gclayton
Date: Tue Oct 4 17:56:35 2011
New Revision: 141130
URL: http://llvm.org/viewvc/llvm-project?rev=141130&view=rev
Log:
Added missing file.
Added:
lldb/trunk/include/lldb/Core/MappedHash.h
Added: lldb/trunk/include/lldb/Core/MappedHash.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/MappedHash.h?rev=141130&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Core/MappedHash.h (added)
+++ lldb/trunk/include/lldb/Core/MappedHash.h Tue Oct 4 17:56:35 2011
@@ -0,0 +1,343 @@
+//
+// MappedHash.h
+//
+
+#ifndef liblldb_MappedHash_h_
+#define liblldb_MappedHash_h_
+
+#include <assert.h>
+#include <stdint.h>
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+
+class MappedHash
+{
+public:
+
+ enum HashFunctionType
+ {
+ eHashFunctionDJB = 0u, // Daniel J Bernstein hash function that is also used by the ELF GNU_HASH sections
+ };
+
+
+ static uint32_t
+ HashStringUsingDJB (const char *s)
+ {
+ uint32_t h = 5381;
+
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+
+ return h;
+ }
+
+ static uint32_t
+ HashString (const uint8_t hash_function, const char *s)
+ {
+ switch (hash_function)
+ {
+ case MappedHash::eHashFunctionDJB:
+ return HashStringUsingDJB (s);
+
+ default:
+ break;
+ }
+ assert (!"Invalid hash function index");
+ return 0;
+ }
+
+
+ static const uint32_t HASH_MAGIC = 0x48415348u;
+ static const uint32_t HASH_CIGAM = 0x48534148u;
+
+ template <typename T>
+ struct Header
+ {
+ typedef T HeaderData;
+
+ uint32_t magic; // 'HASH' magic value to allow endian detection
+ uint16_t version; // Version number
+ uint8_t addr_bytesize; // Size in bytes of an address
+ uint8_t hash_function; // The hash function enumeration that was used
+ uint32_t bucket_count; // The number of buckets in this hash table
+ uint32_t hashes_count; // The total number of unique hash values and hash data offsets in this table
+ uint32_t header_data_len; // The size in bytes of the "header_data" template member below
+ HeaderData header_data; //
+
+ Header () :
+ magic ('HASH'),
+ version (1),
+ addr_bytesize (4),
+ hash_function (eHashFunctionDJB),
+ bucket_count (0),
+ hashes_count (0),
+ header_data_len (sizeof(T)),
+ header_data ()
+ {
+ }
+
+ virtual
+ ~Header()
+ {
+ }
+
+ size_t
+ GetByteSize() const
+ {
+ return sizeof(magic) +
+ sizeof(version) +
+ sizeof(addr_bytesize) +
+ sizeof(hash_function) +
+ sizeof(bucket_count) +
+ sizeof(hashes_count) +
+ sizeof(header_data_len) +
+ header_data_len;
+ }
+
+ virtual size_t
+ GetByteSize (const HeaderData &header_data) = 0;
+
+ size_t
+ SetHeaderDataByteSize (uint32_t header_data_byte_size)
+ {
+ header_data_len = header_data_byte_size;
+ }
+
+ void
+ Dump (lldb_private::Stream &s)
+ {
+ s.Printf ("header.magic = 0x%8.8x\n", magic);
+ s.Printf ("header.version = 0x%4.4x\n", version);
+ s.Printf ("header.addr_bytesize = 0x%2.2x\n", addr_bytesize);
+ s.Printf ("header.hash_function = 0x%2.2x\n", hash_function);
+ s.Printf ("header.bucket_count = 0x%8.8x %u\n", bucket_count, bucket_count);
+ s.Printf ("header.hashes_count = 0x%8.8x %u\n", hashes_count, hashes_count);
+ s.Printf ("header.header_data_len = 0x%8.8x %u\n", header_data_len, header_data_len);
+ }
+
+ virtual uint32_t
+ Read (lldb_private::DataExtractor &data, uint32_t offset)
+ {
+ if (data.ValidOffsetForDataOfSize (offset,
+ sizeof(magic) +
+ sizeof(version) +
+ sizeof(addr_bytesize) +
+ sizeof(hash_function) +
+ sizeof(bucket_count) +
+ sizeof(hashes_count) +
+ sizeof(header_data_len)))
+ {
+ magic = data.GetU32 (&offset);
+ if (magic != HASH_MAGIC)
+ {
+ if (magic == HASH_CIGAM)
+ {
+ switch (data.GetByteOrder())
+ {
+ case lldb::eByteOrderBig:
+ data.SetByteOrder(lldb::eByteOrderLittle);
+ break;
+ case lldb::eByteOrderLittle:
+ data.SetByteOrder(lldb::eByteOrderBig);
+ break;
+ default:
+ return UINT32_MAX;
+ }
+ }
+ else
+ {
+ // Magic bytes didn't match
+ version = 0;
+ return UINT32_MAX;
+ }
+ }
+
+ version = data.GetU16 (&offset);
+ if (version != 1)
+ {
+ // Unsupported version
+ return UINT32_MAX;
+ }
+ addr_bytesize = data.GetU8 (&offset);
+ hash_function = data.GetU8 (&offset);
+ bucket_count = data.GetU32 (&offset);
+ hashes_count = data.GetU32 (&offset);
+ header_data_len = data.GetU32 (&offset);
+ return offset;
+ }
+ return UINT32_MAX;
+ }
+//
+// // Returns a buffer that contains a serialized version of this table
+// // that must be freed with free().
+// virtual void *
+// Write (int fd);
+ };
+
+ // A class for reading and using a saved hash table from a block of data
+ // in memory
+ template <typename __KeyType, class __HeaderType, class __HashData>
+ class MemoryTable
+ {
+ public:
+ typedef __HeaderType HeaderType;
+ typedef __KeyType KeyType;
+ typedef __HashData HashData;
+
+ enum Result
+ {
+ eResultKeyMatch = 0u, // The entry was found, key matched and "pair" was filled in successfully
+ eResultKeyMismatch = 1u, // Bucket hash data collision, but key didn't match
+ eResultEndOfHashData = 2u, // The chain of items for this hash data in this bucket is terminated, search no more
+ eResultError = 3u // Error parsing the hash data, abort
+ };
+
+ struct Pair
+ {
+ KeyType key;
+ HashData value;
+ };
+
+ MemoryTable (lldb_private::DataExtractor &data) :
+ m_header (),
+ m_hash_indexes (NULL),
+ m_hash_values (NULL),
+ m_hash_offsets (NULL)
+ {
+ uint32_t offset = m_header.Read (data, 0);
+ if (offset != UINT32_MAX)
+ {
+ m_hash_indexes = (uint32_t *)data.GetData (&offset, m_header.bucket_count * sizeof(uint32_t));
+ m_hash_values = (uint32_t *)data.GetData (&offset, m_header.hashes_count * sizeof(uint32_t));
+ m_hash_offsets = (uint32_t *)data.GetData (&offset, m_header.hashes_count * sizeof(uint32_t));
+ }
+ }
+
+ virtual
+ ~MemoryTable ()
+ {
+ }
+
+ bool
+ IsValid () const
+ {
+ return m_header.version == 1 && m_header.hash_function == eHashFunctionDJB;
+ }
+
+ uint32_t
+ GetHashIndex (uint32_t bucket_idx) const
+ {
+ if (m_hash_indexes && bucket_idx < m_header.bucket_count)
+ return m_hash_indexes[bucket_idx];
+ return UINT32_MAX;
+ }
+
+ uint32_t
+ GetHashValue (uint32_t hash_idx) const
+ {
+ if (m_hash_values && hash_idx < m_header.hashes_count)
+ return m_hash_values[hash_idx];
+ return UINT32_MAX;
+ }
+
+ uint32_t
+ GetHashDataOffset (uint32_t hash_idx) const
+ {
+ if (m_hash_offsets && hash_idx < m_header.hashes_count)
+ return m_hash_offsets[hash_idx];
+ return UINT32_MAX;
+ }
+
+ bool
+ Find (const char *name, Pair &pair) const
+ {
+ if (IsValid ())
+ {
+ const uint32_t bucket_count = m_header.bucket_count;
+ const uint32_t hash_count = m_header.hashes_count;
+ const uint32_t hash_value = MappedHash::HashString (m_header.hash_function, name);
+ const uint32_t bucket_idx = hash_value % bucket_count;
+ uint32_t hash_idx = GetHashIndex (bucket_idx);
+ if (hash_idx < hash_count)
+ {
+ for (; hash_idx < hash_count; ++hash_idx)
+ {
+ const uint32_t curr_hash_value = GetHashValue (hash_idx);
+ if (curr_hash_value == hash_value)
+ {
+ uint32_t hash_data_offset = GetHashDataOffset (hash_idx);
+ while (hash_data_offset != UINT32_MAX)
+ {
+ const uint32_t prev_hash_data_offset = hash_data_offset;
+ Result hash_result = GetHashDataForName (name, &hash_data_offset, pair);
+ // Check the result of getting our hash data
+ switch (hash_result)
+ {
+ case eResultKeyMatch:
+ return true;
+
+ case eResultKeyMismatch:
+ if (prev_hash_data_offset == hash_data_offset)
+ return false;
+ break;
+
+ case eResultEndOfHashData:
+ // The last HashData for this key has been reached, stop searching
+ return false;
+ case eResultError:
+ // Error parsing the hash data, abort
+ return false;
+ }
+ }
+ }
+ if ((curr_hash_value % bucket_count) != bucket_idx)
+ break;
+ }
+ }
+ }
+ return false;
+ }
+
+ // This method must be implemented in any subclasses.
+ // The KeyType is user specified and must somehow result in a string
+ // value. For example, the KeyType might be a string offset in a string
+ // table and subclasses can store their string table as a member of the
+ // subclass and return a valie "const char *" given a "key". The value
+ // could also be a C string pointer, in which case just returning "key"
+ // will suffice.
+
+ virtual const char *
+ GetStringForKeyType (KeyType key) const = 0;
+
+ // This method must be implemented in any subclasses and it must try to
+ // read one "Pair" at the offset pointed to by the "hash_data_offset_ptr"
+ // parameter. This offset should be updated as bytes are consumed and
+ // a value "Result" enum should be returned. If the "name" matches the
+ // full name for the "pair.key" (which must be filled in by this call),
+ // then the HashData in the pair ("pair.value") should be extracted and
+ // filled in and "eResultKeyMatch" should be returned. If "name" doesn't
+ // match this string for the key, then "eResultKeyMismatch" should be
+ // returned and all data for the current HashData must be consumed or
+ // skipped and the "hash_data_offset_ptr" offset needs to be updated to
+ // point to the next HashData. If the end of the HashData objects for
+ // a given hash value have been reached, then "eResultEndOfHashData"
+ // should be returned. If anything else goes wrong during parsing,
+ // return "eResultError" and the corresponding "Find()" function will
+ // be canceled and return false.
+
+ virtual Result
+ GetHashDataForName (const char *name,
+ uint32_t* hash_data_offset_ptr,
+ Pair &pair) const = 0;
+
+ protected:
+ // Implementation agnostic information
+ HeaderType m_header;
+ uint32_t *m_hash_indexes;
+ uint32_t *m_hash_values;
+ uint32_t *m_hash_offsets;
+ };
+
+};
+
+#endif // #ifndef liblldb_MappedHash_h_
\ No newline at end of file
More information about the lldb-commits
mailing list