forked from OSchip/llvm-project
Code cleanup in preparation of adding split dwarf support
* Remove some unused code * Remove usage of DWARFDebugInfoEntry::Attributes where usage isn't reasonable * Cleanup DWARFMappedHash with separating it to header and implementation file and fixing the visibility of the functions Differential revision: http://reviews.llvm.org/D12374 llvm-svn: 247131
This commit is contained in:
parent
1535bebac6
commit
715cbe8939
|
@ -22,6 +22,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF
|
|||
DWARFFormValue.cpp
|
||||
DWARFLocationDescription.cpp
|
||||
DWARFLocationList.cpp
|
||||
HashedNameToDIE.cpp
|
||||
LogChannelDWARF.cpp
|
||||
NameToDIE.cpp
|
||||
SymbolFileDWARF.cpp
|
||||
|
|
|
@ -569,46 +569,6 @@ DWARFCompileUnit::GetDIE (dw_offset_t die_offset)
|
|||
return DWARFDIE(); // Not found
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// GetDIEPtrContainingOffset()
|
||||
//
|
||||
// Get the DIE (Debug Information Entry) that contains the specified
|
||||
// .debug_info offset.
|
||||
//----------------------------------------------------------------------
|
||||
DWARFDIE
|
||||
DWARFCompileUnit::GetDIEContainingOffset(dw_offset_t die_offset)
|
||||
{
|
||||
if (die_offset != DW_INVALID_OFFSET)
|
||||
{
|
||||
if (ContainsDIEOffset(die_offset))
|
||||
{
|
||||
|
||||
ExtractDIEsIfNeeded (false);
|
||||
DWARFDebugInfoEntry::iterator end = m_die_array.end();
|
||||
DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset);
|
||||
if (pos != end)
|
||||
{
|
||||
if (die_offset >= (*pos).GetOffset())
|
||||
{
|
||||
DWARFDebugInfoEntry::iterator next = pos + 1;
|
||||
if (next != end)
|
||||
{
|
||||
if (die_offset < (*next).GetOffset())
|
||||
return DWARFDIE(this, &(*pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_dwarf2Data->DebugInfo()->GetDIEContainingOffset (die_offset);
|
||||
}
|
||||
}
|
||||
return DWARFDIE(); // Not found
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t
|
||||
DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const
|
||||
{
|
||||
|
|
|
@ -106,9 +106,6 @@ public:
|
|||
DWARFDIE
|
||||
GetDIE (dw_offset_t die_offset);
|
||||
|
||||
DWARFDIE
|
||||
GetDIEContainingOffset (dw_offset_t die_offset);
|
||||
|
||||
static uint8_t
|
||||
GetAddressByteSize(const DWARFCompileUnit* cu);
|
||||
|
||||
|
|
|
@ -295,17 +295,6 @@ DWARFDebugInfo::GetDIE(dw_offset_t die_offset)
|
|||
return DWARFDIE(); // Not found
|
||||
}
|
||||
|
||||
DWARFDIE
|
||||
DWARFDebugInfo::GetDIEContainingOffset (dw_offset_t die_offset)
|
||||
{
|
||||
DWARFCompileUnit *cu = GetCompileUnitContainingDIE(die_offset);
|
||||
if (cu)
|
||||
return cu->GetDIEContainingOffset (die_offset);
|
||||
|
||||
return DWARFDIE(); // Not found
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Parse
|
||||
//
|
||||
|
|
|
@ -57,23 +57,6 @@ public:
|
|||
typedef offset_collection::iterator offset_collection_iterator;
|
||||
typedef offset_collection::const_iterator offset_collection_const_iterator;
|
||||
|
||||
struct CompareState
|
||||
{
|
||||
CompareState() :
|
||||
die_offset_pairs()
|
||||
{
|
||||
assert(sizeof(dw_offset_t)*2 == sizeof(uint64_t));
|
||||
}
|
||||
|
||||
bool AddTypePair(dw_offset_t a, dw_offset_t b)
|
||||
{
|
||||
uint64_t a_b_offsets = (uint64_t)a << 32 | (uint64_t)b;
|
||||
// Return true if this type was inserted, false otherwise
|
||||
return die_offset_pairs.insert(a_b_offsets).second;
|
||||
}
|
||||
std::set< uint64_t > die_offset_pairs;
|
||||
};
|
||||
|
||||
DWARFDebugInfoEntry():
|
||||
m_offset (DW_INVALID_OFFSET),
|
||||
m_parent_idx (0),
|
||||
|
@ -225,22 +208,6 @@ public:
|
|||
const DWARFAttributes& attributes,
|
||||
std::string &storage) const;
|
||||
|
||||
// static int Compare(
|
||||
// SymbolFileDWARF* dwarf2Data,
|
||||
// dw_offset_t a_die_offset,
|
||||
// dw_offset_t b_die_offset,
|
||||
// CompareState &compare_state,
|
||||
// bool compare_siblings,
|
||||
// bool compare_children);
|
||||
//
|
||||
// static int Compare(
|
||||
// SymbolFileDWARF* dwarf2Data,
|
||||
// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
|
||||
// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
|
||||
// CompareState &compare_state,
|
||||
// bool compare_siblings,
|
||||
// bool compare_children);
|
||||
|
||||
static bool OffsetLessThan (
|
||||
const DWARFDebugInfoEntry& a,
|
||||
const DWARFDebugInfoEntry& b);
|
||||
|
|
|
@ -0,0 +1,741 @@
|
|||
//===-- HashedNameToDIE.cpp -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HashedNameToDIE.h"
|
||||
|
||||
void
|
||||
DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets)
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array,
|
||||
const dw_tag_t tag,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
ExtractDIEArray (die_info_array, die_offsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
const dw_tag_t die_tag = die_info_array[i].tag;
|
||||
bool tag_matches = die_tag == 0 || tag == die_tag;
|
||||
if (!tag_matches)
|
||||
{
|
||||
if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
|
||||
tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
|
||||
}
|
||||
if (tag_matches)
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array,
|
||||
const dw_tag_t tag,
|
||||
const uint32_t qualified_name_hash,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
ExtractDIEArray (die_info_array, die_offsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
if (qualified_name_hash != die_info_array[i].qualified_name_hash)
|
||||
continue;
|
||||
const dw_tag_t die_tag = die_info_array[i].tag;
|
||||
bool tag_matches = die_tag == 0 || tag == die_tag;
|
||||
if (!tag_matches)
|
||||
{
|
||||
if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
|
||||
tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
|
||||
}
|
||||
if (tag_matches)
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
|
||||
bool return_implementation_only_if_available,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
const dw_tag_t die_tag = die_info_array[i].tag;
|
||||
if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
|
||||
{
|
||||
if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
|
||||
{
|
||||
if (return_implementation_only_if_available)
|
||||
{
|
||||
// We found the one true definition for this class, so
|
||||
// only return that
|
||||
die_offsets.clear();
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Put the one true definition as the first entry so it
|
||||
// matches first
|
||||
die_offsets.insert (die_offsets.begin(), die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
|
||||
uint32_t type_flag_mask,
|
||||
uint32_t type_flag_value,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
DWARFMappedHash::GetAtomTypeName (uint16_t atom)
|
||||
{
|
||||
switch (atom)
|
||||
{
|
||||
case eAtomTypeNULL: return "NULL";
|
||||
case eAtomTypeDIEOffset: return "die-offset";
|
||||
case eAtomTypeCUOffset: return "cu-offset";
|
||||
case eAtomTypeTag: return "die-tag";
|
||||
case eAtomTypeNameFlags: return "name-flags";
|
||||
case eAtomTypeTypeFlags: return "type-flags";
|
||||
case eAtomTypeQualNameHash: return "qualified-name-hash";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
DWARFMappedHash::DIEInfo::DIEInfo () :
|
||||
offset (DW_INVALID_OFFSET),
|
||||
tag (0),
|
||||
type_flags (0),
|
||||
qualified_name_hash (0)
|
||||
{
|
||||
}
|
||||
|
||||
DWARFMappedHash::DIEInfo::DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) :
|
||||
offset (o),
|
||||
tag (t),
|
||||
type_flags (f),
|
||||
qualified_name_hash (h)
|
||||
{
|
||||
}
|
||||
|
||||
DWARFMappedHash::Prologue::Prologue (dw_offset_t _die_base_offset) :
|
||||
die_base_offset (_die_base_offset),
|
||||
atoms(),
|
||||
atom_mask (0),
|
||||
min_hash_data_byte_size(0),
|
||||
hash_data_has_fixed_byte_size(true)
|
||||
{
|
||||
// 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
|
||||
AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::Prologue::ClearAtoms ()
|
||||
{
|
||||
hash_data_has_fixed_byte_size = true;
|
||||
min_hash_data_byte_size = 0;
|
||||
atom_mask = 0;
|
||||
atoms.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
DWARFMappedHash::Prologue::ContainsAtom (AtomType atom_type) const
|
||||
{
|
||||
return (atom_mask & (1u << atom_type)) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::Prologue::Clear ()
|
||||
{
|
||||
die_base_offset = 0;
|
||||
ClearAtoms ();
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form)
|
||||
{
|
||||
atoms.push_back ({type, form});
|
||||
atom_mask |= 1u << type;
|
||||
switch (form)
|
||||
{
|
||||
case DW_FORM_indirect:
|
||||
case DW_FORM_exprloc:
|
||||
case DW_FORM_flag_present:
|
||||
case DW_FORM_ref_sig8:
|
||||
assert (!"Unhandled atom form");
|
||||
break;
|
||||
|
||||
case DW_FORM_string:
|
||||
case DW_FORM_block:
|
||||
case DW_FORM_block1:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_ref_udata:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
case DW_FORM_GNU_str_index:
|
||||
hash_data_has_fixed_byte_size = false;
|
||||
// Fall through to the cases below...
|
||||
case DW_FORM_flag:
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_ref1:
|
||||
case DW_FORM_sec_offset:
|
||||
min_hash_data_byte_size += 1;
|
||||
break;
|
||||
|
||||
case DW_FORM_block2:
|
||||
hash_data_has_fixed_byte_size = false;
|
||||
// Fall through to the cases below...
|
||||
case DW_FORM_data2:
|
||||
case DW_FORM_ref2:
|
||||
min_hash_data_byte_size += 2;
|
||||
break;
|
||||
|
||||
case DW_FORM_block4:
|
||||
hash_data_has_fixed_byte_size = false;
|
||||
// Fall through to the cases below...
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_ref4:
|
||||
case DW_FORM_addr:
|
||||
case DW_FORM_ref_addr:
|
||||
case DW_FORM_strp:
|
||||
min_hash_data_byte_size += 4;
|
||||
break;
|
||||
|
||||
case DW_FORM_data8:
|
||||
case DW_FORM_ref8:
|
||||
min_hash_data_byte_size += 8;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
lldb::offset_t
|
||||
DWARFMappedHash::Prologue::Read (const lldb_private::DataExtractor &data,
|
||||
lldb::offset_t offset)
|
||||
{
|
||||
ClearAtoms ();
|
||||
|
||||
die_base_offset = data.GetU32 (&offset);
|
||||
|
||||
const uint32_t atom_count = data.GetU32 (&offset);
|
||||
if (atom_count == 0x00060003u)
|
||||
{
|
||||
// Old format, deal with contents of old pre-release format
|
||||
while (data.GetU32(&offset))
|
||||
/* do nothing */;
|
||||
|
||||
// Hardcode to the only known value for now.
|
||||
AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i=0; i<atom_count; ++i)
|
||||
{
|
||||
AtomType type = (AtomType)data.GetU16 (&offset);
|
||||
dw_form_t form = (dw_form_t)data.GetU16 (&offset);
|
||||
AppendAtom (type, form);
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::Prologue::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) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::Prologue::GetMinimumHashDataByteSize () const
|
||||
{
|
||||
return min_hash_data_byte_size;
|
||||
}
|
||||
|
||||
bool
|
||||
DWARFMappedHash::Prologue::HashDataHasFixedByteSize() const
|
||||
{
|
||||
return hash_data_has_fixed_byte_size;
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::Header::GetByteSize (const HeaderData &header_data)
|
||||
{
|
||||
return header_data.GetByteSize();
|
||||
}
|
||||
|
||||
lldb::offset_t
|
||||
DWARFMappedHash::Header::Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
|
||||
{
|
||||
offset = MappedHash::Header<Prologue>::Read (data, offset);
|
||||
if (offset != UINT32_MAX)
|
||||
{
|
||||
offset = header_data.Read (data, offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool
|
||||
DWARFMappedHash::Header::Read (const lldb_private::DWARFDataExtractor &data,
|
||||
lldb::offset_t *offset_ptr,
|
||||
DIEInfo &hash_data) const
|
||||
{
|
||||
const size_t num_atoms = header_data.atoms.size();
|
||||
if (num_atoms == 0)
|
||||
return false;
|
||||
|
||||
for (size_t i=0; i<num_atoms; ++i)
|
||||
{
|
||||
DWARFFormValue form_value (NULL, header_data.atoms[i].form);
|
||||
|
||||
if (!form_value.ExtractValue(data, offset_ptr))
|
||||
return false;
|
||||
|
||||
switch (header_data.atoms[i].type)
|
||||
{
|
||||
case eAtomTypeDIEOffset: // DIE offset, check form for encoding
|
||||
hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
|
||||
break;
|
||||
|
||||
case eAtomTypeTag: // DW_TAG value for the DIE
|
||||
hash_data.tag = (dw_tag_t)form_value.Unsigned ();
|
||||
|
||||
case eAtomTypeTypeFlags: // Flags from enum TypeFlags
|
||||
hash_data.type_flags = (uint32_t)form_value.Unsigned ();
|
||||
break;
|
||||
|
||||
case eAtomTypeQualNameHash: // Flags from enum TypeFlags
|
||||
hash_data.qualified_name_hash = form_value.Unsigned ();
|
||||
break;
|
||||
|
||||
default:
|
||||
// We can always skip atoms we don't know about
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DWARFMappedHash::Header::Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
|
||||
{
|
||||
const size_t num_atoms = header_data.atoms.size();
|
||||
for (size_t i=0; i<num_atoms; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
strm.PutCString (", ");
|
||||
|
||||
DWARFFormValue form_value (NULL, header_data.atoms[i].form);
|
||||
switch (header_data.atoms[i].type)
|
||||
{
|
||||
case eAtomTypeDIEOffset: // DIE offset, check form for encoding
|
||||
strm.Printf ("{0x%8.8x}", hash_data.offset);
|
||||
break;
|
||||
|
||||
case eAtomTypeTag: // DW_TAG value for the DIE
|
||||
{
|
||||
const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
|
||||
if (tag_cstr)
|
||||
strm.PutCString (tag_cstr);
|
||||
else
|
||||
strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
|
||||
}
|
||||
break;
|
||||
|
||||
case eAtomTypeTypeFlags: // Flags from enum TypeFlags
|
||||
strm.Printf ("0x%2.2x", hash_data.type_flags);
|
||||
if (hash_data.type_flags)
|
||||
{
|
||||
strm.PutCString (" (");
|
||||
if (hash_data.type_flags & eTypeFlagClassIsImplementation)
|
||||
strm.PutCString (" implementation");
|
||||
strm.PutCString (" )");
|
||||
}
|
||||
break;
|
||||
|
||||
case eAtomTypeQualNameHash: // Flags from enum TypeFlags
|
||||
strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
|
||||
break;
|
||||
|
||||
default:
|
||||
strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DWARFMappedHash::MemoryTable::MemoryTable (lldb_private::DWARFDataExtractor &table_data,
|
||||
const lldb_private::DWARFDataExtractor &string_table,
|
||||
const char *name) :
|
||||
MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
|
||||
m_data (table_data),
|
||||
m_string_table (string_table),
|
||||
m_name (name)
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
DWARFMappedHash::MemoryTable::GetStringForKeyType (KeyType key) const
|
||||
{
|
||||
// The key in the DWARF table is the .debug_str offset for the string
|
||||
return m_string_table.PeekCStr (key);
|
||||
}
|
||||
|
||||
bool
|
||||
DWARFMappedHash::MemoryTable::ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const
|
||||
{
|
||||
lldb::offset_t offset = hash_data_offset;
|
||||
offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
|
||||
const uint32_t count = m_data.GetU32 (&offset);
|
||||
if (count > 0)
|
||||
{
|
||||
hash_data.resize(count);
|
||||
for (uint32_t i=0; i<count; ++i)
|
||||
{
|
||||
if (!m_header.Read(m_data, &offset, hash_data[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
hash_data.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
DWARFMappedHash::MemoryTable::Result
|
||||
DWARFMappedHash::MemoryTable::GetHashDataForName (const char *name,
|
||||
lldb::offset_t* hash_data_offset_ptr,
|
||||
Pair &pair) const
|
||||
{
|
||||
pair.key = m_data.GetU32 (hash_data_offset_ptr);
|
||||
pair.value.clear();
|
||||
|
||||
// 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)
|
||||
{
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
|
||||
const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
|
||||
const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
|
||||
if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
|
||||
{
|
||||
// We have at least one HashData entry, and we have enough
|
||||
// data to parse at least "count" HashData entries.
|
||||
|
||||
// First make sure the entire C string matches...
|
||||
const bool match = strcmp (name, strp_cstr) == 0;
|
||||
|
||||
if (!match && m_header.header_data.HashDataHasFixedByteSize())
|
||||
{
|
||||
// If the string doesn't match and we have fixed size data,
|
||||
// we can just add the total byte size of all HashData objects
|
||||
// to the hash data offset and be done...
|
||||
*hash_data_offset_ptr += min_total_hash_data_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the string does match, or we don't have fixed size data
|
||||
// then we need to read the hash data as a stream. If the
|
||||
// string matches we also append all HashData objects to the
|
||||
// value array.
|
||||
for (uint32_t i=0; i<count; ++i)
|
||||
{
|
||||
DIEInfo die_info;
|
||||
if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
|
||||
{
|
||||
// Only happened if the HashData of the string matched...
|
||||
if (match)
|
||||
pair.value.push_back (die_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something went wrong while reading the data
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the correct response depending on if the string matched
|
||||
// or not...
|
||||
if (match)
|
||||
return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
|
||||
else
|
||||
return eResultKeyMismatch; // The key doesn't match, this function will get called
|
||||
// again for the next key/value or the key terminator
|
||||
// which in our case is a zero .debug_str offset.
|
||||
}
|
||||
else
|
||||
{
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
|
||||
DWARFMappedHash::MemoryTable::Result
|
||||
DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression (
|
||||
const lldb_private::RegularExpression& regex,
|
||||
lldb::offset_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 size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
|
||||
if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
|
||||
{
|
||||
const bool match = regex.Execute(strp_cstr);
|
||||
|
||||
if (!match && m_header.header_data.HashDataHasFixedByteSize())
|
||||
{
|
||||
// If the regex doesn't match and we have fixed size data,
|
||||
// we can just add the total byte size of all HashData objects
|
||||
// to the hash data offset and be done...
|
||||
*hash_data_offset_ptr += min_total_hash_data_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the string does match, or we don't have fixed size data
|
||||
// then we need to read the hash data as a stream. If the
|
||||
// string matches we also append all HashData objects to the
|
||||
// value array.
|
||||
for (uint32_t i=0; i<count; ++i)
|
||||
{
|
||||
DIEInfo die_info;
|
||||
if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
|
||||
{
|
||||
// Only happened if the HashData of the string matched...
|
||||
if (match)
|
||||
pair.value.push_back (die_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something went wrong while reading the data
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the correct response depending on if the string matched
|
||||
// or not...
|
||||
if (match)
|
||||
return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
|
||||
else
|
||||
return eResultKeyMismatch; // The key doesn't match, this function will get called
|
||||
// again for the next key/value or the key terminator
|
||||
// which in our case is a zero .debug_str offset.
|
||||
}
|
||||
else
|
||||
{
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex (
|
||||
const lldb_private::RegularExpression& regex,
|
||||
DIEInfoArray &die_info_array) const
|
||||
{
|
||||
const uint32_t hash_count = m_header.hashes_count;
|
||||
Pair pair;
|
||||
for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
|
||||
{
|
||||
lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
|
||||
while (hash_data_offset != UINT32_MAX)
|
||||
{
|
||||
const lldb::offset_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_info_array.swap (pair.value);
|
||||
return die_info_array.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::MemoryTable::AppendAllDIEsInRange (const uint32_t die_offset_start,
|
||||
const uint32_t die_offset_end,
|
||||
DIEInfoArray &die_info_array) 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;
|
||||
lldb::offset_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)
|
||||
{
|
||||
DIEInfo die_info;
|
||||
if (m_header.Read(m_data, &hash_data_offset, die_info))
|
||||
{
|
||||
if (die_info.offset == 0)
|
||||
done = true;
|
||||
if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
|
||||
die_info_array.push_back(die_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return die_info_array.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEArray &die_offsets)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
|
||||
return die_info_array.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::MemoryTable::FindByNameAndTag (const char *name,
|
||||
const dw_tag_t tag,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
|
||||
return die_info_array.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash (const char *name,
|
||||
const dw_tag_t tag,
|
||||
const uint32_t qualified_name_hash,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
|
||||
return die_info_array.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName (const char *name,
|
||||
DIEArray &die_offsets,
|
||||
bool must_be_implementation)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
{
|
||||
if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
|
||||
{
|
||||
// If we have two atoms, then we have the DIE offset and
|
||||
// the type flags so we can find the objective C class
|
||||
// efficiently.
|
||||
DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
|
||||
UINT32_MAX,
|
||||
eTypeFlagClassIsImplementation,
|
||||
die_offsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't only want the one true definition, so try and see
|
||||
// what we can find, and only return class or struct DIEs.
|
||||
// If we do have the full implementation, then return it alone,
|
||||
// else return all possible matches.
|
||||
const bool return_implementation_only_if_available = true;
|
||||
DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
|
||||
return_implementation_only_if_available,
|
||||
die_offsets);
|
||||
}
|
||||
}
|
||||
return die_offsets.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEInfoArray &die_info_array)
|
||||
{
|
||||
Pair kv_pair;
|
||||
size_t old_size = die_info_array.size();
|
||||
if (Find (name, kv_pair))
|
||||
{
|
||||
die_info_array.swap(kv_pair.value);
|
||||
return die_info_array.size() - old_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -12,134 +12,36 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "DWARFDefines.h"
|
||||
#include "DWARFFormValue.h"
|
||||
|
||||
#include "lldb/lldb-defines.h"
|
||||
#include "lldb/Core/dwarf.h"
|
||||
#include "lldb/Core/RegularExpression.h"
|
||||
#include "lldb/Core/MappedHash.h"
|
||||
|
||||
struct DWARFMappedHash
|
||||
#include "DWARFDefines.h"
|
||||
#include "DWARFFormValue.h"
|
||||
#include "NameToDIE.h"
|
||||
|
||||
class SymbolFileDWARF;
|
||||
class DWARFCompileUnit;
|
||||
class DWARFDebugInfoEntry;
|
||||
|
||||
class DWARFMappedHash
|
||||
{
|
||||
struct DIEInfo
|
||||
public:
|
||||
enum AtomType : uint16_t
|
||||
{
|
||||
dw_offset_t offset; // The DIE offset
|
||||
dw_tag_t tag;
|
||||
uint32_t type_flags; // Any flags for this DIEInfo
|
||||
uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
|
||||
|
||||
DIEInfo () :
|
||||
offset (DW_INVALID_OFFSET),
|
||||
tag (0),
|
||||
type_flags (0),
|
||||
qualified_name_hash (0)
|
||||
{
|
||||
}
|
||||
|
||||
DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) :
|
||||
offset(o),
|
||||
tag (t),
|
||||
type_flags (f),
|
||||
qualified_name_hash (h)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Clear()
|
||||
{
|
||||
offset = DW_INVALID_OFFSET;
|
||||
tag = 0;
|
||||
type_flags = 0;
|
||||
qualified_name_hash = 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<DIEInfo> DIEInfoArray;
|
||||
typedef std::vector<uint32_t> DIEArray;
|
||||
|
||||
static void
|
||||
ExtractDIEArray (const DIEInfoArray &die_info_array,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ExtractDIEArray (const DIEInfoArray &die_info_array,
|
||||
const dw_tag_t tag,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
ExtractDIEArray (die_info_array, die_offsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
const dw_tag_t die_tag = die_info_array[i].tag;
|
||||
bool tag_matches = die_tag == 0 || tag == die_tag;
|
||||
if (!tag_matches)
|
||||
{
|
||||
if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
|
||||
tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
|
||||
}
|
||||
if (tag_matches)
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ExtractDIEArray (const DIEInfoArray &die_info_array,
|
||||
const dw_tag_t tag,
|
||||
const uint32_t qualified_name_hash,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
ExtractDIEArray (die_info_array, die_offsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
if (qualified_name_hash != die_info_array[i].qualified_name_hash)
|
||||
continue;
|
||||
const dw_tag_t die_tag = die_info_array[i].tag;
|
||||
bool tag_matches = die_tag == 0 || tag == die_tag;
|
||||
if (!tag_matches)
|
||||
{
|
||||
if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
|
||||
tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
|
||||
}
|
||||
if (tag_matches)
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum AtomType
|
||||
{
|
||||
eAtomTypeNULL = 0u,
|
||||
eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding
|
||||
eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question
|
||||
eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
|
||||
eAtomTypeNameFlags = 4u, // Flags from enum NameFlags
|
||||
eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags,
|
||||
eAtomTypeNULL = 0u,
|
||||
eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding
|
||||
eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question
|
||||
eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
|
||||
eAtomTypeNameFlags = 4u, // Flags from enum NameFlags
|
||||
eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags,
|
||||
eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name (since all hash entries are basename only)
|
||||
// For example a type like "std::vector<int>::iterator" would have a name of "iterator"
|
||||
// and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull
|
||||
// in debug info for a type when we know the fully qualified name.
|
||||
};
|
||||
|
||||
|
||||
// Bit definitions for the eAtomTypeTypeFlags flags
|
||||
enum TypeFlags
|
||||
{
|
||||
|
@ -147,719 +49,172 @@ struct DWARFMappedHash
|
|||
// @implementation for class
|
||||
eTypeFlagClassIsImplementation = ( 1u << 1 )
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
|
||||
bool return_implementation_only_if_available,
|
||||
DIEArray &die_offsets)
|
||||
struct DIEInfo
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
const dw_tag_t die_tag = die_info_array[i].tag;
|
||||
if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
|
||||
{
|
||||
if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
|
||||
{
|
||||
if (return_implementation_only_if_available)
|
||||
{
|
||||
// We found the one true definition for this class, so
|
||||
// only return that
|
||||
die_offsets.clear();
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Put the one true definition as the first entry so it
|
||||
// matches first
|
||||
die_offsets.insert (die_offsets.begin(), die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dw_offset_t offset; // The DIE offset
|
||||
dw_tag_t tag;
|
||||
uint32_t type_flags; // Any flags for this DIEInfo
|
||||
uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
|
||||
|
||||
static void
|
||||
ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
|
||||
uint32_t type_flag_mask,
|
||||
uint32_t type_flag_value,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
const size_t count = die_info_array.size();
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
|
||||
die_offsets.push_back (die_info_array[i].offset);
|
||||
}
|
||||
}
|
||||
DIEInfo ();
|
||||
DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h);
|
||||
};
|
||||
|
||||
struct Atom
|
||||
{
|
||||
uint16_t type;
|
||||
AtomType type;
|
||||
dw_form_t form;
|
||||
|
||||
Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) :
|
||||
type (t),
|
||||
form (f)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<DIEInfo> DIEInfoArray;
|
||||
typedef std::vector<Atom> AtomArray;
|
||||
|
||||
static const char *
|
||||
GetAtomTypeName (uint16_t atom)
|
||||
{
|
||||
switch (atom)
|
||||
{
|
||||
case eAtomTypeNULL: return "NULL";
|
||||
case eAtomTypeDIEOffset: return "die-offset";
|
||||
case eAtomTypeCUOffset: return "cu-offset";
|
||||
case eAtomTypeTag: return "die-tag";
|
||||
case eAtomTypeNameFlags: return "name-flags";
|
||||
case eAtomTypeTypeFlags: return "type-flags";
|
||||
case eAtomTypeQualNameHash: return "qualified-name-hash";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
struct Prologue
|
||||
class Prologue
|
||||
{
|
||||
public:
|
||||
Prologue (dw_offset_t _die_base_offset = 0);
|
||||
|
||||
void
|
||||
ClearAtoms ();
|
||||
|
||||
bool
|
||||
ContainsAtom (AtomType atom_type) const;
|
||||
|
||||
void
|
||||
Clear ();
|
||||
|
||||
void
|
||||
AppendAtom (AtomType type, dw_form_t form);
|
||||
|
||||
lldb::offset_t
|
||||
Read (const lldb_private::DataExtractor &data, lldb::offset_t offset);
|
||||
|
||||
size_t
|
||||
GetByteSize () const;
|
||||
|
||||
size_t
|
||||
GetMinimumHashDataByteSize () const;
|
||||
|
||||
bool
|
||||
HashDataHasFixedByteSize() const;
|
||||
|
||||
// DIE offset base so die offsets in hash_data can be CU relative
|
||||
dw_offset_t die_base_offset;
|
||||
AtomArray atoms;
|
||||
uint32_t atom_mask;
|
||||
size_t min_hash_data_byte_size;
|
||||
bool hash_data_has_fixed_byte_size;
|
||||
|
||||
Prologue (dw_offset_t _die_base_offset = 0) :
|
||||
die_base_offset (_die_base_offset),
|
||||
atoms(),
|
||||
atom_mask (0),
|
||||
min_hash_data_byte_size(0),
|
||||
hash_data_has_fixed_byte_size(true)
|
||||
{
|
||||
// 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
|
||||
AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
|
||||
}
|
||||
|
||||
virtual ~Prologue()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ClearAtoms ()
|
||||
{
|
||||
hash_data_has_fixed_byte_size = true;
|
||||
min_hash_data_byte_size = 0;
|
||||
atom_mask = 0;
|
||||
atoms.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
ContainsAtom (AtomType atom_type) const
|
||||
{
|
||||
return (atom_mask & (1u << atom_type)) != 0;
|
||||
}
|
||||
|
||||
virtual void
|
||||
Clear ()
|
||||
{
|
||||
die_base_offset = 0;
|
||||
ClearAtoms ();
|
||||
}
|
||||
|
||||
void
|
||||
AppendAtom (AtomType type, dw_form_t form)
|
||||
{
|
||||
atoms.push_back (Atom(type, form));
|
||||
atom_mask |= 1u << type;
|
||||
switch (form)
|
||||
{
|
||||
case DW_FORM_indirect:
|
||||
case DW_FORM_exprloc:
|
||||
case DW_FORM_flag_present:
|
||||
case DW_FORM_ref_sig8:
|
||||
assert (!"Unhandled atom form");
|
||||
break;
|
||||
|
||||
case DW_FORM_string:
|
||||
case DW_FORM_block:
|
||||
case DW_FORM_block1:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_ref_udata:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
case DW_FORM_GNU_str_index:
|
||||
hash_data_has_fixed_byte_size = false;
|
||||
// Fall through to the cases below...
|
||||
case DW_FORM_flag:
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_ref1:
|
||||
case DW_FORM_sec_offset:
|
||||
min_hash_data_byte_size += 1;
|
||||
break;
|
||||
|
||||
case DW_FORM_block2:
|
||||
hash_data_has_fixed_byte_size = false;
|
||||
// Fall through to the cases below...
|
||||
case DW_FORM_data2:
|
||||
case DW_FORM_ref2:
|
||||
min_hash_data_byte_size += 2;
|
||||
break;
|
||||
|
||||
case DW_FORM_block4:
|
||||
hash_data_has_fixed_byte_size = false;
|
||||
// Fall through to the cases below...
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_ref4:
|
||||
case DW_FORM_addr:
|
||||
case DW_FORM_ref_addr:
|
||||
case DW_FORM_strp:
|
||||
min_hash_data_byte_size += 4;
|
||||
break;
|
||||
|
||||
case DW_FORM_data8:
|
||||
case DW_FORM_ref8:
|
||||
min_hash_data_byte_size += 8;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// void
|
||||
// Dump (std::ostream* ostrm_ptr);
|
||||
|
||||
lldb::offset_t
|
||||
Read (const lldb_private::DataExtractor &data,
|
||||
lldb::offset_t offset)
|
||||
{
|
||||
ClearAtoms ();
|
||||
|
||||
die_base_offset = data.GetU32 (&offset);
|
||||
|
||||
const uint32_t atom_count = data.GetU32 (&offset);
|
||||
if (atom_count == 0x00060003u)
|
||||
{
|
||||
// Old format, deal with contents of old pre-release format
|
||||
while (data.GetU32(&offset))
|
||||
/* do nothing */;
|
||||
|
||||
// Hardcode to the only known value for now.
|
||||
AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i=0; i<atom_count; ++i)
|
||||
{
|
||||
AtomType type = (AtomType)data.GetU16 (&offset);
|
||||
dw_form_t form = (dw_form_t)data.GetU16 (&offset);
|
||||
AppendAtom (type, form);
|
||||
}
|
||||
}
|
||||
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) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
|
||||
}
|
||||
|
||||
size_t
|
||||
GetMinimumHashDataByteSize () const
|
||||
{
|
||||
return min_hash_data_byte_size;
|
||||
}
|
||||
|
||||
bool
|
||||
HashDataHasFixedByteSize() const
|
||||
{
|
||||
return hash_data_has_fixed_byte_size;
|
||||
}
|
||||
};
|
||||
|
||||
struct Header : public MappedHash::Header<Prologue>
|
||||
class Header : public MappedHash::Header<Prologue>
|
||||
{
|
||||
Header (dw_offset_t _die_base_offset = 0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~Header()
|
||||
{
|
||||
}
|
||||
public:
|
||||
size_t
|
||||
GetByteSize (const HeaderData &header_data) override;
|
||||
|
||||
virtual size_t
|
||||
GetByteSize (const HeaderData &header_data)
|
||||
{
|
||||
return header_data.GetByteSize();
|
||||
}
|
||||
lldb::offset_t
|
||||
Read (lldb_private::DataExtractor &data, lldb::offset_t offset) override;
|
||||
|
||||
// virtual void
|
||||
// Dump (std::ostream* ostrm_ptr);
|
||||
//
|
||||
virtual lldb::offset_t
|
||||
Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
|
||||
{
|
||||
offset = MappedHash::Header<Prologue>::Read (data, offset);
|
||||
if (offset != UINT32_MAX)
|
||||
{
|
||||
offset = header_data.Read (data, offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool
|
||||
Read (const lldb_private::DWARFDataExtractor &data,
|
||||
lldb::offset_t *offset_ptr,
|
||||
DIEInfo &hash_data) const
|
||||
{
|
||||
const size_t num_atoms = header_data.atoms.size();
|
||||
if (num_atoms == 0)
|
||||
return false;
|
||||
|
||||
for (size_t i=0; i<num_atoms; ++i)
|
||||
{
|
||||
DWARFFormValue form_value (NULL, header_data.atoms[i].form);
|
||||
|
||||
if (!form_value.ExtractValue(data, offset_ptr))
|
||||
return false;
|
||||
|
||||
switch (header_data.atoms[i].type)
|
||||
{
|
||||
case eAtomTypeDIEOffset: // DIE offset, check form for encoding
|
||||
hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
|
||||
break;
|
||||
DIEInfo &hash_data) const;
|
||||
|
||||
case eAtomTypeTag: // DW_TAG value for the DIE
|
||||
hash_data.tag = (dw_tag_t)form_value.Unsigned ();
|
||||
|
||||
case eAtomTypeTypeFlags: // Flags from enum TypeFlags
|
||||
hash_data.type_flags = (uint32_t)form_value.Unsigned ();
|
||||
break;
|
||||
|
||||
case eAtomTypeQualNameHash: // Flags from enum TypeFlags
|
||||
hash_data.qualified_name_hash = form_value.Unsigned ();
|
||||
break;
|
||||
|
||||
default:
|
||||
// We can always skip atoms we don't know about
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
|
||||
{
|
||||
const size_t num_atoms = header_data.atoms.size();
|
||||
for (size_t i=0; i<num_atoms; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
strm.PutCString (", ");
|
||||
|
||||
DWARFFormValue form_value (NULL, header_data.atoms[i].form);
|
||||
switch (header_data.atoms[i].type)
|
||||
{
|
||||
case eAtomTypeDIEOffset: // DIE offset, check form for encoding
|
||||
strm.Printf ("{0x%8.8x}", hash_data.offset);
|
||||
break;
|
||||
|
||||
case eAtomTypeTag: // DW_TAG value for the DIE
|
||||
{
|
||||
const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
|
||||
if (tag_cstr)
|
||||
strm.PutCString (tag_cstr);
|
||||
else
|
||||
strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
|
||||
}
|
||||
break;
|
||||
|
||||
case eAtomTypeTypeFlags: // Flags from enum TypeFlags
|
||||
strm.Printf ("0x%2.2x", hash_data.type_flags);
|
||||
if (hash_data.type_flags)
|
||||
{
|
||||
strm.PutCString (" (");
|
||||
if (hash_data.type_flags & eTypeFlagClassIsImplementation)
|
||||
strm.PutCString (" implementation");
|
||||
strm.PutCString (" )");
|
||||
}
|
||||
break;
|
||||
|
||||
case eAtomTypeQualNameHash: // Flags from enum TypeFlags
|
||||
strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
|
||||
break;
|
||||
|
||||
default:
|
||||
strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const;
|
||||
};
|
||||
|
||||
|
||||
// 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, DIEInfoArray>
|
||||
{
|
||||
public:
|
||||
|
||||
MemoryTable (lldb_private::DWARFDataExtractor &table_data,
|
||||
const lldb_private::DWARFDataExtractor &string_table,
|
||||
const char *name) :
|
||||
MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
|
||||
m_data (table_data),
|
||||
m_string_table (string_table),
|
||||
m_name (name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~MemoryTable ()
|
||||
{
|
||||
}
|
||||
const char *name);
|
||||
|
||||
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);
|
||||
}
|
||||
const char *
|
||||
GetStringForKeyType (KeyType key) const override;
|
||||
|
||||
virtual bool
|
||||
ReadHashData (uint32_t hash_data_offset,
|
||||
HashData &hash_data) const
|
||||
{
|
||||
lldb::offset_t offset = hash_data_offset;
|
||||
offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
|
||||
const uint32_t count = m_data.GetU32 (&offset);
|
||||
if (count > 0)
|
||||
{
|
||||
hash_data.resize(count);
|
||||
for (uint32_t i=0; i<count; ++i)
|
||||
{
|
||||
if (!m_header.Read(m_data, &offset, hash_data[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
hash_data.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual Result
|
||||
GetHashDataForName (const char *name,
|
||||
lldb::offset_t* hash_data_offset_ptr,
|
||||
Pair &pair) const
|
||||
{
|
||||
pair.key = m_data.GetU32 (hash_data_offset_ptr);
|
||||
pair.value.clear();
|
||||
|
||||
// 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)
|
||||
{
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
|
||||
const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
|
||||
const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
|
||||
if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
|
||||
{
|
||||
// We have at least one HashData entry, and we have enough
|
||||
// data to parse at least "count" HashData entries.
|
||||
|
||||
// First make sure the entire C string matches...
|
||||
const bool match = strcmp (name, strp_cstr) == 0;
|
||||
|
||||
if (!match && m_header.header_data.HashDataHasFixedByteSize())
|
||||
{
|
||||
// If the string doesn't match and we have fixed size data,
|
||||
// we can just add the total byte size of all HashData objects
|
||||
// to the hash data offset and be done...
|
||||
*hash_data_offset_ptr += min_total_hash_data_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the string does match, or we don't have fixed size data
|
||||
// then we need to read the hash data as a stream. If the
|
||||
// string matches we also append all HashData objects to the
|
||||
// value array.
|
||||
for (uint32_t i=0; i<count; ++i)
|
||||
{
|
||||
DIEInfo die_info;
|
||||
if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
|
||||
{
|
||||
// Only happened if the HashData of the string matched...
|
||||
if (match)
|
||||
pair.value.push_back (die_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something went wrong while reading the data
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the correct response depending on if the string matched
|
||||
// or not...
|
||||
if (match)
|
||||
return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
|
||||
else
|
||||
return eResultKeyMismatch; // The key doesn't match, this function will get called
|
||||
// again for the next key/value or the key terminator
|
||||
// which in our case is a zero .debug_str offset.
|
||||
}
|
||||
else
|
||||
{
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Result
|
||||
AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
|
||||
lldb::offset_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 size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
|
||||
if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
|
||||
{
|
||||
const bool match = regex.Execute(strp_cstr);
|
||||
|
||||
if (!match && m_header.header_data.HashDataHasFixedByteSize())
|
||||
{
|
||||
// If the regex doesn't match and we have fixed size data,
|
||||
// we can just add the total byte size of all HashData objects
|
||||
// to the hash data offset and be done...
|
||||
*hash_data_offset_ptr += min_total_hash_data_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the string does match, or we don't have fixed size data
|
||||
// then we need to read the hash data as a stream. If the
|
||||
// string matches we also append all HashData objects to the
|
||||
// value array.
|
||||
for (uint32_t i=0; i<count; ++i)
|
||||
{
|
||||
DIEInfo die_info;
|
||||
if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
|
||||
{
|
||||
// Only happened if the HashData of the string matched...
|
||||
if (match)
|
||||
pair.value.push_back (die_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something went wrong while reading the data
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the correct response depending on if the string matched
|
||||
// or not...
|
||||
if (match)
|
||||
return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
|
||||
else
|
||||
return eResultKeyMismatch; // The key doesn't match, this function will get called
|
||||
// again for the next key/value or the key terminator
|
||||
// which in our case is a zero .debug_str offset.
|
||||
}
|
||||
else
|
||||
{
|
||||
*hash_data_offset_ptr = UINT32_MAX;
|
||||
return eResultError;
|
||||
}
|
||||
}
|
||||
bool
|
||||
ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const override;
|
||||
|
||||
size_t
|
||||
AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,
|
||||
DIEInfoArray &die_info_array) const
|
||||
{
|
||||
const uint32_t hash_count = m_header.hashes_count;
|
||||
Pair pair;
|
||||
for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
|
||||
{
|
||||
lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
|
||||
while (hash_data_offset != UINT32_MAX)
|
||||
{
|
||||
const lldb::offset_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;
|
||||
DIEInfoArray &die_info_array) const;
|
||||
|
||||
// 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_info_array.swap (pair.value);
|
||||
return die_info_array.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
AppendAllDIEsInRange (const uint32_t die_offset_start,
|
||||
const uint32_t die_offset_end,
|
||||
DIEInfoArray &die_info_array) 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;
|
||||
lldb::offset_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)
|
||||
{
|
||||
DIEInfo die_info;
|
||||
if (m_header.Read(m_data, &hash_data_offset, die_info))
|
||||
{
|
||||
if (die_info.offset == 0)
|
||||
done = true;
|
||||
if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
|
||||
die_info_array.push_back(die_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return die_info_array.size();
|
||||
}
|
||||
DIEInfoArray &die_info_array) const;
|
||||
|
||||
size_t
|
||||
FindByName (const char *name, DIEArray &die_offsets)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
|
||||
return die_info_array.size();
|
||||
}
|
||||
FindByName (const char *name, DIEArray &die_offsets);
|
||||
|
||||
size_t
|
||||
FindByNameAndTag (const char *name,
|
||||
const dw_tag_t tag,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
|
||||
return die_info_array.size();
|
||||
}
|
||||
FindByNameAndTag (const char *name, const dw_tag_t tag, DIEArray &die_offsets);
|
||||
|
||||
size_t
|
||||
FindByNameAndTagAndQualifiedNameHash (const char *name,
|
||||
const dw_tag_t tag,
|
||||
const uint32_t qualified_name_hash,
|
||||
DIEArray &die_offsets)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
|
||||
return die_info_array.size();
|
||||
}
|
||||
DIEArray &die_offsets);
|
||||
|
||||
size_t
|
||||
FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation)
|
||||
{
|
||||
DIEInfoArray die_info_array;
|
||||
if (FindByName(name, die_info_array))
|
||||
{
|
||||
if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
|
||||
{
|
||||
// If we have two atoms, then we have the DIE offset and
|
||||
// the type flags so we can find the objective C class
|
||||
// efficiently.
|
||||
DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
|
||||
UINT32_MAX,
|
||||
eTypeFlagClassIsImplementation,
|
||||
die_offsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't only want the one true definition, so try and see
|
||||
// what we can find, and only return class or struct DIEs.
|
||||
// If we do have the full implementation, then return it alone,
|
||||
// else return all possible matches.
|
||||
const bool return_implementation_only_if_available = true;
|
||||
DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
|
||||
return_implementation_only_if_available,
|
||||
die_offsets);
|
||||
}
|
||||
}
|
||||
return die_offsets.size();
|
||||
}
|
||||
FindCompleteObjCClassByName (const char *name,
|
||||
DIEArray &die_offsets,
|
||||
bool must_be_implementation);
|
||||
|
||||
protected:
|
||||
Result
|
||||
AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
|
||||
lldb::offset_t* hash_data_offset_ptr,
|
||||
Pair &pair) const;
|
||||
|
||||
size_t
|
||||
FindByName (const char *name, DIEInfoArray &die_info_array)
|
||||
{
|
||||
Pair kv_pair;
|
||||
size_t old_size = die_info_array.size();
|
||||
if (Find (name, kv_pair))
|
||||
{
|
||||
die_info_array.swap(kv_pair.value);
|
||||
return die_info_array.size() - old_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
FindByName (const char *name, DIEInfoArray &die_info_array);
|
||||
|
||||
Result
|
||||
GetHashDataForName (const char *name,
|
||||
lldb::offset_t* hash_data_offset_ptr,
|
||||
Pair &pair) const;
|
||||
|
||||
const lldb_private::DWARFDataExtractor &m_data;
|
||||
const lldb_private::DWARFDataExtractor &m_string_table;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
static void
|
||||
ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets);
|
||||
|
||||
protected:
|
||||
static void
|
||||
ExtractDIEArray (const DIEInfoArray &die_info_array,
|
||||
const dw_tag_t tag,
|
||||
DIEArray &die_offsets);
|
||||
|
||||
static void
|
||||
ExtractDIEArray (const DIEInfoArray &die_info_array,
|
||||
const dw_tag_t tag,
|
||||
const uint32_t qualified_name_hash,
|
||||
DIEArray &die_offsets);
|
||||
|
||||
|
||||
|
||||
static void
|
||||
ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
|
||||
bool return_implementation_only_if_available,
|
||||
DIEArray &die_offsets);
|
||||
|
||||
static void
|
||||
ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
|
||||
uint32_t type_flag_mask,
|
||||
uint32_t type_flag_value,
|
||||
DIEArray &die_offsets);
|
||||
|
||||
static const char *
|
||||
GetAtomTypeName (uint16_t atom);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1526,13 +1526,9 @@ SymbolFileDWARF::CompleteType (CompilerType &clang_type)
|
|||
dwarf_die.GetTagAsCString(),
|
||||
type->GetName().AsCString());
|
||||
assert (clang_type);
|
||||
DWARFAttributes attributes;
|
||||
|
||||
|
||||
DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser();
|
||||
if (dwarf_ast)
|
||||
return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, clang_type);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue