Enable all the new accelerator tables if they are present and don't manually

index the DWARF. Also fixed an issue with memory accelerator tables with a
size of 1 where we would loop infinitely.

Added support for parsing the new .apple_namespaces section which gives us a
memory hash table for looking up namespaces.

llvm-svn: 141128
This commit is contained in:
Greg Clayton 2011-10-04 22:41:51 +00:00
parent 6c98dfd0f4
commit 7f99513e8f
12 changed files with 843 additions and 346 deletions

View File

@ -477,6 +477,7 @@ namespace lldb {
eSectionTypeDWARFDebugStr,
eSectionTypeDWARFAppleNames,
eSectionTypeDWARFAppleTypes,
eSectionTypeDWARFAppleNamespaces,
eSectionTypeEHFrame,
eSectionTypeOther

View File

@ -80,6 +80,7 @@
26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; };
267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */; };
267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */; };
2682100D143A59AE004BCF2D /* MappedHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2682100C143A59AE004BCF2D /* MappedHash.h */; };
2686536C1370ACB200D186A3 /* OptionGroupBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2686536B1370ACB200D186A3 /* OptionGroupBoolean.cpp */; };
268653701370AE7200D186A3 /* OptionGroupUInt64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2686536F1370AE7200D186A3 /* OptionGroupUInt64.cpp */; };
2689000113353DB600698AC0 /* BreakpointResolverAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D0DD5310FE555900271C65 /* BreakpointResolverAddress.cpp */; };
@ -742,6 +743,7 @@
2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractorGDBRemote.h; path = source/Utility/StringExtractorGDBRemote.h; sourceTree = "<group>"; };
267C0128136880C7006E963E /* OptionGroupValueObjectDisplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupValueObjectDisplay.h; path = include/lldb/Interpreter/OptionGroupValueObjectDisplay.h; sourceTree = "<group>"; };
267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupValueObjectDisplay.cpp; path = source/Interpreter/OptionGroupValueObjectDisplay.cpp; sourceTree = "<group>"; };
2682100C143A59AE004BCF2D /* MappedHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MappedHash.h; path = include/lldb/Core/MappedHash.h; sourceTree = "<group>"; };
2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PseudoTerminal.cpp; path = source/Utility/PseudoTerminal.cpp; sourceTree = "<group>"; };
2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PseudoTerminal.h; path = include/lldb/Utility/PseudoTerminal.h; sourceTree = "<group>"; };
2682F284115EF3A700CCFF99 /* SBError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBError.cpp; path = source/API/SBError.cpp; sourceTree = "<group>"; };
@ -2121,6 +2123,7 @@
26BC7E7F10F1B85900F91463 /* Log.cpp */,
26BC7D6910F1B77400F91463 /* Mangled.h */,
26BC7E8010F1B85900F91463 /* Mangled.cpp */,
2682100C143A59AE004BCF2D /* MappedHash.h */,
26BC7D6A10F1B77400F91463 /* Module.h */,
26BC7E8110F1B85900F91463 /* Module.cpp */,
26BC7D6B10F1B77400F91463 /* ModuleChild.h */,
@ -2885,6 +2888,7 @@
buildActionMask = 2147483647;
files = (
496B015B1406DEB100F830D5 /* IRInterpreter.h in Headers */,
2682100D143A59AE004BCF2D /* MappedHash.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -257,6 +257,7 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr)
case eSectionTypeDWARFDebugStr: return eAddressClassDebug;
case eSectionTypeDWARFAppleNames: return eAddressClassDebug;
case eSectionTypeDWARFAppleTypes: return eAddressClassDebug;
case eSectionTypeDWARFAppleNamespaces: return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeOther: return eAddressClassUnknown;
}
@ -509,6 +510,7 @@ ObjectFileMachO::ParseSections ()
static ConstString g_sect_name_dwarf_debug_str ("__debug_str");
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_dwarf_apple_namespaces ("__apple_namespac");
static ConstString g_sect_name_eh_frame ("__eh_frame");
static ConstString g_sect_name_DATA ("__DATA");
static ConstString g_sect_name_TEXT ("__TEXT");
@ -541,6 +543,8 @@ ObjectFileMachO::ParseSections ()
sect_type = eSectionTypeDWARFAppleNames;
else if (section_name == g_sect_name_dwarf_apple_types)
sect_type = eSectionTypeDWARFAppleTypes;
else if (section_name == g_sect_name_dwarf_apple_namespaces)
sect_type = eSectionTypeDWARFAppleNamespaces;
else if (section_name == g_sect_name_objc_selrefs)
sect_type = eSectionTypeDataCStringPointers;
else if (section_name == g_sect_name_objc_msgrefs)

View File

@ -675,7 +675,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
bool has_address = false;
bool has_location = false;
bool is_global_or_static_variable = false;
dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes);
if (num_attributes > 0)
@ -786,21 +786,20 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (ObjCLanguageRuntime::IsPossibleObjCMethodName(name))
{
ConstString objc_class_name;
ConstString objc_method_name;
ConstString objc_base_name;
ConstString objc_selector_name;
ConstString objc_fullname_no_category_name;
if (ObjCLanguageRuntime::ParseMethodName (name,
&objc_class_name,
&objc_method_name,
&objc_base_name))
&objc_selector_name,
&objc_fullname_no_category_name))
{
objc_class_selectors.Insert(objc_class_name, die.GetOffset());
func_selectors.Insert (objc_method_name, die.GetOffset());
if (!objc_base_name.IsEmpty())
func_selectors.Insert (objc_selector_name, die.GetOffset());
func_fullnames.Insert (ConstString(name), die.GetOffset());
if (objc_fullname_no_category_name)
{
func_basenames.Insert (objc_base_name, die.GetOffset());
func_fullnames.Insert (objc_base_name, die.GetOffset());
func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset());
}
}
}

View File

@ -152,6 +152,7 @@ HashedNameToDIE::MemoryTable::Find (const char *name_cstr, DIEArray &die_ofsets)
const uint32_t name_hash = dl_new_hash (name_cstr);
const uint32_t bucket_count = m_header.bucket_count;
const uint32_t hashes_count = m_header.bucket_count;
// Find the correct bucket for the using the hash value
const uint32_t bucket_idx = name_hash % bucket_count;
@ -172,6 +173,9 @@ HashedNameToDIE::MemoryTable::Find (const char *name_cstr, DIEArray &die_ofsets)
uint32_t hash;
while (((hash = m_data.GetU32 (&hash_offset)) % bucket_count) == bucket_idx)
{
if (hash_idx >= hashes_count)
break;
if (hash == name_hash)
{
// The hash matches, but we still need to verify that the
@ -232,6 +236,7 @@ HashedNameToDIE::MemoryTable::Dump (Stream &s)
uint32_t hash_collisions = 0;
uint32_t hash_idx_offset = GetOffsetOfBucketEntry (0);
const uint32_t bucket_count = m_header.bucket_count;
const uint32_t hashes_count = m_header.hashes_count;
for (uint32_t bucket_idx=0; bucket_idx<bucket_count; ++bucket_idx)
{
uint32_t hash_idx = m_data.GetU32 (&hash_idx_offset);
@ -247,6 +252,9 @@ HashedNameToDIE::MemoryTable::Dump (Stream &s)
uint32_t hash;
while (((hash = m_data.GetU32 (&hash_offset)) % bucket_count) == bucket_idx)
{
if (hash_idx >= hashes_count)
break;
uint32_t hash_data_offset = m_data.GetU32 (&data_offset);
s.Printf(" hash[%u] = 0x%8.8x\n", hash_idx, hash);

View File

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

View File

@ -173,11 +173,13 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
m_data_debug_str (),
m_data_apple_names (),
m_data_apple_types (),
m_data_apple_namespaces (),
m_abbr(),
m_info(),
m_line(),
m_apple_names (this, m_data_apple_names, true),
m_apple_types (this, m_data_apple_types, true),
m_apple_names_ap (),
m_apple_types_ap (),
m_apple_namespaces_ap (),
m_function_basename_index(),
m_function_fullname_index(),
m_function_method_index(),
@ -252,9 +254,27 @@ SymbolFileDWARF::InitializeObject()
section->MemoryMapSectionDataFromObjectFile(m_obj_file, m_dwarf_data);
}
get_apple_names_data();
if (m_data_apple_names.GetByteSize() > 0)
{
m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names, get_debug_str_data(), true));
if (!m_apple_names_ap->IsValid())
m_apple_names_ap.reset();
}
get_apple_types_data();
m_apple_names.Initialize();
m_apple_types.Initialize();
if (m_data_apple_types.GetByteSize() > 0)
{
m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types, get_debug_str_data(), false));
if (!m_apple_types_ap->IsValid())
m_apple_types_ap.reset();
}
get_apple_namespaces_data();
if (m_data_apple_namespaces.GetByteSize() > 0)
{
m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces, get_debug_str_data(), false));
if (!m_apple_namespaces_ap->IsValid())
m_apple_namespaces_ap.reset();
}
}
@ -470,6 +490,12 @@ SymbolFileDWARF::get_apple_types_data()
return GetCachedSectionData (flagsGotDebugTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
}
const DataExtractor&
SymbolFileDWARF::get_apple_namespaces_data()
{
return GetCachedSectionData (flagsGotDebugTypesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
}
DWARFDebugAbbrev*
SymbolFileDWARF::DebugAbbrev()
@ -1937,21 +1963,36 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, bool append, uint
// we are appending the results to a variable list.
const uint32_t original_size = variables.GetSize();
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
assert (sc.module_sp);
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
const size_t num_matches = m_global_index.Find (name, die_offsets);
if (m_apple_names_ap.get())
{
const char *name_cstr = name.GetCString();
DWARFMappedHash::MemoryTable::Pair kv_pair;
if (m_apple_names_ap->Find (name_cstr, kv_pair))
{
die_offsets.swap(kv_pair.value);
}
}
else
{
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
m_global_index.Find (name, die_offsets);
}
const size_t num_matches = die_offsets.size();
if (num_matches)
{
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
assert (sc.module_sp);
DWARFDebugInfo* debug_info = DebugInfo();
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
for (size_t i=0; i<num_matches; ++i)
{
const dw_offset_t die_offset = die_offsets[i];
@ -1986,9 +2027,20 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
// we are appending the results to a variable list.
const uint32_t original_size = variables.GetSize();
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
DIEArray die_offsets;
if (m_apple_names_ap.get())
{
m_apple_names_ap->AppendAllDIEsThatMatchingRegex (regex, die_offsets);
}
else
{
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
m_global_index.Find (regex, die_offsets);
}
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
@ -1996,8 +2048,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
const size_t num_matches = m_global_index.Find (regex, die_offsets);
const size_t num_matches = die_offsets.size();
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
@ -2006,7 +2057,6 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
const dw_offset_t die_offset = die_offsets[i];
die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
assert(sc.comp_unit != NULL);
ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables);
@ -2066,67 +2116,99 @@ SymbolFileDWARF::ResolveFunctions (const DIEArray &die_offsets,
break;
}
}
assert (die->Tag() == DW_TAG_subprogram);
if (GetFunction (dwarf_cu, die, sc))
if (die->Tag() == DW_TAG_subprogram)
{
Address addr;
// Parse all blocks if needed
if (inlined_die)
if (GetFunction (dwarf_cu, die, sc))
{
sc.block = sc.function->GetBlock (true).FindBlockByID (inlined_die->GetOffset());
assert (sc.block != NULL);
if (sc.block->GetStartAddress (addr) == false)
addr.Clear();
}
else
{
sc.block = NULL;
addr = sc.function->GetAddressRange().GetBaseAddress();
}
if (addr.IsValid())
{
// We found the function, so we should find the line table
// and line table entry as well
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table == NULL)
Address addr;
// Parse all blocks if needed
if (inlined_die)
{
if (ParseCompileUnitLineTable(sc))
line_table = sc.comp_unit->GetLineTable();
sc.block = sc.function->GetBlock (true).FindBlockByID (inlined_die->GetOffset());
assert (sc.block != NULL);
if (sc.block->GetStartAddress (addr) == false)
addr.Clear();
}
else
{
sc.block = NULL;
addr = sc.function->GetAddressRange().GetBaseAddress();
}
if (line_table != NULL)
line_table->FindLineEntryByAddress (addr, sc.line_entry);
sc_list.Append(sc);
if (addr.IsValid())
{
// We found the function, so we should find the line table
// and line table entry as well
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table == NULL)
{
if (ParseCompileUnitLineTable(sc))
line_table = sc.comp_unit->GetLineTable();
}
if (line_table != NULL)
line_table->FindLineEntryByAddress (addr, sc.line_entry);
sc_list.Append(sc);
}
}
}
}
return sc_list.GetSize() - sc_list_initial_size;
}
void
SymbolFileDWARF::FindFunctions
(
const ConstString &name,
const NameToDIE &name_to_die,
SymbolContextList& sc_list
)
{
DWARFDebugInfo* info = DebugInfo();
if (info == NULL)
return;
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
assert (sc.module_sp);
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
void
SymbolFileDWARF::FindFunctions (const ConstString &name,
const NameToDIE &name_to_die,
SymbolContextList& sc_list)
{
DIEArray die_offsets;
const size_t num_matches = name_to_die.Find (name, die_offsets);
if (name_to_die.Find (name, die_offsets))
{
ParseFunctions (die_offsets, sc_list);
}
}
void
SymbolFileDWARF::FindFunctions (const RegularExpression &regex,
const NameToDIE &name_to_die,
SymbolContextList& sc_list)
{
DIEArray die_offsets;
if (name_to_die.Find (regex, die_offsets))
{
ParseFunctions (die_offsets, sc_list);
}
}
void
SymbolFileDWARF::FindFunctions (const RegularExpression &regex,
const DWARFMappedHash::MemoryTable &memory_table,
SymbolContextList& sc_list)
{
DIEArray die_offsets;
if (memory_table.AppendAllDIEsThatMatchingRegex (regex, die_offsets))
{
ParseFunctions (die_offsets, sc_list);
}
}
void
SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets,
SymbolContextList& sc_list)
{
const size_t num_matches = die_offsets.size();
if (num_matches)
{
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
@ -2160,10 +2242,10 @@ SymbolFileDWARF::FindFunctions
sc.block = NULL;
addr = sc.function->GetAddressRange().GetBaseAddress();
}
if (addr.IsValid())
{
// We found the function, so we should find the line table
// and line table entry as well
LineTable *line_table = sc.comp_unit->GetLineTable();
@ -2174,7 +2256,7 @@ SymbolFileDWARF::FindFunctions
}
if (line_table != NULL)
line_table->FindLineEntryByAddress (addr, sc.line_entry);
sc_list.Append(sc);
}
}
@ -2183,84 +2265,6 @@ SymbolFileDWARF::FindFunctions
}
void
SymbolFileDWARF::FindFunctions
(
const RegularExpression &regex,
const NameToDIE &name_to_die,
SymbolContextList& sc_list
)
{
DWARFDebugInfo* info = DebugInfo();
if (info == NULL)
return;
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
assert (sc.module_sp);
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
const size_t num_matches = name_to_die.Find (regex, die_offsets);
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
const dw_offset_t die_offset = die_offsets[i];
die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
const DWARFDebugInfoEntry* inlined_die = NULL;
if (die->Tag() == DW_TAG_inlined_subroutine)
{
inlined_die = die;
while ((die = die->GetParent()) != NULL)
{
if (die->Tag() == DW_TAG_subprogram)
break;
}
}
assert (die->Tag() == DW_TAG_subprogram);
if (GetFunction (dwarf_cu, die, sc))
{
Address addr;
// Parse all blocks if needed
if (inlined_die)
{
sc.block = sc.function->GetBlock (true).FindBlockByID (inlined_die->GetOffset());
assert (sc.block != NULL);
if (sc.block->GetStartAddress (addr) == false)
addr.Clear();
}
else
{
sc.block = NULL;
addr = sc.function->GetAddressRange().GetBaseAddress();
}
if (addr.IsValid())
{
// We found the function, so we should find the line table
// and line table entry as well
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table == NULL)
{
if (ParseCompileUnitLineTable(sc))
line_table = sc.comp_unit->GetLineTable();
}
if (line_table != NULL)
line_table->FindLineEntryByAddress (addr, sc.line_entry);
sc_list.Append(sc);
}
}
}
}
}
uint32_t
SymbolFileDWARF::FindFunctions (const ConstString &name,
uint32_t name_type_mask,
@ -2280,31 +2284,31 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
const uint32_t original_size = sc_list.GetSize();
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
if (name_type_mask & eFunctionNameTypeBase)
FindFunctions (name, m_function_basename_index, sc_list);
if (name_type_mask & eFunctionNameTypeFull)
FindFunctions (name, m_function_fullname_index, sc_list);
if (name_type_mask & eFunctionNameTypeMethod)
FindFunctions (name, m_function_method_index, sc_list);
if (name_type_mask & eFunctionNameTypeSelector)
FindFunctions (name, m_function_selector_index, sc_list);
if (m_apple_names.IsValid())
if (m_apple_names_ap.get())
{
SymbolContextList sc_list_apple;
DIEArray die_offsets;
const uint32_t num_matches = m_apple_names.Find(name.GetCString(), die_offsets);
if (num_matches > 0)
ResolveFunctions (die_offsets, sc_list_apple, name, name_type_mask);
if (sc_list != sc_list_apple)
assert (!"__apple_names results differ from DWARF index results");
const char *name_cstr = name.GetCString();
DWARFMappedHash::MemoryTable::Pair kv_pair;
if (m_apple_names_ap->Find (name_cstr, kv_pair))
ResolveFunctions (kv_pair.value, sc_list, name, name_type_mask);
}
else
{
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
if (name_type_mask & eFunctionNameTypeBase)
FindFunctions (name, m_function_basename_index, sc_list);
if (name_type_mask & eFunctionNameTypeFull)
FindFunctions (name, m_function_fullname_index, sc_list);
if (name_type_mask & eFunctionNameTypeMethod)
FindFunctions (name, m_function_method_index, sc_list);
if (name_type_mask & eFunctionNameTypeSelector)
FindFunctions (name, m_function_selector_index, sc_list);
}
// Return the number of variable that were appended to the list
@ -2328,12 +2332,19 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool append, Symb
uint32_t original_size = sc_list.GetSize();
// Index the DWARF if we haven't already
if (!m_indexed)
Index ();
if (m_apple_names_ap.get())
{
FindFunctions (regex, *m_apple_names_ap, sc_list);
}
else
{
if (!m_indexed)
Index ();
FindFunctions (regex, m_function_basename_index, sc_list);
FindFunctions (regex, m_function_basename_index, sc_list);
FindFunctions (regex, m_function_fullname_index, sc_list);
FindFunctions (regex, m_function_fullname_index, sc_list);
}
// Return the number of variable that were appended to the list
return sc_list.GetSize() - original_size;
@ -2384,18 +2395,33 @@ SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, boo
if (!append)
types.Clear();
// Index if we already haven't to make sure the compile units
// get indexed and make their global DIE index list
if (!m_indexed)
Index ();
const uint32_t initial_types_size = types.GetSize();
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
const size_t num_matches = m_type_index.Find (name, die_offsets);
if (m_apple_types_ap.get())
{
const char *name_cstr = name.GetCString();
DWARFMappedHash::MemoryTable::Pair kv_pair;
if (m_apple_types_ap->Find (name_cstr, kv_pair))
{
die_offsets.swap(kv_pair.value);
}
}
else
{
if (!m_indexed)
Index ();
m_type_index.Find (name, die_offsets);
}
const size_t num_matches = die_offsets.size();
if (num_matches)
{
const uint32_t initial_types_size = types.GetSize();
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
@ -2419,8 +2445,9 @@ SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, boo
}
}
}
return types.GetSize() - initial_types_size;
}
return types.GetSize() - initial_types_size;
return 0;
}
@ -2432,16 +2459,30 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
DWARFDebugInfo* info = DebugInfo();
if (info)
{
DIEArray die_offsets;
// Index if we already haven't to make sure the compile units
// get indexed and make their global DIE index list
if (!m_indexed)
Index ();
if (m_apple_namespaces_ap.get())
{
const char *name_cstr = name.GetCString();
DWARFMappedHash::MemoryTable::Pair kv_pair;
if (m_apple_namespaces_ap->Find (name_cstr, kv_pair))
{
die_offsets.swap(kv_pair.value);
}
}
else
{
if (!m_indexed)
Index ();
m_namespace_index.Find (name, die_offsets);
}
DWARFCompileUnit* dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
const size_t num_matches = m_namespace_index.Find (name, die_offsets);
const size_t num_matches = die_offsets.size();
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
@ -3079,26 +3120,41 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWA
// This function can be used when a DIE is found that is a forward declaration
// DIE and we want to try and find a type that has the complete definition.
TypeSP
SymbolFileDWARF::FindDefinitionTypeForDIE (
DWARFCompileUnit* cu,
const DWARFDebugInfoEntry *die,
const ConstString &type_name
)
SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu,
const DWARFDebugInfoEntry *die,
const ConstString &type_name)
{
TypeSP type_sp;
if (cu == NULL || die == NULL || !type_name)
return type_sp;
if (!m_indexed)
Index ();
DIEArray die_offsets;
if (m_apple_types_ap.get())
{
const char *name_cstr = type_name.GetCString();
DWARFMappedHash::MemoryTable::Pair kv_pair;
if (m_apple_types_ap->Find (name_cstr, kv_pair))
{
die_offsets.swap(kv_pair.value);
}
}
else
{
if (!m_indexed)
Index ();
m_type_index.Find (type_name, die_offsets);
}
const size_t num_matches = die_offsets.size();
const dw_tag_t type_tag = die->Tag();
DWARFCompileUnit* type_cu = NULL;
const DWARFDebugInfoEntry* type_die = NULL;
DIEArray die_offsets;
const size_t num_matches = m_type_index.Find (type_name, die_offsets);
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
@ -4235,17 +4291,29 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
variables.reset(new VariableList());
sc.comp_unit->SetVariableList(variables);
// Index if we already haven't to make sure the compile units
// get indexed and make their global DIE index list
if (!m_indexed)
Index ();
DWARFCompileUnit* match_dwarf_cu = NULL;
const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
const size_t num_matches = m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(),
dwarf_cu->GetNextCompileUnitOffset(),
die_offsets);
if (m_apple_names_ap.get())
{
// TODO: implement finding all items in
m_apple_names_ap->AppendAllDIEsInRange (dwarf_cu->GetOffset(),
dwarf_cu->GetNextCompileUnitOffset(),
die_offsets);
}
else
{
// Index if we already haven't to make sure the compile units
// get indexed and make their global DIE index list
if (!m_indexed)
Index ();
m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(),
dwarf_cu->GetNextCompileUnitOffset(),
die_offsets);
}
const size_t num_matches = die_offsets.size();
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
@ -4284,130 +4352,136 @@ SymbolFileDWARF::ParseVariableDIE
return var_sp; // Already been parsed!
const dw_tag_t tag = die->Tag();
DWARFDebugInfoEntry::Attributes attributes;
const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
if (num_attributes > 0)
if ((tag == DW_TAG_variable) ||
(tag == DW_TAG_constant) ||
(tag == DW_TAG_formal_parameter && sc.function))
{
const char *name = NULL;
const char *mangled = NULL;
Declaration decl;
uint32_t i;
Type *var_type = NULL;
DWARFExpression location;
bool is_external = false;
bool is_artificial = false;
bool location_is_const_value_data = false;
AccessType accessibility = eAccessNone;
for (i=0; i<num_attributes; ++i)
DWARFDebugInfoEntry::Attributes attributes;
const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
if (num_attributes > 0)
{
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
const char *name = NULL;
const char *mangled = NULL;
Declaration decl;
uint32_t i;
Type *var_type = NULL;
DWARFExpression location;
bool is_external = false;
bool is_artificial = false;
bool location_is_const_value_data = false;
AccessType accessibility = eAccessNone;
for (i=0; i<num_attributes; ++i)
{
switch (attr)
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
case DW_AT_type: var_type = ResolveTypeUID(form_value.Reference(dwarf_cu)); break;
case DW_AT_external: is_external = form_value.Unsigned() != 0; break;
case DW_AT_const_value:
location_is_const_value_data = true;
// Fall through...
case DW_AT_location:
switch (attr)
{
if (form_value.BlockData())
case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
case DW_AT_type: var_type = ResolveTypeUID(form_value.Reference(dwarf_cu)); break;
case DW_AT_external: is_external = form_value.Unsigned() != 0; break;
case DW_AT_const_value:
location_is_const_value_data = true;
// Fall through...
case DW_AT_location:
{
const DataExtractor& debug_info_data = get_debug_info_data();
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
location.SetOpcodeData(get_debug_info_data(), block_offset, block_length);
}
else
{
const DataExtractor& debug_loc_data = get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
if (form_value.BlockData())
{
location.SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
assert (func_low_pc != LLDB_INVALID_ADDRESS);
location.SetLocationListSlide (func_low_pc - dwarf_cu->GetBaseAddress());
const DataExtractor& debug_info_data = get_debug_info_data();
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
location.SetOpcodeData(get_debug_info_data(), block_offset, block_length);
}
else
{
const DataExtractor& debug_loc_data = get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
location.SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
assert (func_low_pc != LLDB_INVALID_ADDRESS);
location.SetLocationListSlide (func_low_pc - dwarf_cu->GetBaseAddress());
}
}
}
}
break;
break;
case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break;
case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration:
case DW_AT_description:
case DW_AT_endianity:
case DW_AT_segment:
case DW_AT_start_scope:
case DW_AT_visibility:
default:
case DW_AT_abstract_origin:
case DW_AT_sibling:
case DW_AT_specification:
break;
case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break;
case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration:
case DW_AT_description:
case DW_AT_endianity:
case DW_AT_segment:
case DW_AT_start_scope:
case DW_AT_visibility:
default:
case DW_AT_abstract_origin:
case DW_AT_sibling:
case DW_AT_specification:
break;
}
}
}
}
if (location.IsValid())
{
assert(var_type != DIE_IS_BEING_PARSED);
ValueType scope = eValueTypeInvalid;
const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
if (tag == DW_TAG_formal_parameter)
scope = eValueTypeVariableArgument;
else if (is_external || parent_tag == DW_TAG_compile_unit)
scope = eValueTypeVariableGlobal;
else
scope = eValueTypeVariableLocal;
SymbolContextScope * symbol_context_scope = NULL;
if (parent_tag == DW_TAG_compile_unit)
if (location.IsValid())
{
symbol_context_scope = sc.comp_unit;
}
else if (sc.function != NULL)
{
symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
if (symbol_context_scope == NULL)
symbol_context_scope = sc.function;
}
assert(var_type != DIE_IS_BEING_PARSED);
assert(symbol_context_scope != NULL);
var_sp.reset (new Variable(die->GetOffset(),
name,
mangled,
var_type,
scope,
symbol_context_scope,
&decl,
location,
is_external,
is_artificial));
var_sp->SetLocationIsConstantValueData (location_is_const_value_data);
ValueType scope = eValueTypeInvalid;
const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
if (tag == DW_TAG_formal_parameter)
scope = eValueTypeVariableArgument;
else if (is_external || parent_tag == DW_TAG_compile_unit)
scope = eValueTypeVariableGlobal;
else
scope = eValueTypeVariableLocal;
SymbolContextScope * symbol_context_scope = NULL;
if (parent_tag == DW_TAG_compile_unit)
{
symbol_context_scope = sc.comp_unit;
}
else if (sc.function != NULL)
{
symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
if (symbol_context_scope == NULL)
symbol_context_scope = sc.function;
}
assert(symbol_context_scope != NULL);
var_sp.reset (new Variable(die->GetOffset(),
name,
mangled,
var_type,
scope,
symbol_context_scope,
&decl,
location,
is_external,
is_artificial));
var_sp->SetLocationIsConstantValueData (location_is_const_value_data);
}
}
// Cache var_sp even if NULL (the variable was just a specification or
// was missing vital information to be able to be displayed in the debugger
// (missing location due to optimization, etc)) so we don't re-parse
// this DIE over and over later...
m_die_to_variable_sp[die] = var_sp;
}
// Cache var_sp even if NULL (the variable was just a specification or
// was missing vital information to be able to be displayed in the debugger
// (missing location due to optimization, etc)) so we don't re-parse
// this DIE over and over later...
m_die_to_variable_sp[die] = var_sp;
return var_sp;
}

View File

@ -166,6 +166,8 @@ public:
const lldb_private::DataExtractor& get_debug_str_data ();
const lldb_private::DataExtractor& get_apple_names_data ();
const lldb_private::DataExtractor& get_apple_types_data ();
const lldb_private::DataExtractor& get_apple_namespaces_data ();
DWARFDebugAbbrev* DebugAbbrev();
const DWARFDebugAbbrev* DebugAbbrev() const;
@ -326,11 +328,18 @@ protected:
const NameToDIE &name_to_die,
lldb_private::SymbolContextList& sc_list);
void FindFunctions (
const lldb_private::RegularExpression &regex,
const DWARFMappedHash::MemoryTable &memory_table,
lldb_private::SymbolContextList& sc_list);
lldb::TypeSP FindDefinitionTypeForDIE (
DWARFCompileUnit* cu,
const DWARFDebugInfoEntry *die,
const lldb_private::ConstString &type_name);
void ParseFunctions (const DIEArray &die_offsets,
lldb_private::SymbolContextList& sc_list);
lldb::TypeSP GetTypeForDIE (DWARFCompileUnit *cu,
const DWARFDebugInfoEntry* die);
@ -388,22 +397,24 @@ protected:
lldb_private::DataExtractor m_data_debug_str;
lldb_private::DataExtractor m_data_apple_names;
lldb_private::DataExtractor m_data_apple_types;
lldb_private::DataExtractor m_data_apple_namespaces;
// 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::MemoryTable m_apple_names;
HashedNameToDIE::MemoryTable m_apple_types;
std::auto_ptr<DWARFMappedHash::MemoryTable> m_apple_names_ap;
std::auto_ptr<DWARFMappedHash::MemoryTable> m_apple_types_ap;
std::auto_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
NameToDIE m_function_basename_index; // All concrete functions
NameToDIE m_function_fullname_index; // All concrete functions
NameToDIE m_function_method_index; // All inlined functions
NameToDIE m_function_selector_index; // All method names for functions of classes
NameToDIE m_objc_class_selectors_index; // Given a class name, find all selectors for the class
NameToDIE m_global_index; // Global and static variables
NameToDIE m_type_index; // All type DIE offsets
NameToDIE m_namespace_index; // All type DIE offsets
NameToDIE m_global_index; // Global and static variables
NameToDIE m_type_index; // All type DIE offsets
NameToDIE m_namespace_index; // All type DIE offsets
bool m_indexed:1,
m_is_external_ast_source:1;

View File

@ -223,6 +223,7 @@ ObjectFile::GetAddressClass (addr_t file_addr)
case eSectionTypeDWARFDebugStr: return eAddressClassDebug;
case eSectionTypeDWARFAppleNames: return eAddressClassDebug;
case eSectionTypeDWARFAppleTypes: return eAddressClassDebug;
case eSectionTypeDWARFAppleNamespaces: return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeOther: return eAddressClassUnknown;
}

View File

@ -981,7 +981,8 @@ SymbolContextList::Dump(Stream *s, Target *target) const
collection::const_iterator pos, end = m_symbol_contexts.end();
for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
{
pos->Dump(s, target);
//pos->Dump(s, target);
pos->GetDescription(s, eDescriptionLevelVerbose, target);
}
s->IndentLess();
}

View File

@ -104,12 +104,12 @@ ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const
bool
ObjCLanguageRuntime::ParseMethodName (const char *name,
ConstString *class_name,
ConstString *method_name,
ConstString *base_name)
ConstString *selector_name,
ConstString *name_sans_category)
{
if (class_name) { class_name->Clear(); }
if (method_name) { method_name->Clear(); }
if (base_name) { base_name->Clear(); }
if (selector_name) { selector_name->Clear(); }
if (name_sans_category) { name_sans_category->Clear(); }
if (IsPossibleObjCMethodName (name))
{
@ -122,35 +122,35 @@ ObjCLanguageRuntime::ParseMethodName (const char *name,
// "]" suffix
if (name_len >= 6 && name[name_len - 1] == ']')
{
const char *method_name_ptr;
method_name_ptr = strchr (name, ' ');
if (method_name_ptr)
const char *selector_name_ptr;
selector_name_ptr = strchr (name, ' ');
if (selector_name_ptr)
{
if (class_name)
class_name->SetCStringWithLength (name + 2, method_name_ptr - name - 2);
class_name->SetCStringWithLength (name + 2, selector_name_ptr - name - 2);
// Skip the space
++method_name_ptr;
++selector_name_ptr;
// Extract the objective C basename and add it to the
// accelerator tables
size_t method_name_len = name_len - (method_name_ptr - name) - 1;
if (method_name)
method_name->SetCStringWithLength (method_name_ptr, method_name_len);
size_t selector_name_len = name_len - (selector_name_ptr - name) - 1;
if (selector_name)
selector_name->SetCStringWithLength (selector_name_ptr, selector_name_len);
// Also see if this is a "category" on our class. If so strip off the category name,
// and add the class name without it to the basename table.
if (base_name)
if (name_sans_category)
{
const char *first_paren = (char *) memchr (name, '(', method_name_ptr - name);
const char *first_paren = (char *) memchr (name, '(', selector_name_ptr - name);
if (first_paren)
{
const char *second_paren = (char *) memchr (first_paren, ')', method_name_ptr - first_paren);
const char *second_paren = (char *) memchr (first_paren, ')', selector_name_ptr - first_paren);
if (second_paren)
{
std::string buffer (name, first_paren - name);
buffer.append (second_paren + 1);
base_name->SetCString (buffer.c_str());
name_sans_category->SetCString (buffer.c_str());
}
}

View File

@ -261,6 +261,7 @@ lldb_private::GetSectionTypeAsCString (SectionType sect_type)
case eSectionTypeDWARFDebugStr: return "dwarf-str";
case eSectionTypeDWARFAppleNames: return "apple-names";
case eSectionTypeDWARFAppleTypes: return "apple-types";
case eSectionTypeDWARFAppleNamespaces: return "apple-namespaces";
case eSectionTypeEHFrame: return "eh-frame";
case eSectionTypeOther: return "regular";
}