Convert over to the latest and greatest on disc accelerator

hash tables. Renamed the DWARF sections to ".apple_names" and
".apple_types" until we get more buy in from other vendors.

llvm-svn: 140702
This commit is contained in:
Greg Clayton 2011-09-28 17:06:40 +00:00
parent ef8e4efff8
commit 1767440a72
9 changed files with 534 additions and 193 deletions

View File

@ -475,8 +475,8 @@ namespace lldb {
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
eSectionTypeDWARFDebugStr,
eSectionTypeDWARFDebugNames,
eSectionTypeDWARFDebugTypes,
eSectionTypeDWARFAppleNames,
eSectionTypeDWARFAppleTypes,
eSectionTypeEHFrame,
eSectionTypeOther

View File

@ -99,6 +99,12 @@
ReferencedContainer = "container:lldb.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "/Volumes/work/gclayton/Documents/src/WebCore-6530.1/build/Production/WebCore.framework/Versions/A/WebCore"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables>
<EnvironmentVariable
key = "LLDB_LAUNCH_FLAG_DISABLE_ASLR"

View File

@ -255,8 +255,8 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr)
case eSectionTypeDWARFDebugPubTypes: return eAddressClassDebug;
case eSectionTypeDWARFDebugRanges: return eAddressClassDebug;
case eSectionTypeDWARFDebugStr: return eAddressClassDebug;
case eSectionTypeDWARFDebugNames: return eAddressClassDebug;
case eSectionTypeDWARFDebugTypes: return eAddressClassDebug;
case eSectionTypeDWARFAppleNames: return eAddressClassDebug;
case eSectionTypeDWARFAppleTypes: return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeOther: return eAddressClassUnknown;
}
@ -507,8 +507,8 @@ ObjectFileMachO::ParseSections ()
static ConstString g_sect_name_dwarf_debug_pubtypes ("__debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges ("__debug_ranges");
static ConstString g_sect_name_dwarf_debug_str ("__debug_str");
static ConstString g_sect_name_dwarf_debug_names ("__debug_names");
static ConstString g_sect_name_dwarf_debug_types ("__debug_types");
static ConstString g_sect_name_dwarf_apple_names ("__apple_names");
static ConstString g_sect_name_dwarf_apple_types ("__apple_types");
static ConstString g_sect_name_eh_frame ("__eh_frame");
static ConstString g_sect_name_DATA ("__DATA");
static ConstString g_sect_name_TEXT ("__TEXT");
@ -537,10 +537,10 @@ ObjectFileMachO::ParseSections ()
sect_type = eSectionTypeDWARFDebugRanges;
else if (section_name == g_sect_name_dwarf_debug_str)
sect_type = eSectionTypeDWARFDebugStr;
else if (section_name == g_sect_name_dwarf_debug_names)
sect_type = eSectionTypeDWARFDebugNames;
else if (section_name == g_sect_name_dwarf_debug_types)
sect_type = eSectionTypeDWARFDebugTypes;
else if (section_name == g_sect_name_dwarf_apple_names)
sect_type = eSectionTypeDWARFAppleNames;
else if (section_name == g_sect_name_dwarf_apple_types)
sect_type = eSectionTypeDWARFAppleTypes;
else if (section_name == g_sect_name_objc_selrefs)
sect_type = eSectionTypeDataCStringPointers;
else if (section_name == g_sect_name_objc_msgrefs)

View File

@ -18,6 +18,7 @@
#include "DWARFCompileUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDefines.h"
#include "SymbolFileDWARF.h"
using namespace lldb;
using namespace lldb_private;
@ -33,115 +34,275 @@ dl_new_hash (const char *s)
return h;
}
HashedNameToDIE::HashedNameToDIE (SymbolFileDWARF *dwarf, const DataExtractor &data) :
m_dwarf (dwarf),
void
HashedNameToDIE::Header::Dump (Stream &s)
{
s.Printf ("header.magic = 0x%8.8x", magic);
s.Printf ("header.version = 0x%4.4x", version);
s.Printf ("header.addr_bytesize = 0x%2.2x", addr_bytesize);
s.Printf ("header.hash_function = 0x%2.2x", hash_function);
s.Printf ("header.hash_count_bitsize = 0x%2.2x", hash_count_bitsize);
s.Printf ("header.hash_index_bitsize = 0x%2.2x", hash_index_bitsize);
s.Printf ("header.hash_bytesize = 0x%2.2x", hash_bytesize);
s.Printf ("header.offset_bytesize = 0x%2.2x", offset_bytesize);
s.Printf ("header.bucket_count = 0x%8.8x %u", bucket_count, bucket_count);
s.Printf ("header.hashes_count = 0x%8.8x %u", hashes_count, hashes_count);
s.Printf ("header.prologue_length = 0x%8.8x %u", prologue_length, prologue_length);
}
uint32_t
HashedNameToDIE::Header::Read (const DataExtractor &data, uint32_t offset)
{
magic = data.GetU32 (&offset);
if (magic != HASH_MAGIC)
{
// 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);
hash_count_bitsize = data.GetU8 (&offset);
hash_index_bitsize = data.GetU8 (&offset);
hash_bytesize = data.GetU8 (&offset);
offset_bytesize = data.GetU8 (&offset);
bucket_count = data.GetU32 (&offset);
hashes_count = data.GetU32 (&offset);
prologue_length = data.GetU32 (&offset);
return offset;
}
void
HashedNameToDIE::DWARF::Header::Dump (Stream &s)
{
HashedNameToDIE::Header::Dump (s);
dwarf_prologue.Dump (s);
}
uint32_t
HashedNameToDIE::DWARF::Header::Read (const DataExtractor &data, uint32_t offset)
{
offset = HashedNameToDIE::Header::Read (data, offset);
if (offset != UINT32_MAX)
offset = dwarf_prologue.Read (data, offset);
else
dwarf_prologue.Clear();
return offset;
}
void
HashedNameToDIE::DWARF::Prologue::Dump (Stream &s)
{
s.Printf ("dwarf_prologue.die_base_offset = 0x%8.8x\n", die_base_offset);
const size_t num_atoms = atoms.size();
for (size_t i = 0; i < num_atoms; ++i)
{
s.Printf ("dwarf_prologue.atom[%zi] = %17s %s\n",
i,
GetAtomTypeName (atoms[i].type),
DW_FORM_value_to_name(atoms[i].form));
}
}
uint32_t
HashedNameToDIE::DWARF::Prologue::Read (const DataExtractor &data, uint32_t offset)
{
Clear();
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;
}
HashedNameToDIE::MemoryTable::MemoryTable (SymbolFileDWARF *dwarf,
const lldb_private::DataExtractor &data,
bool is_apple_names) :
m_data (data),
m_string_table (dwarf->get_debug_str_data ()),
m_is_apple_names (is_apple_names),
m_header ()
{
}
void
HashedNameToDIE::Initialize()
bool
HashedNameToDIE::MemoryTable::Initialize ()
{
uint32_t offset = 0;
m_header.version = m_data.GetU16(&offset);
if (m_header.version)
{
m_header.hash_type = m_data.GetU8(&offset);
m_header.hash_index_bitsize = m_data.GetU8(&offset);
m_header.num_buckets = m_data.GetU32(&offset);
m_header.num_hashes = m_data.GetU32(&offset);
m_header.die_offset_base = m_data.GetU32(&offset);
}
offset = m_header.Read (m_data, offset);
return m_header.version == 1;
}
size_t
HashedNameToDIE::Find (const ConstString &name, DIEArray &die_ofsets) const
{
const size_t initial_size = die_ofsets.size();
const char *name_cstr = name.GetCString();
if (name_cstr && name_cstr[0])
{
// Hash the C string
const uint32_t name_hash = dl_new_hash (name_cstr);
// Find the correct bucket for the using the hash value
const uint32_t bucket_idx = name_hash % m_header.num_buckets;
// Calculate the offset for the bucket entry for the bucket index
uint32_t offset = GetOffsetOfBucketEntry (bucket_idx);
// Extract the bucket entry.
const uint32_t bucket_entry = m_data.GetU32 (&offset);
if (bucket_entry)
size_t
HashedNameToDIE::MemoryTable::Find (const char *name_cstr, DIEArray &die_ofsets) const
{
if (m_header.version == 1)
{
const size_t initial_size = die_ofsets.size();
if (name_cstr && name_cstr[0])
{
// The bucket entry is non-zero which means it isn't empty.
// The bucket entry is made up of a hash index whose bit width
// is m_header.hash_index_bitsize, and a hash count whose value
// is the remaining bits in the 32 bit value. Below we extract
// the hash index and the hash count
const uint32_t hash_idx = bucket_entry & GetHashIndexMask();
const uint32_t hash_count = bucket_entry >> m_header.hash_index_bitsize;
const uint32_t hash_end_idx = hash_idx + hash_count;
// Figure out the offset to the hash value by index
uint32_t hash_offset = GetOffsetOfHashValue (hash_idx);
for (uint32_t idx = hash_idx; idx < hash_end_idx; ++idx)
// Hash the C string
const uint32_t name_hash = dl_new_hash (name_cstr);
// Find the correct bucket for the using the hash value
const uint32_t bucket_idx = name_hash % m_header.bucket_count;
// Calculate the offset for the bucket entry for the bucket index
uint32_t offset = GetOffsetOfBucketEntry (bucket_idx);
// Extract the bucket entry.
const uint32_t bucket_entry = m_data.GetU32 (&offset);
if (bucket_entry)
{
// Extract the hash value and see if it matches our string
const uint32_t hash = m_data.GetU32 (&hash_offset);
if (hash == name_hash)
// The bucket entry is non-zero which means it isn't empty.
// The bucket entry is made up of a hash index whose bit width
// is m_header.hash_index_bitsize, and a hash count whose value
// is the remaining bits in the 32 bit value. Below we extract
// the hash index and the hash count
const uint32_t hash_idx = bucket_entry & GetHashIndexMask();
const uint32_t hash_count = bucket_entry >> m_header.hash_index_bitsize;
const uint32_t hash_end_idx = hash_idx + hash_count;
// Figure out the offset to the hash value by index
uint32_t hash_offset = GetOffsetOfHashValue (hash_idx);
for (uint32_t idx = hash_idx; idx < hash_end_idx; ++idx)
{
// The hash matches, but we still need to verify that the
// C string matches in case we have a hash collision. Figure
// out the offset for the data associated with this hash entry
offset = GetOffsetOfHashDataOffset (idx);
// Extract the first 32 bit value which is the .debug_str offset
// of the string we need
uint32_t hash_data_offset = m_data.GetU32 (&offset);
const uint32_t str_offset = m_data.GetU32 (&hash_data_offset);
// Extract the C string and comapare it
const char *cstr_name = m_dwarf->get_debug_str_data().PeekCStr(str_offset);
if (cstr_name)
// Extract the hash value and see if it matches our string
const uint32_t hash = m_data.GetU32 (&hash_offset);
if (hash == name_hash)
{
if (strcmp(name_cstr, cstr_name) == 0)
// The hash matches, but we still need to verify that the
// C string matches in case we have a hash collision. Figure
// out the offset for the data associated with this hash entry
offset = GetOffsetOfHashDataOffset (idx);
uint32_t hash_data_offset = m_data.GetU32 (&offset);
uint32_t str_offset;
// Now we have the offset to the data for all strings that match
// our 32 bit hash. The format of the hash bucket is:
//
// uint32_t stroff; // string offset in .debug_str table
// uint32_t num_dies; // Number of DIEs in debug info that match the string that follow this
// uint32_t die_offsets[num_dies]; // An array of DIE offsets
//
// When a "stroff" is read and it is zero, then the data for this
// hash is terminated.
while ((str_offset = m_data.GetU32 (&hash_data_offset)) != 0)
{
// We have a match, now extract the DIE count
const uint32_t die_count = m_data.GetU32 (&hash_data_offset);
// Now extract "die_count" DIE offsets and put them into the
// results
for (uint32_t die_idx = 0; die_idx < die_count; ++die_idx)
die_ofsets.push_back(m_data.GetU32 (&hash_data_offset));
// Extract the C string and comapare it
const char *cstr_name = m_string_table.PeekCStr(str_offset);
if (cstr_name)
{
if (strcmp(name_cstr, cstr_name) == 0)
{
// We have a match, now extract the DIE count
const uint32_t die_count = m_data.GetU32 (&hash_data_offset);
// Now extract "die_count" DIE offsets and put them into the
// results
for (uint32_t die_idx = 0; die_idx < die_count; ++die_idx)
die_ofsets.push_back(m_data.GetU32 (&hash_data_offset));
}
}
}
}
}
}
}
return die_ofsets.size() - initial_size;
}
return die_ofsets.size() - initial_size;
}
size_t
HashedNameToDIE::Find (const RegularExpression& regex, DIEArray &die_ofsets) const
{
// const size_t initial_info_array_size = info_array.size();
// collection::const_iterator pos, end = m_collection.end();
// for (pos = m_collection.begin(); pos != end; ++pos)
// {
// if (regex.Execute(pos->first))
// info_array.push_back (pos->second);
// }
// return info_array.size() - initial_info_array_size;
return 0;
}
void
HashedNameToDIE::Dump (Stream *s)
HashedNameToDIE::MemoryTable::Dump (Stream &s)
{
// collection::const_iterator pos, end = m_collection.end();
// for (pos = m_collection.begin(); pos != end; ++pos)
// {
// s->Printf("%p: 0x%8.8x 0x%8.8x \"%s\"\n", pos->first, pos->second.cu_idx, pos->second.die_idx, pos->first);
// }
if (m_header.version == 1)
{
bool verbose = s.GetVerbose();
if (m_is_apple_names)
s.PutCString (".apple_names contents:\n");
else
s.PutCString (".apple_types contents:\n");
m_header.Dump (s);
uint32_t i,j,k;
uint32_t empty_bucket_count = 0;
uint32_t hash_collisions = 0;
uint32_t bucket_entry_offset = GetOffsetOfBucketEntry (0);
for (i=0; i<m_header.bucket_count; ++i)
{
const uint32_t bucket_entry = m_data.GetU32 (&bucket_entry_offset);
s.Printf("bucket[%u] 0x%8.8x", i, bucket_entry);
if (bucket_entry)
{
const uint32_t hash_idx = bucket_entry & GetHashIndexMask();
const uint32_t hash_count = bucket_entry >> m_header.hash_index_bitsize;
s.Printf(" (hash_idx = %u, hash_count = %u)\n", hash_idx, hash_count);
const uint32_t hash_end_idx = hash_idx + hash_count;
uint32_t hash_offset = GetOffsetOfHashValue (hash_idx);
uint32_t data_offset = GetOffsetOfHashDataOffset (hash_idx);
for (j=hash_idx; j<hash_end_idx; ++j)
{
const uint32_t hash = m_data.GetU32 (&hash_offset);
uint32_t hash_data_offset = m_data.GetU32 (&data_offset);
if (verbose)
s.Printf(" hash[%u] = 0x%8.8x, offset[%u] = 0x%8.8x\n", j, hash, j, hash_data_offset);
else
s.Printf(" hash[%u] = 0x%8.8x\n", j, hash);
uint32_t string_idx = 0;
uint32_t strp_offset;
while ((strp_offset = m_data.GetU32 (&hash_data_offset)) != 0)
{
const uint32_t num_die_offsets = m_data.GetU32 (&hash_data_offset);
s.Printf(" string[%u] = 0x%8.8x \"%s\", dies[%u] = {",
string_idx,
strp_offset,
m_string_table.PeekCStr(strp_offset),
num_die_offsets);
++string_idx;
for (k=0; k<num_die_offsets; ++k)
{
const uint32_t die_offset = m_data.GetU32 (&hash_data_offset);
s.Printf(" 0x%8.8x", die_offset);
}
s.PutCString (" }\n");
}
if (string_idx > 1)
++hash_collisions;
}
}
else
{
s.PutCString(" (empty)\n");
++empty_bucket_count;
}
}
s.Printf ("%u of %u buckets empty (%2.1f%%)\n", empty_bucket_count, m_header.bucket_count, (((float)empty_bucket_count/(float)m_header.bucket_count)*100.0f));
s.Printf ("Average hashes/non-empty bucket = %2.1f%%\n", ((float)m_header.hashes_count/(float)(m_header.bucket_count - empty_bucket_count)));
s.Printf ("Hash collisions = %u\n", hash_collisions);
}
}

View File

@ -21,95 +21,269 @@ typedef std::vector<dw_offset_t> DIEArray;
class HashedNameToDIE
{
public:
enum NameFlags
{
eNameFlagIsExternal = (1u << 0),
eNameFlagIsClassCXX = (1u << 1),
eNameFlagIsClassObjC = (1u << 2),
eNameFlagIsClassObjCMaster = (1u << 3)
};
enum TypeFlags
{
eTypeFlagIsExternal = (1u << 0)
};
enum HashFunctionType
{
eHashFunctionDJB = 0u, // Daniel J Bernstein hash function that is also used by the ELF GNU_HASH sections
};
static const uint32_t HASH_MAGIC = 0x48415348u;
struct Header
{
uint16_t version;
uint8_t hash_type;
uint8_t hash_index_bitsize;
uint32_t num_buckets;
uint32_t num_hashes;
uint32_t die_offset_base;
Header() :
version(0),
hash_type (0),
hash_index_bitsize (0),
num_buckets(0),
num_hashes (0),
die_offset_base(0)
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
uint8_t hash_count_bitsize; // Size in bits of the hash count in each bucket entry
uint8_t hash_index_bitsize; // Size in bits of the hash index in each bucket entry
uint8_t hash_bytesize; // Size in bytes of the hash that is stored in the hashes which must be <= 4
uint8_t offset_bytesize; // Size in bytes of the hash data offsets
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 prologue_length; // The length of the prologue
Header (uint32_t _prologue_length) :
magic (HASH_MAGIC),
version (1),
addr_bytesize (4),
hash_count_bitsize (8),
hash_index_bitsize (24),
hash_function (eHashFunctionDJB),
hash_bytesize (4), // Store the entire 32 bit hash by default
offset_bytesize (4), // Store a 4 byte offset for every hash value
bucket_count (0),
hashes_count (0),
prologue_length (_prologue_length)
{
}
};
HashedNameToDIE (SymbolFileDWARF *dwarf,
const lldb_private::DataExtractor &data);
~HashedNameToDIE ()
{
}
bool
IsValid () const
{
return m_header.version > 0;
}
uint32_t
GetHashIndexMask () const
{
return (1u << m_header.hash_index_bitsize) - 1u;
}
uint32_t
GetOffsetOfBucketEntry (uint32_t idx) const
{
if (idx < m_header.num_buckets)
return sizeof(Header) + 4 * idx;
return UINT32_MAX;
}
uint32_t
GetOffsetOfHashValue (uint32_t idx) const
{
if (idx < m_header.num_hashes)
return sizeof(Header) +
4 * m_header.num_buckets +
4 * idx;
return UINT32_MAX;
}
uint32_t
GetOffsetOfHashDataOffset (uint32_t idx) const
{
if (idx < m_header.num_hashes)
{
return sizeof(Header) +
4 * m_header.num_buckets +
4 * m_header.num_hashes +
4 * idx;
virtual
~Header ()
{
}
return UINT32_MAX;
}
virtual size_t
GetByteSize() const
{
return sizeof(magic) +
sizeof(version) +
sizeof(addr_bytesize) +
sizeof(hash_function) +
sizeof(hash_count_bitsize) +
sizeof(hash_index_bitsize) +
sizeof(hash_bytesize) +
sizeof(offset_bytesize) +
sizeof(bucket_count) +
sizeof(hashes_count) +
sizeof(prologue_length) +
prologue_length;
}
virtual void
Dump (lldb_private::Stream &s);
void
Dump (lldb_private::Stream *s);
virtual uint32_t
Read (const lldb_private::DataExtractor &data, uint32_t offset);
};
size_t
Find (const lldb_private::ConstString &name,
DIEArray &die_ofsets) const;
struct DWARF
{
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();
}
virtual void
Dump (lldb_private::Stream &s);
virtual uint32_t
Read (const lldb_private::DataExtractor &data, uint32_t offset);
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 HashedNameToDIE::Header
{
Header (dw_offset_t _die_base_offset = 0) :
HashedNameToDIE::Header (sizeof(Prologue)),
dwarf_prologue (_die_base_offset)
{
}
virtual
~Header ()
{
}
Prologue dwarf_prologue;
virtual void
Dump (lldb_private::Stream &s);
virtual uint32_t
Read (const lldb_private::DataExtractor &data, uint32_t offset);
};
};
size_t
Find (const lldb_private::RegularExpression& regex,
DIEArray &die_ofsets) const;
void
Initialize();
protected:
SymbolFileDWARF *m_dwarf;
const lldb_private::DataExtractor &m_data;
Header m_header;
class MemoryTable
{
public:
MemoryTable (SymbolFileDWARF *dwarf,
const lldb_private::DataExtractor &data,
bool is_apple_names);
~MemoryTable ()
{
}
bool
Initialize ();
bool
IsValid () const
{
return m_header.version > 0;
}
uint32_t
GetHashIndexMask () const
{
return (1u << m_header.hash_index_bitsize) - 1u;
}
uint32_t
GetOffsetOfBucketEntry (uint32_t idx) const
{
if (idx < m_header.bucket_count)
return m_header.GetByteSize() + 4 * idx;
return UINT32_MAX;
}
uint32_t
GetOffsetOfHashValue (uint32_t idx) const
{
if (idx < m_header.hashes_count)
return m_header.GetByteSize() +
4 * m_header.bucket_count +
4 * idx;
return UINT32_MAX;
}
uint32_t
GetOffsetOfHashDataOffset (uint32_t idx) const
{
if (idx < m_header.hashes_count)
{
return m_header.GetByteSize() +
4 * m_header.bucket_count +
4 * m_header.hashes_count +
4 * idx;
}
return UINT32_MAX;
}
void
Dump (lldb_private::Stream &s);
size_t
Find (const char *name, DIEArray &die_ofsets) const;
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
DWARF::Header m_header;
};
};
#endif // SymbolFileDWARF_HashedNameToDIE_h_

View File

@ -171,12 +171,12 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
m_data_debug_loc (),
m_data_debug_ranges (),
m_data_debug_str (),
m_data_debug_names (),
m_data_debug_types (),
m_data_apple_names (),
m_data_apple_types (),
m_abbr(),
m_info(),
m_line(),
m_debug_names (this, m_data_debug_names),
m_apple_names (this, m_data_apple_names, true),
m_function_basename_index(),
m_function_fullname_index(),
m_function_method_index(),
@ -190,8 +190,8 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
m_ranges(),
m_unique_ast_type_map ()
{
get_debug_names_data();
m_debug_names.Initialize();
get_apple_names_data();
m_apple_names.Initialize();
}
SymbolFileDWARF::~SymbolFileDWARF()
@ -455,15 +455,15 @@ SymbolFileDWARF::get_debug_str_data()
}
const DataExtractor&
SymbolFileDWARF::get_debug_names_data()
SymbolFileDWARF::get_apple_names_data()
{
return GetCachedSectionData (flagsGotDebugNamesData, eSectionTypeDWARFDebugNames, m_data_debug_names);
return GetCachedSectionData (flagsGotDebugNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names);
}
const DataExtractor&
SymbolFileDWARF::get_debug_types_data()
SymbolFileDWARF::get_apple_types_data()
{
return GetCachedSectionData (flagsGotDebugTypesData, eSectionTypeDWARFDebugTypes, m_data_debug_types);
return GetCachedSectionData (flagsGotDebugTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
}
@ -2293,10 +2293,10 @@ SymbolFileDWARF::FindFunctions
// Remember how many sc_list are in the list before we search in case
// we are appending the results to a variable list.
if (m_debug_names.IsValid())
if (m_apple_names.IsValid())
{
DIEArray die_offsets;
const uint32_t num_matches = m_debug_names.Find(name, die_offsets);
const uint32_t num_matches = m_apple_names.Find(name.GetCString(), die_offsets);
if (num_matches > 0)
{
return ResolveFunctions (die_offsets, sc_list);

View File

@ -164,8 +164,8 @@ public:
const lldb_private::DataExtractor& get_debug_loc_data ();
const lldb_private::DataExtractor& get_debug_ranges_data ();
const lldb_private::DataExtractor& get_debug_str_data ();
const lldb_private::DataExtractor& get_debug_names_data ();
const lldb_private::DataExtractor& get_debug_types_data ();
const lldb_private::DataExtractor& get_apple_names_data ();
const lldb_private::DataExtractor& get_apple_types_data ();
DWARFDebugAbbrev* DebugAbbrev();
const DWARFDebugAbbrev* DebugAbbrev() const;
@ -379,15 +379,15 @@ protected:
lldb_private::DataExtractor m_data_debug_loc;
lldb_private::DataExtractor m_data_debug_ranges;
lldb_private::DataExtractor m_data_debug_str;
lldb_private::DataExtractor m_data_debug_names;
lldb_private::DataExtractor m_data_debug_types;
lldb_private::DataExtractor m_data_apple_names;
lldb_private::DataExtractor m_data_apple_types;
// The auto_ptr items below are generated on demand if and when someone accesses
// them through a non const version of this class.
std::auto_ptr<DWARFDebugAbbrev> m_abbr;
std::auto_ptr<DWARFDebugInfo> m_info;
std::auto_ptr<DWARFDebugLine> m_line;
HashedNameToDIE m_debug_names;
HashedNameToDIE::MemoryTable m_apple_names;
NameToDIE m_function_basename_index; // All concrete functions
NameToDIE m_function_fullname_index; // All concrete functions
NameToDIE m_function_method_index; // All inlined functions

View File

@ -221,8 +221,8 @@ ObjectFile::GetAddressClass (addr_t file_addr)
case eSectionTypeDWARFDebugPubTypes: return eAddressClassDebug;
case eSectionTypeDWARFDebugRanges: return eAddressClassDebug;
case eSectionTypeDWARFDebugStr: return eAddressClassDebug;
case eSectionTypeDWARFDebugNames: return eAddressClassDebug;
case eSectionTypeDWARFDebugTypes: return eAddressClassDebug;
case eSectionTypeDWARFAppleNames: return eAddressClassDebug;
case eSectionTypeDWARFAppleTypes: return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeOther: return eAddressClassUnknown;
}

View File

@ -259,8 +259,8 @@ lldb_private::GetSectionTypeAsCString (SectionType sect_type)
case eSectionTypeDWARFDebugPubTypes: return "dwarf-pubtypes";
case eSectionTypeDWARFDebugRanges: return "dwarf-ranges";
case eSectionTypeDWARFDebugStr: return "dwarf-str";
case eSectionTypeDWARFDebugNames: return "dwarf-names";
case eSectionTypeDWARFDebugTypes: return "dwarf-types";
case eSectionTypeDWARFAppleNames: return "apple-names";
case eSectionTypeDWARFAppleTypes: return "apple-types";
case eSectionTypeEHFrame: return "eh-frame";
case eSectionTypeOther: return "regular";
}