diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h --- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h @@ -10,7 +10,6 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_APPLEDWARFINDEX_H #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" -#include "Plugins/SymbolFile/DWARF/HashedNameToDIE.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" namespace lldb_private { @@ -25,7 +24,7 @@ std::unique_ptr apple_names, std::unique_ptr apple_namespaces, std::unique_ptr apple_types, - std::unique_ptr apple_objc) + std::unique_ptr apple_objc) : DWARFIndex(module), m_apple_names_up(std::move(apple_names)), m_apple_namespaces_up(std::move(apple_namespaces)), m_apple_types_up(std::move(apple_types)), @@ -66,7 +65,7 @@ std::unique_ptr m_apple_names_up; std::unique_ptr m_apple_namespaces_up; std::unique_ptr m_apple_types_up; - std::unique_ptr m_apple_objc_up; + std::unique_ptr m_apple_objc_up; /// Search for entries whose name is `name` in `table`, calling `callback` for /// each match. If `search_for_tag` is provided, ignore entries whose tag is diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/Function.h" +#include "llvm/Support/DJB.h" using namespace lldb_private; using namespace lldb; @@ -42,10 +43,8 @@ auto apple_types_table_up = std::make_unique( apple_types.GetAsLLVM(), llvm_debug_str); - auto apple_objc_table_up = std::make_unique( - apple_objc, debug_str, ".apple_objc"); - if (!apple_objc_table_up->IsValid()) - apple_objc_table_up.reset(); + auto apple_objc_table_up = std::make_unique( + apple_objc.GetAsLLVM(), llvm_debug_str); auto extract_and_check = [&](auto &TablePtr) { if (auto E = TablePtr->extract()) { @@ -57,6 +56,7 @@ extract_and_check(apple_names_table_up); extract_and_check(apple_namespaces_table_up); extract_and_check(apple_types_table_up); + extract_and_check(apple_objc_table_up); if (apple_names_table_up || apple_namespaces_table_up || apple_types_table_up || apple_objc_table_up) @@ -179,9 +179,7 @@ ConstString class_name, llvm::function_ref callback) { if (!m_apple_objc_up) return; - m_apple_objc_up->FindByName( - class_name.GetStringRef(), - DIERefCallback(callback, class_name.GetStringRef())); + SearchFor(*m_apple_objc_up, class_name, callback); } void AppleDWARFIndex::GetCompleteObjCClass( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt --- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -31,7 +31,6 @@ DWARFIndex.cpp DWARFTypeUnit.cpp DWARFUnit.cpp - HashedNameToDIE.cpp LogChannelDWARF.cpp ManualDWARFIndex.cpp NameToDIE.cpp diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h deleted file mode 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ /dev/null @@ -1,157 +0,0 @@ -//===-- HashedNameToDIE.h ---------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_HASHEDNAMETODIE_H -#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_HASHEDNAMETODIE_H - -#include - -#include "lldb/Core/MappedHash.h" -#include "lldb/Core/dwarf.h" -#include "lldb/Utility/RegularExpression.h" -#include "lldb/lldb-defines.h" - -#include "DWARFDefines.h" -#include "DWARFFormValue.h" -#include "NameToDIE.h" - -class DWARFMappedHash { -public: - enum AtomType : uint16_t { - eAtomTypeNULL = 0u, - /// DIE offset, check form for encoding. - eAtomTypeDIEOffset = 1u, - /// DIE offset of the compiler unit header that contains the item in - /// question. - eAtomTypeCUOffset = 2u, - /// DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed - /// 255) or DW_FORM_data2. - eAtomTypeTag = 3u, - // Flags from enum NameFlags. - eAtomTypeNameFlags = 4u, - // Flags from enum TypeFlags. - eAtomTypeTypeFlags = 5u, - /// A 32 bit hash of the full qualified name (since all hash entries are - /// basename only) For example a type like "std::vector::iterator" - /// would have a name of "iterator" and a 32 bit hash for - /// "std::vector::iterator" to allow us to not have to pull in debug - /// info for a type when we know the fully qualified name. - eAtomTypeQualNameHash = 6u - }; - - /// Bit definitions for the eAtomTypeTypeFlags flags. - enum TypeFlags { - /// Always set for C++, only set for ObjC if this is the - /// @implementation for class. - eTypeFlagClassIsImplementation = (1u << 1) - }; - - struct DIEInfo { - dw_offset_t die_offset = DW_INVALID_OFFSET; - dw_tag_t tag = llvm::dwarf::DW_TAG_null; - - /// Any flags for this DIEInfo. - uint32_t type_flags = 0; - - /// A 32 bit hash of the fully qualified name. - uint32_t qualified_name_hash = 0; - - DIEInfo() = default; - DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h); - - explicit operator DIERef() const { - return DIERef(std::nullopt, DIERef::Section::DebugInfo, die_offset); - } - }; - - struct Atom { - AtomType type; - dw_form_t form; - }; - - typedef std::vector DIEInfoArray; - typedef std::vector AtomArray; - - 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 = 0; - size_t min_hash_data_byte_size = 0; - bool hash_data_has_fixed_byte_size = true; - }; - - class Header : public MappedHash::Header { - public: - size_t GetByteSize(const HeaderData &header_data) override; - - lldb::offset_t Read(lldb_private::DataExtractor &data, - lldb::offset_t offset) override; - - bool Read(const lldb_private::DWARFDataExtractor &data, - lldb::offset_t *offset_ptr, 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 { - public: - MemoryTable(lldb_private::DWARFDataExtractor &table_data, - const lldb_private::DWARFDataExtractor &string_table, - const char *name); - - const char *GetStringForKeyType(KeyType key) const override; - - bool ReadHashData(uint32_t hash_data_offset, - HashData &hash_data) const override; - - bool FindByName(llvm::StringRef name, - llvm::function_ref callback); - - protected: - void FindByName(llvm::StringRef name, DIEInfoArray &die_info_array); - - Result GetHashDataForName(llvm::StringRef name, - lldb::offset_t *hash_data_offset_ptr, - Pair &pair) const override; - - lldb_private::DWARFDataExtractor m_data; - lldb_private::DWARFDataExtractor m_string_table; - std::string m_name; - }; - - static bool ExtractDIEArray(const DIEInfoArray &die_info_array, - llvm::function_ref callback); - -protected: - static const char *GetAtomTypeName(uint16_t atom); -}; - -#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_HASHEDNAMETODIE_H diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp deleted file mode 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ /dev/null @@ -1,339 +0,0 @@ -//===-- HashedNameToDIE.cpp -----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "HashedNameToDIE.h" -#include "llvm/ADT/StringRef.h" - -#include "lldb/Core/Mangled.h" - -using namespace lldb_private::dwarf; - -bool DWARFMappedHash::ExtractDIEArray( - const DIEInfoArray &die_info_array, - llvm::function_ref callback) { - const size_t count = die_info_array.size(); - for (size_t i = 0; i < count; ++i) - if (!callback(DIERef(die_info_array[i]))) - return false; - return true; -} - -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 ""; -} - -DWARFMappedHash::DIEInfo::DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f, - uint32_t h) - : die_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() { - // 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) { - default: - case DW_FORM_indirect: - case DW_FORM_exprloc: - case DW_FORM_flag_present: - case DW_FORM_ref_sig8: - llvm_unreachable("Unhandled atom form"); - - case DW_FORM_addrx: - 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; - [[fallthrough]]; - 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; - [[fallthrough]]; - 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; - [[fallthrough]]; - 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); - auto form = static_cast(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::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(nullptr, 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.die_offset = - DWARFFormValue::IsDataForm(form_value.Form()) - ? form_value.Unsigned() - : 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(); - break; - - 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 hash_data.die_offset != DW_INVALID_OFFSET; -} - -DWARFMappedHash::MemoryTable::MemoryTable( - lldb_private::DWARFDataExtractor &table_data, - const lldb_private::DWARFDataExtractor &string_table, const char *name) - : MappedHash::MemoryTable(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; - // Skip string table offset that contains offset of hash name in .debug_str. - offset += 4; - 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( - llvm::StringRef 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 == nullptr) { - *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 = name == strp_cstr; - - 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) { - // The key (cstring) matches and we have lookup results! - return eResultKeyMatch; - } else { - // 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. - return eResultKeyMismatch; - } - } else { - *hash_data_offset_ptr = UINT32_MAX; - return eResultError; - } -} - -bool DWARFMappedHash::MemoryTable::FindByName( - llvm::StringRef name, llvm::function_ref callback) { - if (name.empty()) - return true; - - DIEInfoArray die_info_array; - FindByName(name, die_info_array); - return DWARFMappedHash::ExtractDIEArray(die_info_array, callback); -} - -void DWARFMappedHash::MemoryTable::FindByName(llvm::StringRef name, - DIEInfoArray &die_info_array) { - if (name.empty()) - return; - - Pair kv_pair; - if (Find(name, kv_pair)) - die_info_array.swap(kv_pair.value); -}