diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-22 19:14:02 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-22 19:14:02 +0000 |
commit | 580d4aa65a2dadf52a0abc9451ab25918cb25125 (patch) | |
tree | f57af07970c6653570799c317a2ebcf8ea056a10 /contrib/llvm/tools/lldb/source/Plugins/SymbolFile | |
parent | 22d1794578bafc3a0f25691c0531ba10d57713e6 (diff) | |
parent | 5f29bb8a675e8f96452b632e7129113f7dec850e (diff) | |
download | src-580d4aa65a2dadf52a0abc9451ab25918cb25125.tar.gz src-580d4aa65a2dadf52a0abc9451ab25918cb25125.zip |
Merge lldb trunk r366426, resolve conflicts, and update FREEBSD-Xlist.
Notes
Notes:
svn path=/projects/clang900-import/; revision=351400
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/SymbolFile')
107 files changed, 6452 insertions, 8149 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index 2cca7a66b014..d4258274a38c 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -1,84 +1,166 @@ //===-- SymbolFileBreakpad.cpp ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h" +#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h" #include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/PostfixExpression.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" #include "llvm/ADT/StringExtras.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::breakpad; -namespace { -class LineIterator { +class SymbolFileBreakpad::LineIterator { public: // begin iterator for sections of given type - LineIterator(ObjectFile &obj, ConstString section_type) - : m_obj(&obj), m_section_type(section_type), m_next_section_idx(0) { + LineIterator(ObjectFile &obj, Record::Kind section_type) + : m_obj(&obj), m_section_type(toString(section_type)), + m_next_section_idx(0), m_next_line(llvm::StringRef::npos) { ++*this; } + // An iterator starting at the position given by the bookmark. + LineIterator(ObjectFile &obj, Record::Kind section_type, Bookmark bookmark); + // end iterator explicit LineIterator(ObjectFile &obj) : m_obj(&obj), - m_next_section_idx(m_obj->GetSectionList()->GetNumSections(0)) {} + m_next_section_idx(m_obj->GetSectionList()->GetNumSections(0)), + m_current_line(llvm::StringRef::npos), + m_next_line(llvm::StringRef::npos) {} friend bool operator!=(const LineIterator &lhs, const LineIterator &rhs) { assert(lhs.m_obj == rhs.m_obj); if (lhs.m_next_section_idx != rhs.m_next_section_idx) return true; - if (lhs.m_next_text.data() != rhs.m_next_text.data()) + if (lhs.m_current_line != rhs.m_current_line) return true; - assert(lhs.m_current_text == rhs.m_current_text); - assert(rhs.m_next_text == rhs.m_next_text); + assert(lhs.m_next_line == rhs.m_next_line); return false; } const LineIterator &operator++(); - llvm::StringRef operator*() const { return m_current_text; } + llvm::StringRef operator*() const { + return m_section_text.slice(m_current_line, m_next_line); + } + + Bookmark GetBookmark() const { + return Bookmark{m_next_section_idx, m_current_line}; + } private: ObjectFile *m_obj; ConstString m_section_type; uint32_t m_next_section_idx; - llvm::StringRef m_current_text; - llvm::StringRef m_next_text; + llvm::StringRef m_section_text; + size_t m_current_line; + size_t m_next_line; + + void FindNextLine() { + m_next_line = m_section_text.find('\n', m_current_line); + if (m_next_line != llvm::StringRef::npos) { + ++m_next_line; + if (m_next_line >= m_section_text.size()) + m_next_line = llvm::StringRef::npos; + } + } }; -} // namespace -const LineIterator &LineIterator::operator++() { +SymbolFileBreakpad::LineIterator::LineIterator(ObjectFile &obj, + Record::Kind section_type, + Bookmark bookmark) + : m_obj(&obj), m_section_type(toString(section_type)), + m_next_section_idx(bookmark.section), m_current_line(bookmark.offset) { + Section § = + *obj.GetSectionList()->GetSectionAtIndex(m_next_section_idx - 1); + assert(sect.GetName() == m_section_type); + + DataExtractor data; + obj.ReadSectionData(§, data); + m_section_text = toStringRef(data.GetData()); + + assert(m_current_line < m_section_text.size()); + FindNextLine(); +} + +const SymbolFileBreakpad::LineIterator & +SymbolFileBreakpad::LineIterator::operator++() { const SectionList &list = *m_obj->GetSectionList(); size_t num_sections = list.GetNumSections(0); - while (m_next_text.empty() && m_next_section_idx < num_sections) { + while (m_next_line != llvm::StringRef::npos || + m_next_section_idx < num_sections) { + if (m_next_line != llvm::StringRef::npos) { + m_current_line = m_next_line; + FindNextLine(); + return *this; + } + Section § = *list.GetSectionAtIndex(m_next_section_idx++); if (sect.GetName() != m_section_type) continue; DataExtractor data; m_obj->ReadSectionData(§, data); - m_next_text = - llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()), - data.GetByteSize()); + m_section_text = toStringRef(data.GetData()); + m_next_line = 0; } - std::tie(m_current_text, m_next_text) = m_next_text.split('\n'); + // We've reached the end. + m_current_line = m_next_line; return *this; } -static llvm::iterator_range<LineIterator> lines(ObjectFile &obj, - ConstString section_type) { - return llvm::make_range(LineIterator(obj, section_type), LineIterator(obj)); +llvm::iterator_range<SymbolFileBreakpad::LineIterator> +SymbolFileBreakpad::lines(Record::Kind section_type) { + return llvm::make_range(LineIterator(*m_obj_file, section_type), + LineIterator(*m_obj_file)); +} + +namespace { +// A helper class for constructing the list of support files for a given compile +// unit. +class SupportFileMap { +public: + // Given a breakpad file ID, return a file ID to be used in the support files + // for this compile unit. + size_t operator[](size_t file) { + return m_map.try_emplace(file, m_map.size() + 1).first->second; + } + + // Construct a FileSpecList containing only the support files relevant for + // this compile unit (in the correct order). + FileSpecList translate(const FileSpec &cu_spec, + llvm::ArrayRef<FileSpec> all_files); + +private: + llvm::DenseMap<size_t, size_t> m_map; +}; +} // namespace + +FileSpecList SupportFileMap::translate(const FileSpec &cu_spec, + llvm::ArrayRef<FileSpec> all_files) { + std::vector<FileSpec> result; + result.resize(m_map.size() + 1); + result[0] = cu_spec; + for (const auto &KV : m_map) { + if (KV.first < all_files.size()) + result[KV.second] = all_files[KV.first]; + } + return FileSpecList(std::move(result)); } void SymbolFileBreakpad::Initialize() { @@ -102,17 +184,42 @@ uint32_t SymbolFileBreakpad::CalculateAbilities() { if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic()) return 0; - return CompileUnits | Functions; + return CompileUnits | Functions | LineTables; } uint32_t SymbolFileBreakpad::GetNumCompileUnits() { - // TODO - return 0; + ParseCUData(); + return m_cu_data->GetSize(); } CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) { - // TODO - return nullptr; + if (index >= m_cu_data->GetSize()) + return nullptr; + + CompUnitData &data = m_cu_data->GetEntryRef(index).data; + + ParseFileRecords(); + + FileSpec spec; + + // The FileSpec of the compile unit will be the file corresponding to the + // first LINE record. + LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); + assert(Record::classify(*It) == Record::Func); + ++It; // Skip FUNC record. + if (It != End) { + auto record = LineRecord::parse(*It); + if (record && record->FileNum < m_files->size()) + spec = (*m_files)[record->FileNum]; + } + + auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), + /*user_data*/ nullptr, spec, index, + eLanguageTypeUnknown, + /*is_optimized*/ eLazyBoolNo); + + GetSymbolVendor().SetCompileUnitAtIndex(index, cu_sp); + return cu_sp; } size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) { @@ -121,20 +228,67 @@ size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { - // TODO - return 0; + CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data; + + if (!data.line_table_up) + ParseLineTableAndSupportFiles(comp_unit, data); + + comp_unit.SetLineTable(data.line_table_up.release()); + return true; +} + +bool SymbolFileBreakpad::ParseSupportFiles(CompileUnit &comp_unit, + FileSpecList &support_files) { + CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data; + if (!data.support_files) + ParseLineTableAndSupportFiles(comp_unit, data); + + support_files = std::move(*data.support_files); + return true; } uint32_t SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { - // TODO - return 0; + if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry))) + return 0; + + ParseCUData(); + uint32_t idx = + m_cu_data->FindEntryIndexThatContains(so_addr.GetFileAddress()); + if (idx == UINT32_MAX) + return 0; + + sc.comp_unit = GetSymbolVendor().GetCompileUnitAtIndex(idx).get(); + SymbolContextItem result = eSymbolContextCompUnit; + if (resolve_scope & eSymbolContextLineEntry) { + if (sc.comp_unit->GetLineTable()->FindLineEntryByAddress(so_addr, + sc.line_entry)) { + result |= eSymbolContextLineEntry; + } + } + + return result; +} + +uint32_t SymbolFileBreakpad::ResolveSymbolContext( + const FileSpec &file_spec, uint32_t line, bool check_inlines, + lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + if (!(resolve_scope & eSymbolContextCompUnit)) + return 0; + + uint32_t old_size = sc_list.GetSize(); + for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) { + CompileUnit &cu = *GetSymbolVendor().GetCompileUnitAtIndex(i); + cu.ResolveSymbolContext(file_spec, line, check_inlines, + /*exact*/ false, resolve_scope, sc_list); + } + return sc_list.GetSize() - old_size; } uint32_t SymbolFileBreakpad::FindFunctions( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, bool append, SymbolContextList &sc_list) { // TODO @@ -153,7 +307,7 @@ uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, } uint32_t SymbolFileBreakpad::FindTypes( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { if (!append) @@ -172,7 +326,7 @@ SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context, void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); Module &module = *m_obj_file->GetModule(); - addr_t base = module.GetObjectFile()->GetBaseAddress().GetFileAddress(); + addr_t base = GetBaseFileAddress(); if (base == LLDB_INVALID_ADDRESS) { LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping " "symtab population."); @@ -180,44 +334,320 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { } const SectionList &list = *module.GetSectionList(); - for (llvm::StringRef line : lines(*m_obj_file, ConstString("PUBLIC"))) { - // PUBLIC [m] address param_size name - // skip PUBLIC keyword - line = getToken(line).second; - llvm::StringRef token; - std::tie(token, line) = getToken(line); - if (token == "m") - std::tie(token, line) = getToken(line); - - addr_t address; - if (!to_integer(token, address, 16)) - continue; + llvm::DenseMap<addr_t, Symbol> symbols; + auto add_symbol = [&](addr_t address, llvm::Optional<addr_t> size, + llvm::StringRef name) { address += base; - - // skip param_size - line = getToken(line).second; - - llvm::StringRef name = line.trim(); - SectionSP section_sp = list.FindSectionContainingFileAddress(address); if (!section_sp) { LLDB_LOG(log, "Ignoring symbol {0}, whose address ({1}) is outside of the " "object file. Mismatched symbol file?", name, address); + return; + } + symbols.try_emplace( + address, /*symID*/ 0, Mangled(name, /*is_mangled*/ false), + eSymbolTypeCode, /*is_global*/ true, /*is_debug*/ false, + /*is_trampoline*/ false, /*is_artificial*/ false, + AddressRange(section_sp, address - section_sp->GetFileAddress(), + size.getValueOr(0)), + size.hasValue(), /*contains_linker_annotations*/ false, /*flags*/ 0); + }; + + for (llvm::StringRef line : lines(Record::Func)) { + if (auto record = FuncRecord::parse(line)) + add_symbol(record->Address, record->Size, record->Name); + } + + for (llvm::StringRef line : lines(Record::Public)) { + if (auto record = PublicRecord::parse(line)) + add_symbol(record->Address, llvm::None, record->Name); + else + LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", line); + } + + for (auto &KV : symbols) + symtab.AddSymbol(std::move(KV.second)); + symtab.CalculateSymbolSizes(); +} + +static llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> +GetRule(llvm::StringRef &unwind_rules) { + // Unwind rules are of the form + // register1: expression1 register2: expression2 ... + // We assume none of the tokens in expression<n> end with a colon. + + llvm::StringRef lhs, rest; + std::tie(lhs, rest) = getToken(unwind_rules); + if (!lhs.consume_back(":")) + return llvm::None; + + // Seek forward to the next register: expression pair + llvm::StringRef::size_type pos = rest.find(": "); + if (pos == llvm::StringRef::npos) { + // No pair found, this means the rest of the string is a single expression. + unwind_rules = llvm::StringRef(); + return std::make_pair(lhs, rest); + } + + // Go back one token to find the end of the current rule. + pos = rest.rfind(' ', pos); + if (pos == llvm::StringRef::npos) + return llvm::None; + + llvm::StringRef rhs = rest.take_front(pos); + unwind_rules = rest.drop_front(pos); + return std::make_pair(lhs, rhs); +} + +static const RegisterInfo * +ResolveRegister(const SymbolFile::RegisterInfoResolver &resolver, + llvm::StringRef name) { + if (name.consume_front("$")) + return resolver.ResolveName(name); + + return nullptr; +} + +static const RegisterInfo * +ResolveRegisterOrRA(const SymbolFile::RegisterInfoResolver &resolver, + llvm::StringRef name) { + if (name == ".ra") + return resolver.ResolveNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + return ResolveRegister(resolver, name); +} + +bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, + const RegisterInfoResolver &resolver, + UnwindPlan::Row &row) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + + llvm::BumpPtrAllocator node_alloc; + while (auto rule = GetRule(unwind_rules)) { + node_alloc.Reset(); + llvm::StringRef lhs = rule->first; + postfix::Node *rhs = postfix::Parse(rule->second, node_alloc); + if (!rhs) { + LLDB_LOG(log, "Could not parse `{0}` as unwind rhs.", rule->second); + return false; + } + + bool success = postfix::ResolveSymbols( + rhs, [&](postfix::SymbolNode &symbol) -> postfix::Node * { + llvm::StringRef name = symbol.GetName(); + if (name == ".cfa" && lhs != ".cfa") + return postfix::MakeNode<postfix::InitialValueNode>(node_alloc); + + if (const RegisterInfo *info = ResolveRegister(resolver, name)) { + return postfix::MakeNode<postfix::RegisterNode>( + node_alloc, info->kinds[eRegisterKindLLDB]); + } + return nullptr; + }); + + if (!success) { + LLDB_LOG(log, "Resolving symbols in `{0}` failed.", rule->second); + return false; + } + + ArchSpec arch = m_obj_file->GetArchitecture(); + StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(), + arch.GetByteOrder()); + ToDWARF(*rhs, dwarf); + uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize()); + std::memcpy(saved, dwarf.GetData(), dwarf.GetSize()); + + if (lhs == ".cfa") { + row.GetCFAValue().SetIsDWARFExpression(saved, dwarf.GetSize()); + } else if (const RegisterInfo *info = ResolveRegisterOrRA(resolver, lhs)) { + UnwindPlan::Row::RegisterLocation loc; + loc.SetIsDWARFExpression(saved, dwarf.GetSize()); + row.SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc); + } else + LLDB_LOG(log, "Invalid register `{0}` in unwind rule.", lhs); + } + if (unwind_rules.empty()) + return true; + + LLDB_LOG(log, "Could not parse `{0}` as an unwind rule.", unwind_rules); + return false; +} + +UnwindPlanSP +SymbolFileBreakpad::GetUnwindPlan(const Address &address, + const RegisterInfoResolver &resolver) { + ParseUnwindData(); + const UnwindMap::Entry *entry = + m_unwind_data->FindEntryThatContains(address.GetFileAddress()); + if (!entry) + return nullptr; + + addr_t base = GetBaseFileAddress(); + if (base == LLDB_INVALID_ADDRESS) + return nullptr; + + LineIterator It(*m_obj_file, Record::StackCFI, entry->data), End(*m_obj_file); + llvm::Optional<StackCFIRecord> init_record = StackCFIRecord::parse(*It); + assert(init_record.hasValue()); + assert(init_record->Size.hasValue()); + + auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB); + plan_sp->SetSourceName("breakpad STACK CFI"); + plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + plan_sp->SetSourcedFromCompiler(eLazyBoolYes); + plan_sp->SetPlanValidAddressRange( + AddressRange(base + init_record->Address, *init_record->Size, + m_obj_file->GetModule()->GetSectionList())); + + auto row_sp = std::make_shared<UnwindPlan::Row>(); + row_sp->SetOffset(0); + if (!ParseUnwindRow(init_record->UnwindRules, resolver, *row_sp)) + return nullptr; + plan_sp->AppendRow(row_sp); + for (++It; It != End; ++It) { + llvm::Optional<StackCFIRecord> record = StackCFIRecord::parse(*It); + if (!record.hasValue()) + return nullptr; + if (record->Size.hasValue()) + break; + + row_sp = std::make_shared<UnwindPlan::Row>(*row_sp); + row_sp->SetOffset(record->Address - init_record->Address); + if (!ParseUnwindRow(record->UnwindRules, resolver, *row_sp)) + return nullptr; + plan_sp->AppendRow(row_sp); + } + return plan_sp; +} + +SymbolVendor &SymbolFileBreakpad::GetSymbolVendor() { + return *m_obj_file->GetModule()->GetSymbolVendor(); +} + +addr_t SymbolFileBreakpad::GetBaseFileAddress() { + return m_obj_file->GetModule() + ->GetObjectFile() + ->GetBaseAddress() + .GetFileAddress(); +} + +// Parse out all the FILE records from the breakpad file. These will be needed +// when constructing the support file lists for individual compile units. +void SymbolFileBreakpad::ParseFileRecords() { + if (m_files) + return; + m_files.emplace(); + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + for (llvm::StringRef line : lines(Record::File)) { + auto record = FileRecord::parse(line); + if (!record) { + LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", line); continue; } - symtab.AddSymbol(Symbol( - /*symID*/ 0, Mangled(name, /*is_mangled*/ false), eSymbolTypeCode, - /*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false, - /*is_artificial*/ false, - AddressRange(section_sp, address - section_sp->GetFileAddress(), 0), - /*size_is_valid*/ 0, /*contains_linker_annotations*/ false, - /*flags*/ 0)); + if (record->Number >= m_files->size()) + m_files->resize(record->Number + 1); + FileSpec::Style style = FileSpec::GuessPathStyle(record->Name) + .getValueOr(FileSpec::Style::native); + (*m_files)[record->Number] = FileSpec(record->Name, style); } +} - // TODO: Process FUNC records as well. +void SymbolFileBreakpad::ParseCUData() { + if (m_cu_data) + return; - symtab.CalculateSymbolSizes(); + m_cu_data.emplace(); + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + addr_t base = GetBaseFileAddress(); + if (base == LLDB_INVALID_ADDRESS) { + LLDB_LOG(log, "SymbolFile parsing failed: Unable to fetch the base address " + "of object file."); + } + + // We shall create one compile unit for each FUNC record. So, count the number + // of FUNC records, and store them in m_cu_data, together with their ranges. + for (LineIterator It(*m_obj_file, Record::Func), End(*m_obj_file); It != End; + ++It) { + if (auto record = FuncRecord::parse(*It)) { + m_cu_data->Append(CompUnitMap::Entry(base + record->Address, record->Size, + CompUnitData(It.GetBookmark()))); + } else + LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It); + } + m_cu_data->Sort(); +} + +// Construct the list of support files and line table entries for the given +// compile unit. +void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, + CompUnitData &data) { + addr_t base = GetBaseFileAddress(); + assert(base != LLDB_INVALID_ADDRESS && + "How did we create compile units without a base address?"); + + SupportFileMap map; + data.line_table_up = llvm::make_unique<LineTable>(&cu); + std::unique_ptr<LineSequence> line_seq_up( + data.line_table_up->CreateLineSequenceContainer()); + llvm::Optional<addr_t> next_addr; + auto finish_sequence = [&]() { + data.line_table_up->AppendLineEntryToSequence( + line_seq_up.get(), *next_addr, /*line*/ 0, /*column*/ 0, + /*file_idx*/ 0, /*is_start_of_statement*/ false, + /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false, + /*is_epilogue_begin*/ false, /*is_terminal_entry*/ true); + data.line_table_up->InsertSequence(line_seq_up.get()); + line_seq_up->Clear(); + }; + + LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); + assert(Record::classify(*It) == Record::Func); + for (++It; It != End; ++It) { + auto record = LineRecord::parse(*It); + if (!record) + break; + + record->Address += base; + + if (next_addr && *next_addr != record->Address) { + // Discontiguous entries. Finish off the previous sequence and reset. + finish_sequence(); + } + data.line_table_up->AppendLineEntryToSequence( + line_seq_up.get(), record->Address, record->LineNum, /*column*/ 0, + map[record->FileNum], /*is_start_of_statement*/ true, + /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false, + /*is_epilogue_begin*/ false, /*is_terminal_entry*/ false); + next_addr = record->Address + record->Size; + } + if (next_addr) + finish_sequence(); + data.support_files = map.translate(cu, *m_files); +} + +void SymbolFileBreakpad::ParseUnwindData() { + if (m_unwind_data) + return; + + m_unwind_data.emplace(); + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + addr_t base = GetBaseFileAddress(); + if (base == LLDB_INVALID_ADDRESS) { + LLDB_LOG(log, "SymbolFile parsing failed: Unable to fetch the base address " + "of object file."); + } + + for (LineIterator It(*m_obj_file, Record::StackCFI), End(*m_obj_file); + It != End; ++It) { + if (auto record = StackCFIRecord::parse(*It)) { + if (record->Size) + m_unwind_data->Append(UnwindMap::Entry( + base + record->Address, *record->Size, It.GetBookmark())); + } else + LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It); + } + m_unwind_data->Sort(); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 68e8d11c7dd7..8a0b7645fd0a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -1,16 +1,19 @@ //===-- SymbolFileBreakpad.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H #define LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H +#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/UnwindPlan.h" namespace lldb_private { @@ -18,9 +21,7 @@ namespace breakpad { class SymbolFileBreakpad : public SymbolFile { public: - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); static void DebuggerInitialize(Debugger &debugger) {} @@ -34,9 +35,7 @@ public: return new SymbolFileBreakpad(obj_file); } - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ SymbolFileBreakpad(ObjectFile *object_file) : SymbolFile(object_file) {} ~SymbolFileBreakpad() override {} @@ -45,9 +44,7 @@ public: void InitializeObject() override {} - //------------------------------------------------------------------ // Compile Unit function calls - //------------------------------------------------------------------ uint32_t GetNumCompileUnits() override; @@ -64,20 +61,18 @@ public: bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; } bool ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) override { - return false; - } + FileSpecList &support_files) override; size_t ParseTypes(CompileUnit &cu) override { return 0; } - bool - ParseImportedModules(const SymbolContext &sc, - std::vector<ConstString> &imported_modules) override { + bool ParseImportedModules( + const SymbolContext &sc, + std::vector<lldb_private::SourceModule> &imported_modules) override { return false; } size_t ParseBlocksRecursive(Function &func) override { return 0; } - uint32_t FindGlobalVariables(const ConstString &name, + uint32_t FindGlobalVariables(ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) override { @@ -99,12 +94,17 @@ public: lldb::SymbolContextItem resolve_scope, SymbolContext &sc) override; + uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, + bool check_inlines, + lldb::SymbolContextItem resolve_scope, + SymbolContextList &sc_list) override; + size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, TypeList &type_list) override { return 0; } - uint32_t FindFunctions(const ConstString &name, + uint32_t FindFunctions(ConstString name, const CompilerDeclContext *parent_decl_ctx, lldb::FunctionNameType name_type_mask, bool include_inlines, bool append, @@ -113,7 +113,7 @@ public: uint32_t FindFunctions(const RegularExpression ®ex, bool include_inlines, bool append, SymbolContextList &sc_list) override; - uint32_t FindTypes(const ConstString &name, + uint32_t FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, @@ -127,17 +127,93 @@ public: } CompilerDeclContext - FindNamespace(const ConstString &name, + FindNamespace(ConstString name, const CompilerDeclContext *parent_decl_ctx) override { return CompilerDeclContext(); } void AddSymbols(Symtab &symtab) override; + lldb::UnwindPlanSP + GetUnwindPlan(const Address &address, + const RegisterInfoResolver &resolver) override; + ConstString GetPluginName() override { return GetPluginNameStatic(); } uint32_t GetPluginVersion() override { return 1; } private: + // A class representing a position in the breakpad file. Useful for + // remembering the position so we can go back to it later and parse more data. + // Can be converted to/from a LineIterator, but it has a much smaller memory + // footprint. + struct Bookmark { + uint32_t section; + size_t offset; + + friend bool operator<(const Bookmark &lhs, const Bookmark &rhs) { + return std::tie(lhs.section, lhs.offset) < + std::tie(rhs.section, rhs.offset); + } + }; + + // At iterator class for simplifying algorithms reading data from the breakpad + // file. It iterates over all records (lines) in the sections of a given type. + // It also supports saving a specific position (via the GetBookmark() method) + // and then resuming from it afterwards. + class LineIterator; + + // Return an iterator range for all records in the given object file of the + // given type. + llvm::iterator_range<LineIterator> lines(Record::Kind section_type); + + // Breakpad files do not contain sufficient information to correctly + // reconstruct compile units. The approach chosen here is to treat each + // function as a compile unit. The compile unit name is the name if the first + // line entry belonging to this function. + // This class is our internal representation of a compile unit. It stores the + // CompileUnit object and a bookmark pointing to the FUNC record of the + // compile unit function. It also lazily construct the list of support files + // and line table entries for the compile unit, when these are needed. + class CompUnitData { + public: + CompUnitData(Bookmark bookmark) : bookmark(bookmark) {} + + CompUnitData() = default; + CompUnitData(const CompUnitData &rhs) : bookmark(rhs.bookmark) {} + CompUnitData &operator=(const CompUnitData &rhs) { + bookmark = rhs.bookmark; + support_files.reset(); + line_table_up.reset(); + return *this; + } + friend bool operator<(const CompUnitData &lhs, const CompUnitData &rhs) { + return lhs.bookmark < rhs.bookmark; + } + + Bookmark bookmark; + llvm::Optional<FileSpecList> support_files; + std::unique_ptr<LineTable> line_table_up; + + }; + + SymbolVendor &GetSymbolVendor(); + lldb::addr_t GetBaseFileAddress(); + void ParseFileRecords(); + void ParseCUData(); + void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data); + void ParseUnwindData(); + bool ParseUnwindRow(llvm::StringRef unwind_rules, + const RegisterInfoResolver &resolver, + UnwindPlan::Row &row); + + using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>; + + llvm::Optional<std::vector<FileSpec>> m_files; + llvm::Optional<CompUnitMap> m_cu_data; + + using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>; + llvm::Optional<UnwindMap> m_unwind_data; + llvm::BumpPtrAllocator m_allocator; }; } // namespace breakpad diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index db75cf9c3bb3..9ae047da1325 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -1,14 +1,12 @@ //===-- AppleDWARFIndex.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h" -#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" @@ -75,8 +73,8 @@ void AppleDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, return; DWARFMappedHash::DIEInfoArray hash_data; - if (m_apple_names_up->AppendAllDIEsInRange( - cu.GetOffset(), cu.GetNextCompileUnitOffset(), hash_data)) + if (m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(), + cu.GetNextUnitOffset(), hash_data)) DWARFMappedHash::ExtractDIEArray(hash_data, offsets); } @@ -134,14 +132,14 @@ void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets); } -void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, +void AppleDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) { DIEArray offsets; m_apple_names_up->FindByName(name.GetStringRef(), offsets); for (const DIERef &die_ref : offsets) { - ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx, + ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf, parent_decl_ctx, name_type_mask, dies); } } @@ -156,12 +154,12 @@ void AppleDWARFIndex::GetFunctions(const RegularExpression ®ex, DWARFMappedHash::ExtractDIEArray(hash_data, offsets); } -void AppleDWARFIndex::ReportInvalidDIEOffset(dw_offset_t offset, - llvm::StringRef name) { +void AppleDWARFIndex::ReportInvalidDIERef(const DIERef &ref, + llvm::StringRef name) { m_module.ReportErrorIfModifyDetected( "the DWARF debug information has been modified (accelerator table had " "bad die 0x%8.8x for '%s')\n", - offset, name.str().c_str()); + ref.die_offset(), name.str().c_str()); } void AppleDWARFIndex::Dump(Stream &s) { diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h index ea133d0e73cf..d15d61e270b3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h @@ -1,9 +1,8 @@ //===-- AppleDWARFIndex.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -43,14 +42,13 @@ public: void GetTypes(ConstString name, DIEArray &offsets) override; void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override; void GetNamespaces(ConstString name, DIEArray &offsets) override; - void GetFunctions(ConstString name, DWARFDebugInfo &info, + void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) override; void GetFunctions(const RegularExpression ®ex, DIEArray &offsets) override; - void ReportInvalidDIEOffset(dw_offset_t offset, - llvm::StringRef name) override; + void ReportInvalidDIERef(const DIERef &ref, llvm::StringRef name) override; void Dump(Stream &s) override; private: diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp index 0cd0f0c0272a..f7f2a5bf006b 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -1,67 +1,18 @@ //===-- DIERef.cpp ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DIERef.h" -#include "DWARFUnit.h" -#include "DWARFDebugInfo.h" -#include "DWARFFormValue.h" -#include "SymbolFileDWARF.h" -#include "SymbolFileDWARFDebugMap.h" - -DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf) - : cu_offset(DW_INVALID_OFFSET), die_offset(uid & 0xffffffff) { - SymbolFileDWARFDebugMap *debug_map = dwarf->GetDebugMapSymfile(); - if (debug_map) { - const uint32_t oso_idx = debug_map->GetOSOIndexFromUserID(uid); - SymbolFileDWARF *actual_dwarf = debug_map->GetSymbolFileByOSOIndex(oso_idx); - if (actual_dwarf) { - DWARFDebugInfo *debug_info = actual_dwarf->DebugInfo(); - if (debug_info) { - DWARFUnit *dwarf_cu = - debug_info->GetCompileUnitContainingDIEOffset(die_offset); - if (dwarf_cu) { - cu_offset = dwarf_cu->GetOffset(); - return; - } - } - } - die_offset = DW_INVALID_OFFSET; - } else { - cu_offset = uid >> 32; - } -} - -DIERef::DIERef(const DWARFFormValue &form_value) - : cu_offset(DW_INVALID_OFFSET), die_offset(DW_INVALID_OFFSET) { - if (form_value.IsValid()) { - const DWARFUnit *dwarf_cu = form_value.GetCompileUnit(); - if (dwarf_cu) { - if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) - cu_offset = dwarf_cu->GetBaseObjOffset(); - else - cu_offset = dwarf_cu->GetOffset(); - } - die_offset = form_value.Reference(); - } -} +#include "llvm/Support/Format.h" -lldb::user_id_t DIERef::GetUID(SymbolFileDWARF *dwarf) const { - //---------------------------------------------------------------------- - // Each SymbolFileDWARF will set its ID to what is expected. - // - // SymbolFileDWARF, when used for DWARF with .o files on MacOSX, has the - // ID set to the compile unit index. - // - // SymbolFileDWARFDwo sets the ID to the compile unit offset. - //---------------------------------------------------------------------- - if (dwarf && die_offset != DW_INVALID_OFFSET) - return dwarf->GetID() | die_offset; - else - return LLDB_INVALID_UID; +void llvm::format_provider<DIERef>::format(const DIERef &ref, raw_ostream &OS, + StringRef Style) { + if (ref.dwo_num()) + OS << format_hex_no_prefix(*ref.dwo_num(), 8) << "/"; + OS << (ref.section() == DIERef::DebugInfo ? "INFO" : "TYPE"); + OS << "/" << format_hex_no_prefix(ref.die_offset(), 8); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h index cb28c890c25a..5546bb7e8b86 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -1,9 +1,8 @@ //===-- DIERef.h ------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,48 +10,54 @@ #define SymbolFileDWARF_DIERef_h_ #include "lldb/Core/dwarf.h" -#include "lldb/lldb-defines.h" - -class DWARFFormValue; -class SymbolFileDWARF; - -struct DIERef { - DIERef() = default; - - DIERef(dw_offset_t c, dw_offset_t d) : cu_offset(c), die_offset(d) {} - - //---------------------------------------------------------------------- - // In order to properly decode a lldb::user_id_t back into a DIERef we - // need the DWARF file since it knows if DWARF in .o files is being used - // (MacOSX) or if DWO files are being used. The encoding of the user ID - // differs between the two types of DWARF. - //---------------------------------------------------------------------- - explicit DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf); - - explicit DIERef(const DWARFFormValue &form_value); - - //---------------------------------------------------------------------- - // In order to properly encode a DIERef unto a lldb::user_id_t we need - // the DWARF file since it knows if DWARF in .o files is being used - // (MacOSX) or if DWO files are being used. The encoding of the user ID - // differs between the two types of DWARF. - //---------------------------------------------------------------------- - lldb::user_id_t GetUID(SymbolFileDWARF *dwarf) const; +#include "llvm/ADT/Optional.h" +#include "llvm/Support/FormatProviders.h" +#include <cassert> +#include <vector> + +/// Identifies a DWARF debug info entry within a given Module. It contains three +/// "coordinates": +/// - dwo_num: identifies the dwo file in the Module. If this field is not set, +/// the DIERef references the main file. +/// - section: identifies the section of the debug info entry in the given file: +/// debug_info or debug_types. +/// - die_offset: The offset of the debug info entry as an absolute offset from +/// the beginning of the section specified in the section field. +class DIERef { +public: + enum Section : uint8_t { DebugInfo, DebugTypes }; + + DIERef(llvm::Optional<uint32_t> dwo_num, Section section, + dw_offset_t die_offset) + : m_dwo_num(dwo_num.getValueOr(0)), m_dwo_num_valid(bool(dwo_num)), + m_section(section), m_die_offset(die_offset) { + assert(this->dwo_num() == dwo_num && "Dwo number out of range?"); + } - bool operator<(const DIERef &ref) const { - return die_offset < ref.die_offset; + llvm::Optional<uint32_t> dwo_num() const { + if (m_dwo_num_valid) + return m_dwo_num; + return llvm::None; } - bool operator<(const DIERef &ref) { return die_offset < ref.die_offset; } + Section section() const { return static_cast<Section>(m_section); } - explicit operator bool() const { - return cu_offset != DW_INVALID_OFFSET || die_offset != DW_INVALID_OFFSET; - } + dw_offset_t die_offset() const { return m_die_offset; } - dw_offset_t cu_offset = DW_INVALID_OFFSET; - dw_offset_t die_offset = DW_INVALID_OFFSET; +private: + uint32_t m_dwo_num : 30; + uint32_t m_dwo_num_valid : 1; + uint32_t m_section : 1; + dw_offset_t m_die_offset; }; +static_assert(sizeof(DIERef) == 8, ""); typedef std::vector<DIERef> DIEArray; +namespace llvm { +template<> struct format_provider<DIERef> { + static void format(const DIERef &ref, raw_ostream &OS, StringRef Style); +}; +} // namespace llvm + #endif // SymbolFileDWARF_DIERef_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 24d5f26745dc..e7927b31b9c3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -1,9 +1,8 @@ //===-- DWARFASTParser.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 70d48e5f1dfa..b85ab54a10d3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1,9 +1,8 @@ //===-- DWARFASTParserClang.cpp ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,7 +10,6 @@ #include "DWARFASTParserClang.h" #include "DWARFDIE.h" -#include "DWARFDIECollection.h" #include "DWARFDebugInfo.h" #include "DWARFDeclContext.h" #include "DWARFDefines.h" @@ -44,6 +42,7 @@ #include "clang/AST/DeclTemplate.h" #include <map> +#include <memory> #include <vector> //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN @@ -118,10 +117,10 @@ struct BitfieldInfo { }; ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() { - if (!m_clang_ast_importer_ap) { - m_clang_ast_importer_ap.reset(new ClangASTImporter); + if (!m_clang_ast_importer_up) { + m_clang_ast_importer_up.reset(new ClangASTImporter); } - return *m_clang_ast_importer_ap; + return *m_clang_ast_importer_up; } /// Detect a forward declaration that is nested in a DW_TAG_module. @@ -156,8 +155,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { // Since this this type is defined in one of the Clang modules imported by // this symbol file, search all of them. - auto *sym_file = die.GetCU()->GetSymbolFileDWARF(); - for (const auto &name_module : sym_file->getExternalTypeModules()) { + auto &sym_file = die.GetCU()->GetSymbolFileDWARF(); + for (const auto &name_module : sym_file.getExternalTypeModules()) { if (!name_module.second) continue; SymbolVendor *sym_vendor = name_module.second->GetSymbolVendor(); @@ -186,7 +185,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { SymbolFileDWARF *dwarf = die.GetDWARF(); TypeSP type_sp(new Type( die.GetID(), dwarf, dwo_type_sp->GetName(), dwo_type_sp->GetByteSize(), - NULL, LLDB_INVALID_UID, Type::eEncodingInvalid, + nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward)); dwarf->GetTypeList()->Insert(type_sp); @@ -229,1676 +228,1454 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer, } } +namespace { +/// Parsed form of all attributes that are relevant for type reconstruction. +/// Some attributes are relevant for all kinds of types (declaration), while +/// others are only meaningful to a specific type (is_virtual) +struct ParsedTypeAttributes { + explicit ParsedTypeAttributes(const DWARFDIE &die); + + AccessType accessibility = eAccessNone; + bool is_artificial = false; + bool is_complete_objc_class = false; + bool is_explicit = false; + bool is_forward_declaration = false; + bool is_inline = false; + bool is_scoped_enum = false; + bool is_vector = false; + bool is_virtual = false; + clang::StorageClass storage = clang::SC_None; + const char *mangled_name = nullptr; + ConstString name; + Declaration decl; + DWARFDIE object_pointer; + DWARFFormValue abstract_origin; + DWARFFormValue containing_type; + DWARFFormValue signature; + DWARFFormValue specification; + DWARFFormValue type; + LanguageType class_language = eLanguageTypeUnknown; + llvm::Optional<uint64_t> byte_size; + size_t calling_convention = llvm::dwarf::DW_CC_normal; + uint32_t bit_stride = 0; + uint32_t byte_stride = 0; + uint32_t encoding = 0; +}; +} // namespace + +ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die) { + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(i, form_value)) + continue; + switch (attr) { + case DW_AT_abstract_origin: + abstract_origin = form_value; + break; + + case DW_AT_accessibility: + accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); + break; + + case DW_AT_artificial: + is_artificial = form_value.Boolean(); + break; + + case DW_AT_bit_stride: + bit_stride = form_value.Unsigned(); + break; + + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + + case DW_AT_byte_stride: + byte_stride = form_value.Unsigned(); + break; + + case DW_AT_calling_convention: + calling_convention = form_value.Unsigned(); + break; + + case DW_AT_containing_type: + containing_type = form_value; + break; + + case DW_AT_decl_file: + decl.SetFile(die.GetCU()->GetFile(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_declaration: + is_forward_declaration = form_value.Boolean(); + break; + + case DW_AT_encoding: + encoding = form_value.Unsigned(); + break; + + case DW_AT_enum_class: + is_scoped_enum = form_value.Boolean(); + break; + + case DW_AT_explicit: + is_explicit = form_value.Boolean(); + break; + + case DW_AT_external: + if (form_value.Unsigned()) + storage = clang::SC_Extern; + break; + + case DW_AT_inline: + is_inline = form_value.Boolean(); + break; + + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: + mangled_name = form_value.AsCString(); + break; + + case DW_AT_name: + name.SetCString(form_value.AsCString()); + break; + + case DW_AT_object_pointer: + object_pointer = form_value.Reference(); + break; + + case DW_AT_signature: + signature = form_value; + break; + + case DW_AT_specification: + specification = form_value; + break; + + case DW_AT_type: + type = form_value; + break; + + case DW_AT_virtuality: + is_virtual = form_value.Boolean(); + break; + + case DW_AT_APPLE_objc_complete_type: + is_complete_objc_class = form_value.Signed(); + break; + + case DW_AT_APPLE_runtime_class: + class_language = (LanguageType)form_value.Signed(); + break; + + case DW_AT_GNU_vector: + is_vector = form_value.Boolean(); + break; + } + } +} + +static std::string GetUnitName(const DWARFDIE &die) { + if (DWARFUnit *unit = die.GetCU()) + return unit->GetAbsolutePath().GetPath(); + return "<missing DWARF unit path>"; +} + TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, const DWARFDIE &die, Log *log, bool *type_is_new_ptr) { - TypeSP type_sp; - if (type_is_new_ptr) *type_is_new_ptr = false; - AccessType accessibility = eAccessNone; - if (die) { - SymbolFileDWARF *dwarf = die.GetDWARF(); - if (log) { - DWARFDIE context_die; - clang::DeclContext *context = - GetClangDeclContextContainingDIE(die, &context_die); - - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die " - "0x%8.8x)) %s name = '%s')", - die.GetOffset(), static_cast<void *>(context), - context_die.GetOffset(), die.GetTagAsCString(), die.GetName()); + if (!die) + return nullptr; + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (log) { + DWARFDIE context_die; + clang::DeclContext *context = + GetClangDeclContextContainingDIE(die, &context_die); + + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die " + "0x%8.8x)) %s name = '%s')", + die.GetOffset(), static_cast<void *>(context), context_die.GetOffset(), + die.GetTagAsCString(), die.GetName()); + } + + + Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE()); + if (type_ptr == DIE_IS_BEING_PARSED) + return nullptr; + if (type_ptr) + return type_ptr->shared_from_this(); + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + ParsedTypeAttributes attrs(die); + + if (DWARFDIE signature_die = attrs.signature.Reference()) { + if (TypeSP type_sp = + ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + if (clang::DeclContext *decl_ctx = + GetCachedClangDeclContextForDIE(signature_die)) + LinkDeclContextToDIE(decl_ctx, die); + return type_sp; } - Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE()); - TypeList *type_list = dwarf->GetTypeList(); - if (type_ptr == NULL) { - if (type_is_new_ptr) - *type_is_new_ptr = true; + return nullptr; + } - const dw_tag_t tag = die.Tag(); + TypeList *type_list = dwarf->GetTypeList(); + if (type_is_new_ptr) + *type_is_new_ptr = true; - bool is_forward_declaration = false; - DWARFAttributes attributes; - const char *type_name_cstr = NULL; - const char *mangled_name_cstr = NULL; - ConstString type_name_const_str; - Type::ResolveState resolve_state = Type::eResolveStateUnresolved; - uint64_t byte_size = 0; - Declaration decl; - - Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; - CompilerType clang_type; - DWARFFormValue form_value; + const dw_tag_t tag = die.Tag(); - dw_attr_t attr; - - switch (tag) { - case DW_TAG_typedef: - case DW_TAG_base_type: - case DW_TAG_pointer_type: - case DW_TAG_reference_type: - case DW_TAG_rvalue_reference_type: - case DW_TAG_const_type: - case DW_TAG_restrict_type: - case DW_TAG_volatile_type: - case DW_TAG_unspecified_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - - const size_t num_attributes = die.GetAttributes(attributes); - uint32_t encoding = 0; - DWARFFormValue encoding_uid; - - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - 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: - type_name_cstr = form_value.AsCString(); - if (type_name_cstr) - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - case DW_AT_encoding: - encoding = form_value.Unsigned(); - break; - case DW_AT_type: - encoding_uid = form_value; - break; - default: - case DW_AT_sibling: - break; - } - } - } - } + Type::ResolveState resolve_state = Type::eResolveStateUnresolved; - if (tag == DW_TAG_typedef && encoding_uid.IsValid()) { - // Try to parse a typedef from the DWO file first as modules can - // contain typedef'ed structures that have no names like: - // - // typedef struct { int a; } Foo; - // - // In this case we will have a structure with no name and a typedef - // named "Foo" that points to this unnamed structure. The name in the - // typedef is the only identifier for the struct, so always try to - // get typedefs from DWO files if possible. - // - // The type_sp returned will be empty if the typedef doesn't exist in - // a DWO file, so it is cheap to call this function just to check. - // - // If we don't do this we end up creating a TypeSP that says this is - // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in - // the DW_TAG_typedef), and this is the unnamed structure type. We - // will have a hard time tracking down an unnammed structure type in - // the module DWO file, so we make sure we don't get into this - // situation by always resolving typedefs from the DWO file. - const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid)); - - // First make sure that the die that this is typedef'ed to _is_ just - // a declaration (DW_AT_declaration == 1), not a full definition - // since template types can't be represented in modules since only - // concrete instances of templates are ever emitted and modules won't - // contain those - if (encoding_die && - encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == - 1) { - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - } - } + Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; + CompilerType clang_type; - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", - die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, - encoding_uid.Reference()); + TypeSP type_sp; + LanguageType cu_language = die.GetLanguage(); + switch (tag) { + case DW_TAG_typedef: + case DW_TAG_base_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_const_type: + case DW_TAG_restrict_type: + case DW_TAG_volatile_type: + case DW_TAG_unspecified_type: { + if (tag == DW_TAG_typedef && attrs.type.IsValid()) { + // Try to parse a typedef from the DWO file first as modules can + // contain typedef'ed structures that have no names like: + // + // typedef struct { int a; } Foo; + // + // In this case we will have a structure with no name and a typedef + // named "Foo" that points to this unnamed structure. The name in the + // typedef is the only identifier for the struct, so always try to + // get typedefs from DWO files if possible. + // + // The type_sp returned will be empty if the typedef doesn't exist in + // a DWO file, so it is cheap to call this function just to check. + // + // If we don't do this we end up creating a TypeSP that says this is + // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in + // the DW_TAG_typedef), and this is the unnamed structure type. We + // will have a hard time tracking down an unnammed structure type in + // the module DWO file, so we make sure we don't get into this + // situation by always resolving typedefs from the DWO file. + const DWARFDIE encoding_die = attrs.type.Reference(); + + // First make sure that the die that this is typedef'ed to _is_ just + // a declaration (DW_AT_declaration == 1), not a full definition + // since template types can't be represented in modules since only + // concrete instances of templates are ever emitted and modules won't + // contain those + if (encoding_die && + encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + } + } - switch (tag) { - default: - break; + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", + die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, + encoding_uid.Reference()); - case DW_TAG_unspecified_type: - if (strcmp(type_name_cstr, "nullptr_t") == 0 || - strcmp(type_name_cstr, "decltype(nullptr)") == 0) { - resolve_state = Type::eResolveStateFull; - clang_type = m_ast.GetBasicType(eBasicTypeNullPtr); - break; - } - // Fall through to base type below in case we can handle the type - // there... - LLVM_FALLTHROUGH; - - case DW_TAG_base_type: - resolve_state = Type::eResolveStateFull; - clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( - type_name_cstr, encoding, byte_size * 8); - break; + switch (tag) { + default: + break; - case DW_TAG_pointer_type: - encoding_data_type = Type::eEncodingIsPointerUID; - break; - case DW_TAG_reference_type: - encoding_data_type = Type::eEncodingIsLValueReferenceUID; - break; - case DW_TAG_rvalue_reference_type: - encoding_data_type = Type::eEncodingIsRValueReferenceUID; - break; - case DW_TAG_typedef: - encoding_data_type = Type::eEncodingIsTypedefUID; - break; - case DW_TAG_const_type: - encoding_data_type = Type::eEncodingIsConstUID; - break; - case DW_TAG_restrict_type: - encoding_data_type = Type::eEncodingIsRestrictUID; - break; - case DW_TAG_volatile_type: - encoding_data_type = Type::eEncodingIsVolatileUID; - break; - } + case DW_TAG_unspecified_type: + if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") { + resolve_state = Type::eResolveStateFull; + clang_type = m_ast.GetBasicType(eBasicTypeNullPtr); + break; + } + // Fall through to base type below in case we can handle the type + // there... + LLVM_FALLTHROUGH; + + case DW_TAG_base_type: + resolve_state = Type::eResolveStateFull; + clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( + attrs.name.GetCString(), attrs.encoding, + attrs.byte_size.getValueOr(0) * 8); + break; - if (!clang_type && - (encoding_data_type == Type::eEncodingIsPointerUID || - encoding_data_type == Type::eEncodingIsTypedefUID)) { - if (tag == DW_TAG_pointer_type) { - DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type); - - if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) { - // Blocks have a __FuncPtr inside them which is a pointer to a - // function of the proper type. - - for (DWARFDIE child_die = target_die.GetFirstChild(); - child_die.IsValid(); child_die = child_die.GetSibling()) { - if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), - "__FuncPtr")) { - DWARFDIE function_pointer_type = - child_die.GetReferencedDIE(DW_AT_type); - - if (function_pointer_type) { - DWARFDIE function_type = - function_pointer_type.GetReferencedDIE(DW_AT_type); - - bool function_type_is_new_pointer; - TypeSP lldb_function_type_sp = ParseTypeFromDWARF( - sc, function_type, log, &function_type_is_new_pointer); - - if (lldb_function_type_sp) { - clang_type = m_ast.CreateBlockPointerType( - lldb_function_type_sp->GetForwardCompilerType()); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; - } - } + case DW_TAG_pointer_type: + encoding_data_type = Type::eEncodingIsPointerUID; + break; + case DW_TAG_reference_type: + encoding_data_type = Type::eEncodingIsLValueReferenceUID; + break; + case DW_TAG_rvalue_reference_type: + encoding_data_type = Type::eEncodingIsRValueReferenceUID; + break; + case DW_TAG_typedef: + encoding_data_type = Type::eEncodingIsTypedefUID; + break; + case DW_TAG_const_type: + encoding_data_type = Type::eEncodingIsConstUID; + break; + case DW_TAG_restrict_type: + encoding_data_type = Type::eEncodingIsRestrictUID; + break; + case DW_TAG_volatile_type: + encoding_data_type = Type::eEncodingIsVolatileUID; + break; + } - break; + if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || + encoding_data_type == Type::eEncodingIsTypedefUID)) { + if (tag == DW_TAG_pointer_type) { + DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type); + + if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) { + // Blocks have a __FuncPtr inside them which is a pointer to a + // function of the proper type. + + for (DWARFDIE child_die = target_die.GetFirstChild(); + child_die.IsValid(); child_die = child_die.GetSibling()) { + if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), + "__FuncPtr")) { + DWARFDIE function_pointer_type = + child_die.GetReferencedDIE(DW_AT_type); + + if (function_pointer_type) { + DWARFDIE function_type = + function_pointer_type.GetReferencedDIE(DW_AT_type); + + bool function_type_is_new_pointer; + TypeSP lldb_function_type_sp = ParseTypeFromDWARF( + sc, function_type, log, &function_type_is_new_pointer); + + if (lldb_function_type_sp) { + clang_type = m_ast.CreateBlockPointerType( + lldb_function_type_sp->GetForwardCompilerType()); + encoding_data_type = Type::eEncodingIsUID; + attrs.type.Clear(); + resolve_state = Type::eResolveStateFull; } } + + break; } } + } + } - bool translation_unit_is_objc = - (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || - sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); + if (cu_language == eLanguageTypeObjC || + cu_language == eLanguageTypeObjC_plus_plus) { + if (attrs.name) { + static ConstString g_objc_type_name_id("id"); + static ConstString g_objc_type_name_Class("Class"); + static ConstString g_objc_type_name_selector("SEL"); - if (translation_unit_is_objc) { - if (type_name_cstr != NULL) { - static ConstString g_objc_type_name_id("id"); - static ConstString g_objc_type_name_Class("Class"); - static ConstString g_objc_type_name_selector("SEL"); + if (attrs.name == g_objc_type_name_id) { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "is Objective-C 'id' built-in type.", + die.GetOffset(), die.GetTagAsCString(), die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCID); + encoding_data_type = Type::eEncodingIsUID; + attrs.type.Clear(); + resolve_state = Type::eResolveStateFull; - if (type_name_const_str == g_objc_type_name_id) { - if (log) - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " - "is Objective-C 'id' built-in type.", - die.GetOffset(), die.GetTagAsCString(), die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCID); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; + } else if (attrs.name == g_objc_type_name_Class) { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "is Objective-C 'Class' built-in type.", + die.GetOffset(), die.GetTagAsCString(), die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); + encoding_data_type = Type::eEncodingIsUID; + attrs.type.Clear(); + resolve_state = Type::eResolveStateFull; + } else if (attrs.name == g_objc_type_name_selector) { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "is Objective-C 'selector' built-in type.", + die.GetOffset(), die.GetTagAsCString(), die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); + encoding_data_type = Type::eEncodingIsUID; + attrs.type.Clear(); + resolve_state = Type::eResolveStateFull; + } + } else if (encoding_data_type == Type::eEncodingIsPointerUID && + attrs.type.IsValid()) { + // Clang sometimes erroneously emits id as objc_object*. In that + // case we fix up the type to "id". - } else if (type_name_const_str == g_objc_type_name_Class) { - if (log) - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " - "is Objective-C 'Class' built-in type.", - die.GetOffset(), die.GetTagAsCString(), die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; - } else if (type_name_const_str == g_objc_type_name_selector) { + const DWARFDIE encoding_die = attrs.type.Reference(); + + if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) { + if (const char *struct_name = encoding_die.GetName()) { + if (!strcmp(struct_name, "objc_object")) { if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " - "is Objective-C 'selector' built-in type.", + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s " + "'%s' is 'objc_object*', which we overrode to " + "'id'.", die.GetOffset(), die.GetTagAsCString(), die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); + clang_type = m_ast.GetBasicType(eBasicTypeObjCID); encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); + attrs.type.Clear(); resolve_state = Type::eResolveStateFull; } - } else if (encoding_data_type == Type::eEncodingIsPointerUID && - encoding_uid.IsValid()) { - // Clang sometimes erroneously emits id as objc_object*. In that - // case we fix up the type to "id". - - const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid)); - - if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) { - if (const char *struct_name = encoding_die.GetName()) { - if (!strcmp(struct_name, "objc_object")) { - if (log) - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s " - "'%s' is 'objc_object*', which we overrode to " - "'id'.", - die.GetOffset(), die.GetTagAsCString(), - die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCID); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; - } - } - } } } } + } + } - type_sp.reset( - new Type(die.GetID(), dwarf, type_name_const_str, byte_size, NULL, - DIERef(encoding_uid).GetUID(dwarf), encoding_data_type, - &decl, clang_type, resolve_state)); + type_sp = std::make_shared<Type>( + die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, + dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl, + clang_type, resolve_state); - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - } break; + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + } break; - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - bool byte_size_valid = false; + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: { + // UniqueDWARFASTType is large, so don't create a local variables on + // the stack, put it on the heap. This function is often called + // recursively and clang isn't good and sharing the stack space for + // variables in different blocks. + std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_up( + new UniqueDWARFASTType()); + + ConstString unique_typename(attrs.name); + Declaration unique_decl(attrs.decl); + + if (attrs.name) { + if (Language::LanguageIsCPlusPlus(cu_language)) { + // For C++, we rely solely upon the one definition rule that says + // only one thing can exist at a given decl context. We ignore the + // file and line that things are declared on. + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + unique_typename = ConstString(qualified_name); + unique_decl.Clear(); + } - LanguageType class_language = eLanguageTypeUnknown; - bool is_complete_objc_class = false; - size_t calling_convention - = llvm::dwarf::CallingConvention::DW_CC_normal; - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - 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: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - byte_size_valid = true; - break; - - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - - case DW_AT_APPLE_runtime_class: - class_language = (LanguageType)form_value.Signed(); - break; - - case DW_AT_APPLE_objc_complete_type: - is_complete_objc_class = form_value.Signed(); - break; - case DW_AT_calling_convention: - calling_convention = form_value.Unsigned(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - default: - case DW_AT_sibling: - break; - } - } - } + if (dwarf->GetUniqueDWARFASTTypeMap().Find( + unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), + *unique_ast_entry_up)) { + type_sp = unique_ast_entry_up->m_type_sp; + if (type_sp) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; } + } + } - // UniqueDWARFASTType is large, so don't create a local variables on - // the stack, put it on the heap. This function is often called - // recursively and clang isn't good and sharing the stack space for - // variables in different blocks. - std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap( - new UniqueDWARFASTType()); - - ConstString unique_typename(type_name_const_str); - Declaration unique_decl(decl); - - if (type_name_const_str) { - LanguageType die_language = die.GetLanguage(); - if (Language::LanguageIsCPlusPlus(die_language)) { - // For C++, we rely solely upon the one definition rule that says - // only one thing can exist at a given decl context. We ignore the - // file and line that things are declared on. - std::string qualified_name; - if (die.GetQualifiedName(qualified_name)) - unique_typename = ConstString(qualified_name); - unique_decl.Clear(); - } + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + int tag_decl_kind = -1; + AccessType default_accessibility = eAccessNone; + if (tag == DW_TAG_structure_type) { + tag_decl_kind = clang::TTK_Struct; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_union_type) { + tag_decl_kind = clang::TTK_Union; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_class_type) { + tag_decl_kind = clang::TTK_Class; + default_accessibility = eAccessPrivate; + } - if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, - byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) { - type_sp = unique_ast_entry_ap->m_type_sp; - if (type_sp) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } + if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && cu_language == eLanguageTypeObjC) { + // Work around an issue with clang at the moment where forward + // declarations for objective C classes are emitted as: + // DW_TAG_structure_type [2] + // DW_AT_name( "ForwardObjcClass" ) + // DW_AT_byte_size( 0x00 ) + // DW_AT_decl_file( "..." ) + // DW_AT_decl_line( 1 ) + // + // Note that there is no DW_AT_declaration and there are no children, + // and the byte size is zero. + attrs.is_forward_declaration = true; + } + + if (attrs.class_language == eLanguageTypeObjC || + attrs.class_language == eLanguageTypeObjC_plus_plus) { + if (!attrs.is_complete_objc_class && + die.Supports_DW_AT_APPLE_objc_complete_type()) { + // We have a valid eSymbolTypeObjCClass class symbol whose name + // matches the current objective C class that we are trying to find + // and this DIE isn't the complete definition (we checked + // is_complete_objc_class above and know it is false), so the real + // definition is in here somewhere + type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( + die, attrs.name, true); } } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - int tag_decl_kind = -1; - AccessType default_accessibility = eAccessNone; - if (tag == DW_TAG_structure_type) { - tag_decl_kind = clang::TTK_Struct; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_union_type) { - tag_decl_kind = clang::TTK_Union; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_class_type) { - tag_decl_kind = clang::TTK_Class; - default_accessibility = eAccessPrivate; - } + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " + "incomplete objc type, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } - if (byte_size_valid && byte_size == 0 && type_name_cstr && - !die.HasChildren() && - sc.comp_unit->GetLanguage() == eLanguageTypeObjC) { - // Work around an issue with clang at the moment where forward - // declarations for objective C classes are emitted as: - // DW_TAG_structure_type [2] - // DW_AT_name( "ForwardObjcClass" ) - // DW_AT_byte_size( 0x00 ) - // DW_AT_decl_file( "..." ) - // DW_AT_decl_line( 1 ) - // - // Note that there is no DW_AT_declaration and there are no children, - // and the byte size is zero. - is_forward_declaration = true; + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; } + } + } - if (class_language == eLanguageTypeObjC || - class_language == eLanguageTypeObjC_plus_plus) { - if (!is_complete_objc_class && - die.Supports_DW_AT_APPLE_objc_complete_type()) { - // We have a valid eSymbolTypeObjCClass class symbol whose name - // matches the current objective C class that we are trying to find - // and this DIE isn't the complete definition (we checked - // is_complete_objc_class above and know it is false), so the real - // definition is in here somewhere - type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE( - die, type_name_const_str, true); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = - debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( - die, type_name_const_str, true); - } - } + if (attrs.is_forward_declaration) { + // We have a forward declaration to a type and we need to try and + // find a full declaration. We look in the current type index just in + // case we have a forward declaration followed by an actual + // declarations in the DWARF. If this fails, we need to look + // elsewhere... + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, trying to find complete type", + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString()); + } - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " - "incomplete objc type, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, - type_sp->GetID()); - } + // See if the type comes from a DWO module and if so, track down that + // type. + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, + // type_name_const_str); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, see + // if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); + } + } - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); } - if (is_forward_declaration) { - // We have a forward declaration to a type and we need to try and - // find a full declaration. We look in the current type index just in - // case we have a forward declaration followed by an actual - // declarations in the DWARF. If this fails, we need to look - // elsewhere... - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, trying to find complete type", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr); - } + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + assert(tag_decl_kind != -1); + bool clang_type_was_created = false; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + clang::DeclContext *decl_ctx = + GetClangDeclContextContainingDIE(die, nullptr); - // See if the type comes from a DWO module and if so, track down that - // type. - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, - // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, see - // if we have a declaration anywhere else... - type_sp = - debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } - } + // If your decl context is a record that was imported from another + // AST context (in the gmodules case), we need to make sure the type + // backing the Decl is complete before adding children to it. This is + // not an issue in the non-gmodules case because the debug info will + // always contain a full definition of parent types in that case. + CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, + attrs.name.GetCString()); + + if (attrs.accessibility == eAccessNone && decl_ctx) { + // Check the decl context that contains this class/struct/union. If + // it is a class we must give it an accessibility. + const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + if (DeclKindIsCXXClass(containing_decl_kind)) + attrs.accessibility = default_accessibility; + } - if (type_sp) { + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); + + if (attrs.name.GetStringRef().contains('<')) { + ClangASTContext::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, + attrs.name.GetCString(), + tag_decl_kind, template_param_infos); + if (!class_template_decl) { if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); + DW_TAG_value_to_name(tag), attrs.name.GetCString()); } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE( - dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID(), dwarf))); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; - } - } - assert(tag_decl_kind != -1); - bool clang_type_was_created = false; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, nullptr); - - // If your decl context is a record that was imported from another - // AST context (in the gmodules case), we need to make sure the type - // backing the Decl is complete before adding children to it. This is - // not an issue in the non-gmodules case because the debug info will - // always contain a full definition of parent types in that case. - CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, - type_name_cstr); - - if (accessibility == eAccessNone && decl_ctx) { - // Check the decl context that contains this class/struct/union. If - // it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = - decl_ctx->getDeclKind(); - if (DeclKindIsCXXClass(containing_decl_kind)) - accessibility = default_accessibility; + return TypeSP(); } - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - - if (type_name_cstr && strchr(type_name_cstr, '<')) { - ClangASTContext::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, accessibility, - type_name_cstr, tag_decl_kind, - template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr); - } - return TypeSP(); - } - - clang::ClassTemplateSpecializationDecl - *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, class_template_decl, tag_decl_kind, - template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; - - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } - } + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, class_template_decl, tag_decl_kind, + template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType( + class_specialization_decl); + clang_type_was_created = true; - if (!clang_type_was_created) { - clang_type_was_created = true; - clang_type = m_ast.CreateRecordType(decl_ctx, accessibility, - type_name_cstr, tag_decl_kind, - class_language, &metadata); - } - } - - // Store a forward declaration to this class type in case any - // parameters in any class methods need it for the clang types for - // function prototypes. - LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, - byte_size, NULL, LLDB_INVALID_UID, - Type::eEncodingIsUID, &decl, clang_type, - Type::eResolveStateForward)); - - type_sp->SetIsCompleteObjCClass(is_complete_objc_class); - - // Add our type to the unique type map so we don't end up creating many - // copies of the same type over and over in the ASTContext for our - // module - unique_ast_entry_ap->m_type_sp = type_sp; - unique_ast_entry_ap->m_die = die; - unique_ast_entry_ap->m_declaration = unique_decl; - unique_ast_entry_ap->m_byte_size = byte_size; - dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, - *unique_ast_entry_ap); - - if (is_forward_declaration && die.HasChildren()) { - // Check to see if the DIE actually has a definition, some version of - // GCC will - // emit DIEs with DW_AT_declaration set to true, but yet still have - // subprogram, members, or inheritance, so we can't trust it - DWARFDIE child_die = die.GetFirstChild(); - while (child_die) { - switch (child_die.Tag()) { - case DW_TAG_inheritance: - case DW_TAG_subprogram: - case DW_TAG_member: - case DW_TAG_APPLE_property: - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_enumeration_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - child_die.Clear(); - is_forward_declaration = false; - break; - default: - child_die = child_die.GetSibling(); - break; - } - } + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); } + } - if (!is_forward_declaration) { - // Always start the definition for a class type so that if the class - // has child classes or types that require the class to be created - // for use as their decl contexts the class will be ready to accept - // these child definitions. - if (!die.HasChildren()) { - // No children for this struct/union/class, lets finish it - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), type_name_cstr); - } + if (!clang_type_was_created) { + clang_type_was_created = true; + clang_type = m_ast.CreateRecordType( + decl_ctx, attrs.accessibility, attrs.name.GetCString(), + tag_decl_kind, attrs.class_language, &metadata); + } + } - if (tag == DW_TAG_structure_type) // this only applies in C - { - clang::RecordDecl *record_decl = - ClangASTContext::GetAsRecordDecl(clang_type); + // Store a forward declaration to this class type in case any + // parameters in any class methods need it for the clang types for + // function prototypes. + LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); + type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name, + attrs.byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, clang_type, + Type::eResolveStateForward); + + type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); + + // Add our type to the unique type map so we don't end up creating many + // copies of the same type over and over in the ASTContext for our + // module + unique_ast_entry_up->m_type_sp = type_sp; + unique_ast_entry_up->m_die = die; + unique_ast_entry_up->m_declaration = unique_decl; + unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); + dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, + *unique_ast_entry_up); + + if (attrs.is_forward_declaration && die.HasChildren()) { + // Check to see if the DIE actually has a definition, some version of + // GCC will + // emit DIEs with DW_AT_declaration set to true, but yet still have + // subprogram, members, or inheritance, so we can't trust it + DWARFDIE child_die = die.GetFirstChild(); + while (child_die) { + switch (child_die.Tag()) { + case DW_TAG_inheritance: + case DW_TAG_subprogram: + case DW_TAG_member: + case DW_TAG_APPLE_property: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + child_die.Clear(); + attrs.is_forward_declaration = false; + break; + default: + child_die = child_die.GetSibling(); + break; + } + } + } - if (record_decl) { - GetClangASTImporter().InsertRecordDecl( - record_decl, ClangASTImporter::LayoutInfo()); - } - } - } else if (clang_type_was_created) { - // Start the definition if the class is not objective C since the - // underlying decls respond to isCompleteDefinition(). Objective - // C decls don't respond to isCompleteDefinition() so we can't - // start the declaration definition right away. For C++ - // class/union/structs we want to start the definition in case the - // class is needed as the declaration context for a contained class - // or type without the need to complete that type.. - - if (class_language != eLanguageTypeObjC && - class_language != eLanguageTypeObjC_plus_plus) - ClangASTContext::StartTagDeclarationDefinition(clang_type); - - // Leave this as a forward declaration until we need to know the - // details of the type. lldb_private::Type will automatically call - // the SymbolFile virtual function - // "SymbolFileDWARF::CompleteType(Type *)" When the definition - // needs to be defined. - assert(!dwarf->GetForwardDeclClangTypeToDie().count( - ClangUtil::RemoveFastQualifiers(clang_type) - .GetOpaqueQualType()) && - "Type already in the forward declaration map!"); - // Can't assume m_ast.GetSymbolFile() is actually a - // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple - // binaries. - dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = - clang_type.GetOpaqueQualType(); - dwarf->GetForwardDeclClangTypeToDie() - [ClangUtil::RemoveFastQualifiers(clang_type) - .GetOpaqueQualType()] = die.GetDIERef(); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); - } + if (!attrs.is_forward_declaration) { + // Always start the definition for a class type so that if the class + // has child classes or types that require the class to be created + // for use as their decl contexts the class will be ready to accept + // these child definitions. + if (!die.HasChildren()) { + // No children for this struct/union/class, lets finish it + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), attrs.name.GetCString()); } - - // If we made a clang type, set the trivial abi if applicable: We only - // do this for pass by value - which implies the Trivial ABI. There - // isn't a way to assert that something that would normally be pass by - // value is pass by reference, so we ignore that attribute if set. - if (calling_convention == llvm::dwarf::DW_CC_pass_by_value) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + + if (tag == DW_TAG_structure_type) // this only applies in C + { + clang::RecordDecl *record_decl = + ClangASTContext::GetAsRecordDecl(clang_type); + if (record_decl) { - record_decl->setHasTrivialSpecialMemberForCall(); + GetClangASTImporter().InsertRecordDecl( + record_decl, ClangASTImporter::LayoutInfo()); } } + } else if (clang_type_was_created) { + // Start the definition if the class is not objective C since the + // underlying decls respond to isCompleteDefinition(). Objective + // C decls don't respond to isCompleteDefinition() so we can't + // start the declaration definition right away. For C++ + // class/union/structs we want to start the definition in case the + // class is needed as the declaration context for a contained class + // or type without the need to complete that type.. + + if (attrs.class_language != eLanguageTypeObjC && + attrs.class_language != eLanguageTypeObjC_plus_plus) + ClangASTContext::StartTagDeclarationDefinition(clang_type); - } break; + // Leave this as a forward declaration until we need to know the + // details of the type. lldb_private::Type will automatically call + // the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" When the definition + // needs to be defined. + assert(!dwarf->GetForwardDeclClangTypeToDie().count( + ClangUtil::RemoveFastQualifiers(clang_type) + .GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + // Can't assume m_ast.GetSymbolFile() is actually a + // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple + // binaries. + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = + clang_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie() + [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = + die.GetID(); + m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + } + } - case DW_TAG_enumeration_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + // If we made a clang type, set the trivial abi if applicable: We only + // do this for pass by value - which implies the Trivial ABI. There + // isn't a way to assert that something that would normally be pass by + // value is pass by reference, so we ignore that attribute if set. + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) { + record_decl->setHasTrivialSpecialMemberForCall(); + } + } - bool is_scoped = false; - DWARFFormValue encoding_form; + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) + record_decl->setArgPassingRestrictions( + clang::RecordDecl::APK_CannotPassInRegs); + } - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - 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: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_type: - encoding_form = form_value; - break; - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - case DW_AT_accessibility: - break; // accessibility = - // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - case DW_AT_enum_class: - is_scoped = form_value.Boolean(); - break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_bit_stride: - case DW_AT_byte_stride: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } - } - } + } break; - if (is_forward_declaration) { - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - type_sp = - dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = - debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } - } + case DW_TAG_enumeration_type: { + if (attrs.is_forward_declaration) { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, - type_sp->GetID()); - } + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = - GetCachedClangDeclContextForDIE(dwarf->DebugInfo()->GetDIE( - DIERef(type_sp->GetID(), dwarf))); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; - } - } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - CompilerType enumerator_clang_type; - clang_type.SetCompilerType( - &m_ast, - dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - if (encoding_form.IsValid()) { - Type *enumerator_type = - dwarf->ResolveTypeUID(DIERef(encoding_form)); - if (enumerator_type) - enumerator_clang_type = enumerator_type->GetFullCompilerType(); - } + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - if (!enumerator_clang_type) { - if (byte_size > 0) { - enumerator_clang_type = - m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( - NULL, DW_ATE_signed, byte_size * 8); - } else { - enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); - } - } + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); + } + } - clang_type = m_ast.CreateEnumerationType( - type_name_cstr, GetClangDeclContextContainingDIE(die, nullptr), - decl, enumerator_clang_type, is_scoped); - } else { - enumerator_clang_type = - m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); - } + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } - LinkDeclContextToDIE( - ClangASTContext::GetDeclContextForType(clang_type), die); - - type_sp.reset(new Type( - die.GetID(), dwarf, type_name_const_str, byte_size, NULL, - DIERef(encoding_form).GetUID(dwarf), Type::eEncodingIsUID, &decl, - clang_type, Type::eResolveStateForward)); - - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - if (die.HasChildren()) { - SymbolContext cu_sc(die.GetLLDBCompileUnit()); - bool is_signed = false; - enumerator_clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(cu_sc, clang_type, is_signed, - type_sp->GetByteSize(), die); - } - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), type_name_cstr); - } + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + CompilerType enumerator_clang_type; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + if (attrs.type.IsValid()) { + Type *enumerator_type = + dwarf->ResolveTypeUID(attrs.type.Reference(), true); + if (enumerator_type) + enumerator_clang_type = enumerator_type->GetFullCompilerType(); + } + + if (!enumerator_clang_type) { + if (attrs.byte_size) { + enumerator_clang_type = + m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( + NULL, DW_ATE_signed, *attrs.byte_size * 8); + } else { + enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); } - } break; + } - case DW_TAG_inlined_subroutine: - case DW_TAG_subprogram: - case DW_TAG_subroutine_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + clang_type = m_ast.CreateEnumerationType( + attrs.name.GetCString(), + GetClangDeclContextContainingDIE(die, nullptr), attrs.decl, + enumerator_clang_type, attrs.is_scoped_enum); + } else { + enumerator_clang_type = + m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); + } - DWARFFormValue type_die_form; - bool is_variadic = false; - bool is_inline = false; - bool is_static = false; - bool is_virtual = false; - bool is_explicit = false; - bool is_artificial = false; - bool has_template_params = false; - DWARFFormValue specification_die_form; - DWARFFormValue abstract_origin_die_form; - dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET; + LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), + die); - unsigned type_quals = 0; - clang::StorageClass storage = - clang::SC_None; //, Extern, Static, PrivateExtern - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - 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: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_linkage_name: - case DW_AT_MIPS_linkage_name: - mangled_name_cstr = form_value.AsCString(); - break; - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - case DW_AT_declaration: - break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_inline: - is_inline = form_value.Boolean(); - break; - case DW_AT_virtuality: - is_virtual = form_value.Boolean(); - break; - case DW_AT_explicit: - is_explicit = form_value.Boolean(); - break; - case DW_AT_artificial: - is_artificial = form_value.Boolean(); - break; - - case DW_AT_external: - if (form_value.Unsigned()) { - if (storage == clang::SC_None) - storage = clang::SC_Extern; - else - storage = clang::SC_PrivateExtern; - } - break; - - case DW_AT_specification: - specification_die_form = form_value; - break; - - case DW_AT_abstract_origin: - abstract_origin_die_form = form_value; - break; - - case DW_AT_object_pointer: - object_pointer_die_offset = form_value.Reference(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_address_class: - case DW_AT_calling_convention: - case DW_AT_data_location: - case DW_AT_elemental: - case DW_AT_entry_pc: - case DW_AT_frame_base: - case DW_AT_high_pc: - case DW_AT_low_pc: - case DW_AT_prototyped: - case DW_AT_pure: - case DW_AT_ranges: - case DW_AT_recursive: - case DW_AT_return_addr: - case DW_AT_segment: - case DW_AT_start_scope: - case DW_AT_static_link: - case DW_AT_trampoline: - case DW_AT_visibility: - case DW_AT_vtable_elem_location: - case DW_AT_description: - case DW_AT_sibling: - break; - } - } - } - } + type_sp = std::make_shared<Type>( + die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, + dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID, + &attrs.decl, clang_type, Type::eResolveStateForward); - std::string object_pointer_name; - if (object_pointer_die_offset != DW_INVALID_OFFSET) { - DWARFDIE object_pointer_die = die.GetDIE(object_pointer_die_offset); - if (object_pointer_die) { - const char *object_pointer_name_cstr = object_pointer_die.GetName(); - if (object_pointer_name_cstr) - object_pointer_name = object_pointer_name_cstr; - } - } + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + if (die.HasChildren()) { + bool is_signed = false; + enumerator_clang_type.IsIntegerType(is_signed); + ParseChildEnumerators(clang_type, is_signed, + type_sp->GetByteSize().getValueOr(0), die); + } + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), attrs.name.GetCString()); + } + } break; - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); + case DW_TAG_inlined_subroutine: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: { + bool is_variadic = false; + bool is_static = false; + bool has_template_params = false; + + unsigned type_quals = 0; + + std::string object_pointer_name; + if (attrs.object_pointer) { + const char *object_pointer_name_cstr = attrs.object_pointer.GetName(); + if (object_pointer_name_cstr) + object_pointer_name = object_pointer_name_cstr; + } - CompilerType return_clang_type; - Type *func_type = NULL; + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); - if (type_die_form.IsValid()) - func_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); + CompilerType return_clang_type; + Type *func_type = NULL; - if (func_type) - return_clang_type = func_type->GetForwardCompilerType(); - else - return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); + if (attrs.type.IsValid()) + func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true); - std::vector<CompilerType> function_param_types; - std::vector<clang::ParmVarDecl *> function_param_decls; + if (func_type) + return_clang_type = func_type->GetForwardCompilerType(); + else + return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); - // Parse the function children for the parameters + std::vector<CompilerType> function_param_types; + std::vector<clang::ParmVarDecl *> function_param_decls; - DWARFDIE decl_ctx_die; - clang::DeclContext *containing_decl_ctx = - GetClangDeclContextContainingDIE(die, &decl_ctx_die); - const clang::Decl::Kind containing_decl_kind = - containing_decl_ctx->getDeclKind(); - - bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind); - // Start off static. This will be set to false in - // ParseChildParameters(...) if we find a "this" parameters as the - // first parameter - if (is_cxx_method) { - is_static = true; - } + // Parse the function children for the parameters - if (die.HasChildren()) { - bool skip_artificial = true; - ParseChildParameters(*sc.comp_unit, containing_decl_ctx, die, - skip_artificial, is_static, is_variadic, - has_template_params, function_param_types, - function_param_decls, type_quals); - } + DWARFDIE decl_ctx_die; + clang::DeclContext *containing_decl_ctx = + GetClangDeclContextContainingDIE(die, &decl_ctx_die); + const clang::Decl::Kind containing_decl_kind = + containing_decl_ctx->getDeclKind(); - bool ignore_containing_context = false; - // Check for templatized class member functions. If we had any - // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter - // the DW_TAG_subprogram DIE, then we can't let this become a method in - // a class. Why? Because templatized functions are only emitted if one - // of the templatized methods is used in the current compile unit and - // we will end up with classes that may or may not include these member - // functions and this means one class won't match another class - // definition and it affects our ability to use a class in the clang - // expression parser. So for the greater good, we currently must not - // allow any template member functions in a class definition. - if (is_cxx_method && has_template_params) { - ignore_containing_context = true; - is_cxx_method = false; - } + bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind); + // Start off static. This will be set to false in + // ParseChildParameters(...) if we find a "this" parameters as the + // first parameter + if (is_cxx_method) { + is_static = true; + } - // clang_type will get the function prototype clang type after this - // call - clang_type = m_ast.CreateFunctionType( - return_clang_type, function_param_types.data(), - function_param_types.size(), is_variadic, type_quals); - - if (type_name_cstr) { - bool type_handled = false; - if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { - ObjCLanguage::MethodName objc_method(type_name_cstr, true); - if (objc_method.IsValid(true)) { - CompilerType class_opaque_type; - ConstString class_name(objc_method.GetClassName()); - if (class_name) { - TypeSP complete_objc_class_type_sp( - dwarf->FindCompleteObjCDefinitionTypeForDIE( - DWARFDIE(), class_name, false)); - - if (complete_objc_class_type_sp) { - CompilerType type_clang_forward_type = - complete_objc_class_type_sp->GetForwardCompilerType(); - if (ClangASTContext::IsObjCObjectOrInterfaceType( - type_clang_forward_type)) - class_opaque_type = type_clang_forward_type; - } - } + if (die.HasChildren()) { + bool skip_artificial = true; + ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static, + is_variadic, has_template_params, + function_param_types, function_param_decls, + type_quals); + } - if (class_opaque_type) { - // If accessibility isn't set to anything valid, assume public - // for now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; - - clang::ObjCMethodDecl *objc_method_decl = - m_ast.AddMethodToObjCObjectType( - class_opaque_type, type_name_cstr, clang_type, - accessibility, is_artificial, is_variadic); - type_handled = objc_method_decl != NULL; - if (type_handled) { - LinkDeclContextToDIE( - ClangASTContext::GetAsDeclContext(objc_method_decl), die); - m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), " - "please file a bug and attach the file at the start of " - "this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + bool ignore_containing_context = false; + // Check for templatized class member functions. If we had any + // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter + // the DW_TAG_subprogram DIE, then we can't let this become a method in + // a class. Why? Because templatized functions are only emitted if one + // of the templatized methods is used in the current compile unit and + // we will end up with classes that may or may not include these member + // functions and this means one class won't match another class + // definition and it affects our ability to use a class in the clang + // expression parser. So for the greater good, we currently must not + // allow any template member functions in a class definition. + if (is_cxx_method && has_template_params) { + ignore_containing_context = true; + is_cxx_method = false; + } + + // clang_type will get the function prototype clang type after this + // call + clang_type = m_ast.CreateFunctionType( + return_clang_type, function_param_types.data(), + function_param_types.size(), is_variadic, type_quals); + + if (attrs.name) { + bool type_handled = false; + if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { + ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true); + if (objc_method.IsValid(true)) { + CompilerType class_opaque_type; + ConstString class_name(objc_method.GetClassName()); + if (class_name) { + TypeSP complete_objc_class_type_sp( + dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(), + class_name, false)); + + if (complete_objc_class_type_sp) { + CompilerType type_clang_forward_type = + complete_objc_class_type_sp->GetForwardCompilerType(); + if (ClangASTContext::IsObjCObjectOrInterfaceType( + type_clang_forward_type)) + class_opaque_type = type_clang_forward_type; + } + } + + if (class_opaque_type) { + // If accessibility isn't set to anything valid, assume public + // for now... + if (attrs.accessibility == eAccessNone) + attrs.accessibility = eAccessPublic; + + clang::ObjCMethodDecl *objc_method_decl = + m_ast.AddMethodToObjCObjectType( + class_opaque_type, attrs.name.GetCString(), clang_type, + attrs.accessibility, attrs.is_artificial, is_variadic); + type_handled = objc_method_decl != NULL; + if (type_handled) { + LinkDeclContextToDIE( + ClangASTContext::GetAsDeclContext(objc_method_decl), die); + m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), " + "please file a bug and attach the file at the start of " + "this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + } + } + } else if (is_cxx_method) { + // Look at the parent of this DIE and see if is is a class or + // struct and see if this is actually a C++ method + Type *class_type = dwarf->ResolveType(decl_ctx_die); + if (class_type) { + bool alternate_defn = false; + if (class_type->GetID() != decl_ctx_die.GetID() || + decl_ctx_die.GetContainingDWOModuleDIE()) { + alternate_defn = true; + + // We uniqued the parent class of this function to another + // class so we now need to associate all dies under + // "decl_ctx_die" to DIEs in the DIE for "class_type"... + DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); + + if (class_type_die) { + std::vector<DWARFDIE> failures; + + CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, + class_type, failures); + + // FIXME do something with these failures that's smarter + // than + // just dropping them on the ground. Unfortunately classes + // don't like having stuff added to them after their + // definitions are complete... + + type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + type_sp = type_ptr->shared_from_this(); + break; } } - } else if (is_cxx_method) { - // Look at the parent of this DIE and see if is is a class or - // struct and see if this is actually a C++ method - Type *class_type = dwarf->ResolveType(decl_ctx_die); - if (class_type) { - bool alternate_defn = false; - if (class_type->GetID() != decl_ctx_die.GetID() || - decl_ctx_die.GetContainingDWOModuleDIE()) { - alternate_defn = true; - - // We uniqued the parent class of this function to another - // class so we now need to associate all dies under - // "decl_ctx_die" to DIEs in the DIE for "class_type"... - SymbolFileDWARF *class_symfile = NULL; - DWARFDIE class_type_die; - - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex( - SymbolFileDWARFDebugMap::GetOSOIndexFromUserID( - class_type->GetID())); - class_type_die = class_symfile->DebugInfo()->GetDIE( - DIERef(class_type->GetID(), dwarf)); - } else { - class_symfile = dwarf; - class_type_die = dwarf->DebugInfo()->GetDIE( - DIERef(class_type->GetID(), dwarf)); - } - if (class_type_die) { - DWARFDIECollection failures; - - CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, - class_type, failures); - - // FIXME do something with these failures that's smarter - // than - // just dropping them on the ground. Unfortunately classes - // don't like having stuff added to them after their - // definitions are complete... - - type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); - break; - } - } - } + } - if (specification_die_form.IsValid()) { - // We have a specification which we are going to base our - // function prototype off of, so we need this type to be - // completed so that the m_die_to_decl_ctx for the method in - // the specification has a valid clang decl context. - class_type->GetForwardCompilerType(); - // If we have a specification, then the function type should - // have been made with the specification and not with this - // die. - DWARFDIE spec_die = dwarf->DebugInfo()->GetDIE( - DIERef(specification_die_form)); - clang::DeclContext *spec_clang_decl_ctx = - GetClangDeclContextForDIE(spec_die); - if (spec_clang_decl_ctx) { - LinkDeclContextToDIE(spec_clang_decl_ctx, die); - } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8" PRIx64 - ") has no decl\n", - die.GetID(), specification_die_form.Reference()); - } - type_handled = true; - } else if (abstract_origin_die_form.IsValid()) { - // We have a specification which we are going to base our - // function prototype off of, so we need this type to be - // completed so that the m_die_to_decl_ctx for the method in - // the abstract origin has a valid clang decl context. + if (attrs.specification.IsValid()) { + // We have a specification which we are going to base our + // function prototype off of, so we need this type to be + // completed so that the m_die_to_decl_ctx for the method in + // the specification has a valid clang decl context. + class_type->GetForwardCompilerType(); + // If we have a specification, then the function type should + // have been made with the specification and not with this + // die. + DWARFDIE spec_die = attrs.specification.Reference(); + clang::DeclContext *spec_clang_decl_ctx = + GetClangDeclContextForDIE(spec_die); + if (spec_clang_decl_ctx) { + LinkDeclContextToDIE(spec_clang_decl_ctx, die); + } else { + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x" + ") has no decl\n", + die.GetID(), spec_die.GetOffset()); + } + type_handled = true; + } else if (attrs.abstract_origin.IsValid()) { + // We have a specification which we are going to base our + // function prototype off of, so we need this type to be + // completed so that the m_die_to_decl_ctx for the method in + // the abstract origin has a valid clang decl context. + class_type->GetForwardCompilerType(); + + DWARFDIE abs_die = attrs.abstract_origin.Reference(); + clang::DeclContext *abs_clang_decl_ctx = + GetClangDeclContextForDIE(abs_die); + if (abs_clang_decl_ctx) { + LinkDeclContextToDIE(abs_clang_decl_ctx, die); + } else { + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x" + ") has no decl\n", + die.GetID(), abs_die.GetOffset()); + } + type_handled = true; + } else { + CompilerType class_opaque_type = class_type->GetForwardCompilerType(); - - DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE( - DIERef(abstract_origin_die_form)); - clang::DeclContext *abs_clang_decl_ctx = - GetClangDeclContextForDIE(abs_die); - if (abs_clang_decl_ctx) { - LinkDeclContextToDIE(abs_clang_decl_ctx, die); + if (ClangASTContext::IsCXXClassType(class_opaque_type)) { + if (class_opaque_type.IsBeingDefined() || alternate_defn) { + if (!is_static && !die.HasChildren()) { + // We have a C++ member function with no children (this + // pointer!) and clang will get mad if we try and make + // a function that isn't well formed in the DWARF, so + // we will just skip it... + type_handled = true; } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8" PRIx64 - ") has no decl\n", - die.GetID(), abstract_origin_die_form.Reference()); - } - type_handled = true; - } else { - CompilerType class_opaque_type = - class_type->GetForwardCompilerType(); - if (ClangASTContext::IsCXXClassType(class_opaque_type)) { - if (class_opaque_type.IsBeingDefined() || alternate_defn) { - if (!is_static && !die.HasChildren()) { - // We have a C++ member function with no children (this - // pointer!) and clang will get mad if we try and make - // a function that isn't well formed in the DWARF, so - // we will just skip it... - type_handled = true; - } else { - bool add_method = true; - if (alternate_defn) { - // If an alternate definition for the class exists, - // then add the method only if an equivalent is not - // already present. - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl( - class_opaque_type.GetOpaqueQualType()); - if (record_decl) { - for (auto method_iter = record_decl->method_begin(); - method_iter != record_decl->method_end(); - method_iter++) { - clang::CXXMethodDecl *method_decl = *method_iter; - if (method_decl->getNameInfo().getAsString() == - std::string(type_name_cstr)) { - if (method_decl->getType() == - ClangUtil::GetQualType(clang_type)) { - add_method = false; - LinkDeclContextToDIE( - ClangASTContext::GetAsDeclContext( - method_decl), - die); - type_handled = true; - - break; - } - } + bool add_method = true; + if (alternate_defn) { + // If an alternate definition for the class exists, + // then add the method only if an equivalent is not + // already present. + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl( + class_opaque_type.GetOpaqueQualType()); + if (record_decl) { + for (auto method_iter = record_decl->method_begin(); + method_iter != record_decl->method_end(); + method_iter++) { + clang::CXXMethodDecl *method_decl = *method_iter; + if (method_decl->getNameInfo().getAsString() == + attrs.name.GetStringRef()) { + if (method_decl->getType() == + ClangUtil::GetQualType(clang_type)) { + add_method = false; + LinkDeclContextToDIE( + ClangASTContext::GetAsDeclContext( + method_decl), + die); + type_handled = true; + + break; } } } + } + } - if (add_method) { - llvm::PrettyStackTraceFormat stack_trace( - "SymbolFileDWARF::ParseType() is adding a method " - "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", - type_name_cstr, - class_type->GetName().GetCString(), die.GetID(), - dwarf->GetObjectFile() - ->GetFileSpec() - .GetPath() - .c_str()); - - const bool is_attr_used = false; - // Neither GCC 4.2 nor clang++ currently set a valid - // accessibility in the DWARF for C++ methods... - // Default to public for now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; - - clang::CXXMethodDecl *cxx_method_decl = - m_ast.AddMethodToCXXRecordType( - class_opaque_type.GetOpaqueQualType(), - type_name_cstr, mangled_name_cstr, clang_type, - accessibility, is_virtual, is_static, - is_inline, is_explicit, is_attr_used, - is_artificial); - - type_handled = cxx_method_decl != NULL; - - if (type_handled) { - LinkDeclContextToDIE( - ClangASTContext::GetAsDeclContext( - cxx_method_decl), - die); - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName( - object_pointer_name.c_str()); - if (log) - log->Printf( - "Setting object pointer name: %s on method " - "object %p.\n", - object_pointer_name.c_str(), - static_cast<void *>(cxx_method_decl)); - } - m_ast.SetMetadata(cxx_method_decl, metadata); - } else { - ignore_containing_context = true; - } + if (add_method) { + llvm::PrettyStackTraceFormat stack_trace( + "SymbolFileDWARF::ParseType() is adding a method " + "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", + attrs.name.GetCString(), + class_type->GetName().GetCString(), die.GetID(), + dwarf->GetObjectFile() + ->GetFileSpec() + .GetPath() + .c_str()); + + const bool is_attr_used = false; + // Neither GCC 4.2 nor clang++ currently set a valid + // accessibility in the DWARF for C++ methods... + // Default to public for now... + if (attrs.accessibility == eAccessNone) + attrs.accessibility = eAccessPublic; + + clang::CXXMethodDecl *cxx_method_decl = + m_ast.AddMethodToCXXRecordType( + class_opaque_type.GetOpaqueQualType(), + attrs.name.GetCString(), attrs.mangled_name, + clang_type, attrs.accessibility, attrs.is_virtual, + is_static, attrs.is_inline, attrs.is_explicit, + is_attr_used, attrs.is_artificial); + + type_handled = cxx_method_decl != NULL; + + if (type_handled) { + LinkDeclContextToDIE( + ClangASTContext::GetAsDeclContext(cxx_method_decl), + die); + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + + if (!object_pointer_name.empty()) { + metadata.SetObjectPtrName( + object_pointer_name.c_str()); + if (log) + log->Printf( + "Setting object pointer name: %s on method " + "object %p.\n", + object_pointer_name.c_str(), + static_cast<void *>(cxx_method_decl)); } + m_ast.SetMetadata(cxx_method_decl, metadata); + } else { + ignore_containing_context = true; } - } else { - // We were asked to parse the type for a method in a - // class, yet the class hasn't been asked to complete - // itself through the clang::ExternalASTSource protocol, - // so we need to just have the class complete itself and - // do things the right way, then our - // DIE should then have an entry in the - // dwarf->GetDIEToType() map. First - // we need to modify the dwarf->GetDIEToType() so it - // doesn't think we are trying to parse this DIE - // anymore... - dwarf->GetDIEToType()[die.GetDIE()] = NULL; - - // Now we get the full type to force our class type to - // complete itself using the clang::ExternalASTSource - // protocol which will parse all base classes and all - // methods (including the method for this DIE). - class_type->GetFullCompilerType(); - - // The type for this DIE should have been filled in the - // function call above - type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); - break; - } - - // FIXME This is fixing some even uglier behavior but we - // really need to - // uniq the methods of each class as well as the class - // itself. <rdar://problem/11240464> - type_handled = true; } } - } - } - } - } - - if (!type_handled) { - clang::FunctionDecl *function_decl = nullptr; - - if (abstract_origin_die_form.IsValid()) { - DWARFDIE abs_die = - dwarf->DebugInfo()->GetDIE(DIERef(abstract_origin_die_form)); - - SymbolContext sc; - - if (dwarf->ResolveType(abs_die)) { - function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( - GetCachedClangDeclContextForDIE(abs_die)); + } else { + // We were asked to parse the type for a method in a + // class, yet the class hasn't been asked to complete + // itself through the clang::ExternalASTSource protocol, + // so we need to just have the class complete itself and + // do things the right way, then our + // DIE should then have an entry in the + // dwarf->GetDIEToType() map. First + // we need to modify the dwarf->GetDIEToType() so it + // doesn't think we are trying to parse this DIE + // anymore... + dwarf->GetDIEToType()[die.GetDIE()] = NULL; + + // Now we get the full type to force our class type to + // complete itself using the clang::ExternalASTSource + // protocol which will parse all base classes and all + // methods (including the method for this DIE). + class_type->GetFullCompilerType(); + + // The type for this DIE should have been filled in the + // function call above + type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + type_sp = type_ptr->shared_from_this(); + break; + } - if (function_decl) { - LinkDeclContextToDIE(function_decl, die); + // FIXME This is fixing some even uglier behavior but we + // really need to + // uniq the methods of each class as well as the class + // itself. <rdar://problem/11240464> + type_handled = true; } } } + } + } + } - if (!function_decl) { - // We just have a function that isn't part of a class - function_decl = m_ast.CreateFunctionDeclaration( - ignore_containing_context ? m_ast.GetTranslationUnitDecl() - : containing_decl_ctx, - type_name_cstr, clang_type, storage, is_inline); - - if (has_template_params) { - ClangASTContext::TemplateParameterInfos template_param_infos; - ParseTemplateParameterInfos(die, template_param_infos); - clang::FunctionTemplateDecl *func_template_decl = - m_ast.CreateFunctionTemplateDecl( - containing_decl_ctx, function_decl, type_name_cstr, - template_param_infos); - m_ast.CreateFunctionTemplateSpecializationInfo( - function_decl, func_template_decl, template_param_infos); - } - - lldbassert(function_decl); - - if (function_decl) { - LinkDeclContextToDIE(function_decl, die); + if (!type_handled) { + clang::FunctionDecl *function_decl = nullptr; + clang::FunctionDecl *template_function_decl = nullptr; - if (!function_param_decls.empty()) - m_ast.SetFunctionParameters(function_decl, - &function_param_decls.front(), - function_param_decls.size()); + if (attrs.abstract_origin.IsValid()) { + DWARFDIE abs_die = attrs.abstract_origin.Reference(); - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); + if (dwarf->ResolveType(abs_die)) { + function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( + GetCachedClangDeclContextForDIE(abs_die)); - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName(object_pointer_name.c_str()); - if (log) - log->Printf("Setting object pointer name: %s on function " - "object %p.", - object_pointer_name.c_str(), - static_cast<void *>(function_decl)); - } - m_ast.SetMetadata(function_decl, metadata); - } + if (function_decl) { + LinkDeclContextToDIE(function_decl, die); } } } - type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, 0, NULL, - LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, - clang_type, Type::eResolveStateFull)); - assert(type_sp.get()); - } break; - - case DW_TAG_array_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - - DWARFFormValue type_die_form; - int64_t first_index = 0; - uint32_t byte_stride = 0; - uint32_t bit_stride = 0; - bool is_vector = false; - const size_t num_attributes = die.GetAttributes(attributes); - - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - 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: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_byte_size: - break; // byte_size = form_value.Unsigned(); break; - case DW_AT_byte_stride: - byte_stride = form_value.Unsigned(); - break; - case DW_AT_bit_stride: - bit_stride = form_value.Unsigned(); - break; - case DW_AT_GNU_vector: - is_vector = form_value.Boolean(); - break; - case DW_AT_accessibility: - break; // accessibility = - // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: - break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_ordering: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } - } - } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); + if (!function_decl) { + // We just have a function that isn't part of a class + function_decl = m_ast.CreateFunctionDeclaration( + ignore_containing_context ? m_ast.GetTranslationUnitDecl() + : containing_decl_ctx, + attrs.name.GetCString(), clang_type, attrs.storage, + attrs.is_inline); - DIERef type_die_ref(type_die_form); - Type *element_type = dwarf->ResolveTypeUID(type_die_ref); + if (has_template_params) { + ClangASTContext::TemplateParameterInfos template_param_infos; + ParseTemplateParameterInfos(die, template_param_infos); + template_function_decl = m_ast.CreateFunctionDeclaration( + ignore_containing_context ? m_ast.GetTranslationUnitDecl() + : containing_decl_ctx, + attrs.name.GetCString(), clang_type, attrs.storage, + attrs.is_inline); + clang::FunctionTemplateDecl *func_template_decl = + m_ast.CreateFunctionTemplateDecl( + containing_decl_ctx, template_function_decl, + attrs.name.GetCString(), template_param_infos); + m_ast.CreateFunctionTemplateSpecializationInfo( + function_decl, func_template_decl, template_param_infos); + } - if (element_type) { - auto array_info = ParseChildArrayInfo(die); - if (array_info) { - first_index = array_info->first_index; - byte_stride = array_info->byte_stride; - bit_stride = array_info->bit_stride; - } - if (byte_stride == 0 && bit_stride == 0) - byte_stride = element_type->GetByteSize(); - CompilerType array_element_type = - element_type->GetForwardCompilerType(); - - if (ClangASTContext::IsCXXClassType(array_element_type) && - !array_element_type.GetCompleteType()) { - ModuleSP module_sp = die.GetModule(); - if (module_sp) { - if (die.GetCU()->GetProducer() == eProducerClang) - module_sp->ReportError( - "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " - "class/union/struct element type DIE 0x%8.8x that is a " - "forward declaration, not a complete definition.\nTry " - "compiling the source file with -fstandalone-debug or " - "disable -gmodules", - die.GetOffset(), type_die_ref.die_offset); - else - module_sp->ReportError( - "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " - "class/union/struct element type DIE 0x%8.8x that is a " - "forward declaration, not a complete definition.\nPlease " - "file a bug against the compiler and include the " - "preprocessed output for %s", - die.GetOffset(), type_die_ref.die_offset, - die.GetLLDBCompileUnit() - ? die.GetLLDBCompileUnit()->GetPath().c_str() - : "the source file"); - } + lldbassert(function_decl); - // We have no choice other than to pretend that the element class - // type is complete. If we don't do this, clang will crash when - // trying to layout the class. Since we provide layout - // assistance, all ivars in this class and other classes will be - // fine, this is the best we can do short of crashing. - if (ClangASTContext::StartTagDeclarationDefinition( - array_element_type)) { - ClangASTContext::CompleteTagDeclarationDefinition( - array_element_type); - } else { - module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to " - "start its definition.\nPlease file a " - "bug and attach the file at the start " - "of this error message", - type_die_ref.die_offset); - } - } + if (function_decl) { + LinkDeclContextToDIE(function_decl, die); - uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; - if (array_info && array_info->element_orders.size() > 0) { - uint64_t num_elements = 0; - auto end = array_info->element_orders.rend(); - for (auto pos = array_info->element_orders.rbegin(); pos != end; - ++pos) { - num_elements = *pos; - clang_type = m_ast.CreateArrayType(array_element_type, - num_elements, is_vector); - array_element_type = clang_type; - array_element_bit_stride = - num_elements ? array_element_bit_stride * num_elements - : array_element_bit_stride; - } - } else { - clang_type = - m_ast.CreateArrayType(array_element_type, 0, is_vector); + if (!function_param_decls.empty()) { + m_ast.SetFunctionParameters(function_decl, + &function_param_decls.front(), + function_param_decls.size()); + if (template_function_decl) + m_ast.SetFunctionParameters(template_function_decl, + &function_param_decls.front(), + function_param_decls.size()); } - ConstString empty_name; - type_sp.reset(new Type( - die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, - NULL, DIERef(type_die_form).GetUID(dwarf), Type::eEncodingIsUID, - &decl, clang_type, Type::eResolveStateFull)); - type_sp->SetEncodingType(element_type); - m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), - die.GetID()); - } - } - } break; - - case DW_TAG_ptr_to_member_type: { - DWARFFormValue type_die_form; - DWARFFormValue containing_type_die_form; - - const size_t num_attributes = die.GetAttributes(attributes); - - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_containing_type: - containing_type_die_form = form_value; - break; - } - } - } - - Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); - Type *class_type = - dwarf->ResolveTypeUID(DIERef(containing_type_die_form)); - - CompilerType pointee_clang_type = - pointee_type->GetForwardCompilerType(); - CompilerType class_clang_type = class_type->GetLayoutCompilerType(); - clang_type = ClangASTContext::CreateMemberPointerType( - class_clang_type, pointee_clang_type); + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); - if (llvm::Optional<uint64_t> clang_type_size = - clang_type.GetByteSize(nullptr)) { - byte_size = *clang_type_size; - type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, - byte_size, NULL, LLDB_INVALID_UID, - Type::eEncodingIsUID, NULL, clang_type, - Type::eResolveStateForward)); + if (!object_pointer_name.empty()) { + metadata.SetObjectPtrName(object_pointer_name.c_str()); + if (log) + log->Printf("Setting object pointer name: %s on function " + "object %p.", + object_pointer_name.c_str(), + static_cast<void *>(function_decl)); + } + m_ast.SetMetadata(function_decl, metadata); } } - - break; } - default: - dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and " - "attach the file at the start of this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - break; + } + type_sp = std::make_shared<Type>( + die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, clang_type, Type::eResolveStateFull); + assert(type_sp.get()); + } break; + + case DW_TAG_array_type: { + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + DWARFDIE type_die = attrs.type.Reference(); + Type *element_type = dwarf->ResolveTypeUID(type_die, true); + + if (element_type) { + auto array_info = ParseChildArrayInfo(die); + if (array_info) { + attrs.byte_stride = array_info->byte_stride; + attrs.bit_stride = array_info->bit_stride; } + if (attrs.byte_stride == 0 && attrs.bit_stride == 0) + attrs.byte_stride = element_type->GetByteSize().getValueOr(0); + CompilerType array_element_type = element_type->GetForwardCompilerType(); + + if (ClangASTContext::IsCXXClassType(array_element_type) && + !array_element_type.GetCompleteType()) { + ModuleSP module_sp = die.GetModule(); + if (module_sp) { + if (die.GetCU()->GetProducer() == eProducerClang) + module_sp->ReportError( + "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " + "class/union/struct element type DIE 0x%8.8x that is a " + "forward declaration, not a complete definition.\nTry " + "compiling the source file with -fstandalone-debug or " + "disable -gmodules", + die.GetOffset(), type_die.GetOffset()); + else + module_sp->ReportError( + "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " + "class/union/struct element type DIE 0x%8.8x that is a " + "forward declaration, not a complete definition.\nPlease " + "file a bug against the compiler and include the " + "preprocessed output for %s", + die.GetOffset(), type_die.GetOffset(), + GetUnitName(die).c_str()); + } - if (type_sp.get()) { - DWARFDIE sc_parent_die = - SymbolFileDWARF::GetParentSymbolContextDIE(die); - dw_tag_t sc_parent_tag = sc_parent_die.Tag(); - - SymbolContextScope *symbol_context_scope = NULL; - if (sc_parent_tag == DW_TAG_compile_unit || - sc_parent_tag == DW_TAG_partial_unit) { - symbol_context_scope = sc.comp_unit; - } else if (sc.function != NULL && sc_parent_die) { - symbol_context_scope = - sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); - if (symbol_context_scope == NULL) - symbol_context_scope = sc.function; + // We have no choice other than to pretend that the element class + // type is complete. If we don't do this, clang will crash when + // trying to layout the class. Since we provide layout + // assistance, all ivars in this class and other classes will be + // fine, this is the best we can do short of crashing. + if (ClangASTContext::StartTagDeclarationDefinition( + array_element_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(array_element_type); + } else { + module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to " + "start its definition.\nPlease file a " + "bug and attach the file at the start " + "of this error message", + type_die.GetOffset()); } + } - if (symbol_context_scope != NULL) { - type_sp->SetSymbolContextScope(symbol_context_scope); + uint64_t array_element_bit_stride = + attrs.byte_stride * 8 + attrs.bit_stride; + if (array_info && array_info->element_orders.size() > 0) { + uint64_t num_elements = 0; + auto end = array_info->element_orders.rend(); + for (auto pos = array_info->element_orders.rbegin(); pos != end; + ++pos) { + num_elements = *pos; + clang_type = m_ast.CreateArrayType(array_element_type, num_elements, + attrs.is_vector); + array_element_type = clang_type; + array_element_bit_stride = + num_elements ? array_element_bit_stride * num_elements + : array_element_bit_stride; } + } else { + clang_type = m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector); + } + ConstString empty_name; + type_sp = std::make_shared<Type>( + die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr, + dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl, + clang_type, Type::eResolveStateFull); + type_sp->SetEncodingType(element_type); + m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID()); + } + } break; - // We are ready to put this type into the uniqued list up at the module - // level - type_list->Insert(type_sp); + case DW_TAG_ptr_to_member_type: { + Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true); + Type *class_type = + dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true); - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - } - } else if (type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); + CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType(); + CompilerType class_clang_type = class_type->GetLayoutCompilerType(); + + clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, + pointee_clang_type); + + if (llvm::Optional<uint64_t> clang_type_size = + clang_type.GetByteSize(nullptr)) { + type_sp = std::make_shared<Type>( + die.GetID(), dwarf, attrs.name, *clang_type_size, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type, + Type::eResolveStateForward); + } + + break; + } + default: + dwarf->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and " + "attach the file at the start of this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + break; + } + + if (type_sp.get()) { + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit || + sc_parent_tag == DW_TAG_partial_unit) { + symbol_context_scope = sc.comp_unit; + } else if (sc.function != NULL && sc_parent_die) { + symbol_context_scope = + sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; + } else + symbol_context_scope = sc.module_sp.get(); + + if (symbol_context_scope != NULL) { + type_sp->SetSymbolContextScope(symbol_context_scope); } + + // We are ready to put this type into the uniqued list up at the module + // level + type_list->Insert(type_sp); + + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); } return type_sp; } @@ -1920,9 +1697,9 @@ public: m_property_setter_name(property_setter_name), m_property_getter_name(property_getter_name), m_property_attributes(property_attributes) { - if (metadata != NULL) { - m_metadata_ap.reset(new ClangASTMetadata()); - *m_metadata_ap = *metadata; + if (metadata != nullptr) { + m_metadata_up.reset(new ClangASTMetadata()); + *m_metadata_up = *metadata; } } @@ -1940,9 +1717,9 @@ public: m_property_getter_name = rhs.m_property_getter_name; m_property_attributes = rhs.m_property_attributes; - if (rhs.m_metadata_ap.get()) { - m_metadata_ap.reset(new ClangASTMetadata()); - *m_metadata_ap = *rhs.m_metadata_ap; + if (rhs.m_metadata_up) { + m_metadata_up.reset(new ClangASTMetadata()); + *m_metadata_up = *rhs.m_metadata_up; } return *this; } @@ -1951,7 +1728,7 @@ public: return ClangASTContext::AddObjCClassProperty( m_class_opaque_type, m_property_name, m_property_opaque_type, m_ivar_decl, m_property_setter_name, m_property_getter_name, - m_property_attributes, m_metadata_ap.get()); + m_property_attributes, m_metadata_up.get()); } private: @@ -1962,7 +1739,7 @@ private: const char *m_property_setter_name; const char *m_property_getter_name; uint32_t m_property_attributes; - std::unique_ptr<ClangASTMetadata> m_metadata_ap; + std::unique_ptr<ClangASTMetadata> m_metadata_up; }; bool DWARFASTParserClang::ParseTemplateDIE( @@ -2015,7 +1792,7 @@ bool DWARFASTParserClang::ParseTemplateDIE( case DW_AT_type: if (attributes.ExtractFormValueAtIndex(i, form_value)) { - Type *lldb_type = die.ResolveTypeUID(DIERef(form_value)); + Type *lldb_type = die.ResolveTypeUID(form_value.Reference()); if (lldb_type) clang_type = lldb_type->GetForwardCompilerType(); } @@ -2118,7 +1895,6 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, return false; #if defined LLDB_CONFIGURATION_DEBUG - //---------------------------------------------------------------------- // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES environment // variable can be set with one or more typenames separated by ';' // characters. This will cause this function to not complete any types whose @@ -2128,7 +1904,6 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, // // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo;Bar;Baz - //---------------------------------------------------------------------- const char *dont_complete_typenames_cstr = getenv("LLDB_DWARF_DONT_COMPLETE_TYPENAMES"); if (dont_complete_typenames_cstr && dont_complete_typenames_cstr[0]) { @@ -2191,26 +1966,21 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, default_accessibility = eAccessPrivate; } - SymbolContext sc(die.GetLLDBCompileUnit()); std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases; std::vector<int> member_accessibilities; bool is_a_class = false; // Parse members and base classes first - DWARFDIECollection member_function_dies; + std::vector<DWARFDIE> member_function_dies; DelayedPropertyList delayed_properties; - ParseChildMembers(sc, die, clang_type, class_language, bases, + ParseChildMembers(die, clang_type, class_language, bases, member_accessibilities, member_function_dies, delayed_properties, default_accessibility, is_a_class, layout_info); // Now parse any methods if there were any... - size_t num_functions = member_function_dies.Size(); - if (num_functions > 0) { - for (size_t i = 0; i < num_functions; ++i) { - dwarf->ResolveType(member_function_dies.GetDIEAtIndex(i)); - } - } + for (const DWARFDIE &die : member_function_dies) + dwarf->ResolveType(die); if (class_language == eLanguageTypeObjC) { ConstString class_name(clang_type.GetTypeName()); @@ -2313,7 +2083,7 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, !layout_info.base_offsets.empty() || !layout_info.vbase_offsets.empty()) { if (type) - layout_info.bit_size = type->GetByteSize() * 8; + layout_info.bit_size = type->GetByteSize().getValueOr(0) * 8; if (layout_info.bit_size == 0) layout_info.bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; @@ -2394,11 +2164,10 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, case DW_TAG_enumeration_type: if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { if (die.HasChildren()) { - SymbolContext sc(die.GetLLDBCompileUnit()); bool is_signed = false; clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), - die); + ParseChildEnumerators(clang_type, is_signed, + type->GetByteSize().getValueOr(0), die); } ClangASTContext::CompleteTagDeclarationDefinition(clang_type); } @@ -2447,8 +2216,8 @@ DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) { } size_t DWARFASTParserClang::ParseChildEnumerators( - const SymbolContext &sc, lldb_private::CompilerType &clang_type, - bool is_signed, uint32_t enumerator_byte_size, const DWARFDIE &parent_die) { + lldb_private::CompilerType &clang_type, bool is_signed, + uint32_t enumerator_byte_size, const DWARFDIE &parent_die) { if (!parent_die) return 0; @@ -2461,7 +2230,7 @@ size_t DWARFASTParserClang::ParseChildEnumerators( DWARFAttributes attributes; const size_t num_child_attributes = die.GetAttributes(attributes); if (num_child_attributes > 0) { - const char *name = NULL; + const char *name = nullptr; bool got_value = false; int64_t enum_value = 0; Declaration decl; @@ -2487,8 +2256,7 @@ size_t DWARFASTParserClang::ParseChildEnumerators( case DW_AT_description: default: case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); + decl.SetFile(die.GetCU()->GetFile(form_value.Unsigned())); break; case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); @@ -2564,20 +2332,20 @@ protected: Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, const DWARFDIE &die) { DWARFRangeList func_ranges; - const char *name = NULL; - const char *mangled = NULL; + const char *name = nullptr; + const char *mangled = nullptr; int decl_file = 0; int decl_line = 0; int decl_column = 0; int call_file = 0; int call_line = 0; int call_column = 0; - DWARFExpression frame_base(die.GetCU()); + DWARFExpression frame_base; const dw_tag_t tag = die.Tag(); if (tag != DW_TAG_subprogram) - return NULL; + return nullptr; if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column, @@ -2603,7 +2371,8 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, func_name.SetValue(ConstString(mangled), true); else if ((die.GetParent().Tag() == DW_TAG_compile_unit || die.GetParent().Tag() == DW_TAG_partial_unit) && - Language::LanguageIsCPlusPlus(die.GetLanguage()) && name && + Language::LanguageIsCPlusPlus(die.GetLanguage()) && + !Language::LanguageIsObjC(die.GetLanguage()) && name && strcmp(name, "main") != 0) { // If the mangled name is not present in the DWARF, generate the // demangled name using the decl context. We skip if the function is @@ -2622,9 +2391,9 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); - ParseChildParameters(comp_unit, containing_decl_ctx, die, true, - is_static, is_variadic, has_template_params, - param_types, param_decls, type_quals); + ParseChildParameters(containing_decl_ctx, die, true, is_static, + is_variadic, has_template_params, param_types, + param_decls, type_quals); sstr << "("; for (size_t i = 0; i < param_types.size(); i++) { if (i > 0) @@ -2642,26 +2411,26 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, func_name.SetValue(ConstString(name), false); FunctionSP func_sp; - std::unique_ptr<Declaration> decl_ap; + std::unique_ptr<Declaration> decl_up; if (decl_file != 0 || decl_line != 0 || decl_column != 0) - decl_ap.reset(new Declaration( - comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file), - decl_line, decl_column)); + decl_up.reset(new Declaration(die.GetCU()->GetFile(decl_file), + decl_line, decl_column)); SymbolFileDWARF *dwarf = die.GetDWARF(); // Supply the type _only_ if it has already been parsed Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE()); - assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED); if (dwarf->FixupAddress(func_range.GetBaseAddress())) { const user_id_t func_user_id = die.GetID(); - func_sp.reset(new Function(&comp_unit, + func_sp = + std::make_shared<Function>(&comp_unit, func_user_id, // UserID is the DIE offset func_user_id, func_name, func_type, - func_range)); // first address range + func_range); // first address range - if (func_sp.get() != NULL) { + if (func_sp.get() != nullptr) { if (frame_base.IsValid()) func_sp->GetFrameBaseExpression() = frame_base; comp_unit.AddFunction(func_sp); @@ -2670,19 +2439,19 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, } } } - return NULL; + return nullptr; } bool DWARFASTParserClang::ParseChildMembers( - const SymbolContext &sc, const DWARFDIE &parent_die, - CompilerType &class_clang_type, const LanguageType class_language, + const DWARFDIE &parent_die, CompilerType &class_clang_type, + const LanguageType class_language, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, std::vector<int> &member_accessibilities, - DWARFDIECollection &member_function_dies, + std::vector<DWARFDIE> &member_function_dies, DelayedPropertyList &delayed_properties, AccessType &default_accessibility, bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) { if (!parent_die) - return 0; + return false; // Get the parent byte size so we can verify any members will fit const uint64_t parent_byte_size = @@ -2697,7 +2466,7 @@ bool DWARFASTParserClang::ParseChildMembers( ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem()); if (ast == nullptr) - return 0; + return false; for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) { @@ -2709,12 +2478,10 @@ bool DWARFASTParserClang::ParseChildMembers( DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); if (num_attributes > 0) { - Declaration decl; - // DWARFExpression location; - const char *name = NULL; - const char *prop_name = NULL; - const char *prop_getter_name = NULL; - const char *prop_setter_name = NULL; + const char *name = nullptr; + const char *prop_name = nullptr; + const char *prop_getter_name = nullptr; + const char *prop_setter_name = nullptr; uint32_t prop_attributes = 0; bool is_artificial = false; @@ -2722,7 +2489,7 @@ bool DWARFASTParserClang::ParseChildMembers( AccessType accessibility = eAccessNone; uint32_t member_byte_offset = (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX; - size_t byte_size = 0; + llvm::Optional<uint64_t> byte_size; int64_t bit_offset = 0; uint64_t data_bit_offset = UINT64_MAX; size_t bit_size = 0; @@ -2734,16 +2501,6 @@ bool DWARFASTParserClang::ParseChildMembers( DWARFFormValue form_value; if (attributes.ExtractFormValueAtIndex(i, form_value)) { switch (attr) { - 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(); break; @@ -2776,7 +2533,8 @@ bool DWARFASTParserClang::ParseChildMembers( module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, nullptr, memberOffset, nullptr)) { - member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); + member_byte_offset = + memberOffset.ResolveValue(nullptr).UInt(); } } else { // With DWARF 3 and later, if the value is an integer constant, @@ -2865,7 +2623,7 @@ bool DWARFASTParserClang::ParseChildMembers( // with a crash if we try to use this type in an expression when clang // becomes unhappy with its recycled debug info. - if (byte_size == 0 && bit_offset < 0) { + if (byte_size.getValueOr(0) == 0 && bit_offset < 0) { bit_size = 0; bit_offset = 0; } @@ -2877,7 +2635,7 @@ bool DWARFASTParserClang::ParseChildMembers( // Handle static members if (is_external && member_byte_offset == UINT32_MAX) { - Type *var_type = die.ResolveTypeUID(DIERef(encoding_form)); + Type *var_type = die.ResolveTypeUID(encoding_form.Reference()); if (var_type) { if (accessibility == eAccessNone) @@ -2890,9 +2648,9 @@ bool DWARFASTParserClang::ParseChildMembers( } if (!is_artificial) { - Type *member_type = die.ResolveTypeUID(DIERef(encoding_form)); + Type *member_type = die.ResolveTypeUID(encoding_form.Reference()); - clang::FieldDecl *field_decl = NULL; + clang::FieldDecl *field_decl = nullptr; if (tag == DW_TAG_member) { if (member_type) { if (accessibility == eAccessNone) @@ -2927,12 +2685,12 @@ bool DWARFASTParserClang::ParseChildMembers( if (data_bit_offset != UINT64_MAX) { this_field_info.bit_offset = data_bit_offset; } else { - if (byte_size == 0) + if (!byte_size) byte_size = member_type->GetByteSize(); ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); if (objfile->GetByteOrder() == eByteOrderLittle) { - this_field_info.bit_offset += byte_size * 8; + this_field_info.bit_offset += byte_size.getValueOr(0) * 8; this_field_info.bit_offset -= (bit_offset + bit_size); } else { this_field_info.bit_offset += bit_offset; @@ -2945,13 +2703,12 @@ bool DWARFASTParserClang::ParseChildMembers( ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); objfile->GetModule()->ReportWarning( "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid " - "bit offset (0x%8.8" PRIx64 + "bit offset (0x%8.8" PRIx64 ") member will be ignored. Please file a bug against the " "compiler and include the preprocessed output for %s\n", die.GetID(), DW_TAG_value_to_name(tag), name, this_field_info.bit_offset, - sc.comp_unit ? sc.comp_unit->GetPath().c_str() - : "the source file"); + GetUnitName(parent_die).c_str()); this_field_info.Clear(); continue; } @@ -3074,9 +2831,10 @@ bool DWARFASTParserClang::ParseChildMembers( member_byte_offset > parent_byte_size)) { module_sp->ReportError( "0x%8.8" PRIx64 - ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 + ": DW_TAG_member '%s' refers to type 0x%8.8x" " which extends beyond the bounds of 0x%8.8" PRIx64, - die.GetID(), name, encoding_form.Reference(), + die.GetID(), name, + encoding_form.Reference().GetOffset(), parent_die.GetID()); } @@ -3103,9 +2861,7 @@ bool DWARFASTParserClang::ParseChildMembers( "complete definition.\nPlease file a bug against the " "compiler and include the preprocessed output for %s", parent_die.GetOffset(), parent_die.GetName(), - die.GetOffset(), name, - sc.comp_unit ? sc.comp_unit->GetPath().c_str() - : "the source file"); + die.GetOffset(), name, GetUnitName(parent_die).c_str()); // We have no choice other than to pretend that the member // class is complete. If we don't do this, clang will crash // when trying to layout the class. Since we provide layout @@ -3139,24 +2895,23 @@ bool DWARFASTParserClang::ParseChildMembers( if (name) module_sp->ReportError( "0x%8.8" PRIx64 - ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 + ": DW_TAG_member '%s' refers to type 0x%8.8x" " which was unable to be parsed", - die.GetID(), name, encoding_form.Reference()); + die.GetID(), name, encoding_form.Reference().GetOffset()); else module_sp->ReportError( - "0x%8.8" PRIx64 - ": DW_TAG_member refers to type 0x%8.8" PRIx64 + "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x" " which was unable to be parsed", - die.GetID(), encoding_form.Reference()); + die.GetID(), encoding_form.Reference().GetOffset()); } } - if (prop_name != NULL && member_type) { - clang::ObjCIvarDecl *ivar_decl = NULL; + if (prop_name != nullptr && member_type) { + clang::ObjCIvarDecl *ivar_decl = nullptr; if (field_decl) { ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl); - assert(ivar_decl != NULL); + assert(ivar_decl != nullptr); } ClangASTMetadata metadata; @@ -3177,7 +2932,7 @@ bool DWARFASTParserClang::ParseChildMembers( case DW_TAG_subprogram: // Let the type parsing code handle this one for us. - member_function_dies.Append(die); + member_function_dies.push_back(die); break; case DW_TAG_inheritance: { @@ -3188,8 +2943,6 @@ bool DWARFASTParserClang::ParseChildMembers( DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); if (num_attributes > 0) { - Declaration decl; - DWARFExpression location(die.GetCU()); DWARFFormValue encoding_form; AccessType accessibility = default_accessibility; bool is_virtual = false; @@ -3201,16 +2954,6 @@ bool DWARFASTParserClang::ParseChildMembers( DWARFFormValue form_value; if (attributes.ExtractFormValueAtIndex(i, form_value)) { switch (attr) { - 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_type: encoding_form = form_value; break; @@ -3227,7 +2970,8 @@ bool DWARFASTParserClang::ParseChildMembers( block_offset, block_length, eRegisterKindDWARF, &initialValue, nullptr, memberOffset, nullptr)) { - member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); + member_byte_offset = + memberOffset.ResolveValue(nullptr).UInt(); } } else { // With DWARF 3 and later, if the value is an integer constant, @@ -3254,14 +2998,15 @@ bool DWARFASTParserClang::ParseChildMembers( } } - Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form)); - if (base_class_type == NULL) { + Type *base_class_type = die.ResolveTypeUID(encoding_form.Reference()); + if (base_class_type == nullptr) { module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to " - "resolve the base class at 0x%8.8" PRIx64 + "resolve the base class at 0x%8.8x" " from enclosing type 0x%8.8x. \nPlease file " "a bug and attach the file at the start of " "this error message", - die.GetOffset(), encoding_form.Reference(), + die.GetOffset(), + encoding_form.Reference().GetOffset(), parent_die.GetOffset()); break; } @@ -3313,10 +3058,9 @@ bool DWARFASTParserClang::ParseChildMembers( } size_t DWARFASTParserClang::ParseChildParameters( - CompileUnit &comp_unit, clang::DeclContext *containing_decl_ctx, - const DWARFDIE &parent_die, bool skip_artificial, bool &is_static, - bool &is_variadic, bool &has_template_params, - std::vector<CompilerType> &function_param_types, + clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die, + bool skip_artificial, bool &is_static, bool &is_variadic, + bool &has_template_params, std::vector<CompilerType> &function_param_types, std::vector<clang::ParmVarDecl *> &function_param_decls, unsigned &type_quals) { if (!parent_die) @@ -3331,8 +3075,7 @@ size_t DWARFASTParserClang::ParseChildParameters( DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); if (num_attributes > 0) { - const char *name = NULL; - Declaration decl; + const char *name = nullptr; DWARFFormValue param_type_die_form; bool is_artificial = false; // one of None, Auto, Register, Extern, Static, PrivateExtern @@ -3344,16 +3087,6 @@ size_t DWARFASTParserClang::ParseChildParameters( DWARFFormValue form_value; if (attributes.ExtractFormValueAtIndex(i, form_value)) { switch (attr) { - case DW_AT_decl_file: - decl.SetFile(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(); break; @@ -3388,8 +3121,9 @@ size_t DWARFASTParserClang::ParseChildParameters( // Often times compilers omit the "this" name for the // specification DIEs, so we can't rely upon the name being in // the formal parameter DIE... - (name == NULL || ::strcmp(name, "this") == 0)) { - Type *this_type = die.ResolveTypeUID(DIERef(param_type_die_form)); + (name == nullptr || ::strcmp(name, "this") == 0)) { + Type *this_type = + die.ResolveTypeUID(param_type_die_form.Reference()); if (this_type) { uint32_t encoding_mask = this_type->GetEncodingMask(); if (encoding_mask & Type::eEncodingIsPointerUID) { @@ -3406,7 +3140,7 @@ size_t DWARFASTParserClang::ParseChildParameters( } if (!skip) { - Type *type = die.ResolveTypeUID(DIERef(param_type_die_form)); + Type *type = die.ResolveTypeUID(param_type_die_form.Reference()); if (type) { function_param_types.push_back(type->GetForwardCompilerType()); @@ -3554,7 +3288,7 @@ Type *DWARFASTParserClang::GetTypeForDIE(const DWARFDIE &die) { if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) - return dwarf->ResolveTypeUID(dwarf->GetDIE(DIERef(form_value)), true); + return dwarf->ResolveTypeUID(form_value.Reference(), true); } } } @@ -3799,8 +3533,11 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) { const char *namespace_name = die.GetName(); clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); - namespace_decl = m_ast.GetUniqueNamespaceDeclaration(namespace_name, - containing_decl_ctx); + bool is_inline = + die.GetAttributeValueAsUnsigned(DW_AT_export_symbols, 0) != 0; + + namespace_decl = m_ast.GetUniqueNamespaceDeclaration( + namespace_name, containing_decl_ctx, is_inline); Log *log = nullptr; // (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) { @@ -3870,7 +3607,7 @@ void DWARFASTParserClang::LinkDeclContextToDIE(clang::DeclContext *decl_ctx, bool DWARFASTParserClang::CopyUniqueClassMethodTypes( const DWARFDIE &src_class_die, const DWARFDIE &dst_class_die, - lldb_private::Type *class_type, DWARFDIECollection &failures) { + lldb_private::Type *class_type, std::vector<DWARFDIE> &failures) { if (!class_type || !src_class_die || !dst_class_die) return false; if (src_class_die.Tag() != dst_class_die.Tag()) @@ -4075,7 +3812,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( log->Printf("warning: couldn't find a match for 0x%8.8x", dst_die.GetOffset()); - failures.Append(dst_die); + failures.push_back(dst_die); } } } @@ -4140,9 +3877,9 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( "method '%s'", dst_die.GetOffset(), dst_name_artificial.GetCString()); - failures.Append(dst_die); + failures.push_back(dst_die); } } - return (failures.Size() != 0); + return !failures.empty(); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 63e058d7bf21..5b5d83d65932 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -1,9 +1,8 @@ //===-- DWARFASTParserClang.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -22,11 +21,12 @@ #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTImporter.h" +#include <vector> + namespace lldb_private { class CompileUnit; } class DWARFDebugInfoEntry; -class DWARFDIECollection; class SymbolFileDWARF; class DWARFASTParserClang : public DWARFASTParser { @@ -81,19 +81,17 @@ protected: &template_param_infos); bool ParseChildMembers( - const lldb_private::SymbolContext &sc, const DWARFDIE &die, - lldb_private::CompilerType &class_compiler_type, + const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type, const lldb::LanguageType class_language, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, std::vector<int> &member_accessibilities, - DWARFDIECollection &member_function_dies, + std::vector<DWARFDIE> &member_function_dies, DelayedPropertyList &delayed_properties, lldb::AccessType &default_accessibility, bool &is_a_class, lldb_private::ClangASTImporter::LayoutInfo &layout_info); size_t - ParseChildParameters(lldb_private::CompileUnit &comp_unit, - clang::DeclContext *containing_decl_ctx, + ParseChildParameters(clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die, bool skip_artificial, bool &is_static, bool &is_variadic, bool &has_template_params, @@ -101,8 +99,7 @@ protected: std::vector<clang::ParmVarDecl *> &function_param_decls, unsigned &type_quals); - size_t ParseChildEnumerators(const lldb_private::SymbolContext &sc, - lldb_private::CompilerType &compiler_type, + size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type, bool is_signed, uint32_t enumerator_byte_size, const DWARFDIE &parent_die); @@ -118,7 +115,7 @@ protected: bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die, const DWARFDIE &dst_class_die, lldb_private::Type *class_type, - DWARFDIECollection &failures); + std::vector<DWARFDIE> &failures); clang::DeclContext *GetCachedClangDeclContextForDIE(const DWARFDIE &die); @@ -128,10 +125,8 @@ protected: lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log); - //---------------------------------------------------------------------- // Return true if this type is a declaration to a type in an external // module. - //---------------------------------------------------------------------- lldb::ModuleSP GetModuleForType(const DWARFDIE &die); typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; @@ -150,7 +145,7 @@ protected: DeclToDIEMap m_decl_to_die; DIEToDeclContextMap m_die_to_decl_ctx; DeclContextToDIEMap m_decl_ctx_to_die; - std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap; + std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; }; #endif // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp index d78b9ab10f5a..6128163a2926 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp @@ -1,9 +1,8 @@ //===-- DWARFAbbreviationDeclaration.cpp ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,6 +11,8 @@ #include "lldb/Core/dwarf.h" #include "lldb/Utility/Stream.h" +#include "llvm/Object/Error.h" + #include "DWARFFormValue.h" using namespace lldb_private; @@ -24,57 +25,46 @@ DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, : m_code(InvalidCode), m_tag(tag), m_has_children(has_children), m_attributes() {} -bool DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor &data, - lldb::offset_t *offset_ptr) { - return Extract(data, offset_ptr, data.GetULEB128(offset_ptr)); -} +llvm::Expected<DWARFEnumState> +DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, + lldb::offset_t *offset_ptr) { + m_code = data.GetULEB128(offset_ptr); + if (m_code == 0) + return DWARFEnumState::Complete; -bool DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor &data, - lldb::offset_t *offset_ptr, - dw_uleb128_t code) { - m_code = code; m_attributes.clear(); - if (m_code) { - m_tag = data.GetULEB128(offset_ptr); - m_has_children = data.GetU8(offset_ptr); - - while (data.ValidOffset(*offset_ptr)) { - dw_attr_t attr = data.GetULEB128(offset_ptr); - dw_form_t form = data.GetULEB128(offset_ptr); - DWARFFormValue::ValueType val; - - if (form == DW_FORM_implicit_const) - val.value.sval = data.GetULEB128(offset_ptr); - - if (attr && form) - m_attributes.push_back(DWARFAttribute(attr, form, val)); - else - break; - } - - return m_tag != 0; - } else { - m_tag = 0; - m_has_children = 0; - } + m_tag = data.GetULEB128(offset_ptr); + if (m_tag == DW_TAG_null) + return llvm::make_error<llvm::object::GenericBinaryError>( + "abbrev decl requires non-null tag."); - return false; -} + m_has_children = data.GetU8(offset_ptr); -void DWARFAbbreviationDeclaration::Dump(Stream *s) const { - s->Printf("Debug Abbreviation Declaration: code = 0x%4.4x, tag = %s, " - "has_children = %s\n", - m_code, DW_TAG_value_to_name(m_tag), - DW_CHILDREN_value_to_name(m_has_children)); + while (data.ValidOffset(*offset_ptr)) { + dw_attr_t attr = data.GetULEB128(offset_ptr); + dw_form_t form = data.GetULEB128(offset_ptr); - DWARFAttribute::const_iterator pos; + // This is the last attribute for this abbrev decl, but there may still be + // more abbrev decls, so return MoreItems to indicate to the caller that + // they should call this function again. + if (!attr && !form) + return DWARFEnumState::MoreItems; - for (pos = m_attributes.begin(); pos != m_attributes.end(); ++pos) - s->Printf(" attr = %s, form = %s\n", - DW_AT_value_to_name(pos->get_attr()), - DW_FORM_value_to_name(pos->get_form())); + if (!attr || !form) + return llvm::make_error<llvm::object::GenericBinaryError>( + "malformed abbreviation declaration attribute"); + + DWARFFormValue::ValueType val; + + if (form == DW_FORM_implicit_const) + val.value.sval = data.GetULEB128(offset_ptr); + + m_attributes.push_back(DWARFAttribute(attr, form, val)); + } - s->Printf("\n"); + return llvm::make_error<llvm::object::GenericBinaryError>( + "abbreviation declaration attribute list not terminated with a null " + "entry"); } bool DWARFAbbreviationDeclaration::IsValid() { @@ -95,5 +85,5 @@ DWARFAbbreviationDeclaration::FindAttributeIndex(dw_attr_t attr) const { bool DWARFAbbreviationDeclaration:: operator==(const DWARFAbbreviationDeclaration &rhs) const { return Tag() == rhs.Tag() && HasChildren() == rhs.HasChildren() && - Attributes() == rhs.Attributes(); + m_attributes == rhs.m_attributes; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h index afce52558f45..c0cf8823a368 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h @@ -1,9 +1,8 @@ //===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,7 +10,9 @@ #define liblldb_DWARFAbbreviationDeclaration_h_ #include "DWARFAttribute.h" +#include "DWARFDefines.h" #include "SymbolFileDWARF.h" +#include "llvm/Support/Error.h" class DWARFAbbreviationDeclaration { public: @@ -20,18 +21,12 @@ public: // For hand crafting an abbreviation declaration DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children); - void AddAttribute(const DWARFAttribute &attr) { - m_attributes.push_back(attr); - } dw_uleb128_t Code() const { return m_code; } void SetCode(dw_uleb128_t code) { m_code = code; } dw_tag_t Tag() const { return m_tag; } bool HasChildren() const { return m_has_children; } size_t NumAttributes() const { return m_attributes.size(); } - dw_attr_t GetAttrByIndex(uint32_t idx) const { - return m_attributes.size() > idx ? m_attributes[idx].get_attr() : 0; - } dw_form_t GetFormByIndex(uint32_t idx) const { return m_attributes.size() > idx ? m_attributes[idx].get_form() : 0; } @@ -45,14 +40,20 @@ public: return m_attributes[idx].get_form(); } uint32_t FindAttributeIndex(dw_attr_t attr) const; - bool Extract(const lldb_private::DWARFDataExtractor &data, - lldb::offset_t *offset_ptr); - bool Extract(const lldb_private::DWARFDataExtractor &data, - lldb::offset_t *offset_ptr, dw_uleb128_t code); + + /// Extract one abbreviation declaration and all of its associated attributes. + /// Possible return values: + /// DWARFEnumState::Complete - the extraction completed successfully. This + /// was the last abbrev decl in a sequence, and the user should not call + /// this function again. + /// DWARFEnumState::MoreItems - the extraction completed successfully. The + /// user should call this function again to retrieve the next decl. + /// llvm::Error - A parsing error occurred. The debug info is malformed. + llvm::Expected<lldb_private::DWARFEnumState> + extract(const lldb_private::DWARFDataExtractor &data, + lldb::offset_t *offset_ptr); bool IsValid(); - void Dump(lldb_private::Stream *s) const; bool operator==(const DWARFAbbreviationDeclaration &rhs) const; - const DWARFAttribute::collection &Attributes() const { return m_attributes; } protected: dw_uleb128_t m_code; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp index dd830eb7b9dd..b3594a455680 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp @@ -1,9 +1,8 @@ //===-- DWARFAttribute.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -33,41 +32,27 @@ void DWARFAttributes::Append(const DWARFUnit *cu, dw_offset_t attr_die_offset, m_infos.push_back(attr_value); } -bool DWARFAttributes::ContainsAttribute(dw_attr_t attr) const { - return FindAttributeIndex(attr) != UINT32_MAX; -} - -bool DWARFAttributes::RemoveAttribute(dw_attr_t attr) { - uint32_t attr_index = FindAttributeIndex(attr); - if (attr_index != UINT32_MAX) { - m_infos.erase(m_infos.begin() + attr_index); - return true; - } - return false; -} - bool DWARFAttributes::ExtractFormValueAtIndex( uint32_t i, DWARFFormValue &form_value) const { const DWARFUnit *cu = CompileUnitAtIndex(i); - form_value.SetCompileUnit(cu); + form_value.SetUnit(cu); form_value.SetForm(FormAtIndex(i)); lldb::offset_t offset = DIEOffsetAtIndex(i); return form_value.ExtractValue(cu->GetData(), &offset); } -uint64_t DWARFAttributes::FormValueAsUnsigned(dw_attr_t attr, - uint64_t fail_value) const { +DWARFDIE +DWARFAttributes::FormValueAsReference(dw_attr_t attr) const { const uint32_t attr_idx = FindAttributeIndex(attr); if (attr_idx != UINT32_MAX) - return FormValueAsUnsignedAtIndex(attr_idx, fail_value); - return fail_value; + return FormValueAsReferenceAtIndex(attr_idx); + return {}; } -uint64_t -DWARFAttributes::FormValueAsUnsignedAtIndex(uint32_t i, - uint64_t fail_value) const { +DWARFDIE +DWARFAttributes::FormValueAsReferenceAtIndex(uint32_t i) const { DWARFFormValue form_value; if (ExtractFormValueAtIndex(i, form_value)) return form_value.Reference(); - return fail_value; + return {}; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h index 2399861d7fc3..58427b19100a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h @@ -1,9 +1,8 @@ //===-- DWARFAttribute.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -27,8 +26,6 @@ public: m_attr = attr; m_form = form; } - void set_attr(dw_attr_t attr) { m_attr = attr; } - void set_form(dw_form_t form) { m_form = form; } dw_attr_t get_attr() const { return m_attr; } dw_form_t get_form() const { return m_form; } void get(dw_attr_t &attr, dw_form_t &form, @@ -68,11 +65,9 @@ public: } dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); } bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const; - uint64_t FormValueAsUnsignedAtIndex(uint32_t i, uint64_t fail_value) const; - uint64_t FormValueAsUnsigned(dw_attr_t attr, uint64_t fail_value) const; + DWARFDIE FormValueAsReferenceAtIndex(uint32_t i) const; + DWARFDIE FormValueAsReference(dw_attr_t attr) const; uint32_t FindAttributeIndex(dw_attr_t attr) const; - bool ContainsAttribute(dw_attr_t attr) const; - bool RemoveAttribute(dw_attr_t attr); void Clear() { m_infos.clear(); } size_t Size() const { return m_infos.size(); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp index 077de9604f1d..96adb72c9532 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -1,9 +1,8 @@ //===-- DWARFBaseDIE.cpp ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -18,14 +17,12 @@ using namespace lldb_private; -DIERef DWARFBaseDIE::GetDIERef() const { +llvm::Optional<DIERef> DWARFBaseDIE::GetDIERef() const { if (!IsValid()) - return DIERef(); + return llvm::None; - dw_offset_t cu_offset = m_cu->GetOffset(); - if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) - cu_offset = m_cu->GetBaseObjOffset(); - return DIERef(cu_offset, m_die->GetOffset()); + return DIERef(m_cu->GetSymbolFileDWARF().GetDwoNum(), m_cu->GetDebugSection(), + m_die->GetOffset()); } dw_tag_t DWARFBaseDIE::Tag() const { @@ -42,8 +39,7 @@ const char *DWARFBaseDIE::GetTagAsCString() const { const char *DWARFBaseDIE::GetAttributeValueAsString(const dw_attr_t attr, const char *fail_value) const { if (IsValid()) - return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr, - fail_value); + return m_die->GetAttributeValueAsString(GetCU(), attr, fail_value); else return fail_value; } @@ -51,26 +47,7 @@ const char *DWARFBaseDIE::GetAttributeValueAsString(const dw_attr_t attr, uint64_t DWARFBaseDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr, uint64_t fail_value) const { if (IsValid()) - return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr, - fail_value); - else - return fail_value; -} - -int64_t DWARFBaseDIE::GetAttributeValueAsSigned(const dw_attr_t attr, - int64_t fail_value) const { - if (IsValid()) - return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr, - fail_value); - else - return fail_value; -} - -uint64_t DWARFBaseDIE::GetAttributeValueAsReference(const dw_attr_t attr, - uint64_t fail_value) const { - if (IsValid()) - return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr, - fail_value); + return m_die->GetAttributeValueAsUnsigned(GetCU(), attr, fail_value); else return fail_value; } @@ -78,19 +55,20 @@ uint64_t DWARFBaseDIE::GetAttributeValueAsReference(const dw_attr_t attr, uint64_t DWARFBaseDIE::GetAttributeValueAsAddress(const dw_attr_t attr, uint64_t fail_value) const { if (IsValid()) - return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr, - fail_value); + return m_die->GetAttributeValueAsAddress(GetCU(), attr, fail_value); else return fail_value; } lldb::user_id_t DWARFBaseDIE::GetID() const { - return GetDIERef().GetUID(GetDWARF()); + if (IsValid()) + return GetDWARF()->GetUID(*this); + return LLDB_INVALID_UID; } const char *DWARFBaseDIE::GetName() const { if (IsValid()) - return m_die->GetName(GetDWARF(), m_cu); + return m_die->GetName(m_cu); else return nullptr; } @@ -110,13 +88,6 @@ lldb::ModuleSP DWARFBaseDIE::GetModule() const { return lldb::ModuleSP(); } -lldb_private::CompileUnit *DWARFBaseDIE::GetLLDBCompileUnit() const { - if (IsValid()) - return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU()); - else - return nullptr; -} - dw_offset_t DWARFBaseDIE::GetOffset() const { if (IsValid()) return m_die->GetOffset(); @@ -124,16 +95,9 @@ dw_offset_t DWARFBaseDIE::GetOffset() const { return DW_INVALID_OFFSET; } -dw_offset_t DWARFBaseDIE::GetCompileUnitRelativeOffset() const { - if (IsValid()) - return m_die->GetOffset() - m_cu->GetOffset(); - else - return DW_INVALID_OFFSET; -} - SymbolFileDWARF *DWARFBaseDIE::GetDWARF() const { if (m_cu) - return m_cu->GetSymbolFileDWARF(); + return &m_cu->GetSymbolFileDWARF(); else return nullptr; } @@ -163,21 +127,13 @@ bool DWARFBaseDIE::Supports_DW_AT_APPLE_objc_complete_type() const { size_t DWARFBaseDIE::GetAttributes(DWARFAttributes &attributes, uint32_t depth) const { - if (IsValid()) { - return m_die->GetAttributes(m_cu, m_cu->GetFixedFormSizes(), attributes, - depth); - } + if (IsValid()) + return m_die->GetAttributes(m_cu, attributes, depth); if (depth == 0) attributes.Clear(); return 0; } -void DWARFBaseDIE::Dump(lldb_private::Stream *s, - const uint32_t recurse_depth) const { - if (s && IsValid()) - m_die->Dump(GetDWARF(), GetCU(), *s, recurse_depth); -} - bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) { return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU(); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h index 2163a027ffbc..0058043017cd 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -1,9 +1,8 @@ //===-- DWARFBaseDIE.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -13,13 +12,12 @@ #include "lldb/Core/dwarf.h" #include "lldb/lldb-types.h" -struct DIERef; +class DIERef; class DWARFASTParser; class DWARFAttributes; class DWARFUnit; class DWARFDebugInfoEntry; class DWARFDeclContext; -class DWARFDIECollection; class SymbolFileDWARF; class DWARFBaseDIE { @@ -39,9 +37,7 @@ public: : m_cu(const_cast<DWARFUnit *>(cu)), m_die(const_cast<DWARFDebugInfoEntry *>(die)) {} - //---------------------------------------------------------------------- // Tests - //---------------------------------------------------------------------- explicit operator bool() const { return IsValid(); } bool IsValid() const { return m_cu && m_die; } @@ -50,16 +46,14 @@ public: bool Supports_DW_AT_APPLE_objc_complete_type() const; - //---------------------------------------------------------------------- // Accessors - //---------------------------------------------------------------------- SymbolFileDWARF *GetDWARF() const; DWARFUnit *GetCU() const { return m_cu; } DWARFDebugInfoEntry *GetDIE() const { return m_die; } - DIERef GetDIERef() const; + llvm::Optional<DIERef> GetDIERef() const; lldb_private::TypeSystem *GetTypeSystem() const; @@ -79,33 +73,25 @@ public: m_die = nullptr; } - //---------------------------------------------------------------------- // Get the data that contains the attribute values for this DIE. Support // for .debug_types means that any DIE can have its data either in the // .debug_info or the .debug_types section; this method will return the // correct section data. // // Clients must validate that this object is valid before calling this. - //---------------------------------------------------------------------- const lldb_private::DWARFDataExtractor &GetData() const; - //---------------------------------------------------------------------- // Accessing information about a DIE - //---------------------------------------------------------------------- dw_tag_t Tag() const; const char *GetTagAsCString() const; dw_offset_t GetOffset() const; - dw_offset_t GetCompileUnitRelativeOffset() const; - - //---------------------------------------------------------------------- // Get the LLDB user ID for this DIE. This is often just the DIE offset, // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if // we are doing Darwin DWARF in .o file, or DWARF stand alone debug // info. - //---------------------------------------------------------------------- lldb::user_id_t GetID() const; const char *GetName() const; @@ -114,38 +100,22 @@ public: lldb::ModuleSP GetModule() const; - lldb_private::CompileUnit *GetLLDBCompileUnit() const; - - //---------------------------------------------------------------------- // Getting attribute values from the DIE. // // GetAttributeValueAsXXX() functions should only be used if you are // looking for one or two attributes on a DIE. If you are trying to // parse all attributes, use GetAttributes (...) instead - //---------------------------------------------------------------------- const char *GetAttributeValueAsString(const dw_attr_t attr, const char *fail_value) const; uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr, uint64_t fail_value) const; - int64_t GetAttributeValueAsSigned(const dw_attr_t attr, - int64_t fail_value) const; - - uint64_t GetAttributeValueAsReference(const dw_attr_t attr, - uint64_t fail_value) const; - uint64_t GetAttributeValueAsAddress(const dw_attr_t attr, uint64_t fail_value) const; size_t GetAttributes(DWARFAttributes &attributes, uint32_t depth = 0) const; - //---------------------------------------------------------------------- - // Pretty printing - //---------------------------------------------------------------------- - - void Dump(lldb_private::Stream *s, const uint32_t recurse_depth) const; - protected: DWARFUnit *m_cu; DWARFDebugInfoEntry *m_die; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index b9a7231286e3..718f0537d6ed 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -1,98 +1,115 @@ //===-- DWARFCompileUnit.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DWARFCompileUnit.h" +#include "DWARFDebugAranges.h" +#include "SymbolFileDWARFDebugMap.h" -#include "SymbolFileDWARF.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/LineTable.h" #include "lldb/Utility/Stream.h" using namespace lldb; using namespace lldb_private; -extern int g_verbose; - -DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data) - : DWARFUnit(dwarf2Data) {} - -DWARFUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data, - const DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr) { - // std::make_shared would require the ctor to be public. - std::shared_ptr<DWARFCompileUnit> cu_sp(new DWARFCompileUnit(dwarf2Data)); - - cu_sp->m_offset = *offset_ptr; - - if (debug_info.ValidOffset(*offset_ptr)) { - dw_offset_t abbr_offset; - const DWARFDebugAbbrev *abbr = dwarf2Data->DebugAbbrev(); - cu_sp->m_length = debug_info.GetDWARFInitialLength(offset_ptr); - cu_sp->m_is_dwarf64 = debug_info.IsDWARF64(); - cu_sp->m_version = debug_info.GetU16(offset_ptr); - - if (cu_sp->m_version == 5) { - cu_sp->m_unit_type = debug_info.GetU8(offset_ptr); - cu_sp->m_addr_size = debug_info.GetU8(offset_ptr); - abbr_offset = debug_info.GetDWARFOffset(offset_ptr); - - if (cu_sp->m_unit_type == llvm::dwarf::DW_UT_skeleton) - cu_sp->m_dwo_id = debug_info.GetU64(offset_ptr); - } else { - abbr_offset = debug_info.GetDWARFOffset(offset_ptr); - cu_sp->m_addr_size = debug_info.GetU8(offset_ptr); - } - - bool length_OK = - debug_info.ValidOffset(cu_sp->GetNextCompileUnitOffset() - 1); - bool version_OK = SymbolFileDWARF::SupportedVersion(cu_sp->m_version); - bool abbr_offset_OK = - dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); - bool addr_size_OK = (cu_sp->m_addr_size == 4) || (cu_sp->m_addr_size == 8); - - if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && - abbr != NULL) { - cu_sp->m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); - return cu_sp; - } - - // reset the offset to where we tried to parse from if anything went wrong - *offset_ptr = cu_sp->m_offset; - } - - return nullptr; -} - void DWARFCompileUnit::Dump(Stream *s) const { s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, " "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at " "{0x%8.8x})\n", - m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, - GetNextCompileUnitOffset()); + GetOffset(), GetLength(), GetVersion(), GetAbbrevOffset(), + GetAddressByteSize(), GetNextUnitOffset()); } -uint32_t DWARFCompileUnit::GetHeaderByteSize() const { - if (m_version < 5) - return m_is_dwarf64 ? 23 : 11; - - switch (m_unit_type) { - case llvm::dwarf::DW_UT_compile: - case llvm::dwarf::DW_UT_partial: - return 12; - case llvm::dwarf::DW_UT_skeleton: - case llvm::dwarf::DW_UT_split_compile: - return 20; - case llvm::dwarf::DW_UT_type: - case llvm::dwarf::DW_UT_split_type: - return 24; +void DWARFCompileUnit::BuildAddressRangeTable( + DWARFDebugAranges *debug_aranges) { + // This function is usually called if there in no .debug_aranges section in + // order to produce a compile unit level set of address ranges that is + // accurate. + + size_t num_debug_aranges = debug_aranges->GetNumRanges(); + + // First get the compile unit DIE only and check if it has a DW_AT_ranges + const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); + + const dw_offset_t cu_offset = GetOffset(); + if (die) { + DWARFRangeList ranges; + const size_t num_ranges = + die->GetAttributeAddressRanges(this, ranges, false); + if (num_ranges > 0) { + // This compile unit has DW_AT_ranges, assume this is correct if it is + // present since clang no longer makes .debug_aranges by default and it + // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with + // recent GCC builds. + for (size_t i = 0; i < num_ranges; ++i) { + const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); + debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), + range.GetRangeEnd()); + } + + return; // We got all of our ranges from the DW_AT_ranges attribute + } + } + // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF + + // If the DIEs weren't parsed, then we don't want all dies for all compile + // units to stay loaded when they weren't needed. So we can end up parsing + // the DWARF and then throwing them all away to keep memory usage down. + ScopedExtractDIEs clear_dies(ExtractDIEsScoped()); + + die = DIEPtr(); + if (die) + die->BuildAddressRangeTable(this, debug_aranges); + + if (debug_aranges->GetNumRanges() == num_debug_aranges) { + // We got nothing from the functions, maybe we have a line tables only + // situation. Check the line tables and build the arange table from this. + SymbolContext sc; + sc.comp_unit = m_dwarf.GetCompUnitForDWARFCompUnit(*this); + if (sc.comp_unit) { + SymbolFileDWARFDebugMap *debug_map_sym_file = + m_dwarf.GetDebugMapSymfile(); + if (debug_map_sym_file == nullptr) { + if (LineTable *line_table = sc.comp_unit->GetLineTable()) { + LineTable::FileAddressRanges file_ranges; + const bool append = true; + const size_t num_ranges = + line_table->GetContiguousFileAddressRanges(file_ranges, append); + for (uint32_t idx = 0; idx < num_ranges; ++idx) { + const LineTable::FileAddressRanges::Entry &range = + file_ranges.GetEntryRef(idx); + debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), + range.GetRangeEnd()); + } + } + } else + debug_map_sym_file->AddOSOARanges(&m_dwarf, debug_aranges); + } } - llvm_unreachable("invalid UnitType."); -} -const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const { - return m_dwarf->get_debug_info_data(); + if (debug_aranges->GetNumRanges() == num_debug_aranges) { + // We got nothing from the functions, maybe we have a line tables only + // situation. Check the line tables and build the arange table from this. + SymbolContext sc; + sc.comp_unit = m_dwarf.GetCompUnitForDWARFCompUnit(*this); + if (sc.comp_unit) { + if (LineTable *line_table = sc.comp_unit->GetLineTable()) { + LineTable::FileAddressRanges file_ranges; + const bool append = true; + const size_t num_ranges = + line_table->GetContiguousFileAddressRanges(file_ranges, append); + for (uint32_t idx = 0; idx < num_ranges; ++idx) { + const LineTable::FileAddressRanges::Entry &range = + file_ranges.GetEntryRef(idx); + debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), + range.GetRangeEnd()); + } + } + } + } } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index b92a155e0335..75647dbb082f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -1,9 +1,8 @@ //===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,35 +10,26 @@ #define SymbolFileDWARF_DWARFCompileUnit_h_ #include "DWARFUnit.h" +#include "llvm/Support/Error.h" class DWARFCompileUnit : public DWARFUnit { public: - static DWARFUnitSP Extract(SymbolFileDWARF *dwarf2Data, - const lldb_private::DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr); + void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override; + void Dump(lldb_private::Stream *s) const override; - //------------------------------------------------------------------ - /// Get the data that contains the DIE information for this unit. - /// - /// @return - /// The correct data (.debug_types for DWARF 4 and earlier, and - /// .debug_info for DWARF 5 and later) for the DIE information in - /// this unit. - //------------------------------------------------------------------ - const lldb_private::DWARFDataExtractor &GetData() const override; - - //------------------------------------------------------------------ - /// Get the size in bytes of the header. - /// - /// @return - /// Byte size of the compile unit header - //------------------------------------------------------------------ - uint32_t GetHeaderByteSize() const override; + static bool classof(const DWARFUnit *unit) { return !unit->IsTypeUnit(); } private: - DWARFCompileUnit(SymbolFileDWARF *dwarf2Data); + DWARFCompileUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, + const DWARFUnitHeader &header, + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section) + : DWARFUnit(dwarf, uid, header, abbrevs, section) {} + DISALLOW_COPY_AND_ASSIGN(DWARFCompileUnit); + + friend class DWARFUnit; }; #endif // SymbolFileDWARF_DWARFCompileUnit_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp new file mode 100644 index 000000000000..eb307ce1cce1 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp @@ -0,0 +1,138 @@ +//===-- DWARFContext.cpp ----------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "DWARFContext.h" + +#include "lldb/Core/Section.h" + +using namespace lldb; +using namespace lldb_private; + +static DWARFDataExtractor LoadSection(SectionList *section_list, + SectionType section_type) { + if (!section_list) + return DWARFDataExtractor(); + + auto section_sp = section_list->FindSectionByType(section_type, true); + if (!section_sp) + return DWARFDataExtractor(); + + DWARFDataExtractor data; + section_sp->GetSectionData(data); + return data; +} + +const DWARFDataExtractor & +DWARFContext::LoadOrGetSection(SectionType main_section_type, + llvm::Optional<SectionType> dwo_section_type, + SectionData &data) { + llvm::call_once(data.flag, [&] { + if (dwo_section_type && isDwo()) + data.data = LoadSection(m_dwo_section_list, *dwo_section_type); + else + data.data = LoadSection(m_main_section_list, main_section_type); + }); + return data.data; +} + +const DWARFDataExtractor &DWARFContext::getOrLoadAbbrevData() { + return LoadOrGetSection(eSectionTypeDWARFDebugAbbrev, + eSectionTypeDWARFDebugAbbrevDwo, m_data_debug_abbrev); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadArangesData() { + return LoadOrGetSection(eSectionTypeDWARFDebugAranges, llvm::None, + m_data_debug_aranges); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadAddrData() { + return LoadOrGetSection(eSectionTypeDWARFDebugAddr, llvm::None, + m_data_debug_addr); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadDebugInfoData() { + return LoadOrGetSection(eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugInfoDwo, m_data_debug_info); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadLineData() { + return LoadOrGetSection(eSectionTypeDWARFDebugLine, llvm::None, + m_data_debug_line); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadLineStrData() { + return LoadOrGetSection(eSectionTypeDWARFDebugLineStr, llvm::None, + m_data_debug_line_str); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() { + return LoadOrGetSection(eSectionTypeDWARFDebugMacro, llvm::None, + m_data_debug_macro); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadRangesData() { + return LoadOrGetSection(eSectionTypeDWARFDebugRanges, llvm::None, + m_data_debug_ranges); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadRngListsData() { + return LoadOrGetSection(eSectionTypeDWARFDebugRngLists, llvm::None, + m_data_debug_rnglists); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadStrData() { + return LoadOrGetSection(eSectionTypeDWARFDebugStr, + eSectionTypeDWARFDebugStrDwo, m_data_debug_str); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadStrOffsetsData() { + return LoadOrGetSection(eSectionTypeDWARFDebugStrOffsets, + eSectionTypeDWARFDebugStrOffsetsDwo, + m_data_debug_str_offsets); +} + +const DWARFDataExtractor &DWARFContext::getOrLoadDebugTypesData() { + return LoadOrGetSection(eSectionTypeDWARFDebugTypes, + eSectionTypeDWARFDebugTypesDwo, m_data_debug_types); +} + +llvm::DWARFContext &DWARFContext::GetAsLLVM() { + if (!m_llvm_context) { + llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> section_map; + uint8_t addr_size = 0; + + auto AddSection = [&](Section §ion) { + DataExtractor section_data; + section.GetSectionData(section_data); + + // Set the address size the first time we see it. + if (addr_size == 0) + addr_size = section_data.GetByteSize(); + + llvm::StringRef data = llvm::toStringRef(section_data.GetData()); + llvm::StringRef name = section.GetName().GetStringRef(); + if (name.startswith(".")) + name = name.drop_front(); + section_map.try_emplace( + name, llvm::MemoryBuffer::getMemBuffer(data, name, false)); + }; + + if (m_main_section_list) { + for (auto §ion : *m_main_section_list) + AddSection(*section); + } + + if (m_dwo_section_list) { + for (auto §ion : *m_dwo_section_list) + AddSection(*section); + } + + m_llvm_context = llvm::DWARFContext::create(section_map, addr_size); + } + return *m_llvm_context; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h new file mode 100644 index 000000000000..add042384039 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h @@ -0,0 +1,74 @@ +//===-- DWARFContext.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_PLUGINS_SYMBOLFILE_DWARF_DWARFCONTEXT_H +#define LLDB_PLUGINS_SYMBOLFILE_DWARF_DWARFCONTEXT_H + +#include "DWARFDataExtractor.h" +#include "lldb/Core/Section.h" +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Support/Threading.h" +#include <memory> + +namespace lldb_private { +class DWARFContext { +private: + SectionList *m_main_section_list; + SectionList *m_dwo_section_list; + mutable std::unique_ptr<llvm::DWARFContext> m_llvm_context; + + struct SectionData { + llvm::once_flag flag; + DWARFDataExtractor data; + }; + + SectionData m_data_debug_abbrev; + SectionData m_data_debug_addr; + SectionData m_data_debug_aranges; + SectionData m_data_debug_info; + SectionData m_data_debug_line; + SectionData m_data_debug_line_str; + SectionData m_data_debug_macro; + SectionData m_data_debug_ranges; + SectionData m_data_debug_rnglists; + SectionData m_data_debug_str; + SectionData m_data_debug_str_offsets; + SectionData m_data_debug_types; + + bool isDwo() { return m_dwo_section_list != nullptr; } + + const DWARFDataExtractor & + LoadOrGetSection(lldb::SectionType main_section_type, + llvm::Optional<lldb::SectionType> dwo_section_type, + SectionData &data); + +public: + explicit DWARFContext(SectionList *main_section_list, + SectionList *dwo_section_list) + : m_main_section_list(main_section_list), + m_dwo_section_list(dwo_section_list) {} + + const DWARFDataExtractor &getOrLoadAbbrevData(); + const DWARFDataExtractor &getOrLoadAddrData(); + const DWARFDataExtractor &getOrLoadArangesData(); + const DWARFDataExtractor &getOrLoadDebugInfoData(); + const DWARFDataExtractor &getOrLoadLineData(); + const DWARFDataExtractor &getOrLoadLineStrData(); + const DWARFDataExtractor &getOrLoadMacroData(); + const DWARFDataExtractor &getOrLoadRangesData(); + const DWARFDataExtractor &getOrLoadRngListsData(); + const DWARFDataExtractor &getOrLoadStrData(); + const DWARFDataExtractor &getOrLoadStrOffsetsData(); + const DWARFDataExtractor &getOrLoadDebugTypesData(); + + llvm::DWARFContext &GetAsLLVM(); +}; +} // namespace lldb_private + +#endif diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 22b70b2d6852..9d97ca15a252 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -1,16 +1,14 @@ //===-- DWARFDIE.cpp --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DWARFDIE.h" #include "DWARFASTParser.h" -#include "DWARFDIECollection.h" #include "DWARFDebugInfo.h" #include "DWARFDebugInfoEntry.h" #include "DWARFDeclContext.h" @@ -18,20 +16,75 @@ using namespace lldb_private; -void DWARFDIE::ElaboratingDIEIterator::Next() { - assert(!m_worklist.empty() && "Incrementing end iterator?"); +namespace { + +/// Iterate through all DIEs elaborating (i.e. reachable by a chain of +/// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For +/// convenience, the starting die is included in the sequence as the first +/// item. +class ElaboratingDIEIterator + : public std::iterator<std::input_iterator_tag, DWARFDIE> { + + // The operating invariant is: top of m_worklist contains the "current" item + // and the rest of the list are items yet to be visited. An empty worklist + // means we've reached the end. + // Infinite recursion is prevented by maintaining a list of seen DIEs. + // Container sizes are optimized for the case of following DW_AT_specification + // and DW_AT_abstract_origin just once. + llvm::SmallVector<DWARFDIE, 2> m_worklist; + llvm::SmallSet<lldb::user_id_t, 3> m_seen; + + void Next() { + assert(!m_worklist.empty() && "Incrementing end iterator?"); + + // Pop the current item from the list. + DWARFDIE die = m_worklist.back(); + m_worklist.pop_back(); + + // And add back any items that elaborate it. + for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) { + if (DWARFDIE d = die.GetReferencedDIE(attr)) + if (m_seen.insert(die.GetID()).second) + m_worklist.push_back(d); + } + } - // Pop the current item from the list. - DWARFDIE die = m_worklist.back(); - m_worklist.pop_back(); +public: + /// An iterator starting at die d. + explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {} - // And add back any items that elaborate it. - for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) { - if (DWARFDIE d = die.GetReferencedDIE(attr)) - if (m_seen.insert(die.GetID()).second) - m_worklist.push_back(d); + /// End marker + ElaboratingDIEIterator() {} + + const DWARFDIE &operator*() const { return m_worklist.back(); } + ElaboratingDIEIterator &operator++() { + Next(); + return *this; + } + ElaboratingDIEIterator operator++(int) { + ElaboratingDIEIterator I = *this; + Next(); + return I; } + + friend bool operator==(const ElaboratingDIEIterator &a, + const ElaboratingDIEIterator &b) { + if (a.m_worklist.empty() || b.m_worklist.empty()) + return a.m_worklist.empty() == b.m_worklist.empty(); + return a.m_worklist.back() == b.m_worklist.back(); + } + friend bool operator!=(const ElaboratingDIEIterator &a, + const ElaboratingDIEIterator &b) { + return !(a == b); + } +}; + +llvm::iterator_range<ElaboratingDIEIterator> +elaborating_dies(const DWARFDIE &die) { + return llvm::make_range(ElaboratingDIEIterator(die), + ElaboratingDIEIterator()); } +} // namespace DWARFDIE DWARFDIE::GetParent() const { @@ -59,12 +112,10 @@ DWARFDIE::GetSibling() const { DWARFDIE DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const { - const dw_offset_t die_offset = - GetAttributeValueAsReference(attr, DW_INVALID_OFFSET); - if (die_offset != DW_INVALID_OFFSET) - return GetDIE(die_offset); + if (IsValid()) + return m_die->GetAttributeValueAsReference(GetCU(), attr); else - return DWARFDIE(); + return {}; } DWARFDIE @@ -79,12 +130,11 @@ DWARFDIE DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const { if (IsValid()) { DWARFUnit *cu = GetCU(); - SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF(); const bool check_specification_or_abstract_origin = true; DWARFFormValue form_value; - if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr, + if (m_die->GetAttributeValue(cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) - return dwarf->GetDIE(DIERef(form_value)); + return form_value.Reference(); } return DWARFDIE(); } @@ -96,13 +146,14 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const { DWARFUnit *cu = GetCU(); DWARFDebugInfoEntry *function_die = nullptr; DWARFDebugInfoEntry *block_die = nullptr; - if (m_die->LookupAddress(file_addr, dwarf, cu, &function_die, &block_die)) { + if (m_die->LookupAddress(file_addr, cu, &function_die, &block_die)) { if (block_die && block_die != function_die) { if (cu->ContainsDIEOffset(block_die->GetOffset())) return DWARFDIE(cu, block_die); else - return DWARFDIE(dwarf->DebugInfo()->GetCompileUnit( - DIERef(cu->GetOffset(), block_die->GetOffset())), + return DWARFDIE(dwarf->DebugInfo()->GetUnit(DIERef( + cu->GetSymbolFileDWARF().GetDwoNum(), + cu->GetDebugSection(), block_die->GetOffset())), block_die); } } @@ -112,25 +163,149 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const { const char *DWARFDIE::GetMangledName() const { if (IsValid()) - return m_die->GetMangledName(GetDWARF(), m_cu); + return m_die->GetMangledName(m_cu); else return nullptr; } const char *DWARFDIE::GetPubname() const { if (IsValid()) - return m_die->GetPubname(GetDWARF(), m_cu); + return m_die->GetPubname(m_cu); else return nullptr; } const char *DWARFDIE::GetQualifiedName(std::string &storage) const { if (IsValid()) - return m_die->GetQualifiedName(GetDWARF(), m_cu, storage); + return m_die->GetQualifiedName(m_cu, storage); else return nullptr; } +// GetName +// +// Get value of the DW_AT_name attribute and place that value into the supplied +// stream object. If the DIE is a NULL object "NULL" is placed into the stream, +// and if no DW_AT_name attribute exists for the DIE then nothing is printed. +void DWARFDIE::GetName(Stream &s) const { + if (!IsValid()) + return; + if (GetDIE()->IsNULL()) { + s.PutCString("NULL"); + return; + } + const char *name = GetDIE()->GetAttributeValueAsString(GetCU(), DW_AT_name, nullptr, true); + if (!name) + return; + s.PutCString(name); +} + +// AppendTypeName +// +// Follows the type name definition down through all needed tags to end up with +// a fully qualified type name and dump the results to the supplied stream. +// This is used to show the name of types given a type identifier. +void DWARFDIE::AppendTypeName(Stream &s) const { + if (!IsValid()) + return; + if (GetDIE()->IsNULL()) { + s.PutCString("NULL"); + return; + } + if (const char *name = GetPubname()) { + s.PutCString(name); + return; + } + switch (Tag()) { + case DW_TAG_array_type: + break; // print out a "[]" after printing the full type of the element + // below + case DW_TAG_base_type: + s.PutCString("base "); + break; + case DW_TAG_class_type: + s.PutCString("class "); + break; + case DW_TAG_const_type: + s.PutCString("const "); + break; + case DW_TAG_enumeration_type: + s.PutCString("enum "); + break; + case DW_TAG_file_type: + s.PutCString("file "); + break; + case DW_TAG_interface_type: + s.PutCString("interface "); + break; + case DW_TAG_packed_type: + s.PutCString("packed "); + break; + case DW_TAG_pointer_type: + break; // print out a '*' after printing the full type below + case DW_TAG_ptr_to_member_type: + break; // print out a '*' after printing the full type below + case DW_TAG_reference_type: + break; // print out a '&' after printing the full type below + case DW_TAG_restrict_type: + s.PutCString("restrict "); + break; + case DW_TAG_set_type: + s.PutCString("set "); + break; + case DW_TAG_shared_type: + s.PutCString("shared "); + break; + case DW_TAG_string_type: + s.PutCString("string "); + break; + case DW_TAG_structure_type: + s.PutCString("struct "); + break; + case DW_TAG_subrange_type: + s.PutCString("subrange "); + break; + case DW_TAG_subroutine_type: + s.PutCString("function "); + break; + case DW_TAG_thrown_type: + s.PutCString("thrown "); + break; + case DW_TAG_union_type: + s.PutCString("union "); + break; + case DW_TAG_unspecified_type: + s.PutCString("unspecified "); + break; + case DW_TAG_volatile_type: + s.PutCString("volatile "); + break; + default: + return; + } + + // Follow the DW_AT_type if possible + if (DWARFDIE next_die = GetAttributeValueAsReferenceDIE(DW_AT_type)) + next_die.AppendTypeName(s); + + switch (Tag()) { + case DW_TAG_array_type: + s.PutCString("[]"); + break; + case DW_TAG_pointer_type: + s.PutChar('*'); + break; + case DW_TAG_ptr_to_member_type: + s.PutChar('*'); + break; + case DW_TAG_reference_type: + s.PutChar('&'); + break; + default: + break; + } +} + lldb_private::Type *DWARFDIE::ResolveType() const { if (IsValid()) return GetDWARF()->ResolveType(*this, true); @@ -138,29 +313,30 @@ lldb_private::Type *DWARFDIE::ResolveType() const { return nullptr; } -lldb_private::Type *DWARFDIE::ResolveTypeUID(const DIERef &die_ref) const { - SymbolFileDWARF *dwarf = GetDWARF(); - if (dwarf) - return dwarf->ResolveTypeUID(dwarf->GetDIE(die_ref), true); - else - return nullptr; +lldb_private::Type *DWARFDIE::ResolveTypeUID(const DWARFDIE &die) const { + if (SymbolFileDWARF *dwarf = GetDWARF()) + return dwarf->ResolveTypeUID(die, true); + return nullptr; } -void DWARFDIE::GetDeclContextDIEs(DWARFDIECollection &decl_context_dies) const { - if (IsValid()) { - DWARFDIE parent_decl_ctx_die = - m_die->GetParentDeclContextDIE(GetDWARF(), GetCU()); - if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE()) { - decl_context_dies.Append(parent_decl_ctx_die); - parent_decl_ctx_die.GetDeclContextDIEs(decl_context_dies); - } +std::vector<DWARFDIE> DWARFDIE::GetDeclContextDIEs() const { + if (!IsValid()) + return {}; + + std::vector<DWARFDIE> result; + DWARFDIE parent = GetParentDeclContextDIE(); + while (parent.IsValid() && parent.GetDIE() != GetDIE()) { + result.push_back(std::move(parent)); + parent = parent.GetParentDeclContextDIE(); } + + return result; } void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const { if (IsValid()) { dwarf_decl_ctx.SetLanguage(GetLanguage()); - m_die->GetDWARFDeclContext(GetDWARF(), GetCU(), dwarf_decl_ctx); + m_die->GetDWARFDeclContext(GetCU(), dwarf_decl_ctx); } else { dwarf_decl_ctx.Clear(); } @@ -218,7 +394,7 @@ void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const { DWARFDIE DWARFDIE::GetParentDeclContextDIE() const { if (IsValid()) - return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu); + return m_die->GetParentDeclContextDIE(m_cu); else return DWARFDIE(); } @@ -230,7 +406,7 @@ bool DWARFDIE::IsStructUnionOrClass() const { } bool DWARFDIE::IsMethod() const { - for (DWARFDIE d: elaborating_dies()) + for (DWARFDIE d : elaborating_dies(*this)) if (d.GetParent().IsStructUnionOrClass()) return true; return false; @@ -276,8 +452,8 @@ bool DWARFDIE::GetDIENamesAndRanges( lldb_private::DWARFExpression *frame_base) const { if (IsValid()) { return m_die->GetDIENamesAndRanges( - GetDWARF(), GetCU(), name, mangled, ranges, decl_file, decl_line, - decl_column, call_file, call_line, call_column, frame_base); + GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, + call_file, call_line, call_column, frame_base); } else return false; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index b0d06a886ac1..7753ec9008cb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -1,9 +1,8 @@ //===-- DWARFDIE.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -15,46 +14,37 @@ class DWARFDIE : public DWARFBaseDIE { public: - class ElaboratingDIEIterator; - using DWARFBaseDIE::DWARFBaseDIE; - //---------------------------------------------------------------------- // Tests - //---------------------------------------------------------------------- bool IsStructUnionOrClass() const; bool IsMethod() const; - //---------------------------------------------------------------------- // Accessors - //---------------------------------------------------------------------- lldb::ModuleSP GetContainingDWOModule() const; DWARFDIE GetContainingDWOModuleDIE() const; - inline llvm::iterator_range<ElaboratingDIEIterator> elaborating_dies() const; - - //---------------------------------------------------------------------- // Accessing information about a DIE - //---------------------------------------------------------------------- const char *GetMangledName() const; const char *GetPubname() const; const char *GetQualifiedName(std::string &storage) const; + using DWARFBaseDIE::GetName; + void GetName(lldb_private::Stream &s) const; + + void AppendTypeName(lldb_private::Stream &s) const; + lldb_private::Type *ResolveType() const; - //---------------------------------------------------------------------- // Resolve a type by UID using this DIE's DWARF file - //---------------------------------------------------------------------- - lldb_private::Type *ResolveTypeUID(const DIERef &die_ref) const; + lldb_private::Type *ResolveTypeUID(const DWARFDIE &die) const; - //---------------------------------------------------------------------- // Functions for obtaining DIE relations and references - //---------------------------------------------------------------------- DWARFDIE GetParent() const; @@ -68,11 +58,9 @@ public: DWARFDIE GetReferencedDIE(const dw_attr_t attr) const; - //---------------------------------------------------------------------- // Get a another DIE from the same DWARF file as this DIE. This will // check the current DIE's compile unit first to see if "die_offset" is // in the same compile unit, and fall back to checking the DWARF file. - //---------------------------------------------------------------------- DWARFDIE GetDIE(dw_offset_t die_offset) const; using DWARFBaseDIE::GetDIE; @@ -83,10 +71,8 @@ public: DWARFDIE GetParentDeclContextDIE() const; - //---------------------------------------------------------------------- // DeclContext related functions - //---------------------------------------------------------------------- - void GetDeclContextDIEs(DWARFDIECollection &decl_context_dies) const; + std::vector<DWARFDIE> GetDeclContextDIEs() const; void GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const; @@ -95,13 +81,11 @@ public: void GetDeclContext(std::vector<lldb_private::CompilerContext> &context) const; - //---------------------------------------------------------------------- // Getting attribute values from the DIE. // // GetAttributeValueAsXXX() functions should only be used if you are // looking for one or two attributes on a DIE. If you are trying to // parse all attributes, use GetAttributes (...) instead - //---------------------------------------------------------------------- DWARFDIE GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const; @@ -111,9 +95,7 @@ public: int &call_line, int &call_column, lldb_private::DWARFExpression *frame_base) const; - //---------------------------------------------------------------------- // CompilerDecl related functions - //---------------------------------------------------------------------- lldb_private::CompilerDecl GetDecl() const; @@ -122,58 +104,4 @@ public: lldb_private::CompilerDeclContext GetContainingDeclContext() const; }; -/// Iterate through all DIEs elaborating (i.e. reachable by a chain of -/// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For -/// convenience, the starting die is included in the sequence as the first -/// item. -class DWARFDIE::ElaboratingDIEIterator - : public std::iterator<std::input_iterator_tag, DWARFDIE> { - - // The operating invariant is: top of m_worklist contains the "current" item - // and the rest of the list are items yet to be visited. An empty worklist - // means we've reached the end. - // Infinite recursion is prevented by maintaining a list of seen DIEs. - // Container sizes are optimized for the case of following DW_AT_specification - // and DW_AT_abstract_origin just once. - llvm::SmallVector<DWARFDIE, 2> m_worklist; - llvm::SmallSet<lldb::user_id_t, 3> m_seen; - - void Next(); - -public: - /// An iterator starting at die d. - explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {} - - /// End marker - ElaboratingDIEIterator() {} - - const DWARFDIE &operator*() const { return m_worklist.back(); } - ElaboratingDIEIterator &operator++() { - Next(); - return *this; - } - ElaboratingDIEIterator operator++(int) { - ElaboratingDIEIterator I = *this; - Next(); - return I; - } - - friend bool operator==(const ElaboratingDIEIterator &a, - const ElaboratingDIEIterator &b) { - if (a.m_worklist.empty() || b.m_worklist.empty()) - return a.m_worklist.empty() == b.m_worklist.empty(); - return a.m_worklist.back() == b.m_worklist.back(); - } - friend bool operator!=(const ElaboratingDIEIterator &a, - const ElaboratingDIEIterator &b) { - return !(a == b); - } -}; - -llvm::iterator_range<DWARFDIE::ElaboratingDIEIterator> -DWARFDIE::elaborating_dies() const { - return llvm::make_range(ElaboratingDIEIterator(*this), - ElaboratingDIEIterator()); -} - #endif // SymbolFileDWARF_DWARFDIE_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp deleted file mode 100644 index 1e5bf619f798..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===-- DWARFDIECollection.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFDIECollection.h" - -#include <algorithm> - -#include "lldb/Utility/Stream.h" - -using namespace lldb_private; -using namespace std; - -void DWARFDIECollection::Append(const DWARFDIE &die) { m_dies.push_back(die); } - -DWARFDIE -DWARFDIECollection::GetDIEAtIndex(uint32_t idx) const { - if (idx < m_dies.size()) - return m_dies[idx]; - return DWARFDIE(); -} - -size_t DWARFDIECollection::Size() const { return m_dies.size(); } - -void DWARFDIECollection::Dump(Stream *s, const char *title) const { - if (title && title[0] != '\0') - s->Printf("%s\n", title); - for (const auto &die : m_dies) - s->Printf("0x%8.8x\n", die.GetOffset()); -} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h deleted file mode 100644 index e1e73e71ae7f..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h +++ /dev/null @@ -1,38 +0,0 @@ -//===-- DWARFDIECollection.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFDIECollection_h_ -#define SymbolFileDWARF_DWARFDIECollection_h_ - -#include "DWARFDIE.h" -#include <vector> - -class DWARFDIECollection { -public: - DWARFDIECollection() : m_dies() {} - ~DWARFDIECollection() {} - - void Append(const DWARFDIE &die); - - void Dump(lldb_private::Stream *s, const char *title) const; - - DWARFDIE - GetDIEAtIndex(uint32_t idx) const; - - size_t Size() const; - -protected: - typedef std::vector<DWARFDIE> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - - collection m_dies; // Ordered list of die offsets -}; - -#endif // SymbolFileDWARF_DWARFDIECollection_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp index 2fcdd34d532f..1678b228137f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp @@ -1,27 +1,30 @@ //===-- DWARFDataExtractor.cpp ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DWARFDataExtractor.h" +#include "llvm/ADT/StringRef.h" namespace lldb_private { uint64_t DWARFDataExtractor::GetDWARFInitialLength(lldb::offset_t *offset_ptr) const { - uint64_t length = GetU32(offset_ptr); - m_is_dwarf64 = (length == UINT32_MAX); - if (m_is_dwarf64) - length = GetU64(offset_ptr); - return length; + return GetU32(offset_ptr); } dw_offset_t DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const { return GetMaxU64(offset_ptr, GetDWARFSizeOfOffset()); } + +llvm::DWARFDataExtractor DWARFDataExtractor::GetAsLLVM() const { + return llvm::DWARFDataExtractor( + llvm::StringRef(reinterpret_cast<const char *>(GetDataStart()), + GetByteSize()), + GetByteOrder() == lldb::eByteOrderLittle, GetAddressByteSize()); } +} // namespace lldb_private diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h index 1f342035f135..22db5e8c0b79 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h @@ -1,9 +1,8 @@ //===-- DWARFDataExtractor.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,27 +11,26 @@ #include "lldb/Core/dwarf.h" #include "lldb/Utility/DataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" namespace lldb_private { class DWARFDataExtractor : public DataExtractor { public: - DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) {} + DWARFDataExtractor() = default; DWARFDataExtractor(const DWARFDataExtractor &data, lldb::offset_t offset, lldb::offset_t length) - : DataExtractor(data, offset, length), m_is_dwarf64(false) {} + : DataExtractor(data, offset, length) {} uint64_t GetDWARFInitialLength(lldb::offset_t *offset_ptr) const; dw_offset_t GetDWARFOffset(lldb::offset_t *offset_ptr) const; - size_t GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; } - size_t GetDWARFSizeOfOffset() const { return m_is_dwarf64 ? 8 : 4; } - bool IsDWARF64() const { return m_is_dwarf64; } + size_t GetDWARFSizeofInitialLength() const { return 4; } + size_t GetDWARFSizeOfOffset() const { return 4; } -protected: - mutable bool m_is_dwarf64; + llvm::DWARFDataExtractor GetAsLLVM() const; }; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp index affe4b85bdab..26301566a8e1 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp @@ -1,9 +1,8 @@ //===-- DWARFDebugAbbrev.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -15,50 +14,41 @@ using namespace lldb; using namespace lldb_private; using namespace std; -//---------------------------------------------------------------------- // DWARFAbbreviationDeclarationSet::Clear() -//---------------------------------------------------------------------- void DWARFAbbreviationDeclarationSet::Clear() { m_idx_offset = 0; m_decls.clear(); } -//---------------------------------------------------------------------- // DWARFAbbreviationDeclarationSet::Extract() -//---------------------------------------------------------------------- -bool DWARFAbbreviationDeclarationSet::Extract(const DWARFDataExtractor &data, - lldb::offset_t *offset_ptr) { +llvm::Error +DWARFAbbreviationDeclarationSet::extract(const DWARFDataExtractor &data, + lldb::offset_t *offset_ptr) { const lldb::offset_t begin_offset = *offset_ptr; m_offset = begin_offset; Clear(); DWARFAbbreviationDeclaration abbrevDeclaration; dw_uleb128_t prev_abbr_code = 0; - while (abbrevDeclaration.Extract(data, offset_ptr)) { + while (true) { + llvm::Expected<DWARFEnumState> es = + abbrevDeclaration.extract(data, offset_ptr); + if (!es) + return es.takeError(); + if (*es == DWARFEnumState::Complete) + break; m_decls.push_back(abbrevDeclaration); if (m_idx_offset == 0) m_idx_offset = abbrevDeclaration.Code(); - else { - if (prev_abbr_code + 1 != abbrevDeclaration.Code()) - m_idx_offset = - UINT32_MAX; // Out of order indexes, we can't do O(1) lookups... + else if (prev_abbr_code + 1 != abbrevDeclaration.Code()) { + // Out of order indexes, we can't do O(1) lookups... + m_idx_offset = UINT32_MAX; } prev_abbr_code = abbrevDeclaration.Code(); } - return begin_offset != *offset_ptr; + return llvm::ErrorSuccess(); } -//---------------------------------------------------------------------- -// DWARFAbbreviationDeclarationSet::Dump() -//---------------------------------------------------------------------- -void DWARFAbbreviationDeclarationSet::Dump(Stream *s) const { - std::for_each( - m_decls.begin(), m_decls.end(), - bind2nd(std::mem_fun_ref(&DWARFAbbreviationDeclaration::Dump), s)); -} - -//---------------------------------------------------------------------- // DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration() -//---------------------------------------------------------------------- const DWARFAbbreviationDeclaration * DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration( dw_uleb128_t abbrCode) const { @@ -74,32 +64,11 @@ DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration( if (idx < m_decls.size()) return &m_decls[idx]; } - return NULL; + return nullptr; } -//---------------------------------------------------------------------- -// DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential() -// -// Append an abbreviation declaration with a sequential code for O(n) lookups. -// Handy when creating an DWARFAbbreviationDeclarationSet. -//---------------------------------------------------------------------- -dw_uleb128_t DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential( - const DWARFAbbreviationDeclaration &abbrevDecl) { - // Get the next abbreviation code based on our current array size - dw_uleb128_t code = m_decls.size() + 1; - - // Push the new declaration on the back - m_decls.push_back(abbrevDecl); - - // Update the code for this new declaration - m_decls.back().SetCode(code); - - return code; // return the new abbreviation code! -} -//---------------------------------------------------------------------- // DWARFAbbreviationDeclarationSet::GetUnsupportedForms() -//---------------------------------------------------------------------- void DWARFAbbreviationDeclarationSet::GetUnsupportedForms( std::set<dw_form_t> &invalid_forms) const { for (const auto &abbr_decl : m_decls) { @@ -112,13 +81,11 @@ void DWARFAbbreviationDeclarationSet::GetUnsupportedForms( } } -//---------------------------------------------------------------------- // Encode // // Encode the abbreviation table onto the end of the buffer provided into a // byte representation as would be found in a ".debug_abbrev" debug information // section. -//---------------------------------------------------------------------- // void // DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf) // const @@ -130,49 +97,29 @@ void DWARFAbbreviationDeclarationSet::GetUnsupportedForms( // debug_abbrev_buf.Append8(0); //} -//---------------------------------------------------------------------- // DWARFDebugAbbrev constructor -//---------------------------------------------------------------------- DWARFDebugAbbrev::DWARFDebugAbbrev() : m_abbrevCollMap(), m_prev_abbr_offset_pos(m_abbrevCollMap.end()) {} -//---------------------------------------------------------------------- // DWARFDebugAbbrev::Parse() -//---------------------------------------------------------------------- -void DWARFDebugAbbrev::Parse(const DWARFDataExtractor &data) { +llvm::Error DWARFDebugAbbrev::parse(const DWARFDataExtractor &data) { lldb::offset_t offset = 0; while (data.ValidOffset(offset)) { uint32_t initial_cu_offset = offset; DWARFAbbreviationDeclarationSet abbrevDeclSet; - if (abbrevDeclSet.Extract(data, &offset)) - m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet; - else - break; - } - m_prev_abbr_offset_pos = m_abbrevCollMap.end(); -} + llvm::Error error = abbrevDeclSet.extract(data, &offset); + if (error) + return error; -//---------------------------------------------------------------------- -// DWARFDebugAbbrev::Dump() -//---------------------------------------------------------------------- -void DWARFDebugAbbrev::Dump(Stream *s) const { - if (m_abbrevCollMap.empty()) { - s->PutCString("< EMPTY >\n"); - return; - } - - DWARFAbbreviationDeclarationCollMapConstIter pos; - for (pos = m_abbrevCollMap.begin(); pos != m_abbrevCollMap.end(); ++pos) { - s->Printf("Abbrev table for offset: 0x%8.8x\n", pos->first); - pos->second.Dump(s); + m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet; } + m_prev_abbr_offset_pos = m_abbrevCollMap.end(); + return llvm::ErrorSuccess(); } -//---------------------------------------------------------------------- // DWARFDebugAbbrev::GetAbbreviationDeclarationSet() -//---------------------------------------------------------------------- const DWARFAbbreviationDeclarationSet * DWARFDebugAbbrev::GetAbbreviationDeclarationSet( dw_offset_t cu_abbr_offset) const { @@ -188,12 +135,10 @@ DWARFDebugAbbrev::GetAbbreviationDeclarationSet( if (pos != m_abbrevCollMap.end()) return &(pos->second); - return NULL; + return nullptr; } -//---------------------------------------------------------------------- // DWARFDebugAbbrev::GetUnsupportedForms() -//---------------------------------------------------------------------- void DWARFDebugAbbrev::GetUnsupportedForms( std::set<dw_form_t> &invalid_forms) const { for (const auto &pair : m_abbrevCollMap) diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h index 2bacb6349b6f..9c4729326081 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h @@ -1,9 +1,8 @@ //===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -35,17 +34,21 @@ public: void Clear(); dw_offset_t GetOffset() const { return m_offset; } - void Dump(lldb_private::Stream *s) const; - bool Extract(const lldb_private::DWARFDataExtractor &data, - lldb::offset_t *offset_ptr); + + /// Extract all abbrev decls in a set. Returns llvm::ErrorSuccess() on + /// success, and an appropriate llvm::Error object otherwise. + llvm::Error extract(const lldb_private::DWARFDataExtractor &data, + lldb::offset_t *offset_ptr); // void Encode(BinaryStreamBuf& debug_abbrev_buf) const; - dw_uleb128_t - AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration &abbrevDecl); void GetUnsupportedForms(std::set<dw_form_t> &invalid_forms) const; const DWARFAbbreviationDeclaration * GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const; + /// Unit test accessor functions. + /// @{ + uint32_t GetIndexOffset() const { return m_idx_offset; } + /// @} private: dw_offset_t m_offset; uint32_t m_idx_offset; @@ -64,8 +67,10 @@ public: DWARFDebugAbbrev(); const DWARFAbbreviationDeclarationSet * GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const; - void Dump(lldb_private::Stream *s) const; - void Parse(const lldb_private::DWARFDataExtractor &data); + /// Extract all abbreviations for a particular compile unit. Returns + /// llvm::ErrorSuccess() on success, and an appropriate llvm::Error object + /// otherwise. + llvm::Error parse(const lldb_private::DWARFDataExtractor &data); void GetUnsupportedForms(std::set<dw_form_t> &invalid_forms) const; protected: diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp index 00265361f865..86ce3b329b25 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp @@ -1,17 +1,15 @@ //===-- DWARFDebugArangeSet.cpp ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DWARFDebugArangeSet.h" - -#include "SymbolFileDWARF.h" -#include "lldb/Utility/Stream.h" -#include <assert.h> +#include "DWARFDataExtractor.h" +#include "llvm/Object/Error.h" +#include <cassert> using namespace lldb_private; @@ -34,213 +32,88 @@ void DWARFDebugArangeSet::Clear() { m_arange_descriptors.clear(); } -void DWARFDebugArangeSet::SetHeader(uint16_t version, uint32_t cu_offset, - uint8_t addr_size, uint8_t seg_size) { - m_header.version = version; - m_header.cu_offset = cu_offset; - m_header.addr_size = addr_size; - m_header.seg_size = seg_size; -} - -void DWARFDebugArangeSet::Compact() { - if (m_arange_descriptors.empty()) - return; - - // Iterate through all arange descriptors and combine any ranges that overlap - // or have matching boundaries. The m_arange_descriptors are assumed to be in - // ascending order after being built by adding descriptors using the - // AddDescriptor method. - uint32_t i = 0; - while (i + 1 < m_arange_descriptors.size()) { - if (m_arange_descriptors[i].end_address() >= - m_arange_descriptors[i + 1].address) { - // The current range ends at or exceeds the start of the next address - // range. Compute the max end address between the two and use that to - // make the new length. - const dw_addr_t max_end_addr = - std::max(m_arange_descriptors[i].end_address(), - m_arange_descriptors[i + 1].end_address()); - m_arange_descriptors[i].length = - max_end_addr - m_arange_descriptors[i].address; - // Now remove the next entry as it was just combined with the previous - // one. - m_arange_descriptors.erase(m_arange_descriptors.begin() + i + 1); - } else { - // Discontiguous address range, just proceed to the next one. - ++i; - } - } -} -//---------------------------------------------------------------------- -// Compare function DWARFDebugArangeSet::Descriptor structures -//---------------------------------------------------------------------- -static bool DescriptorLessThan(const DWARFDebugArangeSet::Descriptor &range1, - const DWARFDebugArangeSet::Descriptor &range2) { - return range1.address < range2.address; -} - -//---------------------------------------------------------------------- -// Add a range descriptor and keep things sorted so we can easily compact the -// ranges before being saved or used. -//---------------------------------------------------------------------- -void DWARFDebugArangeSet::AddDescriptor( - const DWARFDebugArangeSet::Descriptor &range) { - if (m_arange_descriptors.empty()) { - m_arange_descriptors.push_back(range); - return; - } - - DescriptorIter end = m_arange_descriptors.end(); - DescriptorIter pos = - lower_bound(m_arange_descriptors.begin(), end, range, DescriptorLessThan); - const dw_addr_t range_end_addr = range.end_address(); - if (pos != end) { - const dw_addr_t found_end_addr = pos->end_address(); - if (range.address < pos->address) { - if (range_end_addr < pos->address) { - // Non-contiguous entries, add this one before the found entry - m_arange_descriptors.insert(pos, range); - } else if (range_end_addr == pos->address) { - // The top end of 'range' is the lower end of the entry pointed to by - // 'pos'. We can combine range with the entry we found by setting the - // starting address and increasing the length since they don't overlap. - pos->address = range.address; - pos->length += range.length; - } else { - // We can combine these two and make sure the largest end address is - // used to make end address. - pos->address = range.address; - pos->length = std::max(found_end_addr, range_end_addr) - pos->address; - } - } else if (range.address == pos->address) { - pos->length = std::max(pos->length, range.length); - } - } else { - // NOTE: 'pos' points to entry past the end which is ok for insert, - // don't use otherwise!!! - const dw_addr_t max_addr = m_arange_descriptors.back().end_address(); - if (max_addr < range.address) { - // Non-contiguous entries, add this one before the found entry - m_arange_descriptors.insert(pos, range); - } else if (max_addr == range.address) { - m_arange_descriptors.back().length += range.length; - } else { - m_arange_descriptors.back().length = std::max(max_addr, range_end_addr) - - m_arange_descriptors.back().address; - } - } -} - -bool DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data, - lldb::offset_t *offset_ptr) { - if (data.ValidOffset(*offset_ptr)) { - m_arange_descriptors.clear(); - m_offset = *offset_ptr; +llvm::Error DWARFDebugArangeSet::extract(const DWARFDataExtractor &data, + lldb::offset_t *offset_ptr) { + assert(data.ValidOffset(*offset_ptr)); - // 7.20 Address Range Table - // - // Each set of entries in the table of address ranges contained in the - // .debug_aranges section begins with a header consisting of: a 4-byte - // length containing the length of the set of entries for this compilation - // unit, not including the length field itself; a 2-byte version identifier - // containing the value 2 for DWARF Version 2; a 4-byte offset into - // the.debug_infosection; a 1-byte unsigned integer containing the size in - // bytes of an address (or the offset portion of an address for segmented - // addressing) on the target system; and a 1-byte unsigned integer - // containing the size in bytes of a segment descriptor on the target - // system. This header is followed by a series of tuples. Each tuple - // consists of an address and a length, each in the size appropriate for an - // address on the target architecture. - m_header.length = data.GetDWARFInitialLength(offset_ptr); - m_header.version = data.GetU16(offset_ptr); - m_header.cu_offset = data.GetDWARFOffset(offset_ptr); - m_header.addr_size = data.GetU8(offset_ptr); - m_header.seg_size = data.GetU8(offset_ptr); - - // Try to avoid reading invalid arange sets by making sure: - // 1 - the version looks good - // 2 - the address byte size looks plausible - // 3 - the length seems to make sense - // size looks plausible - if ((m_header.version >= 2 && m_header.version <= 5) && - (m_header.addr_size == 4 || m_header.addr_size == 8) && - (m_header.length > 0)) { - if (data.ValidOffset(m_offset + sizeof(m_header.length) + - m_header.length - 1)) { - // The first tuple following the header in each set begins at an offset - // that is a multiple of the size of a single tuple (that is, twice the - // size of an address). The header is padded, if necessary, to the - // appropriate boundary. - const uint32_t header_size = *offset_ptr - m_offset; - const uint32_t tuple_size = m_header.addr_size << 1; - uint32_t first_tuple_offset = 0; - while (first_tuple_offset < header_size) - first_tuple_offset += tuple_size; - - *offset_ptr = m_offset + first_tuple_offset; - - Descriptor arangeDescriptor; - - static_assert( - sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length), - "DWARFDebugArangeSet::Descriptor.address and " - "DWARFDebugArangeSet::Descriptor.length must have same size"); - - while (data.ValidOffset(*offset_ptr)) { - arangeDescriptor.address = - data.GetMaxU64(offset_ptr, m_header.addr_size); - arangeDescriptor.length = - data.GetMaxU64(offset_ptr, m_header.addr_size); - - // Each set of tuples is terminated by a 0 for the address and 0 for - // the length. - if (arangeDescriptor.address || arangeDescriptor.length) - m_arange_descriptors.push_back(arangeDescriptor); - else - break; // We are done if we get a zero address and length - } - } -#if defined(LLDB_CONFIGURATION_DEBUG) - else { - printf("warning: .debug_arange set length is too large arange data at " - "0x%8.8x: length=0x%8.8x, version=0x%4.4x, cu_offset=0x%8.8x, " - "addr_size=%u, seg_size=%u\n", - m_offset, m_header.length, m_header.version, m_header.cu_offset, - m_header.addr_size, m_header.seg_size); - } -#endif - } -#if defined(LLDB_CONFIGURATION_DEBUG) - else { - printf("warning: .debug_arange set has bad header at 0x%8.8x: " - "length=0x%8.8x, version=0x%4.4x, cu_offset=0x%8.8x, " - "addr_size=%u, seg_size=%u\n", - m_offset, m_header.length, m_header.version, m_header.cu_offset, - m_header.addr_size, m_header.seg_size); - } -#endif - - return !m_arange_descriptors.empty(); + m_arange_descriptors.clear(); + m_offset = *offset_ptr; + + // 7.20 Address Range Table + // + // Each set of entries in the table of address ranges contained in the + // .debug_aranges section begins with a header consisting of: a 4-byte + // length containing the length of the set of entries for this compilation + // unit, not including the length field itself; a 2-byte version identifier + // containing the value 2 for DWARF Version 2; a 4-byte offset into + // the.debug_infosection; a 1-byte unsigned integer containing the size in + // bytes of an address (or the offset portion of an address for segmented + // addressing) on the target system; and a 1-byte unsigned integer + // containing the size in bytes of a segment descriptor on the target + // system. This header is followed by a series of tuples. Each tuple + // consists of an address and a length, each in the size appropriate for an + // address on the target architecture. + m_header.length = data.GetDWARFInitialLength(offset_ptr); + m_header.version = data.GetU16(offset_ptr); + m_header.cu_offset = data.GetDWARFOffset(offset_ptr); + m_header.addr_size = data.GetU8(offset_ptr); + m_header.seg_size = data.GetU8(offset_ptr); + + // Try to avoid reading invalid arange sets by making sure: + // 1 - the version looks good + // 2 - the address byte size looks plausible + // 3 - the length seems to make sense + // size looks plausible + if (m_header.version < 2 || m_header.version > 5) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Invalid arange header version"); + + if (m_header.addr_size != 4 && m_header.addr_size != 8) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Invalid arange header address size"); + + if (m_header.length == 0) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Invalid arange header length"); + + if (!data.ValidOffset(m_offset + sizeof(m_header.length) + m_header.length - + 1)) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Invalid arange header length"); + + // The first tuple following the header in each set begins at an offset + // that is a multiple of the size of a single tuple (that is, twice the + // size of an address). The header is padded, if necessary, to the + // appropriate boundary. + const uint32_t header_size = *offset_ptr - m_offset; + const uint32_t tuple_size = m_header.addr_size << 1; + uint32_t first_tuple_offset = 0; + while (first_tuple_offset < header_size) + first_tuple_offset += tuple_size; + + *offset_ptr = m_offset + first_tuple_offset; + + Descriptor arangeDescriptor; + + static_assert(sizeof(arangeDescriptor.address) == + sizeof(arangeDescriptor.length), + "DWARFDebugArangeSet::Descriptor.address and " + "DWARFDebugArangeSet::Descriptor.length must have same size"); + + while (data.ValidOffset(*offset_ptr)) { + arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size); + arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size); + + // Each set of tuples is terminated by a 0 for the address and 0 for + // the length. + if (!arangeDescriptor.address && !arangeDescriptor.length) + return llvm::ErrorSuccess(); + + m_arange_descriptors.push_back(arangeDescriptor); } - return false; -} - -dw_offset_t DWARFDebugArangeSet::GetOffsetOfNextEntry() const { - return m_offset + m_header.length + 4; -} - -void DWARFDebugArangeSet::Dump(Stream *s) const { - s->Printf("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, " - "cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n", - m_header.length, m_header.version, m_header.cu_offset, - m_header.addr_size, m_header.seg_size); - const uint32_t hex_width = m_header.addr_size * 2; - DescriptorConstIter pos; - DescriptorConstIter end = m_arange_descriptors.end(); - for (pos = m_arange_descriptors.begin(); pos != end; ++pos) - s->Printf("[0x%*.*" PRIx64 " - 0x%*.*" PRIx64 ")\n", hex_width, hex_width, - pos->address, hex_width, hex_width, pos->end_address()); + return llvm::make_error<llvm::object::GenericBinaryError>( + "arange descriptors not terminated by null entry"); } class DescriptorContainsAddress { diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h index ae6319a13d0e..db0cf22a3f45 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h @@ -1,20 +1,18 @@ //===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 SymbolFileDWARF_DWARFDebugArangeSet_h_ #define SymbolFileDWARF_DWARFDebugArangeSet_h_ -#include "SymbolFileDWARF.h" +#include "lldb/Core/dwarf.h" +#include <cstdint> #include <vector> -class SymbolFileDWARF; - class DWARFDebugArangeSet { public: struct Header { @@ -41,23 +39,11 @@ public: DWARFDebugArangeSet(); void Clear(); void SetOffset(uint32_t offset) { m_offset = offset; } - void SetHeader(uint16_t version, uint32_t cu_offset, uint8_t addr_size, - uint8_t seg_size); - void AddDescriptor(const DWARFDebugArangeSet::Descriptor &range); - void Compact(); - bool Extract(const lldb_private::DWARFDataExtractor &data, - lldb::offset_t *offset_ptr); - void Dump(lldb_private::Stream *s) const; - dw_offset_t GetCompileUnitDIEOffset() const { return m_header.cu_offset; } - dw_offset_t GetOffsetOfNextEntry() const; + llvm::Error extract(const lldb_private::DWARFDataExtractor &data, + lldb::offset_t *offset_ptr); dw_offset_t FindAddress(dw_addr_t address) const; size_t NumDescriptors() const { return m_arange_descriptors.size(); } const Header &GetHeader() const { return m_header; } - const Descriptor *GetDescriptor(uint32_t i) const { - if (i < m_arange_descriptors.size()) - return &m_arange_descriptors[i]; - return NULL; - } const Descriptor &GetDescriptorRef(uint32_t i) const { return m_arange_descriptors[i]; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index 02f528d571b0..ccf33e6dc341 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -1,39 +1,24 @@ //===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DWARFDebugAranges.h" - -#include <assert.h> -#include <stdio.h> - -#include <algorithm> - +#include "DWARFDebugArangeSet.h" +#include "DWARFUnit.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" -#include "DWARFUnit.h" -#include "DWARFDebugInfo.h" -#include "LogChannelDWARF.h" -#include "SymbolFileDWARF.h" - using namespace lldb; using namespace lldb_private; -//---------------------------------------------------------------------- // Constructor -//---------------------------------------------------------------------- DWARFDebugAranges::DWARFDebugAranges() : m_aranges() {} -//---------------------------------------------------------------------- // CountArangeDescriptors -//---------------------------------------------------------------------- class CountArangeDescriptors { public: CountArangeDescriptors(uint32_t &count_ref) : count(count_ref) { @@ -45,53 +30,36 @@ public: uint32_t &count; }; -//---------------------------------------------------------------------- // Extract -//---------------------------------------------------------------------- -bool DWARFDebugAranges::Extract(const DWARFDataExtractor &debug_aranges_data) { - if (debug_aranges_data.ValidOffset(0)) { - lldb::offset_t offset = 0; - - DWARFDebugArangeSet set; - Range range; - while (set.Extract(debug_aranges_data, &offset)) { - const uint32_t num_descriptors = set.NumDescriptors(); - if (num_descriptors > 0) { - const dw_offset_t cu_offset = set.GetCompileUnitDIEOffset(); - - for (uint32_t i = 0; i < num_descriptors; ++i) { - const DWARFDebugArangeSet::Descriptor &descriptor = - set.GetDescriptorRef(i); - m_aranges.Append(RangeToDIE::Entry(descriptor.address, - descriptor.length, cu_offset)); - } +llvm::Error +DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) { + lldb::offset_t offset = 0; + + DWARFDebugArangeSet set; + Range range; + while (debug_aranges_data.ValidOffset(offset)) { + llvm::Error error = set.extract(debug_aranges_data, &offset); + if (!error) + return error; + + const uint32_t num_descriptors = set.NumDescriptors(); + if (num_descriptors > 0) { + const dw_offset_t cu_offset = set.GetHeader().cu_offset; + + for (uint32_t i = 0; i < num_descriptors; ++i) { + const DWARFDebugArangeSet::Descriptor &descriptor = + set.GetDescriptorRef(i); + m_aranges.Append(RangeToDIE::Entry(descriptor.address, + descriptor.length, cu_offset)); } - set.Clear(); } + set.Clear(); } - return false; -} - -//---------------------------------------------------------------------- -// Generate -//---------------------------------------------------------------------- -bool DWARFDebugAranges::Generate(SymbolFileDWARF *dwarf2Data) { - Clear(); - DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo(); - if (debug_info) { - uint32_t cu_idx = 0; - const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); - for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { - DWARFUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx); - if (cu) - cu->BuildAddressRangeTable(dwarf2Data, this); - } - } - return !IsEmpty(); + return llvm::ErrorSuccess(); } void DWARFDebugAranges::Dump(Log *log) const { - if (log == NULL) + if (log == nullptr) return; const size_t num_entries = m_aranges.GetSize(); @@ -114,35 +82,11 @@ void DWARFDebugAranges::Sort(bool minimize) { Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); - size_t orig_arange_size = 0; - if (log) { - orig_arange_size = m_aranges.GetSize(); - log->Printf("DWARFDebugAranges::Sort(minimize = %u) with %" PRIu64 - " entries", - minimize, (uint64_t)orig_arange_size); - } - m_aranges.Sort(); m_aranges.CombineConsecutiveEntriesWithEqualData(); - - if (log) { - if (minimize) { - const size_t new_arange_size = m_aranges.GetSize(); - const size_t delta = orig_arange_size - new_arange_size; - log->Printf("DWARFDebugAranges::Sort() %" PRIu64 - " entries after minimizing (%" PRIu64 - " entries combined for %" PRIu64 " bytes saved)", - (uint64_t)new_arange_size, (uint64_t)delta, - (uint64_t)delta * sizeof(Range)); - } - Dump(log); - } } -//---------------------------------------------------------------------- // FindAddress -//---------------------------------------------------------------------- dw_offset_t DWARFDebugAranges::FindAddress(dw_addr_t address) const { const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address); if (entry) diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h index e7a8635f0532..74ba011b27af 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h @@ -1,21 +1,17 @@ //===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 SymbolFileDWARF_DWARFDebugAranges_h_ #define SymbolFileDWARF_DWARFDebugAranges_h_ -#include "DWARFDebugArangeSet.h" -#include <list> - -#include "lldb/Core/RangeMap.h" - -class SymbolFileDWARF; +#include "lldb/Core/dwarf.h" +#include "lldb/Utility/RangeMap.h" +#include "llvm/Support/Error.h" class DWARFDebugAranges { protected: @@ -30,19 +26,14 @@ public: void Clear() { m_aranges.Clear(); } - bool Extract(const lldb_private::DWARFDataExtractor &debug_aranges_data); - - bool Generate(SymbolFileDWARF *dwarf2Data); + llvm::Error + extract(const lldb_private::DWARFDataExtractor &debug_aranges_data); // Use append range multiple times and then call sort void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc); void Sort(bool minimize); - const Range *RangeAtIndex(uint32_t idx) const { - return m_aranges.GetEntryAtIndex(idx); - } - void Dump(lldb_private::Log *log) const; dw_offset_t FindAddress(dw_addr_t address) const; @@ -57,8 +48,6 @@ public: return DW_INVALID_OFFSET; } - static void Dump(SymbolFileDWARF *dwarf2Data, lldb_private::Stream *s); - protected: RangeToDIE m_aranges; }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index dadc30dc918a..100f35f8c6b0 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -1,9 +1,8 @@ //===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -16,213 +15,183 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include "llvm/Support/Casting.h" #include "DWARFCompileUnit.h" -#include "DWARFDebugAranges.h" +#include "DWARFContext.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" #include "DWARFDebugInfoEntry.h" #include "DWARFFormValue.h" -#include "LogChannelDWARF.h" +#include "DWARFTypeUnit.h" using namespace lldb; using namespace lldb_private; using namespace std; -//---------------------------------------------------------------------- // Constructor -//---------------------------------------------------------------------- -DWARFDebugInfo::DWARFDebugInfo() - : m_dwarf2Data(NULL), m_compile_units(), m_cu_aranges_ap() {} - -//---------------------------------------------------------------------- -// SetDwarfData -//---------------------------------------------------------------------- -void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) { - m_dwarf2Data = dwarf2Data; - m_compile_units.clear(); -} +DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf, + lldb_private::DWARFContext &context) + : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {} + +llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { + if (m_cu_aranges_up) + return *m_cu_aranges_up; + + m_cu_aranges_up = llvm::make_unique<DWARFDebugAranges>(); + const DWARFDataExtractor &debug_aranges_data = + m_context.getOrLoadArangesData(); + if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data)) + return std::move(error); + + // Make a list of all CUs represented by the arange data in the file. + std::set<dw_offset_t> cus_with_data; + for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) { + dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n); + if (offset != DW_INVALID_OFFSET) + cus_with_data.insert(offset); + } -DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { - if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) { - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); - - m_cu_aranges_ap.reset(new DWARFDebugAranges()); - const DWARFDataExtractor &debug_aranges_data = - m_dwarf2Data->get_debug_aranges_data(); - if (debug_aranges_data.GetByteSize() > 0) { - if (log) - log->Printf( - "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from " - ".debug_aranges", - m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); - m_cu_aranges_ap->Extract(debug_aranges_data); - } + // Manually build arange data for everything that wasn't in the + // .debug_aranges table. + const size_t num_units = GetNumUnits(); + for (size_t idx = 0; idx < num_units; ++idx) { + DWARFUnit *cu = GetUnitAtIndex(idx); - // Make a list of all CUs represented by the arange data in the file. - std::set<dw_offset_t> cus_with_data; - for (size_t n = 0; n < m_cu_aranges_ap.get()->GetNumRanges(); n++) { - dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n); - if (offset != DW_INVALID_OFFSET) - cus_with_data.insert(offset); - } + dw_offset_t offset = cu->GetOffset(); + if (cus_with_data.find(offset) == cus_with_data.end()) + cu->BuildAddressRangeTable(m_cu_aranges_up.get()); + } + + const bool minimize = true; + m_cu_aranges_up->Sort(minimize); + return *m_cu_aranges_up; +} - // Manually build arange data for everything that wasn't in the - // .debug_aranges table. - bool printed = false; - const size_t num_compile_units = GetNumCompileUnits(); - for (size_t idx = 0; idx < num_compile_units; ++idx) { - DWARFUnit *cu = GetCompileUnitAtIndex(idx); - - dw_offset_t offset = cu->GetOffset(); - if (cus_with_data.find(offset) == cus_with_data.end()) { - if (log) { - if (!printed) - log->Printf( - "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing", - m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); - printed = true; - } - cu->BuildAddressRangeTable(m_dwarf2Data, m_cu_aranges_ap.get()); - } +void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) { + DWARFDataExtractor data = section == DIERef::Section::DebugTypes + ? m_context.getOrLoadDebugTypesData() + : m_context.getOrLoadDebugInfoData(); + lldb::offset_t offset = 0; + while (data.ValidOffset(offset)) { + llvm::Expected<DWARFUnitSP> unit_sp = + DWARFUnit::extract(m_dwarf, m_units.size(), data, section, &offset); + + if (!unit_sp) { + // FIXME: Propagate this error up. + llvm::consumeError(unit_sp.takeError()); + return; } - const bool minimize = true; - m_cu_aranges_ap->Sort(minimize); - } - return *m_cu_aranges_ap.get(); -} + // If it didn't return an error, then it should be returning a valid Unit. + assert(*unit_sp); + m_units.push_back(*unit_sp); + offset = (*unit_sp)->GetNextUnitOffset(); -void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() { - if (m_compile_units.empty()) { - if (m_dwarf2Data != NULL) { - lldb::offset_t offset = 0; - DWARFUnitSP cu_sp; - const auto &debug_info_data = m_dwarf2Data->get_debug_info_data(); - while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data, - &offset))) { - m_compile_units.push_back(cu_sp); - - offset = cu_sp->GetNextCompileUnitOffset(); - } + if (auto *type_unit = llvm::dyn_cast<DWARFTypeUnit>(unit_sp->get())) { + m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(), + unit_sp.get()->GetID()); } } } -size_t DWARFDebugInfo::GetNumCompileUnits() { - ParseCompileUnitHeadersIfNeeded(); - return m_compile_units.size(); -} +void DWARFDebugInfo::ParseUnitHeadersIfNeeded() { + if (!m_units.empty()) + return; -DWARFUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) { - DWARFUnit *cu = NULL; - if (idx < GetNumCompileUnits()) - cu = m_compile_units[idx].get(); - return cu; + ParseUnitsFor(DIERef::Section::DebugInfo); + ParseUnitsFor(DIERef::Section::DebugTypes); + llvm::sort(m_type_hash_to_unit_index, llvm::less_first()); } -bool DWARFDebugInfo::ContainsCompileUnit(const DWARFUnit *cu) const { - // Not a verify efficient function, but it is handy for use in assertions to - // make sure that a compile unit comes from a debug information file. - CompileUnitColl::const_iterator end_pos = m_compile_units.end(); - CompileUnitColl::const_iterator pos; +size_t DWARFDebugInfo::GetNumUnits() { + ParseUnitHeadersIfNeeded(); + return m_units.size(); +} - for (pos = m_compile_units.begin(); pos != end_pos; ++pos) { - if (pos->get() == cu) - return true; - } - return false; +DWARFUnit *DWARFDebugInfo::GetUnitAtIndex(user_id_t idx) { + DWARFUnit *cu = nullptr; + if (idx < GetNumUnits()) + cu = m_units[idx].get(); + return cu; } -bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset( - dw_offset_t offset, const DWARFUnitSP &cu_sp) { - return offset < cu_sp->GetOffset(); +uint32_t DWARFDebugInfo::FindUnitIndex(DIERef::Section section, + dw_offset_t offset) { + ParseUnitHeadersIfNeeded(); + + // llvm::lower_bound is not used as for DIE offsets it would still return + // index +1 and GetOffset() returning index itself would be a special case. + auto pos = llvm::upper_bound( + m_units, std::make_pair(section, offset), + [](const std::pair<DIERef::Section, dw_offset_t> &lhs, + const DWARFUnitSP &rhs) { + return lhs < std::make_pair(rhs->GetDebugSection(), rhs->GetOffset()); + }); + uint32_t idx = std::distance(m_units.begin(), pos); + if (idx == 0) + return DW_INVALID_OFFSET; + return idx - 1; } -DWARFUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, - uint32_t *idx_ptr) { - DWARFUnitSP cu_sp; - uint32_t cu_idx = DW_INVALID_INDEX; - if (cu_offset != DW_INVALID_OFFSET) { - ParseCompileUnitHeadersIfNeeded(); - - // Watch out for single compile unit executable as they are pretty common - const size_t num_cus = m_compile_units.size(); - if (num_cus == 1) { - if (m_compile_units[0]->GetOffset() == cu_offset) { - cu_sp = m_compile_units[0]; - cu_idx = 0; - } - } else if (num_cus) { - CompileUnitColl::const_iterator end_pos = m_compile_units.end(); - CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); - CompileUnitColl::const_iterator pos = std::upper_bound( - begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset); - if (pos != begin_pos) { - --pos; - if ((*pos)->GetOffset() == cu_offset) { - cu_sp = *pos; - cu_idx = std::distance(begin_pos, pos); - } - } - } +DWARFUnit *DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section, + dw_offset_t cu_offset, + uint32_t *idx_ptr) { + uint32_t idx = FindUnitIndex(section, cu_offset); + DWARFUnit *result = GetUnitAtIndex(idx); + if (result && result->GetOffset() != cu_offset) { + result = nullptr; + idx = DW_INVALID_INDEX; } if (idx_ptr) - *idx_ptr = cu_idx; - return cu_sp.get(); + *idx_ptr = idx; + return result; } -DWARFUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) { - if (die_ref.cu_offset == DW_INVALID_OFFSET) - return GetCompileUnitContainingDIEOffset(die_ref.die_offset); - else - return GetCompileUnit(die_ref.cu_offset); +DWARFUnit *DWARFDebugInfo::GetUnit(const DIERef &die_ref) { + return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset()); } DWARFUnit * -DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) { - ParseCompileUnitHeadersIfNeeded(); - - DWARFUnitSP cu_sp; - - // Watch out for single compile unit executable as they are pretty common - const size_t num_cus = m_compile_units.size(); - if (num_cus == 1) { - if (m_compile_units[0]->ContainsDIEOffset(die_offset)) - return m_compile_units[0].get(); - } else if (num_cus) { - CompileUnitColl::const_iterator end_pos = m_compile_units.end(); - CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); - CompileUnitColl::const_iterator pos = std::upper_bound( - begin_pos, end_pos, die_offset, OffsetLessThanCompileUnitOffset); - if (pos != begin_pos) { - --pos; - if ((*pos)->ContainsDIEOffset(die_offset)) - return (*pos).get(); - } - } +DWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section, + dw_offset_t die_offset) { + uint32_t idx = FindUnitIndex(section, die_offset); + DWARFUnit *result = GetUnitAtIndex(idx); + if (result && !result->ContainsDIEOffset(die_offset)) + return nullptr; + return result; +} + +DWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) { + auto pos = llvm::lower_bound(m_type_hash_to_unit_index, + std::make_pair(hash, 0u), llvm::less_first()); + if (pos == m_type_hash_to_unit_index.end() || pos->first != hash) + return nullptr; + return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second)); +} - return nullptr; +bool DWARFDebugInfo::ContainsTypeUnits() { + ParseUnitHeadersIfNeeded(); + return !m_type_hash_to_unit_index.empty(); } DWARFDIE -DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) { - DWARFUnit *cu = GetCompileUnitContainingDIEOffset(die_offset); +DWARFDebugInfo::GetDIEForDIEOffset(DIERef::Section section, + dw_offset_t die_offset) { + DWARFUnit *cu = GetUnitContainingDIEOffset(section, die_offset); if (cu) return cu->GetDIE(die_offset); return DWARFDIE(); } -//---------------------------------------------------------------------- // GetDIE() // // Get the DIE (Debug Information Entry) with the specified offset. -//---------------------------------------------------------------------- DWARFDIE DWARFDebugInfo::GetDIE(const DIERef &die_ref) { - DWARFUnit *cu = GetCompileUnit(die_ref); + DWARFUnit *cu = GetUnit(die_ref); if (cu) - return cu->GetDIE(die_ref.die_offset); + return cu->GetDIE(die_ref.die_offset()); return DWARFDIE(); // Not found } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index fc6085f99a21..d1b066ffe80c 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -1,9 +1,8 @@ //===-- DWARFDebugInfo.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -13,11 +12,17 @@ #include <map> #include <vector> -#include "DWARFUnit.h" #include "DWARFDIE.h" +#include "DWARFTypeUnit.h" +#include "DWARFUnit.h" #include "SymbolFileDWARF.h" #include "lldb/Core/STLUtils.h" #include "lldb/lldb-private.h" +#include "llvm/Support/Error.h" + +namespace lldb_private { +class DWARFContext; +} typedef std::multimap<const char *, dw_offset_t, CStringCompareFunctionObject> CStringToDIEMap; @@ -32,16 +37,20 @@ public: const dw_offset_t next_offset, const uint32_t depth, void *userData); - DWARFDebugInfo(); - void SetDwarfData(SymbolFileDWARF *dwarf2Data); + explicit DWARFDebugInfo(SymbolFileDWARF &dwarf, + lldb_private::DWARFContext &context); - size_t GetNumCompileUnits(); - bool ContainsCompileUnit(const DWARFUnit *cu) const; - DWARFUnit *GetCompileUnitAtIndex(uint32_t idx); - DWARFUnit *GetCompileUnit(dw_offset_t cu_offset, uint32_t *idx_ptr = NULL); - DWARFUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset); - DWARFUnit *GetCompileUnit(const DIERef &die_ref); - DWARFDIE GetDIEForDIEOffset(dw_offset_t die_offset); + size_t GetNumUnits(); + DWARFUnit *GetUnitAtIndex(lldb::user_id_t idx); + DWARFUnit *GetUnitAtOffset(DIERef::Section section, dw_offset_t cu_offset, + uint32_t *idx_ptr = nullptr); + DWARFUnit *GetUnitContainingDIEOffset(DIERef::Section section, + dw_offset_t die_offset); + DWARFUnit *GetUnit(const DIERef &die_ref); + DWARFTypeUnit *GetTypeUnitForHash(uint64_t hash); + bool ContainsTypeUnits(); + DWARFDIE GetDIEForDIEOffset(DIERef::Section section, + dw_offset_t die_offset); DWARFDIE GetDIE(const DIERef &die_ref); enum { @@ -51,26 +60,27 @@ public: (1 << 2) // Show all parent DIEs when dumping single DIEs }; - DWARFDebugAranges &GetCompileUnitAranges(); + llvm::Expected<DWARFDebugAranges &> GetCompileUnitAranges(); protected: - static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset, - const DWARFUnitSP &cu_sp); + typedef std::vector<DWARFUnitSP> UnitColl; - typedef std::vector<DWARFUnitSP> CompileUnitColl; - - //---------------------------------------------------------------------- - // Member variables - //---------------------------------------------------------------------- - SymbolFileDWARF *m_dwarf2Data; - CompileUnitColl m_compile_units; + SymbolFileDWARF &m_dwarf; + lldb_private::DWARFContext &m_context; + UnitColl m_units; std::unique_ptr<DWARFDebugAranges> - m_cu_aranges_ap; // A quick address to compile unit table + m_cu_aranges_up; // A quick address to compile unit table + + std::vector<std::pair<uint64_t, uint32_t>> m_type_hash_to_unit_index; private: // All parsing needs to be done partially any managed by this class as // accessors are called. - void ParseCompileUnitHeadersIfNeeded(); + void ParseUnitHeadersIfNeeded(); + + void ParseUnitsFor(DIERef::Section section); + + uint32_t FindUnitIndex(DIERef::Section section, dw_offset_t offset); DISALLOW_COPY_AND_ASSIGN(DWARFDebugInfo); }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 7531aeac709a..2f55b7d40ed9 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -1,9 +1,8 @@ //===-- DWARFDebugInfoEntry.cpp ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -13,19 +12,21 @@ #include <algorithm> +#include "llvm/Support/LEB128.h" + #include "lldb/Core/Module.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/Stream.h" -#include "DWARFUnit.h" -#include "DWARFDIECollection.h" +#include "DWARFCompileUnit.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" #include "DWARFFormValue.h" +#include "DWARFUnit.h" #include "SymbolFileDWARF.h" #include "SymbolFileDWARFDwo.h" @@ -33,14 +34,15 @@ using namespace lldb_private; using namespace std; extern int g_verbose; -bool DWARFDebugInfoEntry::FastExtract( - const DWARFDataExtractor &debug_info_data, const DWARFUnit *cu, - const DWARFFormValue::FixedFormSizes &fixed_form_sizes, - lldb::offset_t *offset_ptr) { +// Extract a debug info entry for a given DWARFUnit from the data +// starting at the offset in offset_ptr +bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, + const DWARFUnit *cu, + lldb::offset_t *offset_ptr) { m_offset = *offset_ptr; m_parent_idx = 0; m_sibling_idx = 0; - const uint64_t abbr_idx = debug_info_data.GetULEB128(offset_ptr); + const uint64_t abbr_idx = data.GetULEB128(offset_ptr); lldbassert(abbr_idx <= UINT16_MAX); m_abbr_idx = abbr_idx; @@ -49,12 +51,9 @@ bool DWARFDebugInfoEntry::FastExtract( if (m_abbr_idx) { lldb::offset_t offset = *offset_ptr; - - const DWARFAbbreviationDeclaration *abbrevDecl = - cu->GetAbbreviations()->GetAbbreviationDeclaration(m_abbr_idx); - - if (abbrevDecl == NULL) { - cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError( + const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); + if (abbrevDecl == nullptr) { + cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( "{0x%8.8x}: invalid abbreviation code %u, please file a bug and " "attach the file at the start of this error message", m_offset, (unsigned)abbr_idx); @@ -64,16 +63,16 @@ bool DWARFDebugInfoEntry::FastExtract( } m_tag = abbrevDecl->Tag(); m_has_children = abbrevDecl->HasChildren(); - // Skip all data in the .debug_info for the attributes + // Skip all data in the .debug_info or .debug_types for the attributes const uint32_t numAttributes = abbrevDecl->NumAttributes(); uint32_t i; dw_form_t form; for (i = 0; i < numAttributes; ++i) { form = abbrevDecl->GetFormByIndexUnchecked(i); - - const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form); + llvm::Optional<uint8_t> fixed_skip_size = + DWARFFormValue::GetFixedSize(form, cu); if (fixed_skip_size) - offset += fixed_skip_size; + offset += *fixed_skip_size; else { bool form_is_indirect = false; do { @@ -81,24 +80,24 @@ bool DWARFDebugInfoEntry::FastExtract( uint32_t form_size = 0; switch (form) { // Blocks if inlined data that have a length field and the data bytes - // inlined in the .debug_info + // inlined in the .debug_info/.debug_types case DW_FORM_exprloc: case DW_FORM_block: - form_size = debug_info_data.GetULEB128(&offset); + form_size = data.GetULEB128(&offset); break; case DW_FORM_block1: - form_size = debug_info_data.GetU8_unchecked(&offset); + form_size = data.GetU8_unchecked(&offset); break; case DW_FORM_block2: - form_size = debug_info_data.GetU16_unchecked(&offset); + form_size = data.GetU16_unchecked(&offset); break; case DW_FORM_block4: - form_size = debug_info_data.GetU32_unchecked(&offset); + form_size = data.GetU32_unchecked(&offset); break; // Inlined NULL terminated C-strings case DW_FORM_string: - debug_info_data.GetCStr(&offset); + data.GetCStr(&offset); break; // Compile unit address sized values @@ -109,7 +108,7 @@ bool DWARFDebugInfoEntry::FastExtract( if (cu->GetVersion() <= 2) form_size = cu->GetAddressByteSize(); else - form_size = cu->IsDWARF64() ? 8 : 4; + form_size = 4; break; // 0 sized form @@ -164,20 +163,17 @@ bool DWARFDebugInfoEntry::FastExtract( case DW_FORM_GNU_addr_index: case DW_FORM_GNU_str_index: case DW_FORM_strx: - debug_info_data.Skip_LEB128(&offset); + data.Skip_LEB128(&offset); break; case DW_FORM_indirect: form_is_indirect = true; - form = debug_info_data.GetULEB128(&offset); + form = data.GetULEB128(&offset); break; case DW_FORM_strp: case DW_FORM_sec_offset: - if (cu->IsDWARF64()) - debug_info_data.GetU64(&offset); - else - debug_info_data.GetU32(&offset); + data.GetU32(&offset); break; case DW_FORM_implicit_const: @@ -204,233 +200,48 @@ bool DWARFDebugInfoEntry::FastExtract( return false; } -//---------------------------------------------------------------------- -// Extract -// -// Extract a debug info entry for a given compile unit from the .debug_info and -// .debug_abbrev data within the SymbolFileDWARF class starting at the given -// offset -//---------------------------------------------------------------------- -bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, - lldb::offset_t *offset_ptr) { - const DWARFDataExtractor &debug_info_data = cu->GetData(); - // const DWARFDataExtractor& debug_str_data = - // dwarf2Data->get_debug_str_data(); - const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset(); - lldb::offset_t offset = *offset_ptr; - // if (offset >= cu_end_offset) - // Log::Status("DIE at offset 0x%8.8x is beyond the end of the current - // compile unit (0x%8.8x)", m_offset, cu_end_offset); - if ((offset < cu_end_offset) && debug_info_data.ValidOffset(offset)) { - m_offset = offset; - - const uint64_t abbr_idx = debug_info_data.GetULEB128(&offset); - lldbassert(abbr_idx <= UINT16_MAX); - m_abbr_idx = abbr_idx; - if (abbr_idx) { - const DWARFAbbreviationDeclaration *abbrevDecl = - cu->GetAbbreviations()->GetAbbreviationDeclaration(abbr_idx); - - if (abbrevDecl) { - m_tag = abbrevDecl->Tag(); - m_has_children = abbrevDecl->HasChildren(); - - bool isCompileUnitTag = (m_tag == DW_TAG_compile_unit || - m_tag == DW_TAG_partial_unit); - if (cu && isCompileUnitTag) - const_cast<DWARFUnit *>(cu)->SetBaseAddress(0); - - // Skip all data in the .debug_info for the attributes - const uint32_t numAttributes = abbrevDecl->NumAttributes(); - for (uint32_t i = 0; i < numAttributes; ++i) { - DWARFFormValue form_value(cu); - dw_attr_t attr; - abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value); - dw_form_t form = form_value.Form(); - - if (isCompileUnitTag && - ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) { - if (form_value.ExtractValue(debug_info_data, &offset)) { - if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc) - const_cast<DWARFUnit *>(cu)->SetBaseAddress( - form_value.Address()); - } - } else { - bool form_is_indirect = false; - do { - form_is_indirect = false; - uint32_t form_size = 0; - switch (form) { - // Blocks if inlined data that have a length field and the data - // bytes inlined in the .debug_info - case DW_FORM_exprloc: - case DW_FORM_block: - form_size = debug_info_data.GetULEB128(&offset); - break; - case DW_FORM_block1: - form_size = debug_info_data.GetU8(&offset); - break; - case DW_FORM_block2: - form_size = debug_info_data.GetU16(&offset); - break; - case DW_FORM_block4: - form_size = debug_info_data.GetU32(&offset); - break; - - // Inlined NULL terminated C-strings - case DW_FORM_string: - debug_info_data.GetCStr(&offset); - break; - - // Compile unit address sized values - case DW_FORM_addr: - form_size = cu->GetAddressByteSize(); - break; - case DW_FORM_ref_addr: - if (cu->GetVersion() <= 2) - form_size = cu->GetAddressByteSize(); - else - form_size = cu->IsDWARF64() ? 8 : 4; - break; - - // 0 sized form - case DW_FORM_flag_present: - case DW_FORM_implicit_const: - form_size = 0; - break; - - // 1 byte values - case DW_FORM_data1: - case DW_FORM_flag: - case DW_FORM_ref1: - form_size = 1; - break; - - // 2 byte values - case DW_FORM_data2: - case DW_FORM_ref2: - form_size = 2; - break; - - // 4 byte values - case DW_FORM_data4: - case DW_FORM_ref4: - form_size = 4; - break; - - // 8 byte values - case DW_FORM_data8: - case DW_FORM_ref8: - case DW_FORM_ref_sig8: - form_size = 8; - break; - - // signed or unsigned LEB 128 values - 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: - debug_info_data.Skip_LEB128(&offset); - break; - - case DW_FORM_indirect: - form = debug_info_data.GetULEB128(&offset); - form_is_indirect = true; - break; - - case DW_FORM_strp: - case DW_FORM_sec_offset: - if (cu->IsDWARF64()) - debug_info_data.GetU64(&offset); - else - debug_info_data.GetU32(&offset); - break; - - default: - *offset_ptr = offset; - return false; - } - - offset += form_size; - } while (form_is_indirect); - } - } - *offset_ptr = offset; - return true; - } - } else { - m_tag = 0; - m_has_children = false; - *offset_ptr = offset; - return true; // NULL debug tag entry - } - } - - return false; -} - -//---------------------------------------------------------------------- -// DumpAncestry -// -// Dumps all of a debug information entries parents up until oldest and all of -// it's attributes to the specified stream. -//---------------------------------------------------------------------- -void DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, - const DWARFDebugInfoEntry *oldest, - Stream &s, - uint32_t recurse_depth) const { - const DWARFDebugInfoEntry *parent = GetParent(); - if (parent && parent != oldest) - parent->DumpAncestry(dwarf2Data, cu, oldest, s, 0); - Dump(dwarf2Data, cu, s, recurse_depth); +static DWARFRangeList GetRangesOrReportError(const DWARFUnit &unit, + const DWARFDebugInfoEntry &die, + const DWARFFormValue &value) { + llvm::Expected<DWARFRangeList> expected_ranges = + (value.Form() == DW_FORM_rnglistx) + ? unit.FindRnglistFromIndex(value.Unsigned()) + : unit.FindRnglistFromOffset(value.Unsigned()); + if (expected_ranges) + return std::move(*expected_ranges); + unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute, but " + "range extraction failed (%s), please file a bug " + "and attach the file at the start of this error message", + die.GetOffset(), value.Unsigned(), + toString(expected_ranges.takeError()).c_str()); + return DWARFRangeList(); } -static dw_offset_t GetRangesOffset(const DWARFDebugRangesBase *debug_ranges, - DWARFFormValue &form_value) { - if (form_value.Form() == DW_FORM_rnglistx) - return debug_ranges->GetOffset(form_value.Unsigned()); - return form_value.Unsigned(); -} - -//---------------------------------------------------------------------- // GetDIENamesAndRanges // // Gets the valid address ranges for a given DIE by looking for a // DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes. -//---------------------------------------------------------------------- bool DWARFDebugInfoEntry::GetDIENamesAndRanges( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, const char *&name, - const char *&mangled, DWARFRangeList &ranges, int &decl_file, - int &decl_line, int &decl_column, int &call_file, int &call_line, - int &call_column, DWARFExpression *frame_base) const { - if (dwarf2Data == nullptr) - return false; - - SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile(); - if (dwo_symbol_file) - return GetDIENamesAndRanges( - dwo_symbol_file, dwo_symbol_file->GetCompileUnit(), name, mangled, - ranges, decl_file, decl_line, decl_column, call_file, call_line, - call_column, frame_base); - + const DWARFUnit *cu, const char *&name, const char *&mangled, + DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column, + int &call_file, int &call_line, int &call_column, + DWARFExpression *frame_base) const { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; - std::vector<DIERef> die_refs; + std::vector<DWARFDIE> dies; bool set_frame_base_loclist_addr = false; - lldb::offset_t offset; - const DWARFAbbreviationDeclaration *abbrevDecl = - GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); + const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); - lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule(); + SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); + lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule(); if (abbrevDecl) { - const DWARFDataExtractor &debug_info_data = cu->GetData(); + const DWARFDataExtractor &data = cu->GetData(); + lldb::offset_t offset = GetFirstAttributeOffset(); - if (!debug_info_data.ValidOffset(offset)) + if (!data.ValidOffset(offset)) return false; const uint32_t numAttributes = abbrevDecl->NumAttributes(); @@ -441,7 +252,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( dw_attr_t attr; abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value); - if (form_value.ExtractValue(debug_info_data, &offset)) { + if (form_value.ExtractValue(data, &offset)) { switch (attr) { case DW_AT_low_pc: lo_pc = form_value.Address(); @@ -457,6 +268,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( case DW_AT_high_pc: if (form_value.Form() == DW_FORM_addr || + form_value.Form() == DW_FORM_addrx || form_value.Form() == DW_FORM_GNU_addr_index) { hi_pc = form_value.Address(); } else { @@ -469,35 +281,27 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( } break; - case DW_AT_ranges: { - const DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges(); - if (debug_ranges) - debug_ranges->FindRanges(cu, GetRangesOffset(debug_ranges, form_value), ranges); - else - cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 - ") attribute yet DWARF has no .debug_ranges, please file a bug " - "and attach the file at the start of this error message", - m_offset, form_value.Unsigned()); - } break; + case DW_AT_ranges: + ranges = GetRangesOrReportError(*cu, *this, form_value); + break; case DW_AT_name: - if (name == NULL) + if (name == nullptr) name = form_value.AsCString(); break; case DW_AT_MIPS_linkage_name: case DW_AT_linkage_name: - if (mangled == NULL) + if (mangled == nullptr) mangled = form_value.AsCString(); break; case DW_AT_abstract_origin: - die_refs.emplace_back(form_value); + dies.push_back(form_value.Reference()); break; case DW_AT_specification: - die_refs.emplace_back(form_value); + dies.push_back(form_value.Reference()); break; case DW_AT_decl_file: @@ -534,20 +338,20 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( if (frame_base) { if (form_value.BlockData()) { uint32_t block_offset = - form_value.BlockData() - debug_info_data.GetDataStart(); + form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - frame_base->SetOpcodeData(module, debug_info_data, block_offset, - block_length); + *frame_base = DWARFExpression(module, data, cu, + block_offset, block_length); } else { - const DWARFDataExtractor &debug_loc_data = - dwarf2Data->DebugLocData(); + const DWARFDataExtractor &debug_loc_data = dwarf.DebugLocData(); const dw_offset_t debug_loc_offset = form_value.Unsigned(); size_t loc_list_length = DWARFExpression::LocationListSize( cu, debug_loc_data, debug_loc_offset); if (loc_list_length > 0) { - frame_base->SetOpcodeData(module, debug_loc_data, - debug_loc_offset, loc_list_length); + *frame_base = + DWARFExpression(module, debug_loc_data, cu, + debug_loc_offset, loc_list_length); if (lo_pc != LLDB_INVALID_ADDRESS) { assert(lo_pc >= cu->GetBaseAddress()); frame_base->SetLocationListSlide(lo_pc - @@ -582,56 +386,48 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( frame_base->SetLocationListSlide(lowest_range_pc - cu->GetBaseAddress()); } - if (ranges.IsEmpty() || name == NULL || mangled == NULL) { - for (const DIERef &die_ref : die_refs) { - if (die_ref.die_offset != DW_INVALID_OFFSET) { - DWARFDIE die = dwarf2Data->GetDIE(die_ref); - if (die) - die.GetDIE()->GetDIENamesAndRanges( - die.GetDWARF(), die.GetCU(), name, mangled, ranges, decl_file, - decl_line, decl_column, call_file, call_line, call_column); + if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) { + for (const DWARFDIE &die : dies) { + if (die) { + die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges, + decl_file, decl_line, decl_column, + call_file, call_line, call_column); } } } return !ranges.IsEmpty(); } -//---------------------------------------------------------------------- // Dump // // Dumps a debug information entry and all of it's attributes to the specified // stream. -//---------------------------------------------------------------------- -void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, Stream &s, +void DWARFDebugInfoEntry::Dump(const DWARFUnit *cu, Stream &s, uint32_t recurse_depth) const { - const DWARFDataExtractor &debug_info_data = cu->GetData(); + const DWARFDataExtractor &data = cu->GetData(); lldb::offset_t offset = m_offset; - if (debug_info_data.ValidOffset(offset)) { - dw_uleb128_t abbrCode = debug_info_data.GetULEB128(&offset); + if (data.ValidOffset(offset)) { + dw_uleb128_t abbrCode = data.GetULEB128(&offset); s.Printf("\n0x%8.8x: ", m_offset); s.Indent(); if (abbrCode != m_abbr_idx) { s.Printf("error: DWARF has been modified\n"); } else if (abbrCode) { - const DWARFAbbreviationDeclaration *abbrevDecl = - cu->GetAbbreviations()->GetAbbreviationDeclaration(abbrCode); - + const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); if (abbrevDecl) { s.PutCString(DW_TAG_value_to_name(abbrevDecl->Tag())); s.Printf(" [%u] %c\n", abbrCode, abbrevDecl->HasChildren() ? '*' : ' '); - // Dump all data in the .debug_info for the attributes + // Dump all data in the .debug_info/.debug_types for the attributes const uint32_t numAttributes = abbrevDecl->NumAttributes(); for (uint32_t i = 0; i < numAttributes; ++i) { DWARFFormValue form_value(cu); dw_attr_t attr; abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value); - DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr, - form_value); + DumpAttribute(cu, data, &offset, s, attr, form_value); } const DWARFDebugInfoEntry *child = GetFirstChild(); @@ -639,7 +435,7 @@ void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data, s.IndentMore(); while (child) { - child->Dump(dwarf2Data, cu, s, recurse_depth - 1); + child->Dump(cu, s, recurse_depth - 1); child = child->GetSibling(); } s.IndentLess(); @@ -654,34 +450,15 @@ void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data, } } -void DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu, Stream &s) const { - const DWARFBaseDIE cu_die = cu->GetUnitDIEOnly(); - const char *cu_name = NULL; - if (cu_die) - cu_name = cu_die.GetName(); - const char *obj_file_name = NULL; - ObjectFile *obj_file = dwarf2Data->GetObjectFile(); - if (obj_file) - obj_file_name = - obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"); - const char *die_name = GetName(dwarf2Data, cu); - s.Printf("0x%8.8x/0x%8.8x: %-30s (from %s in %s)", cu->GetOffset(), - GetOffset(), die_name ? die_name : "", cu_name ? cu_name : "<NULL>", - obj_file_name ? obj_file_name : "<NULL>"); -} - -//---------------------------------------------------------------------- // DumpAttribute // // Dumps a debug information entry attribute along with it's form. Any special // display of attributes is done (disassemble location lists, show enumeration // values for attributes, etc). -//---------------------------------------------------------------------- void DWARFDebugInfoEntry::DumpAttribute( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr, - Stream &s, dw_attr_t attr, DWARFFormValue &form_value) { + const DWARFUnit *cu, const DWARFDataExtractor &data, + lldb::offset_t *offset_ptr, Stream &s, dw_attr_t attr, + DWARFFormValue &form_value) { bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm); s.Printf(" "); @@ -691,7 +468,7 @@ void DWARFDebugInfoEntry::DumpAttribute( s.Printf("[%s", DW_FORM_value_to_name(form_value.Form())); } - if (!form_value.ExtractValue(debug_info_data, offset_ptr)) + if (!form_value.ExtractValue(data, offset_ptr)) return; if (show_form) { @@ -704,6 +481,8 @@ void DWARFDebugInfoEntry::DumpAttribute( s.PutCString("( "); + SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF(); + // Check to see if we have any special attribute formatters switch (attr) { case DW_AT_stmt_list: @@ -724,7 +503,7 @@ void DWARFDebugInfoEntry::DumpAttribute( const uint8_t *blockData = form_value.BlockData(); if (blockData) { // Location description is inlined in data in the form value - DWARFDataExtractor locationData(debug_info_data, + DWARFDataExtractor locationData(data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned()); DWARFExpression::PrintDWARFExpression( @@ -733,38 +512,26 @@ void DWARFDebugInfoEntry::DumpAttribute( // We have a location list offset as the value that is the offset into // the .debug_loc section that describes the value over it's lifetime uint64_t debug_loc_offset = form_value.Unsigned(); - if (dwarf2Data) { - DWARFExpression::PrintDWARFLocationList( - s, cu, dwarf2Data->DebugLocData(), debug_loc_offset); - } + DWARFExpression::PrintDWARFLocationList(s, cu, dwarf.DebugLocData(), + debug_loc_offset); } } break; case DW_AT_abstract_origin: case DW_AT_specification: { - uint64_t abstract_die_offset = form_value.Reference(); + DWARFDIE abstract_die = form_value.Reference(); form_value.Dump(s); - // *ostrm_ptr << HEX32 << abstract_die_offset << " ( "; - GetName(dwarf2Data, cu, abstract_die_offset, s); + // *ostrm_ptr << HEX32 << abstract_die.GetOffset() << " ( "; + abstract_die.GetName(s); } break; case DW_AT_type: { - uint64_t type_die_offset = form_value.Reference(); + DWARFDIE type_die = form_value.Reference(); s.PutCString(" ( "); - AppendTypeName(dwarf2Data, cu, type_die_offset, s); + type_die.AppendTypeName(s); s.PutCString(" )"); } break; - case DW_AT_ranges: { - if (!dwarf2Data) - break; - lldb::offset_t ranges_offset = - GetRangesOffset(dwarf2Data->DebugRanges(), form_value); - dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; - DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(), - &ranges_offset, base_addr); - } break; - default: break; } @@ -772,36 +539,17 @@ void DWARFDebugInfoEntry::DumpAttribute( s.PutCString(" )\n"); } -//---------------------------------------------------------------------- // Get all attribute values for a given DIE, including following any // specification or abstract origin attributes and including those in the // results. Any duplicate attributes will have the first instance take // precedence (this can happen for declaration attributes). -//---------------------------------------------------------------------- size_t DWARFDebugInfoEntry::GetAttributes( - const DWARFUnit *cu, DWARFFormValue::FixedFormSizes fixed_form_sizes, - DWARFAttributes &attributes, uint32_t curr_depth) const { - SymbolFileDWARF *dwarf2Data = nullptr; - const DWARFAbbreviationDeclaration *abbrevDecl = nullptr; - lldb::offset_t offset = 0; - if (cu) { - if (m_tag != DW_TAG_compile_unit && m_tag != DW_TAG_partial_unit) { - SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile(); - if (dwo_symbol_file) - return GetAttributes(dwo_symbol_file->GetCompileUnit(), - fixed_form_sizes, attributes, curr_depth); - } - - dwarf2Data = cu->GetSymbolFileDWARF(); - abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); - } - + const DWARFUnit *cu, DWARFAttributes &attributes, + uint32_t curr_depth) const { + const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); if (abbrevDecl) { - const DWARFDataExtractor &debug_info_data = cu->GetData(); - - if (fixed_form_sizes.Empty()) - fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize( - cu->GetAddressByteSize(), cu->IsDWARF64()); + const DWARFDataExtractor &data = cu->GetData(); + lldb::offset_t offset = GetFirstAttributeOffset(); const uint32_t num_attributes = abbrevDecl->NumAttributes(); for (uint32_t i = 0; i < num_attributes; ++i) { @@ -829,19 +577,17 @@ size_t DWARFDebugInfoEntry::GetAttributes( } if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) { - if (form_value.ExtractValue(debug_info_data, &offset)) { - dw_offset_t die_offset = form_value.Reference(); - DWARFDIE spec_die = - const_cast<DWARFUnit *>(cu)->GetDIE(die_offset); + if (form_value.ExtractValue(data, &offset)) { + DWARFDIE spec_die = form_value.Reference(); if (spec_die) spec_die.GetAttributes(attributes, curr_depth + 1); } } else { - const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form); + llvm::Optional<uint8_t> fixed_skip_size = DWARFFormValue::GetFixedSize(form, cu); if (fixed_skip_size) - offset += fixed_skip_size; + offset += *fixed_skip_size; else - DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu); + DWARFFormValue::SkipValue(form, data, &offset, cu); } } } else { @@ -850,45 +596,32 @@ size_t DWARFDebugInfoEntry::GetAttributes( return attributes.Size(); } -//---------------------------------------------------------------------- // GetAttributeValue // -// Get the value of an attribute and return the .debug_info offset of the -// attribute if it was properly extracted into form_value, or zero if we fail -// since an offset of zero is invalid for an attribute (it would be a compile -// unit header). -//---------------------------------------------------------------------- +// Get the value of an attribute and return the .debug_info or .debug_types +// offset of the attribute if it was properly extracted into form_value, +// or zero if we fail since an offset of zero is invalid for an attribute (it +// would be a compile unit header). dw_offset_t DWARFDebugInfoEntry::GetAttributeValue( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, DWARFFormValue &form_value, + const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value, dw_offset_t *end_attr_offset_ptr, bool check_specification_or_abstract_origin) const { - SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile(); - if (dwo_symbol_file && m_tag != DW_TAG_compile_unit && - m_tag != DW_TAG_partial_unit) - return GetAttributeValue(dwo_symbol_file, dwo_symbol_file->GetCompileUnit(), - attr, form_value, end_attr_offset_ptr, - check_specification_or_abstract_origin); - - lldb::offset_t offset; - const DWARFAbbreviationDeclaration *abbrevDecl = - GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); - - if (abbrevDecl) { + if (const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) { uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr); if (attr_idx != DW_INVALID_INDEX) { - const DWARFDataExtractor &debug_info_data = cu->GetData(); + const DWARFDataExtractor &data = cu->GetData(); + lldb::offset_t offset = GetFirstAttributeOffset(); uint32_t idx = 0; while (idx < attr_idx) DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), - debug_info_data, &offset, cu); + data, &offset, cu); const dw_offset_t attr_offset = offset; - form_value.SetCompileUnit(cu); + form_value.SetUnit(cu); form_value.SetForm(abbrevDecl->GetFormByIndex(idx)); - if (form_value.ExtractValue(debug_info_data, &offset)) { + if (form_value.ExtractValue(data, &offset)) { if (end_attr_offset_ptr) *end_attr_offset_ptr = offset; return attr_offset; @@ -897,35 +630,35 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue( } if (check_specification_or_abstract_origin) { - if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) { - DWARFDIE die = - const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference()); + if (GetAttributeValue(cu, DW_AT_specification, form_value)) { + DWARFDIE die = form_value.Reference(); if (die) { dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( - die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr, - false); + die.GetCU(), attr, form_value, end_attr_offset_ptr, false); if (die_offset) return die_offset; } } - if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) { - DWARFDIE die = - const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference()); + if (GetAttributeValue(cu, DW_AT_abstract_origin, form_value)) { + DWARFDIE die = form_value.Reference(); if (die) { dw_offset_t die_offset = die.GetDIE()->GetAttributeValue( - die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr, - false); + die.GetCU(), attr, form_value, end_attr_offset_ptr, false); if (die_offset) return die_offset; } } } + // If we're a unit DIE, also check the attributes of the dwo unit (if any). + if (GetParent()) + return 0; + SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile(); if (!dwo_symbol_file) return 0; - DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); + DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); if (!dwo_cu) return 0; @@ -934,105 +667,78 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue( return 0; return dwo_cu_die.GetDIE()->GetAttributeValue( - dwo_symbol_file, dwo_cu, attr, form_value, end_attr_offset_ptr, + dwo_cu, attr, form_value, end_attr_offset_ptr, check_specification_or_abstract_origin); } -//---------------------------------------------------------------------- // GetAttributeValueAsString // // Get the value of an attribute as a string return it. The resulting pointer // to the string data exists within the supplied SymbolFileDWARF and will only // be available as long as the SymbolFileDWARF is still around and it's content // doesn't change. -//---------------------------------------------------------------------- const char *DWARFDebugInfoEntry::GetAttributeValueAsString( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, const char *fail_value, + const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, bool check_specification_or_abstract_origin) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, + if (GetAttributeValue(cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) return form_value.AsCString(); return fail_value; } -//---------------------------------------------------------------------- // GetAttributeValueAsUnsigned // // Get the value of an attribute as unsigned and return it. -//---------------------------------------------------------------------- uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, uint64_t fail_value, + const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, + if (GetAttributeValue(cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) return form_value.Unsigned(); return fail_value; } -//---------------------------------------------------------------------- -// GetAttributeValueAsSigned -// -// Get the value of an attribute a signed value and return it. -//---------------------------------------------------------------------- -int64_t DWARFDebugInfoEntry::GetAttributeValueAsSigned( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, int64_t fail_value, - bool check_specification_or_abstract_origin) const { - DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, - check_specification_or_abstract_origin)) - return form_value.Signed(); - return fail_value; -} - -//---------------------------------------------------------------------- // GetAttributeValueAsReference // // Get the value of an attribute as reference and fix up and compile unit // relative offsets as needed. -//---------------------------------------------------------------------- -uint64_t DWARFDebugInfoEntry::GetAttributeValueAsReference( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, uint64_t fail_value, +DWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference( + const DWARFUnit *cu, const dw_attr_t attr, bool check_specification_or_abstract_origin) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, + if (GetAttributeValue(cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) return form_value.Reference(); - return fail_value; + return {}; } uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, uint64_t fail_value, + const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, + if (GetAttributeValue(cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) return form_value.Address(); return fail_value; } -//---------------------------------------------------------------------- // GetAttributeHighPC // // Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low- // pc>. // // Returns the hi_pc or fail_value. -//---------------------------------------------------------------------- dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t lo_pc, - uint64_t fail_value, bool check_specification_or_abstract_origin) const { + const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, + bool check_specification_or_abstract_origin) const { DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr, + if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr, check_specification_or_abstract_origin)) { dw_form_t form = form_value.Form(); - if (form == DW_FORM_addr || form == DW_FORM_GNU_addr_index) + if (form == DW_FORM_addr || form == DW_FORM_addrx || + form == DW_FORM_GNU_addr_index) return form_value.Address(); // DWARF4 can specify the hi_pc as an <offset-from-lowpc> @@ -1041,22 +747,19 @@ dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC( return fail_value; } -//---------------------------------------------------------------------- // GetAttributeAddressRange // // Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset- // from-low-pc>. // // Returns true or sets lo_pc and hi_pc to fail_value. -//---------------------------------------------------------------------- bool DWARFDebugInfoEntry::GetAttributeAddressRange( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t &lo_pc, - dw_addr_t &hi_pc, uint64_t fail_value, - bool check_specification_or_abstract_origin) const { - lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value, + const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, + uint64_t fail_value, bool check_specification_or_abstract_origin) const { + lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value, check_specification_or_abstract_origin); if (lo_pc != fail_value) { - hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value, + hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value, check_specification_or_abstract_origin); if (hi_pc != fail_value) return true; @@ -1067,21 +770,17 @@ bool DWARFDebugInfoEntry::GetAttributeAddressRange( } size_t DWARFDebugInfoEntry::GetAttributeAddressRanges( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - DWARFRangeList &ranges, bool check_hi_lo_pc, + const DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc, bool check_specification_or_abstract_origin) const { ranges.Clear(); DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, DW_AT_ranges, form_value)) { - if (DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges()) - debug_ranges->FindRanges(cu, GetRangesOffset(debug_ranges, form_value), - ranges); + if (GetAttributeValue(cu, DW_AT_ranges, form_value)) { + ranges = GetRangesOrReportError(*cu, *this, form_value); } else if (check_hi_lo_pc) { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, - LLDB_INVALID_ADDRESS, + if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, check_specification_or_abstract_origin)) { if (lo_pc < hi_pc) ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc)); @@ -1090,250 +789,67 @@ size_t DWARFDebugInfoEntry::GetAttributeAddressRanges( return ranges.GetSize(); } -//---------------------------------------------------------------------- // GetName // // Get value of the DW_AT_name attribute and return it if one exists, else // return NULL. -//---------------------------------------------------------------------- -const char *DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu) const { - return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); +const char *DWARFDebugInfoEntry::GetName(const DWARFUnit *cu) const { + return GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); } -//---------------------------------------------------------------------- // GetMangledName // // Get value of the DW_AT_MIPS_linkage_name attribute and return it if one // exists, else return the value of the DW_AT_name attribute -//---------------------------------------------------------------------- const char * -DWARFDebugInfoEntry::GetMangledName(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, +DWARFDebugInfoEntry::GetMangledName(const DWARFUnit *cu, bool substitute_name_allowed) const { const char *name = nullptr; - name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, - nullptr, true); + name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true); if (name) return name; - name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, - true); + name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true); if (name) return name; if (!substitute_name_allowed) return nullptr; - name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); + name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); return name; } -//---------------------------------------------------------------------- // GetPubname // // Get value the name for a DIE as it should appear for a .debug_pubnames or // .debug_pubtypes section. -//---------------------------------------------------------------------- -const char *DWARFDebugInfoEntry::GetPubname(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu) const { +const char *DWARFDebugInfoEntry::GetPubname(const DWARFUnit *cu) const { const char *name = nullptr; - if (!dwarf2Data) + if (!cu) return name; - name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, - nullptr, true); + name = GetAttributeValueAsString(cu, DW_AT_MIPS_linkage_name, nullptr, true); if (name) return name; - name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, - true); + name = GetAttributeValueAsString(cu, DW_AT_linkage_name, nullptr, true); if (name) return name; - name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); + name = GetAttributeValueAsString(cu, DW_AT_name, nullptr, true); return name; } -//---------------------------------------------------------------------- -// GetName -// -// Get value of the DW_AT_name attribute for a debug information entry that -// exists at offset "die_offset" and place that value into the supplied stream -// object. If the DIE is a NULL object "NULL" is placed into the stream, and if -// no DW_AT_name attribute exists for the DIE then nothing is printed. -//---------------------------------------------------------------------- -bool DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, - const dw_offset_t die_offset, Stream &s) { - if (dwarf2Data == NULL) { - s.PutCString("NULL"); - return false; - } - - DWARFDebugInfoEntry die; - lldb::offset_t offset = die_offset; - if (die.Extract(dwarf2Data, cu, &offset)) { - if (die.IsNULL()) { - s.PutCString("NULL"); - return true; - } else { - const char *name = die.GetAttributeValueAsString( - dwarf2Data, cu, DW_AT_name, nullptr, true); - if (name) { - s.PutCString(name); - return true; - } - } - } - return false; -} - -//---------------------------------------------------------------------- -// AppendTypeName -// -// Follows the type name definition down through all needed tags to end up with -// a fully qualified type name and dump the results to the supplied stream. -// This is used to show the name of types given a type identifier. -//---------------------------------------------------------------------- -bool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, - const dw_offset_t die_offset, - Stream &s) { - if (dwarf2Data == NULL) { - s.PutCString("NULL"); - return false; - } - - DWARFDebugInfoEntry die; - lldb::offset_t offset = die_offset; - if (die.Extract(dwarf2Data, cu, &offset)) { - if (die.IsNULL()) { - s.PutCString("NULL"); - return true; - } else { - const char *name = die.GetPubname(dwarf2Data, cu); - if (name) - s.PutCString(name); - else { - bool result = true; - const DWARFAbbreviationDeclaration *abbrevDecl = - die.GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); - - if (abbrevDecl == NULL) - return false; - - switch (abbrevDecl->Tag()) { - case DW_TAG_array_type: - break; // print out a "[]" after printing the full type of the element - // below - case DW_TAG_base_type: - s.PutCString("base "); - break; - case DW_TAG_class_type: - s.PutCString("class "); - break; - case DW_TAG_const_type: - s.PutCString("const "); - break; - case DW_TAG_enumeration_type: - s.PutCString("enum "); - break; - case DW_TAG_file_type: - s.PutCString("file "); - break; - case DW_TAG_interface_type: - s.PutCString("interface "); - break; - case DW_TAG_packed_type: - s.PutCString("packed "); - break; - case DW_TAG_pointer_type: - break; // print out a '*' after printing the full type below - case DW_TAG_ptr_to_member_type: - break; // print out a '*' after printing the full type below - case DW_TAG_reference_type: - break; // print out a '&' after printing the full type below - case DW_TAG_restrict_type: - s.PutCString("restrict "); - break; - case DW_TAG_set_type: - s.PutCString("set "); - break; - case DW_TAG_shared_type: - s.PutCString("shared "); - break; - case DW_TAG_string_type: - s.PutCString("string "); - break; - case DW_TAG_structure_type: - s.PutCString("struct "); - break; - case DW_TAG_subrange_type: - s.PutCString("subrange "); - break; - case DW_TAG_subroutine_type: - s.PutCString("function "); - break; - case DW_TAG_thrown_type: - s.PutCString("thrown "); - break; - case DW_TAG_union_type: - s.PutCString("union "); - break; - case DW_TAG_unspecified_type: - s.PutCString("unspecified "); - break; - case DW_TAG_volatile_type: - s.PutCString("volatile "); - break; - default: - return false; - } - - // Follow the DW_AT_type if possible - DWARFFormValue form_value; - if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value)) { - uint64_t next_die_offset = form_value.Reference(); - result = AppendTypeName(dwarf2Data, cu, next_die_offset, s); - } - - switch (abbrevDecl->Tag()) { - case DW_TAG_array_type: - s.PutCString("[]"); - break; - case DW_TAG_pointer_type: - s.PutChar('*'); - break; - case DW_TAG_ptr_to_member_type: - s.PutChar('*'); - break; - case DW_TAG_reference_type: - s.PutChar('&'); - break; - default: - break; - } - return result; - } - } - } - return false; -} - -//---------------------------------------------------------------------- // BuildAddressRangeTable -//---------------------------------------------------------------------- void DWARFDebugInfoEntry::BuildAddressRangeTable( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - DWARFDebugAranges *debug_aranges) const { + const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const { if (m_tag) { if (m_tag == DW_TAG_subprogram) { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, - LLDB_INVALID_ADDRESS)) { + if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) { /// printf("BuildAddressRangeTable() 0x%8.8x: %30s: [0x%8.8x - /// 0x%8.8x)\n", m_offset, DW_TAG_value_to_name(tag), lo_pc, hi_pc); debug_aranges->AppendRange(cu->GetOffset(), lo_pc, hi_pc); @@ -1342,29 +858,25 @@ void DWARFDebugInfoEntry::BuildAddressRangeTable( const DWARFDebugInfoEntry *child = GetFirstChild(); while (child) { - child->BuildAddressRangeTable(dwarf2Data, cu, debug_aranges); + child->BuildAddressRangeTable(cu, debug_aranges); child = child->GetSibling(); } } } -//---------------------------------------------------------------------- // BuildFunctionAddressRangeTable // // This function is very similar to the BuildAddressRangeTable function except // that the actual DIE offset for the function is placed in the table instead // of the compile unit offset (which is the way the standard .debug_aranges // section does it). -//---------------------------------------------------------------------- void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - DWARFDebugAranges *debug_aranges) const { + const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const { if (m_tag) { if (m_tag == DW_TAG_subprogram) { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, - LLDB_INVALID_ADDRESS)) { + if (GetAttributeAddressRange(cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) { // printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16" PRIx64 " - // 0x%16.16" PRIx64 ")\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY debug_aranges->AppendRange(GetOffset(), lo_pc, hi_pc); @@ -1373,57 +885,37 @@ void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable( const DWARFDebugInfoEntry *child = GetFirstChild(); while (child) { - child->BuildFunctionAddressRangeTable(dwarf2Data, cu, debug_aranges); + child->BuildFunctionAddressRangeTable(cu, debug_aranges); child = child->GetSibling(); } } } -void DWARFDebugInfoEntry::GetDeclContextDIEs( - DWARFUnit *cu, DWARFDIECollection &decl_context_dies) const { - - DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this)); - die.GetDeclContextDIEs(decl_context_dies); -} - void DWARFDebugInfoEntry::GetDWARFDeclContext( - SymbolFileDWARF *dwarf2Data, DWARFUnit *cu, - DWARFDeclContext &dwarf_decl_ctx) const { + DWARFUnit *cu, DWARFDeclContext &dwarf_decl_ctx) const { const dw_tag_t tag = Tag(); if (tag != DW_TAG_compile_unit && tag != DW_TAG_partial_unit) { - dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu)); - DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(dwarf2Data, cu); + dwarf_decl_ctx.AppendDeclContext(tag, GetName(cu)); + DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu); if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this) { if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit && parent_decl_ctx_die.Tag() != DW_TAG_partial_unit) parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext( - parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(), - dwarf_decl_ctx); + parent_decl_ctx_die.GetCU(), dwarf_decl_ctx); } } } -bool DWARFDebugInfoEntry::MatchesDWARFDeclContext( - SymbolFileDWARF *dwarf2Data, DWARFUnit *cu, - const DWARFDeclContext &dwarf_decl_ctx) const { - - DWARFDeclContext this_dwarf_decl_ctx; - GetDWARFDeclContext(dwarf2Data, cu, this_dwarf_decl_ctx); - return this_dwarf_decl_ctx == dwarf_decl_ctx; -} - DWARFDIE -DWARFDebugInfoEntry::GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu) const { +DWARFDebugInfoEntry::GetParentDeclContextDIE(DWARFUnit *cu) const { DWARFAttributes attributes; - GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes); - return GetParentDeclContextDIE(dwarf2Data, cu, attributes); + GetAttributes(cu, attributes); + return GetParentDeclContextDIE(cu, attributes); } DWARFDIE DWARFDebugInfoEntry::GetParentDeclContextDIE( - SymbolFileDWARF *dwarf2Data, DWARFUnit *cu, - const DWARFAttributes &attributes) const { + DWARFUnit *cu, const DWARFAttributes &attributes) const { DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this)); while (die) { @@ -1445,28 +937,18 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE( } } - dw_offset_t die_offset; - - die_offset = - attributes.FormValueAsUnsigned(DW_AT_specification, DW_INVALID_OFFSET); - if (die_offset != DW_INVALID_OFFSET) { - DWARFDIE spec_die = cu->GetDIE(die_offset); - if (spec_die) { - DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE(); - if (decl_ctx_die) - return decl_ctx_die; - } + DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification); + if (spec_die) { + DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE(); + if (decl_ctx_die) + return decl_ctx_die; } - die_offset = attributes.FormValueAsUnsigned(DW_AT_abstract_origin, - DW_INVALID_OFFSET); - if (die_offset != DW_INVALID_OFFSET) { - DWARFDIE abs_die = cu->GetDIE(die_offset); - if (abs_die) { - DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE(); - if (decl_ctx_die) - return decl_ctx_die; - } + DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin); + if (abs_die) { + DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE(); + if (decl_ctx_die) + return decl_ctx_die; } die = die.GetParent(); @@ -1474,22 +956,22 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE( return DWARFDIE(); } -const char *DWARFDebugInfoEntry::GetQualifiedName(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu, +const char *DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, std::string &storage) const { DWARFAttributes attributes; - GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes); - return GetQualifiedName(dwarf2Data, cu, attributes, storage); + GetAttributes(cu, attributes); + return GetQualifiedName(cu, attributes, storage); } -const char *DWARFDebugInfoEntry::GetQualifiedName( - SymbolFileDWARF *dwarf2Data, DWARFUnit *cu, - const DWARFAttributes &attributes, std::string &storage) const { +const char * +DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, + const DWARFAttributes &attributes, + std::string &storage) const { - const char *name = GetName(dwarf2Data, cu); + const char *name = GetName(cu); if (name) { - DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(dwarf2Data, cu); + DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu); storage.clear(); // TODO: change this to get the correct decl context parent.... while (parent_decl_ctx_die) { @@ -1530,15 +1012,11 @@ const char *DWARFDebugInfoEntry::GetQualifiedName( storage.append(name); } if (storage.empty()) - return NULL; + return nullptr; return storage.c_str(); } -//---------------------------------------------------------------------- -// LookupAddress -//---------------------------------------------------------------------- bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, DWARFDebugInfoEntry **function_die, DWARFDebugInfoEntry **block_die) { @@ -1555,13 +1033,9 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, check_children = true; break; case DW_TAG_entry_point: - break; case DW_TAG_enumeration_type: - break; case DW_TAG_formal_parameter: - break; case DW_TAG_imported_declaration: - break; case DW_TAG_label: break; case DW_TAG_lexical_block: @@ -1569,9 +1043,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, match_addr_range = true; break; case DW_TAG_member: - break; case DW_TAG_pointer_type: - break; case DW_TAG_reference_type: break; case DW_TAG_compile_unit: @@ -1583,20 +1055,15 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, check_children = true; break; case DW_TAG_subroutine_type: - break; case DW_TAG_typedef: - break; case DW_TAG_union_type: - break; case DW_TAG_unspecified_parameters: - break; case DW_TAG_variant: break; case DW_TAG_common_block: check_children = true; break; case DW_TAG_common_inclusion: - break; case DW_TAG_inheritance: break; case DW_TAG_inlined_subroutine: @@ -1607,86 +1074,62 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, match_addr_range = true; break; case DW_TAG_ptr_to_member_type: - break; case DW_TAG_set_type: - break; case DW_TAG_subrange_type: - break; case DW_TAG_with_stmt: - break; case DW_TAG_access_declaration: - break; case DW_TAG_base_type: break; case DW_TAG_catch_block: match_addr_range = true; break; case DW_TAG_const_type: - break; case DW_TAG_constant: - break; case DW_TAG_enumerator: - break; case DW_TAG_file_type: - break; case DW_TAG_friend: - break; case DW_TAG_namelist: - break; case DW_TAG_namelist_item: - break; case DW_TAG_packed_type: break; case DW_TAG_subprogram: match_addr_range = true; break; case DW_TAG_template_type_parameter: - break; case DW_TAG_template_value_parameter: - break; case DW_TAG_GNU_template_parameter_pack: - break; case DW_TAG_thrown_type: break; case DW_TAG_try_block: match_addr_range = true; break; case DW_TAG_variant_part: - break; case DW_TAG_variable: - break; case DW_TAG_volatile_type: - break; case DW_TAG_dwarf_procedure: - break; case DW_TAG_restrict_type: - break; case DW_TAG_interface_type: break; case DW_TAG_namespace: check_children = true; break; case DW_TAG_imported_module: - break; case DW_TAG_unspecified_type: break; case DW_TAG_partial_unit: match_addr_range = true; break; case DW_TAG_imported_unit: - break; case DW_TAG_shared_type: - break; default: break; } if (match_addr_range) { - dw_addr_t lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, - LLDB_INVALID_ADDRESS); + dw_addr_t lo_pc = + GetAttributeValueAsAddress(cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (lo_pc != LLDB_INVALID_ADDRESS) { - dw_addr_t hi_pc = - GetAttributeHighPC(dwarf2Data, cu, lo_pc, LLDB_INVALID_ADDRESS); + dw_addr_t hi_pc = GetAttributeHighPC(cu, lo_pc, LLDB_INVALID_ADDRESS); if (hi_pc != LLDB_INVALID_ADDRESS) { // printf("\n0x%8.8x: %30s: address = 0x%8.8x [0x%8.8x - 0x%8.8x) ", // m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc); @@ -1696,13 +1139,14 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, switch (m_tag) { case DW_TAG_compile_unit: // File case DW_TAG_partial_unit: // File - check_children = ((function_die != NULL) || (block_die != NULL)); + check_children = + ((function_die != nullptr) || (block_die != nullptr)); break; case DW_TAG_subprogram: // Function if (function_die) *function_die = this; - check_children = (block_die != NULL); + check_children = (block_die != nullptr); break; case DW_TAG_inlined_subroutine: // Inlined Function @@ -1722,48 +1166,43 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, // Compile units may not have a valid high/low pc when there // are address gaps in subroutines so we must always search // if there is no valid high and low PC. - check_children = (m_tag == DW_TAG_compile_unit || - m_tag == DW_TAG_partial_unit) && - ((function_die != NULL) || (block_die != NULL)); + check_children = + (m_tag == DW_TAG_compile_unit || m_tag == DW_TAG_partial_unit) && + ((function_die != nullptr) || (block_die != nullptr)); } } else { - DWARFFormValue form_value; - if (GetAttributeValue(dwarf2Data, cu, DW_AT_ranges, form_value)) { - DWARFRangeList ranges; - DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges(); - debug_ranges->FindRanges( - cu, GetRangesOffset(debug_ranges, form_value), ranges); - - if (ranges.FindEntryThatContains(address)) { - found_address = true; - // puts("***MATCH***"); - switch (m_tag) { - case DW_TAG_compile_unit: // File - case DW_TAG_partial_unit: // File - check_children = ((function_die != NULL) || (block_die != NULL)); + DWARFRangeList ranges; + if (GetAttributeAddressRanges(cu, ranges, /*check_hi_lo_pc*/ false) && + ranges.FindEntryThatContains(address)) { + found_address = true; + // puts("***MATCH***"); + switch (m_tag) { + case DW_TAG_compile_unit: // File + case DW_TAG_partial_unit: // File + check_children = + ((function_die != nullptr) || (block_die != nullptr)); break; - case DW_TAG_subprogram: // Function - if (function_die) - *function_die = this; - check_children = (block_die != NULL); - break; - - case DW_TAG_inlined_subroutine: // Inlined Function - case DW_TAG_lexical_block: // Block { } in code - if (block_die) { - *block_die = this; - check_children = true; - } - break; + case DW_TAG_subprogram: // Function + if (function_die) + *function_die = this; + check_children = (block_die != nullptr); + break; - default: + case DW_TAG_inlined_subroutine: // Inlined Function + case DW_TAG_lexical_block: // Block { } in code + if (block_die) { + *block_die = this; check_children = true; - break; } - } else { - check_children = false; + break; + + default: + check_children = true; + break; } + } else { + check_children = false; } } } @@ -1772,8 +1211,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, // printf("checking children\n"); DWARFDebugInfoEntry *child = GetFirstChild(); while (child) { - if (child->LookupAddress(address, dwarf2Data, cu, function_die, - block_die)) + if (child->LookupAddress(address, cu, function_die, block_die)) return true; child = child->GetSibling(); } @@ -1782,59 +1220,18 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, return found_address; } -const DWARFAbbreviationDeclaration * -DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - lldb::offset_t &offset) const { - if (dwarf2Data) { - offset = GetOffset(); - - const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations(); - if (abbrev_set) { - const DWARFAbbreviationDeclaration *abbrev_decl = - abbrev_set->GetAbbreviationDeclaration(m_abbr_idx); - if (abbrev_decl) { - // Make sure the abbreviation code still matches. If it doesn't and the - // DWARF data was mmap'ed, the backing file might have been modified - // which is bad news. - const uint64_t abbrev_code = cu->GetData().GetULEB128(&offset); - - if (abbrev_decl->Code() == abbrev_code) - return abbrev_decl; - - dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected( - "0x%8.8x: the DWARF debug information has been modified (abbrev " - "code was %u, and is now %u)", - GetOffset(), (uint32_t)abbrev_decl->Code(), (uint32_t)abbrev_code); - } - } - } - offset = DW_INVALID_OFFSET; - return NULL; -} - -bool DWARFDebugInfoEntry::OffsetLessThan(const DWARFDebugInfoEntry &a, - const DWARFDebugInfoEntry &b) { - return a.GetOffset() < b.GetOffset(); +lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const { + return GetOffset() + llvm::getULEB128Size(m_abbr_idx); } -void DWARFDebugInfoEntry::DumpDIECollection( - Stream &strm, DWARFDebugInfoEntry::collection &die_collection) { - DWARFDebugInfoEntry::const_iterator pos; - DWARFDebugInfoEntry::const_iterator end = die_collection.end(); - strm.PutCString("\noffset parent sibling child\n"); - strm.PutCString("-------- -------- -------- --------\n"); - for (pos = die_collection.begin(); pos != end; ++pos) { - const DWARFDebugInfoEntry &die_ref = *pos; - const DWARFDebugInfoEntry *p = die_ref.GetParent(); - const DWARFDebugInfoEntry *s = die_ref.GetSibling(); - const DWARFDebugInfoEntry *c = die_ref.GetFirstChild(); - strm.Printf("%.8x: %.8x %.8x %.8x 0x%4.4x %s%s\n", die_ref.GetOffset(), - p ? p->GetOffset() : 0, s ? s->GetOffset() : 0, - c ? c->GetOffset() : 0, die_ref.Tag(), - DW_TAG_value_to_name(die_ref.Tag()), - die_ref.HasChildren() ? " *" : ""); +const DWARFAbbreviationDeclaration * +DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const { + if (cu) { + const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations(); + if (abbrev_set) + return abbrev_set->GetAbbreviationDeclaration(m_abbr_idx); } + return nullptr; } bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const { diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index ec19fc814fba..1e7b5f27642d 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -1,9 +1,8 @@ //===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -20,26 +19,6 @@ #include <set> #include <vector> -typedef std::map<const DWARFDebugInfoEntry *, dw_addr_t> DIEToAddressMap; -typedef DIEToAddressMap::iterator DIEToAddressMapIter; -typedef DIEToAddressMap::const_iterator DIEToAddressMapConstIter; - -typedef std::map<dw_addr_t, const DWARFDebugInfoEntry *> AddressToDIEMap; -typedef AddressToDIEMap::iterator AddressToDIEMapIter; -typedef AddressToDIEMap::const_iterator AddressToDIEMapConstIter; - -typedef std::map<dw_offset_t, dw_offset_t> DIEToDIEMap; -typedef DIEToDIEMap::iterator DIEToDIEMapIter; -typedef DIEToDIEMap::const_iterator DIEToDIEMapConstIter; - -typedef std::map<uint32_t, const DWARFDebugInfoEntry *> UInt32ToDIEMap; -typedef UInt32ToDIEMap::iterator UInt32ToDIEMapIter; -typedef UInt32ToDIEMap::const_iterator UInt32ToDIEMapConstIter; - -typedef std::multimap<uint32_t, const DWARFDebugInfoEntry *> UInt32ToDIEMMap; -typedef UInt32ToDIEMMap::iterator UInt32ToDIEMMapIter; -typedef UInt32ToDIEMMap::const_iterator UInt32ToDIEMMapConstIter; - class DWARFDeclContext; #define DIE_SIBLING_IDX_BITSIZE 31 @@ -50,10 +29,6 @@ public: typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; - typedef std::vector<dw_offset_t> offset_collection; - typedef offset_collection::iterator offset_collection_iterator; - typedef offset_collection::const_iterator offset_collection_const_iterator; - DWARFDebugInfoEntry() : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), m_has_children(false), m_abbr_idx(0), m_tag(0) {} @@ -62,138 +37,90 @@ public: bool operator==(const DWARFDebugInfoEntry &rhs) const; bool operator!=(const DWARFDebugInfoEntry &rhs) const; - void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, + void BuildAddressRangeTable(const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const; - void BuildFunctionAddressRangeTable(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, + void BuildFunctionAddressRangeTable(const DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const; - bool FastExtract(const lldb_private::DWARFDataExtractor &debug_info_data, - const DWARFUnit *cu, - const DWARFFormValue::FixedFormSizes &fixed_form_sizes, - lldb::offset_t *offset_ptr); + bool Extract(const lldb_private::DWARFDataExtractor &data, + const DWARFUnit *cu, lldb::offset_t *offset_ptr); - bool Extract(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - lldb::offset_t *offset_ptr); - - bool LookupAddress(const dw_addr_t address, SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, + bool LookupAddress(const dw_addr_t address, const DWARFUnit *cu, DWARFDebugInfoEntry **function_die, DWARFDebugInfoEntry **block_die); size_t GetAttributes(const DWARFUnit *cu, - DWARFFormValue::FixedFormSizes fixed_form_sizes, DWARFAttributes &attrs, uint32_t curr_depth = 0) const; // "curr_depth" for internal use only, don't set this yourself!!! dw_offset_t - GetAttributeValue(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, DWARFFormValue &formValue, + GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, + DWARFFormValue &formValue, dw_offset_t *end_attr_offset_ptr = nullptr, bool check_specification_or_abstract_origin = false) const; const char *GetAttributeValueAsString( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, const char *fail_value, + const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, bool check_specification_or_abstract_origin = false) const; uint64_t GetAttributeValueAsUnsigned( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, uint64_t fail_value, - bool check_specification_or_abstract_origin = false) const; - - uint64_t GetAttributeValueAsReference( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, uint64_t fail_value, + const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin = false) const; - int64_t GetAttributeValueAsSigned( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, int64_t fail_value, + DWARFDIE GetAttributeValueAsReference( + const DWARFUnit *cu, const dw_attr_t attr, bool check_specification_or_abstract_origin = false) const; uint64_t GetAttributeValueAsAddress( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_attr_t attr, uint64_t fail_value, + const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin = false) const; dw_addr_t - GetAttributeHighPC(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - dw_addr_t lo_pc, uint64_t fail_value, + GetAttributeHighPC(const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, bool check_specification_or_abstract_origin = false) const; bool GetAttributeAddressRange( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t &lo_pc, - dw_addr_t &hi_pc, uint64_t fail_value, + const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, + uint64_t fail_value, bool check_specification_or_abstract_origin = false) const; size_t GetAttributeAddressRanges( - SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - DWARFRangeList &ranges, bool check_hi_lo_pc, + const DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc, bool check_specification_or_abstract_origin = false) const; - const char *GetName(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu) const; + const char *GetName(const DWARFUnit *cu) const; - const char *GetMangledName(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, + const char *GetMangledName(const DWARFUnit *cu, bool substitute_name_allowed = true) const; - const char *GetPubname(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu) const; + const char *GetPubname(const DWARFUnit *cu) const; - static bool GetName(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const dw_offset_t die_offset, lldb_private::Stream &s); - - static bool AppendTypeName(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, - const dw_offset_t die_offset, - lldb_private::Stream &s); - - const char *GetQualifiedName(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu, - std::string &storage) const; + const char *GetQualifiedName(DWARFUnit *cu, std::string &storage) const; - const char *GetQualifiedName(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu, - const DWARFAttributes &attributes, + const char *GetQualifiedName(DWARFUnit *cu, const DWARFAttributes &attributes, std::string &storage) const; - static bool OffsetLessThan(const DWARFDebugInfoEntry &a, - const DWARFDebugInfoEntry &b); - - void Dump(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - lldb_private::Stream &s, uint32_t recurse_depth) const; - - void DumpAncestry(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const DWARFDebugInfoEntry *oldest, lldb_private::Stream &s, - uint32_t recurse_depth) const; + void Dump(const DWARFUnit *cu, lldb_private::Stream &s, + uint32_t recurse_depth) const; static void - DumpAttribute(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const lldb_private::DWARFDataExtractor &debug_info_data, + DumpAttribute(const DWARFUnit *cu, + const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr, lldb_private::Stream &s, dw_attr_t attr, DWARFFormValue &form_value); - // This one dumps the comp unit name, objfile name and die offset for this die - // so the stream S. - void DumpLocation(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu, - lldb_private::Stream &s) const; - - bool - GetDIENamesAndRanges(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, - const char *&name, const char *&mangled, - DWARFRangeList &rangeList, int &decl_file, - int &decl_line, int &decl_column, int &call_file, - int &call_line, int &call_column, - lldb_private::DWARFExpression *frame_base = NULL) const; + + bool GetDIENamesAndRanges( + const DWARFUnit *cu, const char *&name, const char *&mangled, + DWARFRangeList &rangeList, int &decl_file, int &decl_line, + int &decl_column, int &call_file, int &call_line, int &call_column, + lldb_private::DWARFExpression *frame_base = nullptr) const; const DWARFAbbreviationDeclaration * - GetAbbreviationDeclarationPtr(SymbolFileDWARF *dwarf2Data, - const DWARFUnit *cu, - lldb::offset_t &offset) const; + GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const; + + lldb::offset_t GetFirstAttributeOffset() const; dw_tag_t Tag() const { return m_tag; } @@ -208,74 +135,41 @@ public: // We know we are kept in a vector of contiguous entries, so we know // our parent will be some index behind "this". DWARFDebugInfoEntry *GetParent() { - return m_parent_idx > 0 ? this - m_parent_idx : NULL; + return m_parent_idx > 0 ? this - m_parent_idx : nullptr; } const DWARFDebugInfoEntry *GetParent() const { - return m_parent_idx > 0 ? this - m_parent_idx : NULL; + return m_parent_idx > 0 ? this - m_parent_idx : nullptr; } // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". DWARFDebugInfoEntry *GetSibling() { - return m_sibling_idx > 0 ? this + m_sibling_idx : NULL; + return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; } const DWARFDebugInfoEntry *GetSibling() const { - return m_sibling_idx > 0 ? this + m_sibling_idx : NULL; + return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; } // We know we are kept in a vector of contiguous entries, so we know // we don't need to store our child pointer, if we have a child it will // be the next entry in the list... DWARFDebugInfoEntry *GetFirstChild() { - return HasChildren() ? this + 1 : NULL; + return HasChildren() ? this + 1 : nullptr; } const DWARFDebugInfoEntry *GetFirstChild() const { - return HasChildren() ? this + 1 : NULL; + return HasChildren() ? this + 1 : nullptr; } - void GetDeclContextDIEs(DWARFUnit *cu, - DWARFDIECollection &decl_context_dies) const; - - void GetDWARFDeclContext(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu, + void GetDWARFDeclContext(DWARFUnit *cu, DWARFDeclContext &dwarf_decl_ctx) const; - bool MatchesDWARFDeclContext(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu, - const DWARFDeclContext &dwarf_decl_ctx) const; - - DWARFDIE GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu) const; - DWARFDIE GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu, + DWARFDIE GetParentDeclContextDIE(DWARFUnit *cu) const; + DWARFDIE GetParentDeclContextDIE(DWARFUnit *cu, const DWARFAttributes &attributes) const; - void SetParent(DWARFDebugInfoEntry *parent) { - if (parent) { - // We know we are kept in a vector of contiguous entries, so we know - // our parent will be some index behind "this". - m_parent_idx = this - parent; - } else - m_parent_idx = 0; - } - void SetSibling(DWARFDebugInfoEntry *sibling) { - if (sibling) { - // We know we are kept in a vector of contiguous entries, so we know - // our sibling will be some index after "this". - m_sibling_idx = sibling - this; - sibling->SetParent(GetParent()); - } else - m_sibling_idx = 0; - } - void SetSiblingIndex(uint32_t idx) { m_sibling_idx = idx; } - void SetParentIndex(uint32_t idx) { m_parent_idx = idx; } - static void - DumpDIECollection(lldb_private::Stream &strm, - DWARFDebugInfoEntry::collection &die_collection); - protected: - dw_offset_t - m_offset; // Offset within the .debug_info of the start of this entry + dw_offset_t m_offset; // Offset within the .debug_info/.debug_types uint32_t m_parent_idx; // How many to subtract from "this" to get the parent. // If zero this die has no parent uint32_t m_sibling_idx : 31, // How many to add to "this" to get the sibling. diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp index d9f50122bd6f..953089fee22b 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp @@ -1,9 +1,8 @@ //===-- DWARFDebugLine.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,12 +11,15 @@ //#define ENABLE_DEBUG_PRINTF // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!! #include <assert.h> +#include <memory> + #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Host/Host.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Timer.h" +#include "DWARFUnit.h" #include "LogChannelDWARF.h" #include "SymbolFileDWARF.h" @@ -25,12 +27,10 @@ using namespace lldb; using namespace lldb_private; using namespace std; -//---------------------------------------------------------------------- // Parse // // Parse all information in the debug_line_data into an internal // representation. -//---------------------------------------------------------------------- void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) { m_lineTableMap.clear(); lldb::offset_t offset = 0; @@ -38,7 +38,7 @@ void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) { while (debug_line_data.ValidOffset(offset)) { const lldb::offset_t debug_line_offset = offset; - if (line_table_sp.get() == NULL) + if (line_table_sp.get() == nullptr) break; if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) { @@ -48,7 +48,7 @@ void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) { // DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n", // debug_line_offset); m_lineTableMap[debug_line_offset] = line_table_sp; - line_table_sp.reset(new LineTable); + line_table_sp = std::make_shared<LineTable>(); } else ++offset; // Try next byte in line table } @@ -59,9 +59,7 @@ void DWARFDebugLine::ParseIfNeeded(const DWARFDataExtractor &debug_line_data) { Parse(debug_line_data); } -//---------------------------------------------------------------------- // DWARFDebugLine::GetLineTable -//---------------------------------------------------------------------- DWARFDebugLine::LineTable::shared_ptr DWARFDebugLine::GetLineTable(const dw_offset_t offset) const { DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr; @@ -71,296 +69,11 @@ DWARFDebugLine::GetLineTable(const dw_offset_t offset) const { return line_table_shared_ptr; } -//---------------------------------------------------------------------- -// DumpStateToFile -//---------------------------------------------------------------------- -static void DumpStateToFile(dw_offset_t offset, - const DWARFDebugLine::State &state, - void *userData) { - Log *log = (Log *)userData; - if (state.row == DWARFDebugLine::State::StartParsingLineTable) { - // If the row is zero we are being called with the prologue only - state.prologue->Dump(log); - log->PutCString("Address Line Column File"); - log->PutCString("------------------ ------ ------ ------"); - } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) { - // Done parsing line table - } else { - log->Printf("0x%16.16" PRIx64 " %6u %6u %6u%s\n", state.address, state.line, - state.column, state.file, state.end_sequence ? " END" : ""); - } -} - -//---------------------------------------------------------------------- -// DWARFDebugLine::DumpLineTableRows -//---------------------------------------------------------------------- -bool DWARFDebugLine::DumpLineTableRows(Log *log, SymbolFileDWARF *dwarf2Data, - dw_offset_t debug_line_offset) { - const DWARFDataExtractor &debug_line_data = dwarf2Data->get_debug_line_data(); - - if (debug_line_offset == DW_INVALID_OFFSET) { - // Dump line table to a single file only - debug_line_offset = 0; - while (debug_line_data.ValidOffset(debug_line_offset)) - debug_line_offset = - DumpStatementTable(log, debug_line_data, debug_line_offset); - } else { - // Dump line table to a single file only - DumpStatementTable(log, debug_line_data, debug_line_offset); - } - return false; -} - -//---------------------------------------------------------------------- -// DWARFDebugLine::DumpStatementTable -//---------------------------------------------------------------------- -dw_offset_t -DWARFDebugLine::DumpStatementTable(Log *log, - const DWARFDataExtractor &debug_line_data, - const dw_offset_t debug_line_offset) { - if (debug_line_data.ValidOffset(debug_line_offset)) { - lldb::offset_t offset = debug_line_offset; - log->Printf("--------------------------------------------------------------" - "--------\n" - "debug_line[0x%8.8x]\n" - "--------------------------------------------------------------" - "--------\n", - debug_line_offset); - - if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log, nullptr)) - return offset; - else - return debug_line_offset + 1; // Skip to next byte in .debug_line section - } - - return DW_INVALID_OFFSET; -} - -//---------------------------------------------------------------------- -// DumpOpcodes -//---------------------------------------------------------------------- -bool DWARFDebugLine::DumpOpcodes(Log *log, SymbolFileDWARF *dwarf2Data, - dw_offset_t debug_line_offset, - uint32_t dump_flags) { - const DWARFDataExtractor &debug_line_data = dwarf2Data->get_debug_line_data(); - - if (debug_line_data.GetByteSize() == 0) { - log->Printf("< EMPTY >\n"); - return false; - } - - if (debug_line_offset == DW_INVALID_OFFSET) { - // Dump line table to a single file only - debug_line_offset = 0; - while (debug_line_data.ValidOffset(debug_line_offset)) - debug_line_offset = DumpStatementOpcodes(log, debug_line_data, - debug_line_offset, dump_flags); - } else { - // Dump line table to a single file only - DumpStatementOpcodes(log, debug_line_data, debug_line_offset, dump_flags); - } - return false; -} - -//---------------------------------------------------------------------- -// DumpStatementOpcodes -//---------------------------------------------------------------------- -dw_offset_t DWARFDebugLine::DumpStatementOpcodes( - Log *log, const DWARFDataExtractor &debug_line_data, - const dw_offset_t debug_line_offset, uint32_t flags) { - lldb::offset_t offset = debug_line_offset; - if (debug_line_data.ValidOffset(offset)) { - Prologue prologue; - - if (ParsePrologue(debug_line_data, &offset, &prologue)) { - log->PutCString("--------------------------------------------------------" - "--------------"); - log->Printf("debug_line[0x%8.8x]", debug_line_offset); - log->PutCString("--------------------------------------------------------" - "--------------\n"); - prologue.Dump(log); - } else { - offset = debug_line_offset; - log->Printf("0x%8.8" PRIx64 ": skipping pad byte %2.2x", offset, - debug_line_data.GetU8(&offset)); - return offset; - } - - Row row(prologue.default_is_stmt); - const dw_offset_t end_offset = debug_line_offset + prologue.total_length + - sizeof(prologue.total_length); - - assert(debug_line_data.ValidOffset(end_offset - 1)); - - while (offset < end_offset) { - const uint32_t op_offset = offset; - uint8_t opcode = debug_line_data.GetU8(&offset); - switch (opcode) { - case 0: // Extended Opcodes always start with a zero opcode followed by - { // a uleb128 length so you can skip ones you don't know about - - dw_offset_t ext_offset = offset; - dw_uleb128_t len = debug_line_data.GetULEB128(&offset); - dw_offset_t arg_size = len - (offset - ext_offset); - uint8_t sub_opcode = debug_line_data.GetU8(&offset); - // if (verbose) - // log->Printf( "Extended: <%u> %2.2x ", len, - // sub_opcode); - - switch (sub_opcode) { - case DW_LNE_end_sequence: - log->Printf("0x%8.8x: DW_LNE_end_sequence", op_offset); - row.Dump(log); - row.Reset(prologue.default_is_stmt); - break; - - case DW_LNE_set_address: { - row.address = debug_line_data.GetMaxU64(&offset, arg_size); - log->Printf("0x%8.8x: DW_LNE_set_address (0x%" PRIx64 ")", op_offset, - row.address); - } break; - - case DW_LNE_define_file: { - FileNameEntry fileEntry; - fileEntry.name = debug_line_data.GetCStr(&offset); - fileEntry.dir_idx = debug_line_data.GetULEB128(&offset); - fileEntry.mod_time = debug_line_data.GetULEB128(&offset); - fileEntry.length = debug_line_data.GetULEB128(&offset); - log->Printf("0x%8.8x: DW_LNE_define_file('%s', dir=%i, " - "mod_time=0x%8.8x, length=%i )", - op_offset, fileEntry.name, fileEntry.dir_idx, - fileEntry.mod_time, fileEntry.length); - prologue.file_names.push_back(fileEntry); - } break; - - case DW_LNE_set_discriminator: { - uint64_t discriminator = debug_line_data.GetULEB128(&offset); - log->Printf("0x%8.8x: DW_LNE_set_discriminator (0x%" PRIx64 ")", - op_offset, discriminator); - } break; - default: - log->Printf("0x%8.8x: DW_LNE_??? (%2.2x) - Skipping unknown upcode", - op_offset, opcode); - // Length doesn't include the zero opcode byte or the length itself, - // but it does include the sub_opcode, so we have to adjust for that - // below - offset += arg_size; - break; - } - } break; - - // Standard Opcodes - case DW_LNS_copy: - log->Printf("0x%8.8x: DW_LNS_copy", op_offset); - row.Dump(log); - break; - - case DW_LNS_advance_pc: { - dw_uleb128_t addr_offset_n = debug_line_data.GetULEB128(&offset); - dw_uleb128_t addr_offset = addr_offset_n * prologue.min_inst_length; - log->Printf("0x%8.8x: DW_LNS_advance_pc (0x%x)", op_offset, - addr_offset); - row.address += addr_offset; - } break; - - case DW_LNS_advance_line: { - dw_sleb128_t line_offset = debug_line_data.GetSLEB128(&offset); - log->Printf("0x%8.8x: DW_LNS_advance_line (%i)", op_offset, - line_offset); - row.line += line_offset; - } break; - - case DW_LNS_set_file: - row.file = debug_line_data.GetULEB128(&offset); - log->Printf("0x%8.8x: DW_LNS_set_file (%u)", op_offset, row.file); - break; - - case DW_LNS_set_column: - row.column = debug_line_data.GetULEB128(&offset); - log->Printf("0x%8.8x: DW_LNS_set_column (%u)", op_offset, row.column); - break; - - case DW_LNS_negate_stmt: - row.is_stmt = !row.is_stmt; - log->Printf("0x%8.8x: DW_LNS_negate_stmt", op_offset); - break; - - case DW_LNS_set_basic_block: - row.basic_block = true; - log->Printf("0x%8.8x: DW_LNS_set_basic_block", op_offset); - break; - - case DW_LNS_const_add_pc: { - uint8_t adjust_opcode = 255 - prologue.opcode_base; - dw_addr_t addr_offset = - (adjust_opcode / prologue.line_range) * prologue.min_inst_length; - log->Printf("0x%8.8x: DW_LNS_const_add_pc (0x%8.8" PRIx64 ")", - op_offset, addr_offset); - row.address += addr_offset; - } break; - - case DW_LNS_fixed_advance_pc: { - uint16_t pc_offset = debug_line_data.GetU16(&offset); - log->Printf("0x%8.8x: DW_LNS_fixed_advance_pc (0x%4.4x)", op_offset, - pc_offset); - row.address += pc_offset; - } break; - - case DW_LNS_set_prologue_end: - row.prologue_end = true; - log->Printf("0x%8.8x: DW_LNS_set_prologue_end", op_offset); - break; - - case DW_LNS_set_epilogue_begin: - row.epilogue_begin = true; - log->Printf("0x%8.8x: DW_LNS_set_epilogue_begin", op_offset); - break; - - case DW_LNS_set_isa: - row.isa = debug_line_data.GetULEB128(&offset); - log->Printf("0x%8.8x: DW_LNS_set_isa (%u)", op_offset, row.isa); - break; - - // Special Opcodes - default: - if (opcode < prologue.opcode_base) { - // We have an opcode that this parser doesn't know about, skip the - // number of ULEB128 numbers that is says to skip in the prologue's - // standard_opcode_lengths array - uint8_t n = prologue.standard_opcode_lengths[opcode - 1]; - log->Printf("0x%8.8x: Special : Unknown skipping %u ULEB128 values.", - op_offset, n); - while (n > 0) { - debug_line_data.GetULEB128(&offset); - --n; - } - } else { - uint8_t adjust_opcode = opcode - prologue.opcode_base; - dw_addr_t addr_offset = - (adjust_opcode / prologue.line_range) * prologue.min_inst_length; - int32_t line_offset = - prologue.line_base + (adjust_opcode % prologue.line_range); - log->Printf("0x%8.8x: address += 0x%" PRIx64 ", line += %i\n", - op_offset, (uint64_t)addr_offset, line_offset); - row.address += addr_offset; - row.line += line_offset; - row.Dump(log); - } - break; - } - } - return end_offset; - } - return DW_INVALID_OFFSET; -} - -//---------------------------------------------------------------------- // Parse // // Parse the entire line table contents calling callback each time a new // prologue is parsed and every time a new row is to be added to the line // table. -//---------------------------------------------------------------------- void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data, DWARFDebugLine::State::Callback callback, void *userData) { @@ -392,9 +105,7 @@ ReadDescriptors(const DWARFDataExtractor &debug_line_data, } } // namespace -//---------------------------------------------------------------------- // DWARFDebugLine::ParsePrologue -//---------------------------------------------------------------------- bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, Prologue *prologue, DWARFUnit *dwarf_cu) { @@ -528,8 +239,7 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data, bool DWARFDebugLine::ParseSupportFiles( const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data, - const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list, - FileSpecList &support_files, DWARFUnit *dwarf_cu) { + dw_offset_t stmt_list, FileSpecList &support_files, DWARFUnit *dwarf_cu) { lldb::offset_t offset = stmt_list; Prologue prologue; @@ -545,7 +255,9 @@ bool DWARFDebugLine::ParseSupportFiles( std::string remapped_file; for (uint32_t file_idx = 1; - prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx) { + prologue.GetFile(file_idx, dwarf_cu->GetCompilationDirectory(), + dwarf_cu->GetPathStyle(), file_spec); + ++file_idx) { if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file)) file_spec.SetFile(remapped_file, FileSpec::Style::native); support_files.Append(file_spec); @@ -553,13 +265,11 @@ bool DWARFDebugLine::ParseSupportFiles( return true; } -//---------------------------------------------------------------------- // ParseStatementTable // // Parse a single line table (prologue and all rows) and call the callback // function once for the prologue (row in state will be zero) and each time a // row is to be added to the line table. -//---------------------------------------------------------------------- bool DWARFDebugLine::ParseStatementTable( const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, DWARFDebugLine::State::Callback callback, void *userData, DWARFUnit *dwarf_cu) { @@ -832,9 +542,7 @@ bool DWARFDebugLine::ParseStatementTable( return end_offset; } -//---------------------------------------------------------------------- // ParseStatementTableCallback -//---------------------------------------------------------------------- static void ParseStatementTableCallback(dw_offset_t offset, const DWARFDebugLine::State &state, void *userData) { @@ -851,12 +559,10 @@ static void ParseStatementTableCallback(dw_offset_t offset, } } -//---------------------------------------------------------------------- // ParseStatementTable // // Parse a line table at offset and populate the LineTable class with the // prologue and all rows. -//---------------------------------------------------------------------- bool DWARFDebugLine::ParseStatementTable( const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, LineTable *line_table, DWARFUnit *dwarf_cu) { @@ -868,9 +574,7 @@ inline bool DWARFDebugLine::Prologue::IsValid() const { return SymbolFileDWARF::SupportedVersion(version); } -//---------------------------------------------------------------------- // DWARFDebugLine::Prologue::Dump -//---------------------------------------------------------------------- void DWARFDebugLine::Prologue::Dump(Log *log) { uint32_t i; @@ -909,11 +613,9 @@ void DWARFDebugLine::Prologue::Dump(Log *log) { } } -//---------------------------------------------------------------------- // DWARFDebugLine::ParsePrologue::Append // // Append the contents of the prologue to the binary stream buffer -//---------------------------------------------------------------------- // void // DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const //{ @@ -947,10 +649,12 @@ void DWARFDebugLine::Prologue::Dump(Log *log) { //} bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, - const lldb_private::FileSpec &comp_dir, FileSpec &file) const { + const FileSpec &comp_dir, + FileSpec::Style style, + FileSpec &file) const { uint32_t idx = file_idx - 1; // File indexes are 1 based... if (idx < file_names.size()) { - file.SetFile(file_names[idx].name, FileSpec::Style::native); + file.SetFile(file_names[idx].name, style); if (file.IsRelative()) { if (file_names[idx].dir_idx > 0) { const uint32_t dir_idx = file_names[idx].dir_idx - 1; @@ -969,42 +673,18 @@ bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, return false; } -//---------------------------------------------------------------------- -// DWARFDebugLine::LineTable::Dump -//---------------------------------------------------------------------- -void DWARFDebugLine::LineTable::Dump(Log *log) const { - if (prologue.get()) - prologue->Dump(log); - - if (!rows.empty()) { - log->PutCString("Address Line Column File ISA Flags"); - log->PutCString( - "------------------ ------ ------ ------ --- -------------"); - Row::const_iterator pos = rows.begin(); - Row::const_iterator end = rows.end(); - while (pos != end) { - (*pos).Dump(log); - ++pos; - } - } -} - void DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row &state) { rows.push_back(state); } -//---------------------------------------------------------------------- // Compare function for the binary search in // DWARFDebugLine::LineTable::LookupAddress() -//---------------------------------------------------------------------- static bool FindMatchingAddress(const DWARFDebugLine::Row &row1, const DWARFDebugLine::Row &row2) { return row1.address < row2.address; } -//---------------------------------------------------------------------- // DWARFDebugLine::LineTable::LookupAddress -//---------------------------------------------------------------------- uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const { uint32_t index = UINT32_MAX; @@ -1037,26 +717,20 @@ uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, return index; // Failed to find address } -//---------------------------------------------------------------------- // DWARFDebugLine::Row::Row -//---------------------------------------------------------------------- DWARFDebugLine::Row::Row(bool default_is_stmt) : address(0), line(1), column(0), file(1), is_stmt(default_is_stmt), basic_block(false), end_sequence(false), prologue_end(false), epilogue_begin(false), isa(0) {} -//---------------------------------------------------------------------- // Called after a row is appended to the matrix -//---------------------------------------------------------------------- void DWARFDebugLine::Row::PostAppend() { basic_block = false; prologue_end = false; epilogue_begin = false; } -//---------------------------------------------------------------------- // DWARFDebugLine::Row::Reset -//---------------------------------------------------------------------- void DWARFDebugLine::Row::Reset(bool default_is_stmt) { address = 0; line = 1; @@ -1069,9 +743,7 @@ void DWARFDebugLine::Row::Reset(bool default_is_stmt) { epilogue_begin = false; isa = 0; } -//---------------------------------------------------------------------- // DWARFDebugLine::Row::Dump -//---------------------------------------------------------------------- void DWARFDebugLine::Row::Dump(Log *log) const { log->Printf("0x%16.16" PRIx64 " %6u %6u %6u %3u %s%s%s%s%s", address, line, column, file, isa, is_stmt ? " is_stmt" : "", @@ -1081,9 +753,7 @@ void DWARFDebugLine::Row::Dump(Log *log) const { end_sequence ? " end_sequence" : ""); } -//---------------------------------------------------------------------- // Compare function LineTable structures -//---------------------------------------------------------------------- static bool AddressLessThan(const DWARFDebugLine::Row &a, const DWARFDebugLine::Row &b) { return a.address < b.address; @@ -1123,14 +793,7 @@ void DWARFDebugLine::Row::Insert(Row::collection &state_coll, } } -void DWARFDebugLine::Row::Dump(Log *log, const Row::collection &state_coll) { - std::for_each(state_coll.begin(), state_coll.end(), - bind2nd(std::mem_fun_ref(&Row::Dump), log)); -} - -//---------------------------------------------------------------------- // DWARFDebugLine::State::State -//---------------------------------------------------------------------- DWARFDebugLine::State::State(Prologue::shared_ptr &p, Log *l, DWARFDebugLine::State::Callback cb, void *userData) : Row(p->default_is_stmt), prologue(p), log(l), callback(cb), @@ -1140,14 +803,10 @@ DWARFDebugLine::State::State(Prologue::shared_ptr &p, Log *l, callback(0, *this, callbackUserData); } -//---------------------------------------------------------------------- // DWARFDebugLine::State::Reset -//---------------------------------------------------------------------- void DWARFDebugLine::State::Reset() { Row::Reset(prologue->default_is_stmt); } -//---------------------------------------------------------------------- // DWARFDebugLine::State::AppendRowToMatrix -//---------------------------------------------------------------------- void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) { // Each time we are to add an entry into the line table matrix call the // callback function so that someone can do something with the current state @@ -1167,9 +826,7 @@ void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) { PostAppend(); } -//---------------------------------------------------------------------- // DWARFDebugLine::State::Finalize -//---------------------------------------------------------------------- void DWARFDebugLine::State::Finalize(dw_offset_t offset) { // Call the callback with a special row state when we are done parsing a line // table diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h index 04f72e03a2db..0d236ca686b5 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h @@ -1,9 +1,8 @@ //===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -14,6 +13,7 @@ #include <string> #include <vector> +#include "lldb/Utility/FileSpec.h" #include "lldb/lldb-private.h" #include "DWARFDataExtractor.h" @@ -24,16 +24,13 @@ class DWARFUnit; class SymbolFileDWARF; -//---------------------------------------------------------------------- // DWARFDebugLine -//---------------------------------------------------------------------- class DWARFDebugLine { public: - //------------------------------------------------------------------ // FileNameEntry - //------------------------------------------------------------------ struct FileNameEntry { - FileNameEntry() : name(nullptr), dir_idx(0), mod_time(0), length(0) {} + FileNameEntry() + : name(nullptr), dir_idx(0), mod_time(0), length(0), checksum() {} const char *name; dw_sleb128_t dir_idx; @@ -42,9 +39,7 @@ public: llvm::MD5::MD5Result checksum; }; - //------------------------------------------------------------------ // Prologue - //------------------------------------------------------------------ struct Prologue { Prologue() @@ -99,6 +94,7 @@ public: file_names.clear(); } bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir, + lldb_private::FileSpec::Style style, lldb_private::FileSpec &file) const; }; @@ -114,7 +110,6 @@ public: void Reset(bool default_is_stmt); void Dump(lldb_private::Log *log) const; static void Insert(Row::collection &state_coll, const Row &state); - static void Dump(lldb_private::Log *log, const Row::collection &state_coll); dw_addr_t address; // The program-counter value corresponding to a machine // instruction generated by the compiler. @@ -145,9 +140,7 @@ public: // instruction set architecture for the current instruction. }; - //------------------------------------------------------------------ // LineTable - //------------------------------------------------------------------ struct LineTable { typedef std::shared_ptr<LineTable> shared_ptr; @@ -160,15 +153,12 @@ public: } uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const; - void Dump(lldb_private::Log *log) const; Prologue::shared_ptr prologue; Row::collection rows; }; - //------------------------------------------------------------------ // State - //------------------------------------------------------------------ struct State : public Row { typedef void (*Callback)(dw_offset_t offset, const State &state, void *userData); @@ -196,20 +186,12 @@ public: DISALLOW_COPY_AND_ASSIGN(State); }; - static bool DumpOpcodes( - lldb_private::Log *log, SymbolFileDWARF *dwarf2Data, - dw_offset_t line_offset = DW_INVALID_OFFSET, - uint32_t dump_flags = 0); // If line_offset is invalid, dump everything - static bool DumpLineTableRows( - lldb_private::Log *log, SymbolFileDWARF *dwarf2Data, - dw_offset_t line_offset = - DW_INVALID_OFFSET); // If line_offset is invalid, dump everything static bool ParseSupportFiles(const lldb::ModuleSP &module_sp, const lldb_private::DWARFDataExtractor &debug_line_data, - const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list, - lldb_private::FileSpecList &support_files, DWARFUnit *dwarf_cu); + lldb_private::FileSpecList &support_files, + DWARFUnit *dwarf_cu); static bool ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, Prologue *prologue, @@ -218,14 +200,6 @@ public: ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, State::Callback callback, void *userData, DWARFUnit *dwarf_cu); - static dw_offset_t - DumpStatementTable(lldb_private::Log *log, - const lldb_private::DWARFDataExtractor &debug_line_data, - const dw_offset_t line_offset); - static dw_offset_t - DumpStatementOpcodes(lldb_private::Log *log, - const lldb_private::DWARFDataExtractor &debug_line_data, - const dw_offset_t line_offset, uint32_t flags); static bool ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, LineTable *line_table, diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp deleted file mode 100644 index 19074b8865ff..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===-- DWARFDebugMacinfo.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugMacinfo.h" - -#include "DWARFDebugMacinfoEntry.h" -#include "SymbolFileDWARF.h" - -#include "lldb/Utility/Stream.h" - -using namespace lldb_private; -using namespace std; - -DWARFDebugMacinfo::DWARFDebugMacinfo() {} - -DWARFDebugMacinfo::~DWARFDebugMacinfo() {} - -void DWARFDebugMacinfo::Dump(Stream *s, const DWARFDataExtractor &macinfo_data, - lldb::offset_t offset) { - DWARFDebugMacinfoEntry maninfo_entry; - if (macinfo_data.GetByteSize() == 0) { - s->PutCString("< EMPTY >\n"); - return; - } - if (offset == LLDB_INVALID_OFFSET) { - offset = 0; - while (maninfo_entry.Extract(macinfo_data, &offset)) - maninfo_entry.Dump(s); - } else { - if (maninfo_entry.Extract(macinfo_data, &offset)) - maninfo_entry.Dump(s); - } -} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h deleted file mode 100644 index ec9dc85669c4..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h +++ /dev/null @@ -1,26 +0,0 @@ -//===-- DWARFDebugMacinfo.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFDebugMacinfo_h_ -#define SymbolFileDWARF_DWARFDebugMacinfo_h_ - -#include "SymbolFileDWARF.h" - -class DWARFDebugMacinfo { -public: - DWARFDebugMacinfo(); - - ~DWARFDebugMacinfo(); - - static void Dump(lldb_private::Stream *s, - const lldb_private::DWARFDataExtractor &macinfo_data, - lldb::offset_t offset = LLDB_INVALID_OFFSET); -}; - -#endif // SymbolFileDWARF_DWARFDebugMacinfo_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp deleted file mode 100644 index f078fbd44f2f..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//===-- DWARFDebugMacinfoEntry.cpp ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugMacinfoEntry.h" - -#include "lldb/Utility/Stream.h" - -using namespace lldb_private; -using namespace std; - -DWARFDebugMacinfoEntry::DWARFDebugMacinfoEntry() - : m_type_code(0), m_line(0), m_op2() { - m_op2.cstr = NULL; -} - -DWARFDebugMacinfoEntry::~DWARFDebugMacinfoEntry() {} - -const char *DWARFDebugMacinfoEntry::GetCString() const { - switch (m_type_code) { - case 0: - case DW_MACINFO_start_file: - case DW_MACINFO_end_file: - return NULL; - default: - break; - } - return m_op2.cstr; -} - -void DWARFDebugMacinfoEntry::Dump(Stream *s) const { - if (m_type_code) { - s->PutCString(DW_MACINFO_value_to_name(m_type_code)); - - switch (m_type_code) { - case DW_MACINFO_define: - s->Printf(" line:%u #define %s\n", (uint32_t)m_line, m_op2.cstr); - break; - - case DW_MACINFO_undef: - s->Printf(" line:%u #undef %s\n", (uint32_t)m_line, m_op2.cstr); - break; - - default: - s->Printf(" line:%u str: '%s'\n", (uint32_t)m_line, m_op2.cstr); - break; - - case DW_MACINFO_start_file: - s->Printf(" line:%u file index: '%u'\n", (uint32_t)m_line, - (uint32_t)m_op2.file_idx); - break; - - case DW_MACINFO_end_file: - break; - } - } else { - s->PutCString(" END\n"); - } -} - -bool DWARFDebugMacinfoEntry::Extract(const DWARFDataExtractor &mac_info_data, - lldb::offset_t *offset_ptr) { - if (mac_info_data.ValidOffset(*offset_ptr)) { - m_type_code = mac_info_data.GetU8(offset_ptr); - - switch (m_type_code) { - - case DW_MACINFO_define: - case DW_MACINFO_undef: - // 2 operands: - // Arg 1: operand encodes the line number of the source line on which - // the relevant defining or undefining pre-processor directives - // appeared. - m_line = mac_info_data.GetULEB128(offset_ptr); - // Arg 2: define string - m_op2.cstr = mac_info_data.GetCStr(offset_ptr); - break; - - case DW_MACINFO_start_file: - // 2 operands: - // Op 1: line number of the source line on which the inclusion - // pre-processor directive occurred. - m_line = mac_info_data.GetULEB128(offset_ptr); - // Op 2: a source file name index to a file number in the statement - // information table for the relevant compilation unit. - m_op2.file_idx = mac_info_data.GetULEB128(offset_ptr); - break; - - case 0: // End of list - case DW_MACINFO_end_file: - // No operands - m_line = DW_INVALID_OFFSET; - m_op2.cstr = NULL; - break; - default: - // Vendor specific entries always have a ULEB128 and a string - m_line = mac_info_data.GetULEB128(offset_ptr); - m_op2.cstr = mac_info_data.GetCStr(offset_ptr); - break; - } - return true; - } else - m_type_code = 0; - - return false; -} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h deleted file mode 100644 index 96829c2fc09b..000000000000 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h +++ /dev/null @@ -1,42 +0,0 @@ -//===-- DWARFDebugMacinfoEntry.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFDebugMacinfoEntry_h_ -#define SymbolFileDWARF_DWARFDebugMacinfoEntry_h_ - -#include "SymbolFileDWARF.h" - -class DWARFDebugMacinfoEntry { -public: - DWARFDebugMacinfoEntry(); - - ~DWARFDebugMacinfoEntry(); - - uint8_t TypeCode() const { return m_type_code; } - - uint8_t GetLineNumber() const { return m_line; } - - void Dump(lldb_private::Stream *s) const; - - const char *GetCString() const; - - bool Extract(const lldb_private::DWARFDataExtractor &mac_info_data, - lldb::offset_t *offset_ptr); - -protected: -private: - uint8_t m_type_code; - dw_uleb128_t m_line; - union { - dw_uleb128_t file_idx; - const char *cstr; - } m_op2; -}; - -#endif // SymbolFileDWARF_DWARFDebugMacinfoEntry_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp index d79acdc5cfc4..4238be7ec1c3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp @@ -1,9 +1,8 @@ //===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h index 021b434cd457..c3a93a9f4d14 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h @@ -1,10 +1,9 @@ //===-- DWARFDebugMacro.h ----------------------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index a0436dd7ffad..207c71211c9a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -1,20 +1,16 @@ //===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DWARFDebugRanges.h" #include "DWARFUnit.h" -#include "SymbolFileDWARF.h" #include "lldb/Utility/Stream.h" -#include <assert.h> using namespace lldb_private; -using namespace std; static dw_addr_t GetBaseAddressMarker(uint32_t addr_size) { switch(addr_size) { @@ -30,25 +26,24 @@ static dw_addr_t GetBaseAddressMarker(uint32_t addr_size) { DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} -void DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data) { +void DWARFDebugRanges::Extract(DWARFContext &context) { DWARFRangeList range_list; lldb::offset_t offset = 0; dw_offset_t debug_ranges_offset = offset; - while (Extract(dwarf2Data, &offset, range_list)) { + while (Extract(context, &offset, range_list)) { range_list.Sort(); m_range_map[debug_ranges_offset] = range_list; debug_ranges_offset = offset; } } -bool DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data, +bool DWARFDebugRanges::Extract(DWARFContext &context, lldb::offset_t *offset_ptr, DWARFRangeList &range_list) { range_list.Clear(); lldb::offset_t range_offset = *offset_ptr; - const DWARFDataExtractor &debug_ranges_data = - dwarf2Data->get_debug_ranges_data(); + const DWARFDataExtractor &debug_ranges_data = context.getOrLoadRangesData(); uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); dw_addr_t base_addr = 0; dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size); @@ -106,7 +101,7 @@ void DWARFDebugRanges::Dump(Stream &s, dw_addr_t begin_addr = begin + base_addr; dw_addr_t end_addr = end + base_addr; - s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), NULL); + s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), nullptr); } } } @@ -205,8 +200,10 @@ static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu, uint32_t index_size = cu->GetAddressByteSize(); dw_offset_t addr_base = cu->GetAddrBase(); lldb::offset_t offset = addr_base + index * index_size; - return cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, - index_size); + return cu->GetSymbolFileDWARF() + .GetDWARFContext() + .getOrLoadAddrData() + .GetMaxU64(&offset, index_size); } bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu, @@ -256,14 +253,12 @@ bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu, return false; } -void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) { - const DWARFDataExtractor &data = dwarf2Data->get_debug_rnglists_data(); +void DWARFDebugRngLists::Extract(DWARFContext &context) { + const DWARFDataExtractor &data = context.getOrLoadRngListsData(); lldb::offset_t offset = 0; uint64_t length = data.GetU32(&offset); - bool isDwarf64 = (length == 0xffffffff); - if (isDwarf64) - length = data.GetU64(&offset); + // FIXME: Handle DWARF64. lldb::offset_t end = offset + length; // Check version. @@ -280,7 +275,7 @@ void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) { uint32_t offsetsAmount = data.GetU32(&offset); for (uint32_t i = 0; i < offsetsAmount; ++i) - Offsets.push_back(data.GetMaxU64(&offset, isDwarf64 ? 8 : 4)); + Offsets.push_back(data.GetMaxU64(&offset, 4)); lldb::offset_t listOffset = offset; std::vector<RngListEntry> rangeList; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h index 5790f448ba85..baf2667f0afe 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -1,25 +1,27 @@ //===-- DWARFDebugRanges.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 SymbolFileDWARF_DWARFDebugRanges_h_ #define SymbolFileDWARF_DWARFDebugRanges_h_ -#include "DWARFDIE.h" -#include "SymbolFileDWARF.h" - +#include "lldb/Core/dwarf.h" #include <map> +class DWARFUnit; +namespace lldb_private { +class DWARFContext; +} + class DWARFDebugRangesBase { public: virtual ~DWARFDebugRangesBase(){}; - virtual void Extract(SymbolFileDWARF *dwarf2Data) = 0; + virtual void Extract(lldb_private::DWARFContext &context) = 0; virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const = 0; virtual uint64_t GetOffset(size_t Index) const = 0; @@ -29,7 +31,7 @@ class DWARFDebugRanges final : public DWARFDebugRangesBase { public: DWARFDebugRanges(); - void Extract(SymbolFileDWARF *dwarf2Data) override; + void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; uint64_t GetOffset(size_t Index) const override; @@ -39,7 +41,7 @@ public: lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr); protected: - bool Extract(SymbolFileDWARF *dwarf2Data, lldb::offset_t *offset_ptr, + bool Extract(lldb_private::DWARFContext &context, lldb::offset_t *offset_ptr, DWARFRangeList &range_list); typedef std::map<dw_offset_t, DWARFRangeList> range_map; @@ -57,7 +59,7 @@ class DWARFDebugRngLists final : public DWARFDebugRangesBase { }; public: - void Extract(SymbolFileDWARF *dwarf2Data) override; + void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; uint64_t GetOffset(size_t Index) const override; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp index dbaf0b0ed127..a664314035e4 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp @@ -1,9 +1,8 @@ //===-- DWARFDeclContext.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -30,7 +29,7 @@ const char *DWARFDeclContext::GetQualifiedName() const { for (pos = begin; pos != end; ++pos) { if (pos != begin) m_qualified_name.append("::"); - if (pos->name == NULL) { + if (pos->name == nullptr) { if (pos->tag == DW_TAG_namespace) m_qualified_name.append("(anonymous namespace)"); else if (pos->tag == DW_TAG_class_type) @@ -48,7 +47,7 @@ const char *DWARFDeclContext::GetQualifiedName() const { } } if (m_qualified_name.empty()) - return NULL; + return nullptr; return m_qualified_name.c_str(); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index aff5ea64e9ce..d0d70dd5123e 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -1,9 +1,8 @@ //===-- DWARFDeclContext.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -15,18 +14,16 @@ #include "lldb/Utility/ConstString.h" #include "DWARFDefines.h" -//---------------------------------------------------------------------- // DWARFDeclContext // // A class that represents a declaration context all the way down to a // DIE. This is useful when trying to find a DIE in one DWARF to a DIE // in another DWARF file. -//---------------------------------------------------------------------- class DWARFDeclContext { public: struct Entry { - Entry() : tag(0), name(NULL) {} + Entry() : tag(0), name(nullptr) {} Entry(dw_tag_t t, const char *n) : tag(t), name(n) {} bool NameMatches(const Entry &rhs) const { diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp index 99becdbb2bc1..3bf0bb088227 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp @@ -1,9 +1,8 @@ //===-- DWARFDefines.cpp ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -29,17 +28,6 @@ const char *DW_TAG_value_to_name(uint32_t val) { return llvmstr.data(); } -const char *DW_CHILDREN_value_to_name(uint8_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::ChildrenString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_CHILDREN constant: 0x%x", - val); - return invalid; - } - return llvmstr.data(); -} - const char *DW_AT_value_to_name(uint32_t val) { static char invalid[100]; llvm::StringRef llvmstr = llvm::dwarf::AttributeString(val); @@ -391,38 +379,6 @@ const char *DW_ATE_value_to_name(uint32_t val) { return llvmstr.data(); } -const char *DW_ACCESS_value_to_name(uint32_t val) { - static char invalid[100]; - - llvm::StringRef llvmstr = llvm::dwarf::AccessibilityString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_ACCESS constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - -const char *DW_VIS_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::VisibilityString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_VIS constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - -const char *DW_VIRTUALITY_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::VirtualityString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_VIRTUALITY constant: 0x%x", - val); - return invalid; - } - return llvmstr.data(); -} - const char *DW_LANG_value_to_name(uint32_t val) { static char invalid[100]; llvm::StringRef llvmstr = llvm::dwarf::LanguageString(val); @@ -433,46 +389,6 @@ const char *DW_LANG_value_to_name(uint32_t val) { return llvmstr.data(); } -const char *DW_ID_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::CaseString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_ID constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - -const char *DW_CC_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::ConventionString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_CC constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - -const char *DW_INL_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::InlineCodeString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_INL constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - -const char *DW_ORD_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::ArrayOrderString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_ORD constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - const char *DW_LNS_value_to_name(uint32_t val) { static char invalid[100]; llvm::StringRef llvmstr = llvm::dwarf::LNStandardString(val); @@ -483,157 +399,4 @@ const char *DW_LNS_value_to_name(uint32_t val) { return llvmstr.data(); } -const char *DW_LNE_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::LNExtendedString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_LNE constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - -const char *DW_MACINFO_value_to_name(uint32_t val) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::MacinfoString(val); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_MACINFO constant: 0x%x", - val); - return invalid; - } - return llvmstr.data(); -} - -const char *DW_CFA_value_to_name(uint32_t val, llvm::Triple::ArchType Arch) { - static char invalid[100]; - llvm::StringRef llvmstr = llvm::dwarf::CallFrameString(val, Arch); - if (llvmstr.empty()) { - snprintf(invalid, sizeof(invalid), "Unknown DW_CFA constant: 0x%x", val); - return invalid; - } - return llvmstr.data(); -} - -DW_TAG_CategoryEnum get_tag_category(uint16_t tag) { - switch (tag) { - case DW_TAG_array_type: - return TagCategoryType; - case DW_TAG_class_type: - return TagCategoryType; - case DW_TAG_entry_point: - return TagCategoryProgram; - case DW_TAG_enumeration_type: - return TagCategoryType; - case DW_TAG_formal_parameter: - return TagCategoryVariable; - case DW_TAG_imported_declaration: - return TagCategoryProgram; - case DW_TAG_label: - return TagCategoryProgram; - case DW_TAG_lexical_block: - return TagCategoryProgram; - case DW_TAG_member: - return TagCategoryType; - case DW_TAG_pointer_type: - return TagCategoryType; - case DW_TAG_reference_type: - return TagCategoryType; - case DW_TAG_compile_unit: - return TagCategoryProgram; - case DW_TAG_string_type: - return TagCategoryType; - case DW_TAG_structure_type: - return TagCategoryType; - case DW_TAG_subroutine_type: - return TagCategoryType; - case DW_TAG_typedef: - return TagCategoryType; - case DW_TAG_union_type: - return TagCategoryType; - case DW_TAG_unspecified_parameters: - return TagCategoryVariable; - case DW_TAG_variant: - return TagCategoryType; - case DW_TAG_common_block: - return TagCategoryProgram; - case DW_TAG_common_inclusion: - return TagCategoryProgram; - case DW_TAG_inheritance: - return TagCategoryType; - case DW_TAG_inlined_subroutine: - return TagCategoryProgram; - case DW_TAG_module: - return TagCategoryProgram; - case DW_TAG_ptr_to_member_type: - return TagCategoryType; - case DW_TAG_set_type: - return TagCategoryType; - case DW_TAG_subrange_type: - return TagCategoryType; - case DW_TAG_with_stmt: - return TagCategoryProgram; - case DW_TAG_access_declaration: - return TagCategoryProgram; - case DW_TAG_base_type: - return TagCategoryType; - case DW_TAG_catch_block: - return TagCategoryProgram; - case DW_TAG_const_type: - return TagCategoryType; - case DW_TAG_constant: - return TagCategoryVariable; - case DW_TAG_enumerator: - return TagCategoryType; - case DW_TAG_file_type: - return TagCategoryType; - case DW_TAG_friend: - return TagCategoryType; - case DW_TAG_namelist: - return TagCategoryVariable; - case DW_TAG_namelist_item: - return TagCategoryVariable; - case DW_TAG_packed_type: - return TagCategoryType; - case DW_TAG_subprogram: - return TagCategoryProgram; - case DW_TAG_template_type_parameter: - return TagCategoryType; - case DW_TAG_template_value_parameter: - return TagCategoryType; - case DW_TAG_GNU_template_parameter_pack: - return TagCategoryType; - case DW_TAG_thrown_type: - return TagCategoryType; - case DW_TAG_try_block: - return TagCategoryProgram; - case DW_TAG_variant_part: - return TagCategoryType; - case DW_TAG_variable: - return TagCategoryVariable; - case DW_TAG_volatile_type: - return TagCategoryType; - case DW_TAG_dwarf_procedure: - return TagCategoryProgram; - case DW_TAG_restrict_type: - return TagCategoryType; - case DW_TAG_interface_type: - return TagCategoryType; - case DW_TAG_namespace: - return TagCategoryProgram; - case DW_TAG_imported_module: - return TagCategoryProgram; - case DW_TAG_unspecified_type: - return TagCategoryType; - case DW_TAG_partial_unit: - return TagCategoryProgram; - case DW_TAG_imported_unit: - return TagCategoryProgram; - case DW_TAG_shared_type: - return TagCategoryType; - default: - break; - } - return TagCategoryProgram; -} - } // namespace lldb_private diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h index 0f5a885efb86..d16cb07baf88 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h @@ -1,9 +1,8 @@ //===-- DWARFDefines.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -15,23 +14,12 @@ namespace lldb_private { -typedef uint32_t DRC_class; // Holds DRC_* class bitfields - -enum DW_TAG_Category { - TagCategoryVariable, - TagCategoryType, - TagCategoryProgram, - kNumTagCategories -}; +enum class DWARFEnumState { MoreItems, Complete }; -typedef enum DW_TAG_Category DW_TAG_CategoryEnum; +typedef uint32_t DRC_class; // Holds DRC_* class bitfields const char *DW_TAG_value_to_name(uint32_t val); -DW_TAG_CategoryEnum get_tag_category(uint16_t tag); - -const char *DW_CHILDREN_value_to_name(uint8_t val); - const char *DW_AT_value_to_name(uint32_t val); const char *DW_FORM_value_to_name(uint32_t val); @@ -42,32 +30,10 @@ DRC_class DW_OP_value_to_class(uint32_t val); const char *DW_ATE_value_to_name(uint32_t val); -const char *DW_ACCESS_value_to_name(uint32_t val); - -const char *DW_VIS_value_to_name(uint32_t val); - -const char *DW_VIRTUALITY_value_to_name(uint32_t val); - const char *DW_LANG_value_to_name(uint32_t val); -const char *DW_ID_value_to_name(uint32_t val); - -const char *DW_CC_value_to_name(uint32_t val); - -const char *DW_INL_value_to_name(uint32_t val); - -const char *DW_ORD_value_to_name(uint32_t val); - const char *DW_LNS_value_to_name(uint32_t val); -const char *DW_LNE_value_to_name(uint32_t val); - -const char *DW_MACINFO_value_to_name(uint32_t val); - -const char *DW_CFA_value_to_name(uint32_t val, llvm::Triple::ArchType Arch); - -const char *DW_GNU_EH_PE_value_to_name(uint32_t val); - /* These DRC are entirely our own construction, although they are derived from various comments in the DWARF standard. Most of these are not useful to the parser, but the DW_AT and DW_FORM diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 5d2a8ffdb85b..046ae67446af 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -1,169 +1,30 @@ //===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 <assert.h> +#include "lldb/Core/Module.h" #include "lldb/Core/dwarf.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/Stream.h" -#include "DWARFUnit.h" +#include "DWARFDebugInfo.h" #include "DWARFFormValue.h" +#include "DWARFUnit.h" class DWARFUnit; using namespace lldb_private; -static uint8_t g_form_sizes_addr4[] = { - 0, // 0x00 unused - 4, // 0x01 DW_FORM_addr - 0, // 0x02 unused - 0, // 0x03 DW_FORM_block2 - 0, // 0x04 DW_FORM_block4 - 2, // 0x05 DW_FORM_data2 - 4, // 0x06 DW_FORM_data4 - 8, // 0x07 DW_FORM_data8 - 0, // 0x08 DW_FORM_string - 0, // 0x09 DW_FORM_block - 0, // 0x0a DW_FORM_block1 - 1, // 0x0b DW_FORM_data1 - 1, // 0x0c DW_FORM_flag - 0, // 0x0d DW_FORM_sdata - 4, // 0x0e DW_FORM_strp - 0, // 0x0f DW_FORM_udata - 0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - 1, // 0x11 DW_FORM_ref1 - 2, // 0x12 DW_FORM_ref2 - 4, // 0x13 DW_FORM_ref4 - 8, // 0x14 DW_FORM_ref8 - 0, // 0x15 DW_FORM_ref_udata - 0, // 0x16 DW_FORM_indirect - 4, // 0x17 DW_FORM_sec_offset - 0, // 0x18 DW_FORM_exprloc - 0, // 0x19 DW_FORM_flag_present - 0, // 0x1a - 0, // 0x1b - 0, // 0x1c - 0, // 0x1d - 0, // 0x1e - 0, // 0x1f - 8, // 0x20 DW_FORM_ref_sig8 - -}; - -static uint8_t g_form_sizes_addr8[] = { - 0, // 0x00 unused - 8, // 0x01 DW_FORM_addr - 0, // 0x02 unused - 0, // 0x03 DW_FORM_block2 - 0, // 0x04 DW_FORM_block4 - 2, // 0x05 DW_FORM_data2 - 4, // 0x06 DW_FORM_data4 - 8, // 0x07 DW_FORM_data8 - 0, // 0x08 DW_FORM_string - 0, // 0x09 DW_FORM_block - 0, // 0x0a DW_FORM_block1 - 1, // 0x0b DW_FORM_data1 - 1, // 0x0c DW_FORM_flag - 0, // 0x0d DW_FORM_sdata - 4, // 0x0e DW_FORM_strp - 0, // 0x0f DW_FORM_udata - 0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - 1, // 0x11 DW_FORM_ref1 - 2, // 0x12 DW_FORM_ref2 - 4, // 0x13 DW_FORM_ref4 - 8, // 0x14 DW_FORM_ref8 - 0, // 0x15 DW_FORM_ref_udata - 0, // 0x16 DW_FORM_indirect - 4, // 0x17 DW_FORM_sec_offset - 0, // 0x18 DW_FORM_exprloc - 0, // 0x19 DW_FORM_flag_present - 0, // 0x1a - 0, // 0x1b - 0, // 0x1c - 0, // 0x1d - 0, // 0x1e - 0, // 0x1f - 8, // 0x20 DW_FORM_ref_sig8 -}; - -// Difference with g_form_sizes_addr8: -// DW_FORM_strp and DW_FORM_sec_offset are 8 instead of 4 -static uint8_t g_form_sizes_addr8_dwarf64[] = { - 0, // 0x00 unused - 8, // 0x01 DW_FORM_addr - 0, // 0x02 unused - 0, // 0x03 DW_FORM_block2 - 0, // 0x04 DW_FORM_block4 - 2, // 0x05 DW_FORM_data2 - 4, // 0x06 DW_FORM_data4 - 8, // 0x07 DW_FORM_data8 - 0, // 0x08 DW_FORM_string - 0, // 0x09 DW_FORM_block - 0, // 0x0a DW_FORM_block1 - 1, // 0x0b DW_FORM_data1 - 1, // 0x0c DW_FORM_flag - 0, // 0x0d DW_FORM_sdata - 8, // 0x0e DW_FORM_strp - 0, // 0x0f DW_FORM_udata - 0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - 1, // 0x11 DW_FORM_ref1 - 2, // 0x12 DW_FORM_ref2 - 4, // 0x13 DW_FORM_ref4 - 8, // 0x14 DW_FORM_ref8 - 0, // 0x15 DW_FORM_ref_udata - 0, // 0x16 DW_FORM_indirect - 8, // 0x17 DW_FORM_sec_offset - 0, // 0x18 DW_FORM_exprloc - 0, // 0x19 DW_FORM_flag_present - 0, // 0x1a - 0, // 0x1b - 0, // 0x1c - 0, // 0x1d - 0, // 0x1e - 0, // 0x1f - 8, // 0x20 DW_FORM_ref_sig8 -}; - -DWARFFormValue::FixedFormSizes -DWARFFormValue::GetFixedFormSizesForAddressSize(uint8_t addr_size, - bool is_dwarf64) { - if (!is_dwarf64) { - switch (addr_size) { - case 4: - return FixedFormSizes(g_form_sizes_addr4, sizeof(g_form_sizes_addr4)); - case 8: - return FixedFormSizes(g_form_sizes_addr8, sizeof(g_form_sizes_addr8)); - } - } else { - if (addr_size == 8) - return FixedFormSizes(g_form_sizes_addr8_dwarf64, - sizeof(g_form_sizes_addr8_dwarf64)); - // is_dwarf64 && addr_size == 4 : no provider does this. - } - return FixedFormSizes(); -} - -DWARFFormValue::DWARFFormValue() : m_cu(NULL), m_form(0), m_value() {} - -DWARFFormValue::DWARFFormValue(const DWARFUnit *cu) - : m_cu(cu), m_form(0), m_value() {} - -DWARFFormValue::DWARFFormValue(const DWARFUnit *cu, dw_form_t form) - : m_cu(cu), m_form(form), m_value() {} - void DWARFFormValue::Clear() { - m_cu = nullptr; + m_unit = nullptr; m_form = 0; - memset(&m_value, 0, sizeof(m_value)); + m_value = ValueTypeTag(); } bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, @@ -173,7 +34,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, bool indirect = false; bool is_block = false; - m_value.data = NULL; + m_value.data = nullptr; uint8_t ref_addr_size; // Read the value for the form into value and follow and DW_FORM_indirect // instances we run into @@ -181,9 +42,9 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, indirect = false; switch (m_form) { case DW_FORM_addr: - assert(m_cu); + assert(m_unit); m_value.value.uval = - data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_cu)); + data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit)); break; case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); @@ -215,9 +76,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, case DW_FORM_strp: case DW_FORM_line_strp: case DW_FORM_sec_offset: - assert(m_cu); - m_value.value.uval = - data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4); + m_value.value.uval = data.GetMaxU64(offset_ptr, 4); break; case DW_FORM_addrx1: case DW_FORM_strx1: @@ -257,11 +116,11 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, m_value.value.uval = data.GetULEB128(offset_ptr); break; case DW_FORM_ref_addr: - assert(m_cu); - if (m_cu->GetVersion() <= 2) - ref_addr_size = m_cu->GetAddressByteSize(); + assert(m_unit); + if (m_unit->GetVersion() <= 2) + ref_addr_size = m_unit->GetAddressByteSize(); else - ref_addr_size = m_cu->IsDWARF64() ? 8 : 4; + ref_addr_size = 4; m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size); break; case DW_FORM_indirect: @@ -278,7 +137,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, if (is_block) { m_value.data = data.PeekData(*offset_ptr, m_value.value.uval); - if (m_value.data != NULL) { + if (m_value.data != nullptr) { *offset_ptr += m_value.value.uval; } } @@ -286,15 +145,68 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, return true; } +struct FormSize { + uint8_t valid:1, size:7; +}; +static FormSize g_form_sizes[] = { + {0,0}, // 0x00 unused + {0,0}, // 0x01 DW_FORM_addr + {0,0}, // 0x02 unused + {0,0}, // 0x03 DW_FORM_block2 + {0,0}, // 0x04 DW_FORM_block4 + {1,2}, // 0x05 DW_FORM_data2 + {1,4}, // 0x06 DW_FORM_data4 + {1,8}, // 0x07 DW_FORM_data8 + {0,0}, // 0x08 DW_FORM_string + {0,0}, // 0x09 DW_FORM_block + {0,0}, // 0x0a DW_FORM_block1 + {1,1}, // 0x0b DW_FORM_data1 + {1,1}, // 0x0c DW_FORM_flag + {0,0}, // 0x0d DW_FORM_sdata + {1,4}, // 0x0e DW_FORM_strp + {0,0}, // 0x0f DW_FORM_udata + {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for + // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later + {1,1}, // 0x11 DW_FORM_ref1 + {1,2}, // 0x12 DW_FORM_ref2 + {1,4}, // 0x13 DW_FORM_ref4 + {1,8}, // 0x14 DW_FORM_ref8 + {0,0}, // 0x15 DW_FORM_ref_udata + {0,0}, // 0x16 DW_FORM_indirect + {1,4}, // 0x17 DW_FORM_sec_offset + {0,0}, // 0x18 DW_FORM_exprloc + {1,0}, // 0x19 DW_FORM_flag_present + {0,0}, // 0x1a + {0,0}, // 0x1b + {0,0}, // 0x1c + {0,0}, // 0x1d + {0,0}, // 0x1e + {0,0}, // 0x1f + {1,8}, // 0x20 DW_FORM_ref_sig8 +}; + +llvm::Optional<uint8_t> +DWARFFormValue::GetFixedSize(dw_form_t form, const DWARFUnit *u) { + if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid) + return g_form_sizes[form].size; + if (form == DW_FORM_addr && u) + return u->GetAddressByteSize(); + return llvm::None; +} + +llvm::Optional<uint8_t> DWARFFormValue::GetFixedSize() const { + return GetFixedSize(m_form, m_unit); +} + bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr) const { - return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_cu); + return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit); } bool DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr, - const DWARFUnit *cu) { + const DWARFUnit *unit) { uint8_t ref_addr_size; switch (form) { // Blocks if inlined data that have a length field and the data bytes inlined @@ -328,17 +240,17 @@ bool DWARFFormValue::SkipValue(dw_form_t form, // Compile unit address sized values case DW_FORM_addr: - *offset_ptr += DWARFUnit::GetAddressByteSize(cu); + *offset_ptr += DWARFUnit::GetAddressByteSize(unit); return true; case DW_FORM_ref_addr: ref_addr_size = 4; - assert(cu); // CU must be valid for DW_FORM_ref_addr objects or we will get - // this wrong - if (cu->GetVersion() <= 2) - ref_addr_size = cu->GetAddressByteSize(); + assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will + // get this wrong + if (unit->GetVersion() <= 2) + ref_addr_size = unit->GetAddressByteSize(); else - ref_addr_size = cu->IsDWARF64() ? 8 : 4; + ref_addr_size = 4; *offset_ptr += ref_addr_size; return true; @@ -373,8 +285,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, // 32 bit for DWARF 32, 64 for DWARF 64 case DW_FORM_sec_offset: case DW_FORM_strp: - assert(cu); - *offset_ptr += (cu->IsDWARF64() ? 8 : 4); + *offset_ptr += 4; return true; // 4 byte values @@ -407,7 +318,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, case DW_FORM_indirect: { dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr); return DWARFFormValue::SkipValue(indirect_form, debug_info_data, offset_ptr, - cu); + unit); } default: @@ -418,7 +329,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, void DWARFFormValue::Dump(Stream &s) const { uint64_t uvalue = Unsigned(); - bool cu_relative_offset = false; + bool unit_relative_offset = false; switch (m_form) { case DW_FORM_addr: @@ -495,9 +406,9 @@ void DWARFFormValue::Dump(Stream &s) const { } break; case DW_FORM_ref_addr: { - assert(m_cu); // CU must be valid for DW_FORM_ref_addr objects or we will - // get this wrong - if (m_cu->GetVersion() <= 2) + assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we + // will get this wrong + if (m_unit->GetVersion() <= 2) s.Address(uvalue, sizeof(uint64_t) * 2); else s.Address(uvalue, 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't @@ -505,19 +416,19 @@ void DWARFFormValue::Dump(Stream &s) const { break; } case DW_FORM_ref1: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref2: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref4: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref8: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref_udata: - cu_relative_offset = true; + unit_relative_offset = true; break; // All DW_FORM_indirect attributes should be resolved prior to calling this @@ -532,33 +443,29 @@ void DWARFFormValue::Dump(Stream &s) const { break; } - if (cu_relative_offset) { - assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile - // unit relative or we will get this wrong - s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_cu->GetOffset()); + if (unit_relative_offset) { + assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile + // unit relative or we will get this wrong + s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset()); } } const char *DWARFFormValue::AsCString() const { - SymbolFileDWARF *symbol_file = m_cu->GetSymbolFileDWARF(); + SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); if (m_form == DW_FORM_string) { return m_value.value.cstr; } else if (m_form == DW_FORM_strp) { - if (!symbol_file) - return nullptr; - - return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval); + return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( + m_value.value.uval); } else if (m_form == DW_FORM_GNU_str_index) { - if (!symbol_file) - return nullptr; - - uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4; + uint32_t index_size = 4; lldb::offset_t offset = m_value.value.uval * index_size; dw_offset_t str_offset = - symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, - index_size); - return symbol_file->get_debug_str_data().PeekCStr(str_offset); + symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( + &offset, index_size); + return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( + str_offset); } if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 || @@ -566,44 +473,41 @@ const char *DWARFFormValue::AsCString() const { m_form == DW_FORM_strx4) { // The same code as above. - if (!symbol_file) - return nullptr; - - uint32_t indexSize = m_cu->IsDWARF64() ? 8 : 4; + uint32_t indexSize = 4; lldb::offset_t offset = - m_cu->GetStrOffsetsBase() + m_value.value.uval * indexSize; + m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize; dw_offset_t strOffset = - symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, indexSize); - return symbol_file->get_debug_str_data().PeekCStr(strOffset); + symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( + &offset, indexSize); + return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset); } if (m_form == DW_FORM_line_strp) - return symbol_file->get_debug_line_str_data().PeekCStr(m_value.value.uval); + return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr( + m_value.value.uval); return nullptr; } dw_addr_t DWARFFormValue::Address() const { - SymbolFileDWARF *symbol_file = m_cu->GetSymbolFileDWARF(); + SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); if (m_form == DW_FORM_addr) return Unsigned(); - assert(m_cu); + assert(m_unit); assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx || m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 || m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4); - if (!symbol_file) - return 0; - - uint32_t index_size = m_cu->GetAddressByteSize(); - dw_offset_t addr_base = m_cu->GetAddrBase(); + uint32_t index_size = m_unit->GetAddressByteSize(); + dw_offset_t addr_base = m_unit->GetAddrBase(); lldb::offset_t offset = addr_base + m_value.value.uval * index_size; - return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size); + return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64( + &offset, index_size); } -uint64_t DWARFFormValue::Reference() const { +DWARFDIE DWARFFormValue::Reference() const { uint64_t value = m_value.value.uval; switch (m_form) { case DW_FORM_ref1: @@ -611,17 +515,40 @@ uint64_t DWARFFormValue::Reference() const { case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile - // unit relative or we will get this wrong - return value + m_cu->GetOffset(); + assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile + // unit relative or we will get this wrong + value += m_unit->GetOffset(); + if (!m_unit->ContainsDIEOffset(value)) { + m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU", + value); + return {}; + } + return const_cast<DWARFUnit *>(m_unit)->GetDIE(value); - case DW_FORM_ref_addr: - case DW_FORM_ref_sig8: - case DW_FORM_GNU_ref_alt: - return value; + case DW_FORM_ref_addr: { + DWARFUnit *ref_cu = + m_unit->GetSymbolFileDWARF().DebugInfo()->GetUnitContainingDIEOffset( + DIERef::Section::DebugInfo, value); + if (!ref_cu) { + m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU", + value); + return {}; + } + return ref_cu->GetDIE(value); + } + + case DW_FORM_ref_sig8: { + DWARFTypeUnit *tu = + m_unit->GetSymbolFileDWARF().DebugInfo()->GetTypeUnitForHash(value); + if (!tu) + return {}; + return tu->GetDIE(tu->GetTypeOffset()); + } default: - return DW_INVALID_OFFSET; + return {}; } } @@ -682,6 +609,7 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, return 1; switch (a_form) { case DW_FORM_addr: + case DW_FORM_addrx: case DW_FORM_flag: case DW_FORM_data1: case DW_FORM_data2: @@ -721,7 +649,7 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, return 0; else if (a_string && b_string) return strcmp(a_string, b_string); - else if (a_string == NULL) + else if (a_string == nullptr) return -1; // A string is NULL, and B is valid else return 1; // A string valid, and B is NULL @@ -747,8 +675,8 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: { - uint64_t a = a_value.Reference(); - uint64_t b = b_value.Reference(); + uint64_t a = a_value.m_value.value.uval; + uint64_t b = b_value.m_value.value.uval; if (a < b) return -1; if (a > b) diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 0890f0c1bfc5..848db2990ded 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -1,9 +1,8 @@ //===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,14 +11,16 @@ #include "DWARFDataExtractor.h" #include <stddef.h> +#include "llvm/ADT/Optional.h" class DWARFUnit; class SymbolFileDWARF; +class DWARFDIE; class DWARFFormValue { public: typedef struct ValueTypeTag { - ValueTypeTag() : value(), data(NULL) { value.uval = 0; } + ValueTypeTag() : value(), data(nullptr) { value.uval = 0; } union { uint64_t uval; @@ -29,24 +30,6 @@ public: const uint8_t *data; } ValueType; - class FixedFormSizes { - public: - FixedFormSizes() : m_fix_sizes(nullptr), m_size(0) {} - - FixedFormSizes(const uint8_t *fix_sizes, size_t size) - : m_fix_sizes(fix_sizes), m_size(size) {} - - uint8_t GetSize(uint32_t index) const { - return index < m_size ? m_fix_sizes[index] : 0; - } - - bool Empty() const { return m_size == 0; } - - private: - const uint8_t *m_fix_sizes; - size_t m_size; - }; - enum { eValueTypeInvalid = 0, eValueTypeUnsigned, @@ -55,11 +38,11 @@ public: eValueTypeBlock }; - DWARFFormValue(); - DWARFFormValue(const DWARFUnit *cu); - DWARFFormValue(const DWARFUnit *cu, dw_form_t form); - const DWARFUnit *GetCompileUnit() const { return m_cu; } - void SetCompileUnit(const DWARFUnit *cu) { m_cu = cu; } + DWARFFormValue() = default; + DWARFFormValue(const DWARFUnit *unit) : m_unit(unit) {} + DWARFFormValue(const DWARFUnit *unit, dw_form_t form) + : m_unit(unit), m_form(form) {} + void SetUnit(const DWARFUnit *unit) { m_unit = unit; } dw_form_t Form() const { return m_form; } dw_form_t& FormRef() { return m_form; } void SetForm(dw_form_t form) { m_form = form; } @@ -71,7 +54,10 @@ public: bool ExtractValue(const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr); const uint8_t *BlockData() const; - uint64_t Reference() const; + static llvm::Optional<uint8_t> GetFixedSize(dw_form_t form, + const DWARFUnit *u); + llvm::Optional<uint8_t> GetFixedSize() const; + DWARFDIE Reference() const; uint64_t Reference(dw_offset_t offset) const; bool Boolean() const { return m_value.value.uval != 0; } uint64_t Unsigned() const { return m_value.value.uval; } @@ -85,18 +71,18 @@ public: lldb::offset_t *offset_ptr) const; static bool SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor &debug_info_data, - lldb::offset_t *offset_ptr, const DWARFUnit *cu); + lldb::offset_t *offset_ptr, const DWARFUnit *unit); static bool IsBlockForm(const dw_form_t form); static bool IsDataForm(const dw_form_t form); - static FixedFormSizes GetFixedFormSizesForAddressSize(uint8_t addr_size, - bool is_dwarf64); static int Compare(const DWARFFormValue &a, const DWARFFormValue &b); void Clear(); static bool FormIsSupported(dw_form_t form); protected: - const DWARFUnit *m_cu; // Compile unit for this form - dw_form_t m_form; // Form for this value + // Compile unit where m_value was located. + // It may be different from compile unit where m_value refers to. + const DWARFUnit *m_unit = nullptr; // Unit for this form + dw_form_t m_form = 0; // Form for this value ValueType m_value; // Contains all data for the form }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp index 4577f0557a1d..c122f756e81a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp @@ -1,17 +1,15 @@ //===-- DWARFIndex.cpp -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "Plugins/SymbolFile/DWARF/DWARFIndex.h" -#include "Plugins/SymbolFile/DWARF/DWARFDIE.h" -#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" - #include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "Plugins/SymbolFile/DWARF/DWARFDIE.h" +#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" using namespace lldb_private; using namespace lldb; @@ -19,13 +17,13 @@ using namespace lldb; DWARFIndex::~DWARFIndex() = default; void DWARFIndex::ProcessFunctionDIE(llvm::StringRef name, DIERef ref, - DWARFDebugInfo &info, + SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) { - DWARFDIE die = info.GetDIE(ref); + DWARFDIE die = dwarf.GetDIE(ref); if (!die) { - ReportInvalidDIEOffset(ref.die_offset, name); + ReportInvalidDIERef(ref, name); return; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h index 77af67b8e60f..e3c7c5e63ac8 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -1,9 +1,8 @@ //===-- DWARFIndex.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -14,7 +13,6 @@ #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" #include "Plugins/SymbolFile/DWARF/DWARFFormValue.h" -class DWARFDebugInfo; class DWARFDeclContext; class DWARFDIE; @@ -41,15 +39,14 @@ public: virtual void GetTypes(ConstString name, DIEArray &offsets) = 0; virtual void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) = 0; virtual void GetNamespaces(ConstString name, DIEArray &offsets) = 0; - virtual void GetFunctions(ConstString name, DWARFDebugInfo &info, + virtual void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) = 0; virtual void GetFunctions(const RegularExpression ®ex, DIEArray &offsets) = 0; - virtual void ReportInvalidDIEOffset(dw_offset_t offset, - llvm::StringRef name) = 0; + virtual void ReportInvalidDIERef(const DIERef &ref, llvm::StringRef name) = 0; virtual void Dump(Stream &s) = 0; protected: @@ -60,7 +57,7 @@ protected: /// "parent_decl_ctx" and "name_type_mask", it is inserted into the "dies" /// vector. void ProcessFunctionDIE(llvm::StringRef name, DIERef ref, - DWARFDebugInfo &info, + SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies); }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp new file mode 100644 index 000000000000..fcc031bf1ea0 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp @@ -0,0 +1,23 @@ +//===-- DWARFTypeUnit.cpp ---------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "DWARFTypeUnit.h" + +#include "SymbolFileDWARF.h" +#include "lldb/Utility/Stream.h" + +using namespace lldb; +using namespace lldb_private; + +void DWARFTypeUnit::Dump(Stream *s) const { + s->Printf("0x%8.8x: Type Unit: length = 0x%8.8x, version = 0x%4.4x, " + "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at " + "{0x%8.8x})\n", + GetOffset(), GetLength(), GetVersion(), GetAbbrevOffset(), + GetAddressByteSize(), GetNextUnitOffset()); +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h new file mode 100644 index 000000000000..6ff73ecd8efa --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h @@ -0,0 +1,37 @@ +//===-- DWARFTypeUnit.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 SymbolFileDWARF_DWARFTypeUnit_h_ +#define SymbolFileDWARF_DWARFTypeUnit_h_ + +#include "DWARFUnit.h" +#include "llvm/Support/Error.h" + +class DWARFTypeUnit : public DWARFUnit { +public: + void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override {} + + void Dump(lldb_private::Stream *s) const override; + + uint64_t GetTypeHash() { return m_header.GetTypeHash(); } + + dw_offset_t GetTypeOffset() { return GetOffset() + m_header.GetTypeOffset(); } + + static bool classof(const DWARFUnit *unit) { return unit->IsTypeUnit(); } + +private: + DWARFTypeUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, + const DWARFUnitHeader &header, + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section) + : DWARFUnit(dwarf, uid, header, abbrevs, section) {} + + friend class DWARFUnit; +}; + +#endif // SymbolFileDWARF_DWARFTypeUnit_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 7afc71bc24f0..33e83d1fe57f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -1,9 +1,8 @@ //===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,18 +10,17 @@ #include "lldb/Core/Module.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" +#include "llvm/Object/Error.h" -#include "DWARFDIECollection.h" +#include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" +#include "DWARFTypeUnit.h" #include "LogChannelDWARF.h" -#include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" using namespace lldb; @@ -31,14 +29,16 @@ using namespace std; extern int g_verbose; -DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf) - : m_dwarf(dwarf), m_cancel_scopes(false) {} +DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, + const DWARFUnitHeader &header, + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section) + : UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs), + m_cancel_scopes(false), m_section(section) {} -DWARFUnit::~DWARFUnit() {} +DWARFUnit::~DWARFUnit() = default; -//---------------------------------------------------------------------- // Parses first DIE of a compile unit. -//---------------------------------------------------------------------- void DWARFUnit::ExtractUnitDIEIfNeeded() { { llvm::sys::ScopedReader lock(m_first_die_mutex); @@ -50,8 +50,8 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() { return; // Already parsed static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset); + Timer scoped_timer(func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", + GetOffset()); // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. @@ -60,22 +60,15 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() { // We are in our compile unit, parse starting at the offset we were told to // parse const DWARFDataExtractor &data = GetData(); - DWARFFormValue::FixedFormSizes fixed_form_sizes = - DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), - IsDWARF64()); - if (offset < GetNextCompileUnitOffset() && - m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) { + if (offset < GetNextUnitOffset() && + m_first_die.Extract(data, this, &offset)) { AddUnitDIE(m_first_die); return; } - - ExtractDIEsEndCheck(offset); } -//---------------------------------------------------------------------- // Parses a compile unit and indexes its DIEs if it hasn't already been done. // It will leave this compile unit extracted forever. -//---------------------------------------------------------------------- void DWARFUnit::ExtractDIEsIfNeeded() { m_cancel_scopes = true; @@ -91,15 +84,13 @@ void DWARFUnit::ExtractDIEsIfNeeded() { ExtractDIEsRWLocked(); } -//---------------------------------------------------------------------- // Parses a compile unit and indexes its DIEs if it hasn't already been done. // It will clear this compile unit after returned instance gets out of scope, // no other ScopedExtractDIEs instance is running for this compile unit // and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs // lifetime. -//---------------------------------------------------------------------- DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() { - ScopedExtractDIEs scoped(this); + ScopedExtractDIEs scoped(*this); { llvm::sys::ScopedReader lock(m_die_array_mutex); @@ -118,8 +109,7 @@ DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() { return scoped; } -DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit *cu) : m_cu(cu) { - lldbassert(m_cu); +DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit &cu) : m_cu(&cu) { m_cu->m_die_array_scoped_mutex.lock_shared(); } @@ -150,33 +140,21 @@ DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=( return *this; } -//---------------------------------------------------------------------- // Parses a compile unit and indexes its DIEs, m_die_array_mutex must be // held R/W and m_die_array must be empty. -//---------------------------------------------------------------------- void DWARFUnit::ExtractDIEsRWLocked() { llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset); + Timer scoped_timer(func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", + GetOffset()); // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. lldb::offset_t offset = GetFirstDIEOffset(); - lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); + lldb::offset_t next_cu_offset = GetNextUnitOffset(); DWARFDebugInfoEntry die; - // Keep a flat array of the DIE for binary lookup by DIE offset - Log *log( - LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); - if (log) { - m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( - log, - "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at " - ".debug_info[0x%8.8x]", - GetOffset()); - } uint32_t depth = 0; // We are in our compile unit, parse starting at the offset we were told to @@ -186,11 +164,7 @@ void DWARFUnit::ExtractDIEsRWLocked() { die_index_stack.reserve(32); die_index_stack.push_back(0); bool prev_die_had_children = false; - DWARFFormValue::FixedFormSizes fixed_form_sizes = - DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), - IsDWARF64()); - while (offset < next_cu_offset && - die.FastExtract(data, this, fixed_form_sizes, &offset)) { + while (offset < next_cu_offset && die.Extract(data, this, &offset)) { const bool null_die = die.IsNULL(); if (depth == 0) { assert(m_die_array.empty() && "Compile unit DIE already added"); @@ -208,6 +182,17 @@ void DWARFUnit::ExtractDIEsRWLocked() { if (!m_first_die) AddUnitDIE(m_die_array.front()); + + // With -fsplit-dwarf-inlining, clang will emit non-empty skeleton compile + // units. We are not able to access these DIE *and* the dwo file + // simultaneously. We also don't need to do that as the dwo file will + // contain a superset of information. So, we don't even attempt to parse + // any remaining DIEs. + if (m_dwo_symbol_file) { + m_die_array.front().SetHasChildren(false); + break; + } + } else { if (null_die) { if (prev_die_had_children) { @@ -264,40 +249,12 @@ void DWARFUnit::ExtractDIEsRWLocked() { m_die_array.shrink_to_fit(); - ExtractDIEsEndCheck(offset); - if (m_dwo_symbol_file) { DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); dwo_cu->ExtractDIEsIfNeeded(); } } -//-------------------------------------------------------------------------- -// Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded(). -//-------------------------------------------------------------------------- -void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { - // Give a little bit of info if we encounter corrupt DWARF (our offset should - // always terminate at or before the start of the next compilation unit - // header). - if (offset > GetNextCompileUnitOffset()) { - m_dwarf->GetObjectFile()->GetModule()->ReportWarning( - "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " - "0x%8.8" PRIx64 "\n", - GetOffset(), offset); - } - - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); - if (log && log->GetVerbose()) { - StreamString strm; - Dump(&strm); - if (m_die_array.empty()) - strm.Printf("error: no DIE for compile unit"); - else - m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); - log->PutString(strm.GetString()); - } -} - // This is used when a split dwarf is enabled. // A skeleton compilation unit may contain the DW_AT_str_offsets_base attribute // that points to the first string offset of the CU contribution to the @@ -308,7 +265,7 @@ static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) { lldb::offset_t baseOffset = 0; const DWARFDataExtractor &strOffsets = - dwo_cu->GetSymbolFileDWARF()->get_debug_str_offsets_data(); + dwo_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); uint64_t length = strOffsets.GetU32(&baseOffset); if (length == 0xffffffff) length = strOffsets.GetU64(&baseOffset); @@ -325,28 +282,50 @@ static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) { // m_die_array_mutex must be already held as read/write. void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { - dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned( - m_dwarf, this, DW_AT_addr_base, LLDB_INVALID_ADDRESS); - if (addr_base != LLDB_INVALID_ADDRESS) - SetAddrBase(addr_base); - - dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( - m_dwarf, this, DW_AT_rnglists_base, LLDB_INVALID_ADDRESS); - if (ranges_base != LLDB_INVALID_ADDRESS) - SetRangesBase(ranges_base); - - SetStrOffsetsBase(cu_die.GetAttributeValueAsUnsigned( - m_dwarf, this, DW_AT_str_offsets_base, 0)); - - uint64_t base_addr = cu_die.GetAttributeValueAsAddress( - m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); - if (base_addr == LLDB_INVALID_ADDRESS) - base_addr = cu_die.GetAttributeValueAsAddress( - m_dwarf, this, DW_AT_entry_pc, 0); - SetBaseAddress(base_addr); + llvm::Optional<uint64_t> addr_base, gnu_addr_base, ranges_base, + gnu_ranges_base; + + DWARFAttributes attributes; + size_t num_attributes = cu_die.GetAttributes(this, attributes); + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(i, form_value)) + continue; + switch (attr) { + case DW_AT_addr_base: + addr_base = form_value.Unsigned(); + SetAddrBase(*addr_base); + break; + case DW_AT_rnglists_base: + ranges_base = form_value.Unsigned(); + SetRangesBase(*ranges_base); + break; + case DW_AT_str_offsets_base: + SetStrOffsetsBase(form_value.Unsigned()); + break; + case DW_AT_low_pc: + SetBaseAddress(form_value.Address()); + break; + case DW_AT_entry_pc: + // If the value was already set by DW_AT_low_pc, don't update it. + if (m_base_addr == LLDB_INVALID_ADDRESS) + SetBaseAddress(form_value.Address()); + break; + case DW_AT_stmt_list: + m_line_table_offset = form_value.Unsigned(); + break; + case DW_AT_GNU_addr_base: + gnu_addr_base = form_value.Unsigned(); + break; + case DW_AT_GNU_ranges_base: + gnu_ranges_base = form_value.Unsigned(); + break; + } + } std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = - m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); + m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die); if (!dwo_symbol_file) return; @@ -359,7 +338,7 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { return; // Can't fetch the compile unit DIE from the dwo file. uint64_t main_dwo_id = - cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0); + cu_die.GetAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, 0); uint64_t sub_dwo_id = dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); if (main_dwo_id != sub_dwo_id) @@ -374,19 +353,20 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { // attributes which were applicable to the DWO units. The corresponding // DW_AT_* attributes standardized in DWARF v5 are also applicable to the main // unit in contrast. - if (addr_base == LLDB_INVALID_ADDRESS) - addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, - DW_AT_GNU_addr_base, 0); - dwo_cu->SetAddrBase(addr_base); - - if (ranges_base == LLDB_INVALID_ADDRESS) - ranges_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, - DW_AT_GNU_ranges_base, 0); - dwo_cu->SetRangesBase(ranges_base); - - dwo_cu->SetBaseObjOffset(m_offset); - - SetDwoStrOffsetsBase(dwo_cu); + if (addr_base) + dwo_cu->SetAddrBase(*addr_base); + else if (gnu_addr_base) + dwo_cu->SetAddrBase(*gnu_addr_base); + + if (ranges_base) + dwo_cu->SetRangesBase(*ranges_base); + else if (gnu_ranges_base) + dwo_cu->SetRangesBase(*gnu_ranges_base); + + for (size_t i = 0; i < m_dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) { + DWARFUnit *unit = m_dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i); + SetDwoStrOffsetsBase(unit); + } } DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { @@ -401,35 +381,21 @@ DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { } size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, - DWARFDIECollection &dies, - uint32_t depth) const { - size_t old_size = dies.Size(); + std::vector<DWARFDIE> &dies, + uint32_t depth) const { + size_t old_size = dies.size(); { llvm::sys::ScopedReader lock(m_die_array_mutex); DWARFDebugInfoEntry::const_iterator pos; DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); for (pos = m_die_array.begin(); pos != end; ++pos) { if (pos->Tag() == tag) - dies.Append(DWARFDIE(this, &(*pos))); + dies.emplace_back(this, &(*pos)); } } // Return the number of DIEs added to the collection - return dies.Size() - old_size; -} - - -lldb::user_id_t DWARFUnit::GetID() const { - dw_offset_t local_id = - m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; - if (m_dwarf) - return DIERef(local_id, local_id).GetUID(m_dwarf); - else - return local_id; -} - -dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { - return m_offset + GetLengthByteSize() + GetLength(); + return dies.size() - old_size; } size_t DWARFUnit::GetDebugInfoSize() const { @@ -444,16 +410,17 @@ dw_offset_t DWARFUnit::GetAbbrevOffset() const { return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; } +dw_offset_t DWARFUnit::GetLineTableOffset() { + ExtractUnitDIEIfNeeded(); + return m_line_table_offset; +} + void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; } void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { m_ranges_base = ranges_base; } -void DWARFUnit::SetBaseObjOffset(dw_offset_t base_obj_offset) { - m_base_obj_offset = base_obj_offset; -} - void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { m_str_offsets_base = str_offsets_base; } @@ -467,132 +434,27 @@ void DWARFUnit::ClearDIEsRWLocked() { m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked(); } -void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, - DWARFDebugAranges *debug_aranges) { - // This function is usually called if there in no .debug_aranges section in - // order to produce a compile unit level set of address ranges that is - // accurate. - - size_t num_debug_aranges = debug_aranges->GetNumRanges(); - - // First get the compile unit DIE only and check if it has a DW_AT_ranges - const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); - - const dw_offset_t cu_offset = GetOffset(); - if (die) { - DWARFRangeList ranges; - const size_t num_ranges = - die->GetAttributeAddressRanges(dwarf, this, ranges, false); - if (num_ranges > 0) { - // This compile unit has DW_AT_ranges, assume this is correct if it is - // present since clang no longer makes .debug_aranges by default and it - // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with - // recent GCC builds. - for (size_t i = 0; i < num_ranges; ++i) { - const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); - debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), - range.GetRangeEnd()); - } - - return; // We got all of our ranges from the DW_AT_ranges attribute - } - } - // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF - - // If the DIEs weren't parsed, then we don't want all dies for all compile - // units to stay loaded when they weren't needed. So we can end up parsing - // the DWARF and then throwing them all away to keep memory usage down. - ScopedExtractDIEs clear_dies(ExtractDIEsScoped()); - - die = DIEPtr(); - if (die) - die->BuildAddressRangeTable(dwarf, this, debug_aranges); - - if (debug_aranges->GetNumRanges() == num_debug_aranges) { - // We got nothing from the functions, maybe we have a line tables only - // situation. Check the line tables and build the arange table from this. - SymbolContext sc; - sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); - if (sc.comp_unit) { - SymbolFileDWARFDebugMap *debug_map_sym_file = - m_dwarf->GetDebugMapSymfile(); - if (debug_map_sym_file == NULL) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - - if (line_table) { - LineTable::FileAddressRanges file_ranges; - const bool append = true; - const size_t num_ranges = - line_table->GetContiguousFileAddressRanges(file_ranges, append); - for (uint32_t idx = 0; idx < num_ranges; ++idx) { - const LineTable::FileAddressRanges::Entry &range = - file_ranges.GetEntryRef(idx); - debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), - range.GetRangeEnd()); - } - } - } else - debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges); - } - } - - if (debug_aranges->GetNumRanges() == num_debug_aranges) { - // We got nothing from the functions, maybe we have a line tables only - // situation. Check the line tables and build the arange table from this. - SymbolContext sc; - sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); - if (sc.comp_unit) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - - if (line_table) { - LineTable::FileAddressRanges file_ranges; - const bool append = true; - const size_t num_ranges = - line_table->GetContiguousFileAddressRanges(file_ranges, append); - for (uint32_t idx = 0; idx < num_ranges; ++idx) { - const LineTable::FileAddressRanges::Entry &range = - file_ranges.GetEntryRef(idx); - debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), - range.GetRangeEnd()); - } - } - } - } -} - lldb::ByteOrder DWARFUnit::GetByteOrder() const { - return m_dwarf->GetObjectFile()->GetByteOrder(); + return m_dwarf.GetObjectFile()->GetByteOrder(); } TypeSystem *DWARFUnit::GetTypeSystem() { - if (m_dwarf) - return m_dwarf->GetTypeSystemForLanguage(GetLanguageType()); - else - return nullptr; -} - -DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { - return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), - IsDWARF64()); + return m_dwarf.GetTypeSystemForLanguage(GetLanguageType()); } void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } -//---------------------------------------------------------------------- // Compare function DWARFDebugAranges::Range structures -//---------------------------------------------------------------------- static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, const dw_offset_t die_offset) { return die.GetOffset() < die_offset; } -//---------------------------------------------------------------------- // GetDIE() // // Get the DIE (Debug Information Entry) with the specified offset by first // checking if the DIE is contained within this compile unit and grabbing the // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. -//---------------------------------------------------------------------- DWARFDIE DWARFUnit::GetDIE(dw_offset_t die_offset) { if (die_offset != DW_INVALID_OFFSET) { @@ -608,28 +470,26 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) { if (die_offset == (*pos).GetOffset()) return DWARFDIE(this, &(*pos)); } - } else { - // Don't specify the compile unit offset as we don't know it because the - // DIE belongs to - // a different compile unit in the same symbol file. - return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset); - } + } else + GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "GetDIE for DIE 0x%" PRIx32 " is outside of its CU 0x%" PRIx32, + die_offset, GetOffset()); } return DWARFDIE(); // Not found } +DWARFUnit &DWARFUnit::GetNonSkeletonUnit() { + if (SymbolFileDWARFDwo *dwo = GetDwoSymbolFile()) + return *dwo->GetCompileUnit(); + return *this; +} + uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { if (cu) return cu->GetAddressByteSize(); return DWARFUnit::GetDefaultAddressSize(); } -bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { - if (cu) - return cu->IsDWARF64(); - return false; -} - uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } void *DWARFUnit::GetUserData() const { return m_user_data; } @@ -660,8 +520,6 @@ bool DWARFUnit::Supports_unnamed_objc_bitfields() { // info } -SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; } - void DWARFUnit::ParseProducerInfo() { m_producer_version_major = UINT32_MAX; m_producer_version_minor = UINT32_MAX; @@ -671,7 +529,7 @@ void DWARFUnit::ParseProducerInfo() { if (die) { const char *producer_cstr = - die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL); + die->GetAttributeValueAsString(this, DW_AT_producer, nullptr); if (producer_cstr) { RegularExpression llvm_gcc_regex( llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " @@ -748,7 +606,7 @@ LanguageType DWARFUnit::GetLanguageType() { const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); if (die) m_language_type = LanguageTypeFromDWARF( - die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0)); + die->GetAttributeValueAsUnsigned(this, DW_AT_language, 0)); return m_language_type; } @@ -757,8 +615,8 @@ bool DWARFUnit::GetIsOptimized() { const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); if (die) { m_is_optimized = eLazyBoolNo; - if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized, - 0) == 1) { + if (die->GetAttributeValueAsUnsigned(this, DW_AT_APPLE_optimized, 0) == + 1) { m_is_optimized = eLazyBoolYes; } } @@ -766,40 +624,255 @@ bool DWARFUnit::GetIsOptimized() { return m_is_optimized == eLazyBoolYes; } +FileSpec::Style DWARFUnit::GetPathStyle() { + if (!m_comp_dir) + ComputeCompDirAndGuessPathStyle(); + return m_comp_dir->GetPathStyle(); +} + +const FileSpec &DWARFUnit::GetCompilationDirectory() { + if (!m_comp_dir) + ComputeCompDirAndGuessPathStyle(); + return *m_comp_dir; +} + +const FileSpec &DWARFUnit::GetAbsolutePath() { + if (!m_file_spec) + ComputeAbsolutePath(); + return *m_file_spec; +} + +FileSpec DWARFUnit::GetFile(size_t file_idx) { + return m_dwarf.GetFile(*this, file_idx); +} + +// DWARF2/3 suggests the form hostname:pathname for compilation directory. +// Remove the host part if present. +static llvm::StringRef +removeHostnameFromPathname(llvm::StringRef path_from_dwarf) { + llvm::StringRef host, path; + std::tie(host, path) = path_from_dwarf.split(':'); + + if (host.contains('/')) + return path_from_dwarf; + + // check whether we have a windows path, and so the first character is a + // drive-letter not a hostname. + if (host.size() == 1 && llvm::isAlpha(host[0]) && path.startswith("\\")) + return path_from_dwarf; + + return path; +} + +static FileSpec resolveCompDir(const FileSpec &path) { + bool is_symlink = SymbolFileDWARF::GetSymlinkPaths().FindFileIndex( + 0, path, /*full*/ true) != UINT32_MAX; + + if (!is_symlink) + return path; + + namespace fs = llvm::sys::fs; + if (fs::get_file_type(path.GetPath(), false) != fs::file_type::symlink_file) + return path; + + FileSpec resolved_symlink; + const auto error = FileSystem::Instance().Readlink(path, resolved_symlink); + if (error.Success()) + return resolved_symlink; + + return path; +} + +void DWARFUnit::ComputeCompDirAndGuessPathStyle() { + m_comp_dir = FileSpec(); + const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); + if (!die) + return; + + llvm::StringRef comp_dir = removeHostnameFromPathname( + die->GetAttributeValueAsString(this, DW_AT_comp_dir, nullptr)); + if (!comp_dir.empty()) { + FileSpec::Style comp_dir_style = + FileSpec::GuessPathStyle(comp_dir).getValueOr(FileSpec::Style::native); + m_comp_dir = resolveCompDir(FileSpec(comp_dir, comp_dir_style)); + } else { + // Try to detect the style based on the DW_AT_name attribute, but just store + // the detected style in the m_comp_dir field. + const char *name = + die->GetAttributeValueAsString(this, DW_AT_name, nullptr); + m_comp_dir = FileSpec( + "", FileSpec::GuessPathStyle(name).getValueOr(FileSpec::Style::native)); + } +} + +void DWARFUnit::ComputeAbsolutePath() { + m_file_spec = FileSpec(); + const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); + if (!die) + return; + + m_file_spec = + FileSpec(die->GetAttributeValueAsString(this, DW_AT_name, nullptr), + GetPathStyle()); + + if (m_file_spec->IsRelative()) + m_file_spec->MakeAbsolute(GetCompilationDirectory()); +} + SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { return m_dwo_symbol_file.get(); } -dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } - const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { - if (m_func_aranges_ap.get() == NULL) { - m_func_aranges_ap.reset(new DWARFDebugAranges()); - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); - - if (log) { - m_dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "DWARFUnit::GetFunctionAranges() for compile unit at " - ".debug_info[0x%8.8x]", - GetOffset()); - } + if (m_func_aranges_up == nullptr) { + m_func_aranges_up.reset(new DWARFDebugAranges()); const DWARFDebugInfoEntry *die = DIEPtr(); if (die) - die->BuildFunctionAddressRangeTable(m_dwarf, this, - m_func_aranges_ap.get()); + die->BuildFunctionAddressRangeTable(this, m_func_aranges_up.get()); if (m_dwo_symbol_file) { DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); if (dwo_die) - dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, - m_func_aranges_ap.get()); + dwo_die->BuildFunctionAddressRangeTable(dwo_cu, + m_func_aranges_up.get()); } const bool minimize = false; - m_func_aranges_ap->Sort(minimize); + m_func_aranges_up->Sort(minimize); + } + return *m_func_aranges_up; +} + +llvm::Expected<DWARFUnitHeader> +DWARFUnitHeader::extract(const DWARFDataExtractor &data, DIERef::Section section, + lldb::offset_t *offset_ptr) { + DWARFUnitHeader header; + header.m_offset = *offset_ptr; + header.m_length = data.GetDWARFInitialLength(offset_ptr); + header.m_version = data.GetU16(offset_ptr); + if (header.m_version == 5) { + header.m_unit_type = data.GetU8(offset_ptr); + header.m_addr_size = data.GetU8(offset_ptr); + header.m_abbr_offset = data.GetDWARFOffset(offset_ptr); + if (header.m_unit_type == llvm::dwarf::DW_UT_skeleton) + header.m_dwo_id = data.GetU64(offset_ptr); + } else { + header.m_abbr_offset = data.GetDWARFOffset(offset_ptr); + header.m_addr_size = data.GetU8(offset_ptr); + header.m_unit_type = + section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile; + } + + if (header.IsTypeUnit()) { + header.m_type_hash = data.GetU64(offset_ptr); + header.m_type_offset = data.GetDWARFOffset(offset_ptr); + } + + bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); + bool version_OK = SymbolFileDWARF::SupportedVersion(header.m_version); + bool addr_size_OK = (header.m_addr_size == 4) || (header.m_addr_size == 8); + bool type_offset_OK = + !header.IsTypeUnit() || (header.m_type_offset <= header.GetLength()); + + if (!length_OK) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Invalid unit length"); + if (!version_OK) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Unsupported unit version"); + if (!addr_size_OK) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Invalid unit address size"); + if (!type_offset_OK) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Type offset out of range"); + + return header; +} + +llvm::Expected<DWARFUnitSP> +DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, + const DWARFDataExtractor &debug_info, + DIERef::Section section, lldb::offset_t *offset_ptr) { + assert(debug_info.ValidOffset(*offset_ptr)); + + auto expected_header = + DWARFUnitHeader::extract(debug_info, section, offset_ptr); + if (!expected_header) + return expected_header.takeError(); + + const DWARFDebugAbbrev *abbr = dwarf.DebugAbbrev(); + if (!abbr) + return llvm::make_error<llvm::object::GenericBinaryError>( + "No debug_abbrev data"); + + bool abbr_offset_OK = + dwarf.GetDWARFContext().getOrLoadAbbrevData().ValidOffset( + expected_header->GetAbbrOffset()); + if (!abbr_offset_OK) + return llvm::make_error<llvm::object::GenericBinaryError>( + "Abbreviation offset for unit is not valid"); + + const DWARFAbbreviationDeclarationSet *abbrevs = + abbr->GetAbbreviationDeclarationSet(expected_header->GetAbbrOffset()); + if (!abbrevs) + return llvm::make_error<llvm::object::GenericBinaryError>( + "No abbrev exists at the specified offset."); + + if (expected_header->IsTypeUnit()) + return DWARFUnitSP( + new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs, section)); + return DWARFUnitSP( + new DWARFCompileUnit(dwarf, uid, *expected_header, *abbrevs, section)); +} + +const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const { + return m_section == DIERef::Section::DebugTypes + ? m_dwarf.GetDWARFContext().getOrLoadDebugTypesData() + : m_dwarf.GetDWARFContext().getOrLoadDebugInfoData(); +} + +uint32_t DWARFUnit::GetHeaderByteSize() const { + switch (m_header.GetUnitType()) { + case llvm::dwarf::DW_UT_compile: + case llvm::dwarf::DW_UT_partial: + return GetVersion() < 5 ? 11 : 12; + case llvm::dwarf::DW_UT_skeleton: + case llvm::dwarf::DW_UT_split_compile: + return 20; + case llvm::dwarf::DW_UT_type: + case llvm::dwarf::DW_UT_split_type: + return GetVersion() < 5 ? 23 : 24; } - return *m_func_aranges_ap.get(); + llvm_unreachable("invalid UnitType."); +} + +llvm::Expected<DWARFRangeList> +DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const { + const DWARFDebugRangesBase *debug_ranges; + llvm::StringRef section; + if (GetVersion() <= 4) { + debug_ranges = m_dwarf.GetDebugRanges(); + section = "debug_ranges"; + } else { + debug_ranges = m_dwarf.GetDebugRngLists(); + section = "debug_rnglists"; + } + if (!debug_ranges) + return llvm::make_error<llvm::object::GenericBinaryError>("No " + section + + " section"); + + DWARFRangeList ranges; + debug_ranges->FindRanges(this, offset, ranges); + return ranges; } +llvm::Expected<DWARFRangeList> +DWARFUnit::FindRnglistFromIndex(uint32_t index) const { + const DWARFDebugRangesBase *debug_rnglists = m_dwarf.GetDebugRngLists(); + if (!debug_rnglists) + return llvm::make_error<llvm::object::GenericBinaryError>( + "No debug_rnglists section"); + return FindRnglistFromOffset(debug_rnglists->GetOffset(index)); +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 178c894686ee..8aa1e449f3ed 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -1,9 +1,8 @@ //===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -32,11 +31,52 @@ enum DWARFProducer { eProcucerOther }; -class DWARFUnit { +/// Base class describing the header of any kind of "unit." Some information +/// is specific to certain unit types. We separate this class out so we can +/// parse the header before deciding what specific kind of unit to construct. +class DWARFUnitHeader { + dw_offset_t m_offset = 0; + dw_offset_t m_length = 0; + uint16_t m_version = 0; + dw_offset_t m_abbr_offset = 0; + uint8_t m_unit_type = 0; + uint8_t m_addr_size = 0; + + uint64_t m_type_hash = 0; + uint32_t m_type_offset = 0; + + uint64_t m_dwo_id = 0; + + DWARFUnitHeader() = default; + +public: + dw_offset_t GetOffset() const { return m_offset; } + uint16_t GetVersion() const { return m_version; } + uint16_t GetAddressByteSize() const { return m_addr_size; } + dw_offset_t GetLength() const { return m_length; } + dw_offset_t GetAbbrOffset() const { return m_abbr_offset; } + uint8_t GetUnitType() const { return m_unit_type; } + uint64_t GetTypeHash() const { return m_type_hash; } + dw_offset_t GetTypeOffset() const { return m_type_offset; } + bool IsTypeUnit() const { + return m_unit_type == DW_UT_type || m_unit_type == DW_UT_split_type; + } + uint32_t GetNextUnitOffset() const { return m_offset + m_length + 4; } + + static llvm::Expected<DWARFUnitHeader> + extract(const lldb_private::DWARFDataExtractor &data, DIERef::Section section, + lldb::offset_t *offset_ptr); +}; + +class DWARFUnit : public lldb_private::UserID { using die_iterator_range = llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>; public: + static llvm::Expected<DWARFUnitSP> + extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid, + const lldb_private::DWARFDataExtractor &debug_info, + DIERef::Section section, lldb::offset_t *offset_ptr); virtual ~DWARFUnit(); void ExtractUnitDIEIfNeeded(); @@ -46,7 +86,7 @@ public: DWARFUnit *m_cu; public: bool m_clear_dies = false; - ScopedExtractDIEs(DWARFUnit *cu); + ScopedExtractDIEs(DWARFUnit &cu); ~ScopedExtractDIEs(); DISALLOW_COPY_AND_ASSIGN(ScopedExtractDIEs); ScopedExtractDIEs(ScopedExtractDIEs &&rhs); @@ -55,69 +95,61 @@ public: ScopedExtractDIEs ExtractDIEsScoped(); DWARFDIE LookupAddress(const dw_addr_t address); - size_t AppendDIEsWithTag(const dw_tag_t tag, - DWARFDIECollection &matching_dies, + size_t AppendDIEsWithTag(const dw_tag_t tag, std::vector<DWARFDIE> &dies, uint32_t depth = UINT32_MAX) const; bool Verify(lldb_private::Stream *s) const; virtual void Dump(lldb_private::Stream *s) const = 0; - //------------------------------------------------------------------ /// Get the data that contains the DIE information for this unit. /// /// This will return the correct bytes that contain the data for /// this DWARFUnit. It could be .debug_info or .debug_types /// depending on where the data for this unit originates. /// - /// @return + /// \return /// The correct data for the DIE information in this unit. - //------------------------------------------------------------------ - virtual const lldb_private::DWARFDataExtractor &GetData() const = 0; - //------------------------------------------------------------------ - /// Get the size in bytes of the compile unit header. + const lldb_private::DWARFDataExtractor &GetData() const; + + /// Get the size in bytes of the unit header. /// - /// @return - /// Byte size of the compile unit header - //------------------------------------------------------------------ - virtual uint32_t GetHeaderByteSize() const = 0; + /// \return + /// Byte size of the unit header + uint32_t GetHeaderByteSize() const; + // Offset of the initial length field. - dw_offset_t GetOffset() const { return m_offset; } - lldb::user_id_t GetID() const; - //------------------------------------------------------------------ + dw_offset_t GetOffset() const { return m_header.GetOffset(); } /// Get the size in bytes of the length field in the header. /// - /// In DWARF32 this is just 4 bytes, and DWARF64 it is 12 where 4 - /// are 0xFFFFFFFF followed by the actual 64 bit length. + /// In DWARF32 this is just 4 bytes /// - /// @return + /// \return /// Byte size of the compile unit header length field - //------------------------------------------------------------------ - size_t GetLengthByteSize() const { return IsDWARF64() ? 12 : 4; } - + size_t GetLengthByteSize() const { return 4; } + bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && - die_offset < GetNextCompileUnitOffset(); + die_offset < GetNextUnitOffset(); } dw_offset_t GetFirstDIEOffset() const { - return m_offset + GetHeaderByteSize(); + return GetOffset() + GetHeaderByteSize(); } - dw_offset_t GetNextCompileUnitOffset() const; + dw_offset_t GetNextUnitOffset() const { return m_header.GetNextUnitOffset(); } // Size of the CU data (without initial length and without header). size_t GetDebugInfoSize() const; // Size of the CU data incl. header but without initial length. - uint32_t GetLength() const { return m_length; } - uint16_t GetVersion() const { return m_version; } + uint32_t GetLength() const { return m_header.GetLength(); } + uint16_t GetVersion() const { return m_header.GetVersion(); } const DWARFAbbreviationDeclarationSet *GetAbbreviations() const; dw_offset_t GetAbbrevOffset() const; - uint8_t GetAddressByteSize() const { return m_addr_size; } - dw_addr_t GetBaseAddress() const { return m_base_addr; } + uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); } dw_addr_t GetAddrBase() const { return m_addr_base; } + dw_addr_t GetBaseAddress() const { return m_base_addr; } + dw_offset_t GetLineTableOffset(); dw_addr_t GetRangesBase() const { return m_ranges_base; } dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; } void SetAddrBase(dw_addr_t addr_base); void SetRangesBase(dw_addr_t ranges_base); - void SetBaseObjOffset(dw_offset_t base_obj_offset); void SetStrOffsetsBase(dw_offset_t str_offsets_base); - void BuildAddressRangeTable(SymbolFileDWARF *dwarf, - DWARFDebugAranges *debug_aranges); + virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0; lldb::ByteOrder GetByteOrder() const; @@ -125,8 +157,6 @@ public: const DWARFDebugAranges &GetFunctionAranges(); - DWARFFormValue::FixedFormSizes GetFixedFormSizes(); - void SetBaseAddress(dw_addr_t base_addr); DWARFBaseDIE GetUnitDIEOnly() { return DWARFDIE(this, GetUnitDIEPtrOnly()); } @@ -135,9 +165,9 @@ public: DWARFDIE GetDIE(dw_offset_t die_offset); - static uint8_t GetAddressByteSize(const DWARFUnit *cu); + DWARFUnit &GetNonSkeletonUnit(); - static bool IsDWARF64(const DWARFUnit *cu); + static uint8_t GetAddressByteSize(const DWARFUnit *cu); static uint8_t GetDefaultAddressSize(); @@ -151,7 +181,7 @@ public: bool Supports_unnamed_objc_bitfields(); - SymbolFileDWARF *GetSymbolFileDWARF() const; + SymbolFileDWARF &GetSymbolFileDWARF() const { return m_dwarf; } DWARFProducer GetProducer(); @@ -165,24 +195,65 @@ public: lldb::LanguageType GetLanguageType(); - bool IsDWARF64() const { return m_is_dwarf64; } - bool GetIsOptimized(); - SymbolFileDWARFDwo *GetDwoSymbolFile() const; + const lldb_private::FileSpec &GetCompilationDirectory(); + const lldb_private::FileSpec &GetAbsolutePath(); + lldb_private::FileSpec GetFile(size_t file_idx); + lldb_private::FileSpec::Style GetPathStyle(); - dw_offset_t GetBaseObjOffset() const; + SymbolFileDWARFDwo *GetDwoSymbolFile() const; die_iterator_range dies() { ExtractDIEsIfNeeded(); return die_iterator_range(m_die_array.begin(), m_die_array.end()); } + DIERef::Section GetDebugSection() const { return m_section; } + + uint8_t GetUnitType() const { return m_header.GetUnitType(); } + bool IsTypeUnit() const { return m_header.IsTypeUnit(); } + + /// Return a list of address ranges resulting from a (possibly encoded) + /// range list starting at a given offset in the appropriate ranges section. + llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset) const; + + /// Return a list of address ranges retrieved from an encoded range + /// list whose offset is found via a table lookup given an index (DWARF v5 + /// and later). + llvm::Expected<DWARFRangeList> FindRnglistFromIndex(uint32_t index) const; + protected: - DWARFUnit(SymbolFileDWARF *dwarf); + DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, + const DWARFUnitHeader &header, + const DWARFAbbreviationDeclarationSet &abbrevs, + DIERef::Section section); + + llvm::Error ExtractHeader(SymbolFileDWARF &dwarf, + const lldb_private::DWARFDataExtractor &data, + lldb::offset_t *offset_ptr); + + // Get the DWARF unit DWARF debug information entry. Parse the single DIE + // if needed. + const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() { + ExtractUnitDIEIfNeeded(); + // m_first_die_mutex is not required as m_first_die is never cleared. + if (!m_first_die) + return NULL; + return &m_first_die; + } + + // Get all DWARF debug informration entries. Parse all DIEs if needed. + const DWARFDebugInfoEntry *DIEPtr() { + ExtractDIEsIfNeeded(); + if (m_die_array.empty()) + return NULL; + return &m_die_array[0]; + } - SymbolFileDWARF *m_dwarf = nullptr; + SymbolFileDWARF &m_dwarf; std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file; + DWARFUnitHeader m_header; const DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr; void *m_user_data = nullptr; // The compile unit debug information entry item @@ -200,54 +271,34 @@ protected: llvm::sys::RWMutex m_first_die_mutex; // A table similar to the .debug_aranges table, but this one points to the // exact DW_TAG_subprogram DIEs - std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap; + std::unique_ptr<DWARFDebugAranges> m_func_aranges_up; dw_addr_t m_base_addr = 0; - dw_offset_t m_length = 0; - uint16_t m_version = 0; - uint8_t m_addr_size = 0; - uint8_t m_unit_type = 0; - uint64_t m_dwo_id = 0; DWARFProducer m_producer = eProducerInvalid; uint32_t m_producer_version_major = 0; uint32_t m_producer_version_minor = 0; uint32_t m_producer_version_update = 0; lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown; - bool m_is_dwarf64 = false; lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; + llvm::Optional<lldb_private::FileSpec> m_comp_dir; + llvm::Optional<lldb_private::FileSpec> m_file_spec; dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base - // If this is a dwo compile unit this is the offset of the base compile unit - // in the main object file - dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET; + + /// Value of DW_AT_stmt_list. + dw_offset_t m_line_table_offset = DW_INVALID_OFFSET; + dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. - // Offset of the initial length field. - dw_offset_t m_offset; + const DIERef::Section m_section; private: void ParseProducerInfo(); void ExtractDIEsRWLocked(); void ClearDIEsRWLocked(); - // Get the DWARF unit DWARF debug informration entry. Parse the single DIE - // if needed. - const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() { - ExtractUnitDIEIfNeeded(); - // m_first_die_mutex is not required as m_first_die is never cleared. - if (!m_first_die) - return NULL; - return &m_first_die; - } - - // Get all DWARF debug informration entries. Parse all DIEs if needed. - const DWARFDebugInfoEntry *DIEPtr() { - ExtractDIEsIfNeeded(); - if (m_die_array.empty()) - return NULL; - return &m_die_array[0]; - } - void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); - void ExtractDIEsEndCheck(lldb::offset_t offset) const; + + void ComputeCompDirAndGuessPathStyle(); + void ComputeAbsolutePath(); DISALLOW_COPY_AND_ASSIGN(DWARFUnit); }; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index c043272f8a3e..9746ad76c930 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -1,9 +1,8 @@ //===-- DebugNamesDWARFIndex.cpp -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -17,13 +16,6 @@ using namespace lldb_private; using namespace lldb; -static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data) { - return llvm::DWARFDataExtractor( - llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()), - data.GetByteSize()), - data.GetByteOrder() == eByteOrderLittle, data.GetAddressByteSize()); -} - llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, @@ -32,8 +24,8 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, return llvm::make_error<llvm::StringError>("debug info null", llvm::inconvertibleErrorCode()); } - auto index_up = - llvm::make_unique<DebugNames>(ToLLVM(debug_names), ToLLVM(debug_str)); + auto index_up = llvm::make_unique<DebugNames>(debug_names.GetAsLLVM(), + debug_str.GetAsLLVM()); if (llvm::Error E = index_up->extract()) return std::move(E); @@ -51,31 +43,33 @@ DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { return result; } -DIERef DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) { +llvm::Optional<DIERef> +DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) { llvm::Optional<uint64_t> cu_offset = entry.getCUOffset(); if (!cu_offset) - return DIERef(); + return llvm::None; - DWARFUnit *cu = m_debug_info.GetCompileUnit(*cu_offset); + DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset); if (!cu) - return DIERef(); + return llvm::None; // This initializes the DWO symbol file. It's not possible for // GetDwoSymbolFile to call this automatically because of mutual recursion // between this and DWARFDebugInfoEntry::GetAttributeValue. cu->ExtractUnitDIEIfNeeded(); - uint64_t die_bias = cu->GetDwoSymbolFile() ? 0 : *cu_offset; + cu = &cu->GetNonSkeletonUnit(); if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset()) - return DIERef(*cu_offset, die_bias + *die_offset); + return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(), + DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset); - return DIERef(); + return llvm::None; } void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry, DIEArray &offsets) { - if (DIERef ref = ToDIERef(entry)) - offsets.push_back(ref); + if (llvm::Optional<DIERef> ref = ToDIERef(entry)) + offsets.push_back(*ref); } void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error, @@ -161,27 +155,27 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name, entry.tag() != DW_TAG_class_type) continue; - DIERef ref = ToDIERef(entry); + llvm::Optional<DIERef> ref = ToDIERef(entry); if (!ref) continue; - DWARFUnit *cu = m_debug_info.GetCompileUnit(ref.cu_offset); + DWARFUnit *cu = m_debug_info.GetUnit(*ref); if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) { - incomplete_types.push_back(ref); + incomplete_types.push_back(*ref); continue; } // FIXME: We should return DWARFDIEs so we don't have to resolve it twice. - DWARFDIE die = m_debug_info.GetDIE(ref); + DWARFDIE die = m_debug_info.GetDIE(*ref); if (!die) continue; if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) { // If we find the complete version we're done. - offsets.push_back(ref); + offsets.push_back(*ref); return; } else { - incomplete_types.push_back(ref); + incomplete_types.push_back(*ref); } } @@ -221,12 +215,12 @@ void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { } void DebugNamesDWARFIndex::GetFunctions( - ConstString name, DWARFDebugInfo &info, + ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) { std::vector<DWARFDIE> v; - m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, v); + m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask, v); for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name.GetStringRef())) { @@ -234,8 +228,8 @@ void DebugNamesDWARFIndex::GetFunctions( if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) continue; - if (DIERef ref = ToDIERef(entry)) - ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx, + if (llvm::Optional<DIERef> ref = ToDIERef(entry)) + ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx, name_type_mask, v); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h index 30423c7ca2a2..dca25496373f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -1,9 +1,8 @@ //===-- DebugNamesDWARFIndex.h ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -35,15 +34,14 @@ public: void GetTypes(ConstString name, DIEArray &offsets) override; void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override; void GetNamespaces(ConstString name, DIEArray &offsets) override; - void GetFunctions(ConstString name, DWARFDebugInfo &info, + void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) override; void GetFunctions(const RegularExpression ®ex, DIEArray &offsets) override; - void ReportInvalidDIEOffset(dw_offset_t offset, - llvm::StringRef name) override {} + void ReportInvalidDIERef(const DIERef &ref, llvm::StringRef name) override {} void Dump(Stream &s) override; private: @@ -68,7 +66,7 @@ private: std::unique_ptr<DebugNames> m_debug_names_up; ManualDWARFIndex m_fallback; - DIERef ToDIERef(const DebugNames::Entry &entry); + llvm::Optional<DIERef> ToDIERef(const DebugNames::Entry &entry); void Append(const DebugNames::Entry &entry, DIEArray &offsets); static void MaybeLogLookupError(llvm::Error error, diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index f83ba6663dfc..62b0ad37a9fc 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -1,9 +1,8 @@ //===-- HashedNameToDIE.cpp -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -14,8 +13,7 @@ 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.emplace_back(die_info_array[i].cu_offset, - die_info_array[i].offset); + die_offsets.emplace_back(die_info_array[i]); } void DWARFMappedHash::ExtractDIEArray(const DIEInfoArray &die_info_array, @@ -34,8 +32,7 @@ void DWARFMappedHash::ExtractDIEArray(const DIEInfoArray &die_info_array, tag == DW_TAG_structure_type || tag == DW_TAG_class_type; } if (tag_matches) - die_offsets.emplace_back(die_info_array[i].cu_offset, - die_info_array[i].offset); + die_offsets.emplace_back(die_info_array[i]); } } } @@ -59,8 +56,7 @@ void DWARFMappedHash::ExtractDIEArray(const DIEInfoArray &die_info_array, tag == DW_TAG_structure_type || tag == DW_TAG_class_type; } if (tag_matches) - die_offsets.emplace_back(die_info_array[i].cu_offset, - die_info_array[i].offset); + die_offsets.emplace_back(die_info_array[i]); } } } @@ -78,17 +74,14 @@ void DWARFMappedHash::ExtractClassOrStructDIEArray( // We found the one true definition for this class, so only return // that die_offsets.clear(); - die_offsets.emplace_back(die_info_array[i].cu_offset, - die_info_array[i].offset); + die_offsets.emplace_back(die_info_array[i]); return; } else { // Put the one true definition as the first entry so it matches first - die_offsets.emplace(die_offsets.begin(), die_info_array[i].cu_offset, - die_info_array[i].offset); + die_offsets.emplace(die_offsets.begin(), die_info_array[i]); } } else { - die_offsets.emplace_back(die_info_array[i].cu_offset, - die_info_array[i].offset); + die_offsets.emplace_back(die_info_array[i]); } } } @@ -100,8 +93,7 @@ void DWARFMappedHash::ExtractTypesFromDIEArray( 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.emplace_back(die_info_array[i].cu_offset, - die_info_array[i].offset); + die_offsets.emplace_back(die_info_array[i]); } } @@ -125,13 +117,9 @@ const char *DWARFMappedHash::GetAtomTypeName(uint16_t atom) { return "<invalid>"; } -DWARFMappedHash::DIEInfo::DIEInfo() - : cu_offset(DW_INVALID_OFFSET), offset(DW_INVALID_OFFSET), tag(0), - type_flags(0), qualified_name_hash(0) {} - -DWARFMappedHash::DIEInfo::DIEInfo(dw_offset_t c, dw_offset_t o, dw_tag_t t, - uint32_t f, uint32_t h) - : cu_offset(c), offset(o), tag(t), type_flags(f), qualified_name_hash(h) {} +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(), atom_mask(0), @@ -167,6 +155,7 @@ void DWARFMappedHash::Prologue::AppendAtom(AtomType type, dw_form_t form) { 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: @@ -271,14 +260,14 @@ bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data, return false; for (size_t i = 0; i < num_atoms; ++i) { - DWARFFormValue form_value(NULL, header_data.atoms[i].form); + 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.offset = + hash_data.die_offset = DWARFFormValue::IsDataForm(form_value.Form()) ? form_value.Unsigned() : form_value.Reference(header_data.die_base_offset); @@ -301,50 +290,7 @@ bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data, 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; - } - } + return hash_data.die_offset != DW_INVALID_OFFSET; } DWARFMappedHash::MemoryTable::MemoryTable( @@ -391,7 +337,7 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( // 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) { + if (strp_cstr == nullptr) { *hash_data_offset_ptr = UINT32_MAX; return eResultError; } @@ -458,7 +404,7 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( // 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) + if (strp_cstr == nullptr) return eResultError; const uint32_t count = m_data.GetU32(hash_data_offset_ptr); @@ -556,10 +502,10 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsInRange( 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) + if (die_info.die_offset == 0) done = true; - if (die_offset_start <= die_info.offset && - die_info.offset < die_offset_end) + if (die_offset_start <= die_info.die_offset && + die_info.die_offset < die_offset_end) die_info_array.push_back(die_info); } } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index 17600df2edd4..a01612b59528 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -1,9 +1,8 @@ //===-- HashedNameToDIE.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -49,14 +48,21 @@ public: }; struct DIEInfo { - dw_offset_t cu_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 - - DIEInfo(); - DIEInfo(dw_offset_t c, dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h); + dw_offset_t die_offset = DW_INVALID_OFFSET; + dw_tag_t tag = 0; + + /// 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(llvm::None, DIERef::Section::DebugInfo, die_offset); + } }; struct Atom { @@ -105,8 +111,6 @@ public: bool Read(const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr, DIEInfo &hash_data) const; - - void 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 diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp index 0b06713f9543..8495016d4280 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp @@ -1,9 +1,8 @@ //===-- LogChannelDWARF.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,9 +11,6 @@ using namespace lldb_private; static constexpr Log::Category g_categories[] = { - {{"aranges"}, - {"log the parsing of .debug_aranges"}, - DWARF_LOG_DEBUG_ARANGES}, {{"comp"}, {"log insertions of object files into DWARF debug maps"}, DWARF_LOG_TYPE_COMPLETION}, @@ -26,12 +22,6 @@ static constexpr Log::Category g_categories[] = { {{"map"}, {"log struct/unions/class type completions"}, DWARF_LOG_DEBUG_MAP}, - {{"pubnames"}, - {"log the parsing of .debug_pubnames"}, - DWARF_LOG_DEBUG_PUBNAMES}, - {{"pubtypes"}, - {"log the parsing of .debug_pubtypes"}, - DWARF_LOG_DEBUG_PUBTYPES}, }; Log::Channel LogChannelDWARF::g_channel(g_categories, DWARF_LOG_DEFAULT); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h index 038e9b8c2b08..a89c686735d2 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h @@ -1,9 +1,8 @@ //===-- LogChannelDWARF.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -14,12 +13,9 @@ #define DWARF_LOG_DEBUG_INFO (1u << 1) #define DWARF_LOG_DEBUG_LINE (1u << 2) -#define DWARF_LOG_DEBUG_PUBNAMES (1u << 3) -#define DWARF_LOG_DEBUG_PUBTYPES (1u << 4) -#define DWARF_LOG_DEBUG_ARANGES (1u << 5) -#define DWARF_LOG_LOOKUPS (1u << 6) -#define DWARF_LOG_TYPE_COMPLETION (1u << 7) -#define DWARF_LOG_DEBUG_MAP (1u << 8) +#define DWARF_LOG_LOOKUPS (1u << 3) +#define DWARF_LOG_TYPE_COMPLETION (1u << 4) +#define DWARF_LOG_DEBUG_MAP (1u << 5) #define DWARF_LOG_ALL (UINT32_MAX) #define DWARF_LOG_DEFAULT (DWARF_LOG_DEBUG_INFO) diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index 6438f02fe8ec..aff8b5d8c15f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -1,9 +1,8 @@ //===-- ManualDWARFIndex.cpp -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -33,9 +32,9 @@ void ManualDWARFIndex::Index() { Timer scoped_timer(func_cat, "%p", static_cast<void *>(&debug_info)); std::vector<DWARFUnit *> units_to_index; - units_to_index.reserve(debug_info.GetNumCompileUnits()); - for (size_t U = 0; U < debug_info.GetNumCompileUnits(); ++U) { - DWARFUnit *unit = debug_info.GetCompileUnitAtIndex(U); + units_to_index.reserve(debug_info.GetNumUnits()); + for (size_t U = 0; U < debug_info.GetNumUnits(); ++U) { + DWARFUnit *unit = debug_info.GetUnitAtIndex(U); if (unit && m_units_to_avoid.count(unit->GetOffset()) == 0) units_to_index.push_back(unit); } @@ -44,10 +43,8 @@ void ManualDWARFIndex::Index() { std::vector<IndexSet> sets(units_to_index.size()); - //---------------------------------------------------------------------- - // Keep memory down by clearing DIEs for any compile units if indexing - // caused us to load the compile unit's DIEs. - //---------------------------------------------------------------------- + // Keep memory down by clearing DIEs for any units if indexing + // caused us to load the unit's DIEs. std::vector<llvm::Optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies( units_to_index.size()); auto parser_fn = [&](size_t cu_idx) { @@ -58,19 +55,17 @@ void ManualDWARFIndex::Index() { clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped(); }; - // Create a task runner that extracts dies for each DWARF compile unit in a + // Create a task runner that extracts dies for each DWARF unit in a // separate thread - //---------------------------------------------------------------------- - // First figure out which compile units didn't have their DIEs already + // First figure out which units didn't have their DIEs already // parsed and remember this. If no DIEs were parsed prior to this index // function call, we are going to want to clear the CU dies after we are // done indexing to make sure we don't pull in all DWARF dies, but we need - // to wait until all compile units have been indexed in case a DIE in one - // compile unit refers to another and the indexes accesses those DIEs. - //---------------------------------------------------------------------- + // to wait until all units have been indexed in case a DIE in one + // unit refers to another and the indexes accesses those DIEs. TaskMapOverInt(0, units_to_index.size(), extract_fn); - // Now create a task runner that can index each DWARF compile unit in a + // Now create a task runner that can index each DWARF unit in a // separate thread so we can index quickly. TaskMapOverInt(0, units_to_index.size(), parser_fn); @@ -93,30 +88,32 @@ void ManualDWARFIndex::Index() { } void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, IndexSet &set) { + assert( + !unit.GetSymbolFileDWARF().GetBaseCompileUnit() && + "DWARFUnit associated with .dwo or .dwp should not be indexed directly"); + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS); if (log) { m_module.LogMessage( - log, "ManualDWARFIndex::IndexUnit for compile unit at .debug_info[0x%8.8x]", + log, "ManualDWARFIndex::IndexUnit for unit at .debug_info[0x%8.8x]", unit.GetOffset()); } const LanguageType cu_language = unit.GetLanguageType(); - DWARFFormValue::FixedFormSizes fixed_form_sizes = unit.GetFixedFormSizes(); - IndexUnitImpl(unit, cu_language, fixed_form_sizes, unit.GetOffset(), set); + IndexUnitImpl(unit, cu_language, set); - SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile(); - if (dwo_symbol_file && dwo_symbol_file->GetCompileUnit()) { - IndexUnitImpl(*dwo_symbol_file->GetCompileUnit(), cu_language, - fixed_form_sizes, unit.GetOffset(), set); + if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) { + DWARFDebugInfo &dwo_info = *dwo_symbol_file->DebugInfo(); + for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i) + IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set); } } -void ManualDWARFIndex::IndexUnitImpl( - DWARFUnit &unit, const LanguageType cu_language, - const DWARFFormValue::FixedFormSizes &fixed_form_sizes, - const dw_offset_t cu_offset, IndexSet &set) { +void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit, + const LanguageType cu_language, + IndexSet &set) { for (const DWARFDebugInfoEntry &die : unit.dies()) { const dw_tag_t tag = die.Tag(); @@ -143,8 +140,8 @@ void ManualDWARFIndex::IndexUnitImpl( } DWARFAttributes attributes; - const char *name = NULL; - const char *mangled_cstr = NULL; + const char *name = nullptr; + const char *mangled_cstr = nullptr; bool is_declaration = false; // bool is_artificial = false; bool has_address = false; @@ -152,8 +149,7 @@ void ManualDWARFIndex::IndexUnitImpl( bool is_global_or_static_variable = false; DWARFFormValue specification_die_form; - const size_t num_attributes = - die.GetAttributes(&unit, fixed_form_sizes, attributes); + const size_t num_attributes = die.GetAttributes(&unit, attributes); if (num_attributes > 0) { for (uint32_t i = 0; i < num_attributes; ++i) { dw_attr_t attr = attributes.AttributeAtIndex(i); @@ -196,7 +192,7 @@ void ManualDWARFIndex::IndexUnitImpl( has_location_or_const_value = true; if (tag == DW_TAG_variable) { const DWARFDebugInfoEntry *parent_die = die.GetParent(); - while (parent_die != NULL) { + while (parent_die != nullptr) { switch (parent_die->Tag()) { case DW_TAG_subprogram: case DW_TAG_lexical_block: @@ -215,19 +211,19 @@ void ManualDWARFIndex::IndexUnitImpl( // if (block_data) { // uint32_t block_length = form_value.Unsigned(); // if (block_length == 1 + - // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) { + // attributes.UnitAtIndex(i)->GetAddressByteSize()) { // if (block_data[0] == DW_OP_addr) // add_die = true; // } // } // } - parent_die = NULL; // Terminate the while loop. + parent_die = nullptr; // Terminate the while loop. break; case DW_TAG_compile_unit: case DW_TAG_partial_unit: is_global_or_static_variable = true; - parent_die = NULL; // Terminate the while loop. + parent_die = nullptr; // Terminate the while loop. break; default: @@ -247,51 +243,48 @@ void ManualDWARFIndex::IndexUnitImpl( } } + DIERef ref = *DWARFDIE(&unit, &die).GetDIERef(); switch (tag) { case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: if (has_address) { if (name) { - ObjCLanguage::MethodName objc_method(name, true); - if (objc_method.IsValid(true)) { - ConstString objc_class_name_with_category( - objc_method.GetClassNameWithCategory()); - ConstString objc_selector_name(objc_method.GetSelector()); - ConstString objc_fullname_no_category_name( - objc_method.GetFullNameWithoutCategory(true)); - ConstString objc_class_name_no_category(objc_method.GetClassName()); - set.function_fullnames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - if (objc_class_name_with_category) - set.objc_class_selectors.Insert( - objc_class_name_with_category, - DIERef(cu_offset, die.GetOffset())); - if (objc_class_name_no_category && - objc_class_name_no_category != objc_class_name_with_category) - set.objc_class_selectors.Insert( - objc_class_name_no_category, - DIERef(cu_offset, die.GetOffset())); - if (objc_selector_name) - set.function_selectors.Insert(objc_selector_name, - DIERef(cu_offset, die.GetOffset())); - if (objc_fullname_no_category_name) - set.function_fullnames.Insert(objc_fullname_no_category_name, - DIERef(cu_offset, die.GetOffset())); + bool is_objc_method = false; + if (cu_language == eLanguageTypeObjC || + cu_language == eLanguageTypeObjC_plus_plus) { + ObjCLanguage::MethodName objc_method(name, true); + if (objc_method.IsValid(true)) { + is_objc_method = true; + ConstString class_name_with_category( + objc_method.GetClassNameWithCategory()); + ConstString objc_selector_name(objc_method.GetSelector()); + ConstString objc_fullname_no_category_name( + objc_method.GetFullNameWithoutCategory(true)); + ConstString class_name_no_category(objc_method.GetClassName()); + set.function_fullnames.Insert(ConstString(name), ref); + if (class_name_with_category) + set.objc_class_selectors.Insert(class_name_with_category, ref); + if (class_name_no_category && + class_name_no_category != class_name_with_category) + set.objc_class_selectors.Insert(class_name_no_category, ref); + if (objc_selector_name) + set.function_selectors.Insert(objc_selector_name, ref); + if (objc_fullname_no_category_name) + set.function_fullnames.Insert(objc_fullname_no_category_name, + ref); + } } // If we have a mangled name, then the DW_AT_name attribute is // usually the method name without the class or any parameters bool is_method = DWARFDIE(&unit, &die).IsMethod(); if (is_method) - set.function_methods.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); + set.function_methods.Insert(ConstString(name), ref); else - set.function_basenames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); + set.function_basenames.Insert(ConstString(name), ref); - if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) - set.function_fullnames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); + if (!is_method && !mangled_cstr && !is_objc_method) + set.function_fullnames.Insert(ConstString(name), ref); } if (mangled_cstr) { // Make sure our mangled name isn't the same string table entry as @@ -301,8 +294,7 @@ void ManualDWARFIndex::IndexUnitImpl( if (name && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { - set.function_fullnames.Insert(ConstString(mangled_cstr), - DIERef(cu_offset, die.GetOffset())); + set.function_fullnames.Insert(ConstString(mangled_cstr), ref); } } } @@ -320,22 +312,19 @@ void ManualDWARFIndex::IndexUnitImpl( case DW_TAG_union_type: case DW_TAG_unspecified_type: if (name && !is_declaration) - set.types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); + set.types.Insert(ConstString(name), ref); if (mangled_cstr && !is_declaration) - set.types.Insert(ConstString(mangled_cstr), - DIERef(cu_offset, die.GetOffset())); + set.types.Insert(ConstString(mangled_cstr), ref); break; case DW_TAG_namespace: if (name) - set.namespaces.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); + set.namespaces.Insert(ConstString(name), ref); break; case DW_TAG_variable: if (name && has_location_or_const_value && is_global_or_static_variable) { - set.globals.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); + set.globals.Insert(ConstString(name), ref); // Be sure to include variables by their mangled and demangled names if // they have any since a variable can have a basename "i", a mangled // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name @@ -347,8 +336,7 @@ void ManualDWARFIndex::IndexUnitImpl( // entries if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { - set.globals.Insert(ConstString(mangled_cstr), - DIERef(cu_offset, die.GetOffset())); + set.globals.Insert(ConstString(mangled_cstr), ref); } } break; @@ -370,10 +358,10 @@ void ManualDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, m_set.globals.Find(regex, offsets); } -void ManualDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, +void ManualDWARFIndex::GetGlobalVariables(const DWARFUnit &unit, DIEArray &offsets) { Index(); - m_set.globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets); + m_set.globals.FindAllEntriesForUnit(unit, offsets); } void ManualDWARFIndex::GetObjCMethods(ConstString class_name, @@ -405,7 +393,7 @@ void ManualDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { m_set.namespaces.Find(name, offsets); } -void ManualDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, +void ManualDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) { @@ -417,7 +405,7 @@ void ManualDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, m_set.function_methods.Find(name, offsets); m_set.function_fullnames.Find(name, offsets); for (const DIERef &die_ref: offsets) { - DWARFDIE die = info.GetDIE(die_ref); + DWARFDIE die = dwarf.GetDIE(die_ref); if (!die) continue; if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die)) @@ -428,7 +416,7 @@ void ManualDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, DIEArray offsets; m_set.function_basenames.Find(name, offsets); for (const DIERef &die_ref: offsets) { - DWARFDIE die = info.GetDIE(die_ref); + DWARFDIE die = dwarf.GetDIE(die_ref); if (!die) continue; if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die)) @@ -441,7 +429,7 @@ void ManualDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, DIEArray offsets; m_set.function_methods.Find(name, offsets); for (const DIERef &die_ref: offsets) { - if (DWARFDIE die = info.GetDIE(die_ref)) + if (DWARFDIE die = dwarf.GetDIE(die_ref)) dies.push_back(die); } } @@ -451,7 +439,7 @@ void ManualDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, DIEArray offsets; m_set.function_selectors.Find(name, offsets); for (const DIERef &die_ref: offsets) { - if (DWARFDIE die = info.GetDIE(die_ref)) + if (DWARFDIE die = dwarf.GetDIE(die_ref)) dies.push_back(die); } } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h index 79ab1d95b380..dd03b103c936 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -1,9 +1,8 @@ -//===-- ManulaDWARFIndex.h -------------------------------------*- C++ -*-===// +//===-- ManualDWARFIndex.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -14,6 +13,8 @@ #include "Plugins/SymbolFile/DWARF/NameToDIE.h" #include "llvm/ADT/DenseSet.h" +class DWARFDebugInfo; + namespace lldb_private { class ManualDWARFIndex : public DWARFIndex { public: @@ -27,21 +28,20 @@ public: void GetGlobalVariables(ConstString basename, DIEArray &offsets) override; void GetGlobalVariables(const RegularExpression ®ex, DIEArray &offsets) override; - void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override; + void GetGlobalVariables(const DWARFUnit &unit, DIEArray &offsets) override; void GetObjCMethods(ConstString class_name, DIEArray &offsets) override; void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, DIEArray &offsets) override; void GetTypes(ConstString name, DIEArray &offsets) override; void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override; void GetNamespaces(ConstString name, DIEArray &offsets) override; - void GetFunctions(ConstString name, DWARFDebugInfo &info, + void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector<DWARFDIE> &dies) override; void GetFunctions(const RegularExpression ®ex, DIEArray &offsets) override; - void ReportInvalidDIEOffset(dw_offset_t offset, - llvm::StringRef name) override {} + void ReportInvalidDIERef(const DIERef &ref, llvm::StringRef name) override {} void Dump(Stream &s) override; private: @@ -58,10 +58,9 @@ private: void Index(); void IndexUnit(DWARFUnit &unit, IndexSet &set); - static void - IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language, - const DWARFFormValue::FixedFormSizes &fixed_form_sizes, - const dw_offset_t cu_offset, IndexSet &set); + static void IndexUnitImpl(DWARFUnit &unit, + const lldb::LanguageType cu_language, + IndexSet &set); /// Non-null value means we haven't built the index yet. DWARFDebugInfo *m_debug_info; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index c8d6bba16976..7d81afb1b226 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -1,23 +1,19 @@ //===-- NameToDIE.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "NameToDIE.h" +#include "DWARFUnit.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" -#include "DWARFDebugInfo.h" -#include "DWARFDebugInfoEntry.h" -#include "SymbolFileDWARF.h" - using namespace lldb; using namespace lldb_private; @@ -26,11 +22,11 @@ void NameToDIE::Finalize() { m_map.SizeToFit(); } -void NameToDIE::Insert(const ConstString &name, const DIERef &die_ref) { +void NameToDIE::Insert(ConstString name, const DIERef &die_ref) { m_map.Append(name, die_ref); } -size_t NameToDIE::Find(const ConstString &name, DIEArray &info_array) const { +size_t NameToDIE::Find(ConstString name, DIEArray &info_array) const { return m_map.GetValues(name, info_array); } @@ -39,13 +35,16 @@ size_t NameToDIE::Find(const RegularExpression ®ex, return m_map.GetValues(regex, info_array); } -size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset, - DIEArray &info_array) const { +size_t NameToDIE::FindAllEntriesForUnit(const DWARFUnit &unit, + DIEArray &info_array) const { const size_t initial_size = info_array.size(); const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) { const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i); - if (cu_offset == die_ref.cu_offset) + if (unit.GetSymbolFileDWARF().GetDwoNum() == die_ref.dwo_num() && + unit.GetDebugSection() == die_ref.section() && + unit.GetOffset() <= die_ref.die_offset() && + die_ref.die_offset() < unit.GetNextUnitOffset()) info_array.push_back(die_ref); } return info_array.size() - initial_size; @@ -54,10 +53,8 @@ size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset, void NameToDIE::Dump(Stream *s) { const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) { - ConstString cstr = m_map.GetCStringAtIndex(i); - const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i); - s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", (const void *)cstr.GetCString(), - die_ref.cu_offset, die_ref.die_offset, cstr.GetCString()); + s->Format("{0} \"{1}\"\n", m_map.GetValueAtIndexUnchecked(i), + m_map.GetCStringAtIndexUnchecked(i)); } } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h index bba44fda3c04..b504f45e81b5 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -1,9 +1,8 @@ //===-- NameToDIE.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -17,7 +16,7 @@ #include "lldb/Core/dwarf.h" #include "lldb/lldb-defines.h" -class SymbolFileDWARF; +class DWARFUnit; class NameToDIE { public: @@ -27,20 +26,20 @@ public: void Dump(lldb_private::Stream *s); - void Insert(const lldb_private::ConstString &name, const DIERef &die_ref); + void Insert(lldb_private::ConstString name, const DIERef &die_ref); void Append(const NameToDIE &other); void Finalize(); - size_t Find(const lldb_private::ConstString &name, + size_t Find(lldb_private::ConstString name, DIEArray &info_array) const; size_t Find(const lldb_private::RegularExpression ®ex, DIEArray &info_array) const; - size_t FindAllEntriesForCompileUnit(dw_offset_t cu_offset, - DIEArray &info_array) const; + size_t FindAllEntriesForUnit(const DWARFUnit &unit, + DIEArray &info_array) const; void ForEach(std::function<bool(lldb_private::ConstString name, diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 2a0a89f0b25a..e2ddcfc5d64b 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1,9 +1,8 @@ //===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -30,7 +29,6 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" -#include "lldb/Host/Symbols.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueProperties.h" @@ -43,6 +41,7 @@ #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TypeMap.h" @@ -50,11 +49,12 @@ #include "lldb/Symbol/VariableList.h" #include "lldb/Target/Language.h" +#include "lldb/Target/Target.h" #include "AppleDWARFIndex.h" #include "DWARFASTParser.h" #include "DWARFASTParserClang.h" -#include "DWARFDIECollection.h" +#include "DWARFCompileUnit.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" @@ -63,6 +63,7 @@ #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" #include "DWARFFormValue.h" +#include "DWARFTypeUnit.h" #include "DWARFUnit.h" #include "DebugNamesDWARFIndex.h" #include "LogChannelDWARF.h" @@ -73,7 +74,9 @@ #include "llvm/Support/FileSystem.h" +#include <algorithm> #include <map> +#include <memory> #include <ctype.h> #include <string.h> @@ -131,12 +134,12 @@ public: } PluginProperties() { - m_collection_sp.reset(new OptionValueProperties(GetSettingName())); + m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); m_collection_sp->Initialize(g_properties); } - FileSpecList &GetSymLinkPaths() { - OptionValueFileSpecList *option_value = + FileSpecList GetSymLinkPaths() { + const OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList( nullptr, true, ePropertySymLinkPaths); assert(option_value); @@ -158,68 +161,8 @@ static const SymbolFileDWARFPropertiesSP &GetGlobalPluginProperties() { } // anonymous namespace end -static const char *removeHostnameFromPathname(const char *path_from_dwarf) { - if (!path_from_dwarf || !path_from_dwarf[0]) { - return path_from_dwarf; - } - - const char *colon_pos = strchr(path_from_dwarf, ':'); - if (nullptr == colon_pos) { - return path_from_dwarf; - } - - const char *slash_pos = strchr(path_from_dwarf, '/'); - if (slash_pos && (slash_pos < colon_pos)) { - return path_from_dwarf; - } - - // check whether we have a windows path, and so the first character is a - // drive-letter not a hostname. - if (colon_pos == path_from_dwarf + 1 && isalpha(*path_from_dwarf) && - strlen(path_from_dwarf) > 2 && '\\' == path_from_dwarf[2]) { - return path_from_dwarf; - } - - return colon_pos + 1; -} - -static FileSpec resolveCompDir(const char *path_from_dwarf) { - if (!path_from_dwarf) - return FileSpec(); - - // DWARF2/3 suggests the form hostname:pathname for compilation directory. - // Remove the host part if present. - const char *local_path = removeHostnameFromPathname(path_from_dwarf); - if (!local_path) - return FileSpec(); - - bool is_symlink = false; - // Always normalize our compile unit directory to get rid of redundant - // slashes and other path anomalies before we use it for path prepending - FileSpec local_spec(local_path); - const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths(); - for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i) - is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i), - local_spec, true); - - if (!is_symlink) - return local_spec; - - namespace fs = llvm::sys::fs; - if (fs::get_file_type(local_spec.GetPath(), false) != - fs::file_type::symlink_file) - return local_spec; - - FileSpec resolved_symlink; - const auto error = FileSystem::Instance().Readlink(local_spec, resolved_symlink); - if (error.Success()) - return resolved_symlink; - - return local_spec; -} - -DWARFUnit *SymbolFileDWARF::GetBaseCompileUnit() { - return nullptr; +FileSpecList SymbolFileDWARF::GetSymlinkPaths() { + return GetGlobalPluginProperties()->GetSymLinkPaths(); } void SymbolFileDWARF::Initialize() { @@ -255,7 +198,8 @@ const char *SymbolFileDWARF::GetPluginDescriptionStatic() { } SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileDWARF(obj_file); + return new SymbolFileDWARF(obj_file, + /*dwo_section_list*/ nullptr); } TypeList *SymbolFileDWARF::GetTypeList() { @@ -346,23 +290,23 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, ASSERT_MODULE_LOCK(this); TypeSet type_set; - CompileUnit *comp_unit = NULL; - DWARFUnit *dwarf_cu = NULL; + CompileUnit *comp_unit = nullptr; + DWARFUnit *dwarf_cu = nullptr; if (sc_scope) comp_unit = sc_scope->CalculateSymbolContextCompileUnit(); if (comp_unit) { dwarf_cu = GetDWARFCompileUnit(comp_unit); - if (dwarf_cu == 0) + if (dwarf_cu == nullptr) return 0; GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(), - dwarf_cu->GetNextCompileUnitOffset(), type_mask, type_set); + dwarf_cu->GetNextUnitOffset(), type_mask, type_set); } else { DWARFDebugInfo *info = DebugInfo(); if (info) { - const size_t num_cus = info->GetNumCompileUnits(); + const size_t num_cus = info->GetNumUnits(); for (size_t cu_idx = 0; cu_idx < num_cus; ++cu_idx) { - dwarf_cu = info->GetCompileUnitAtIndex(cu_idx); + dwarf_cu = info->GetUnitAtIndex(cu_idx); if (dwarf_cu) { GetTypes(dwarf_cu->DIE(), 0, UINT32_MAX, type_mask, type_set); } @@ -383,10 +327,8 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, return num_types_added; } -//---------------------------------------------------------------------- // Gets the first parent that is a lexical block, function or inlined // subroutine, or compile unit. -//---------------------------------------------------------------------- DWARFDIE SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) { DWARFDIE die; @@ -405,23 +347,21 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) { return DWARFDIE(); } -SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile) - : SymbolFile(objfile), UserID(uint64_t(DW_INVALID_OFFSET) - << 32), // Used by SymbolFileDWARFDebugMap to - // when this class parses .o files to - // contain the .o file index/ID - m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(), - m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(), - m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(), - m_data_debug_ranges(), m_data_debug_rnglists(), m_data_debug_str(), - m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(), - m_abbr(), m_info(), m_line(), m_fetched_external_modules(false), - m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(), +SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile, + SectionList *dwo_section_list) + : SymbolFile(objfile), + UserID(0x7fffffff00000000), // Used by SymbolFileDWARFDebugMap to + // when this class parses .o files to + // contain the .o file index/ID + m_debug_map_module_wp(), m_debug_map_symfile(nullptr), + m_context(objfile->GetModule()->GetSectionList(), dwo_section_list), + m_data_debug_loc(), m_abbr(), m_info(), m_fetched_external_modules(false), + m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_unique_ast_type_map() {} SymbolFileDWARF::~SymbolFileDWARF() {} -static const ConstString &GetDWARFMachOSegmentName() { +static ConstString GetDWARFMachOSegmentName() { static ConstString g_dwarf_section_name("__DWARF"); return g_dwarf_section_name; } @@ -449,15 +389,6 @@ TypeSystem *SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { void SymbolFileDWARF::InitializeObject() { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); - ModuleSP module_sp(m_obj_file->GetModule()); - if (module_sp) { - const SectionList *section_list = module_sp->GetSectionList(); - Section *section = - section_list->FindSectionByName(GetDWARFMachOSegmentName()).get(); - - if (section) - m_obj_file->ReadSectionData(section, m_dwarf_data); - } if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) { DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc; @@ -468,7 +399,7 @@ void SymbolFileDWARF::InitializeObject() { m_index = AppleDWARFIndex::Create( *GetObjectFile()->GetModule(), apple_names, apple_namespaces, - apple_types, apple_objc, get_debug_str_data()); + apple_types, apple_objc, m_context.getOrLoadStrData()); if (m_index) return; @@ -477,9 +408,9 @@ void SymbolFileDWARF::InitializeObject() { LoadSectionData(eSectionTypeDWARFDebugNames, debug_names); if (debug_names.GetByteSize() > 0) { llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or = - DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(), - debug_names, get_debug_str_data(), - DebugInfo()); + DebugNamesDWARFIndex::Create( + *GetObjectFile()->GetModule(), debug_names, + m_context.getOrLoadStrData(), DebugInfo()); if (index_or) { m_index = std::move(*index_or); return; @@ -499,25 +430,11 @@ bool SymbolFileDWARF::SupportedVersion(uint16_t version) { uint32_t SymbolFileDWARF::CalculateAbilities() { uint32_t abilities = 0; - if (m_obj_file != NULL) { - const Section *section = NULL; + if (m_obj_file != nullptr) { + const Section *section = nullptr; const SectionList *section_list = m_obj_file->GetSectionList(); - if (section_list == NULL) - return 0; - - // On non Apple platforms we might have .debug_types debug info that is - // created by using "-fdebug-types-section". LLDB currently will try to - // load this debug info, but it causes crashes during debugging when types - // are missing since it doesn't know how to parse the info in the - // .debug_types type units. This causes all complex debug info types to be - // unresolved. Because this causes LLDB to crash and since it really - // doesn't provide a solid debuggiung experience, we should disable trying - // to debug this kind of DWARF until support gets added or deprecated. - if (section_list->FindSectionByName(ConstString(".debug_types"))) { - m_obj_file->GetModule()->ReportWarning( - "lldb doesn’t support .debug_types debug info"); + if (section_list == nullptr) return 0; - } uint64_t debug_abbrev_file_size = 0; uint64_t debug_info_file_size = 0; @@ -530,7 +447,7 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { section = section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, true).get(); - if (section != NULL) { + if (section != nullptr) { debug_info_file_size = section->GetFileSize(); section = @@ -604,53 +521,15 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { ModuleSP module_sp(m_obj_file->GetModule()); const SectionList *section_list = module_sp->GetSectionList(); - if (section_list) { - SectionSP section_sp(section_list->FindSectionByType(sect_type, true)); - if (section_sp) { - // See if we memory mapped the DWARF segment? - if (m_dwarf_data.GetByteSize()) { - data.SetData(m_dwarf_data, section_sp->GetOffset(), - section_sp->GetFileSize()); - } else { - if (m_obj_file->ReadSectionData(section_sp.get(), data) == 0) - data.Clear(); - } - } - } -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_abbrev_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugAbbrev, - m_data_debug_abbrev); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_addr_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugAddr, m_data_debug_addr); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_aranges_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugAranges, - m_data_debug_aranges); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_frame_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugFrame, m_data_debug_frame); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_info_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugInfo, m_data_debug_info); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugLine, m_data_debug_line); -} + if (!section_list) + return; -const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_str_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugLineStr, m_data_debug_line_str); -} + SectionSP section_sp(section_list->FindSectionByType(sect_type, true)); + if (!section_sp) + return; -const DWARFDataExtractor &SymbolFileDWARF::get_debug_macro_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugMacro, m_data_debug_macro); + data.Clear(); + m_obj_file->ReadSectionData(section_sp.get(), data); } const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() { @@ -669,60 +548,24 @@ const DWARFDataExtractor &SymbolFileDWARF::get_debug_loclists_data() { m_data_debug_loclists); } -const DWARFDataExtractor &SymbolFileDWARF::get_debug_ranges_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugRanges, - m_data_debug_ranges); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_rnglists_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugRngLists, - m_data_debug_rnglists); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugStr, m_data_debug_str); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_offsets_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugStrOffsets, - m_data_debug_str_offsets); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_debug_types_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugTypes, m_data_debug_types); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() { - return GetCachedSectionData(eSectionTypeDWARFAppleNames, m_data_apple_names); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_apple_types_data() { - return GetCachedSectionData(eSectionTypeDWARFAppleTypes, m_data_apple_types); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_apple_namespaces_data() { - return GetCachedSectionData(eSectionTypeDWARFAppleNamespaces, - m_data_apple_namespaces); -} - -const DWARFDataExtractor &SymbolFileDWARF::get_apple_objc_data() { - return GetCachedSectionData(eSectionTypeDWARFAppleObjC, m_data_apple_objc); -} +DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { + if (m_abbr) + return m_abbr.get(); -const DWARFDataExtractor &SymbolFileDWARF::get_gnu_debugaltlink() { - return GetCachedSectionData(eSectionTypeDWARFGNUDebugAltLink, - m_data_gnu_debugaltlink); -} + const DWARFDataExtractor &debug_abbrev_data = m_context.getOrLoadAbbrevData(); + if (debug_abbrev_data.GetByteSize() == 0) + return nullptr; -DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { - if (m_abbr.get() == NULL) { - const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data(); - if (debug_abbrev_data.GetByteSize() > 0) { - m_abbr.reset(new DWARFDebugAbbrev()); - if (m_abbr.get()) - m_abbr->Parse(debug_abbrev_data); - } + auto abbr = llvm::make_unique<DWARFDebugAbbrev>(); + llvm::Error error = abbr->parse(debug_abbrev_data); + if (error) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG_ERROR(log, std::move(error), + "Unable to read .debug_abbrev section: {0}"); + return nullptr; } + + m_abbr = std::move(abbr); return m_abbr.get(); } @@ -731,16 +574,12 @@ const DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() const { } DWARFDebugInfo *SymbolFileDWARF::DebugInfo() { - if (m_info.get() == NULL) { + if (m_info == nullptr) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); - if (get_debug_info_data().GetByteSize() > 0) { - m_info.reset(new DWARFDebugInfo()); - if (m_info.get()) { - m_info->SetDwarfData(this); - } - } + if (m_context.getOrLoadDebugInfoData().GetByteSize() > 0) + m_info = llvm::make_unique<DWARFDebugInfo>(*this, m_context); } return m_info.get(); } @@ -756,109 +595,90 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { DWARFDebugInfo *info = DebugInfo(); if (info) { - // Just a normal DWARF file whose user ID for the compile unit is the DWARF - // offset itself - - DWARFUnit *dwarf_cu = - info->GetCompileUnit((dw_offset_t)comp_unit->GetID()); - if (dwarf_cu && dwarf_cu->GetUserData() == NULL) + // The compile unit ID is the index of the DWARF unit. + DWARFUnit *dwarf_cu = info->GetUnitAtIndex(comp_unit->GetID()); + if (dwarf_cu && dwarf_cu->GetUserData() == nullptr) dwarf_cu->SetUserData(comp_unit); return dwarf_cu; } - return NULL; + return nullptr; } -DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() { - if (m_ranges.get() == NULL) { +DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { + if (!m_ranges) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); - if (get_debug_ranges_data().GetByteSize() > 0) + if (m_context.getOrLoadRangesData().GetByteSize() > 0) m_ranges.reset(new DWARFDebugRanges()); - else if (get_debug_rnglists_data().GetByteSize() > 0) - m_ranges.reset(new DWARFDebugRngLists()); - if (m_ranges.get()) - m_ranges->Extract(this); + if (m_ranges) + m_ranges->Extract(m_context); } return m_ranges.get(); } -const DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() const { - return m_ranges.get(); +DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRngLists() { + if (!m_rnglists) { + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, + static_cast<void *>(this)); + + if (m_context.getOrLoadRngListsData().GetByteSize() > 0) + m_rnglists.reset(new DWARFDebugRngLists()); + + if (m_rnglists) + m_rnglists->Extract(m_context); + } + return m_rnglists.get(); } -lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu, - uint32_t cu_idx) { +lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { CompUnitSP cu_sp; - if (dwarf_cu) { - CompileUnit *comp_unit = (CompileUnit *)dwarf_cu->GetUserData(); - if (comp_unit) { - // We already parsed this compile unit, had out a shared pointer to it - cu_sp = comp_unit->shared_from_this(); + CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData(); + if (comp_unit) { + // We already parsed this compile unit, had out a shared pointer to it + cu_sp = comp_unit->shared_from_this(); + } else { + if (&dwarf_cu.GetSymbolFileDWARF() != this) { + return dwarf_cu.GetSymbolFileDWARF().ParseCompileUnit(dwarf_cu); + } else if (dwarf_cu.GetOffset() == 0 && GetDebugMapSymfile()) { + // Let the debug map create the compile unit + cu_sp = m_debug_map_symfile->GetCompileUnit(this); + dwarf_cu.SetUserData(cu_sp.get()); } else { - if (dwarf_cu->GetSymbolFileDWARF() != this) { - return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu, - cu_idx); - } else if (dwarf_cu->GetOffset() == 0 && GetDebugMapSymfile()) { - // Let the debug map create the compile unit - cu_sp = m_debug_map_symfile->GetCompileUnit(this); - dwarf_cu->SetUserData(cu_sp.get()); - } else { - ModuleSP module_sp(m_obj_file->GetModule()); - if (module_sp) { - const DWARFDIE cu_die = dwarf_cu->DIE(); - if (cu_die) { - FileSpec cu_file_spec(cu_die.GetName()); - if (cu_file_spec) { - // If we have a full path to the compile unit, we don't need to - // resolve the file. This can be expensive e.g. when the source - // files are - // NFS mounted. - if (cu_file_spec.IsRelative()) { - const char *cu_comp_dir{ - cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)}; - cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir)); - } - - std::string remapped_file; - if (module_sp->RemapSourceFile(cu_file_spec.GetPath(), - remapped_file)) - cu_file_spec.SetFile(remapped_file, FileSpec::Style::native); - } + ModuleSP module_sp(m_obj_file->GetModule()); + if (module_sp) { + const DWARFDIE cu_die = dwarf_cu.DIE(); + if (cu_die) { + FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle()); + if (cu_file_spec) { + // If we have a full path to the compile unit, we don't need to + // resolve the file. This can be expensive e.g. when the source + // files are NFS mounted. + cu_file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory()); + + std::string remapped_file; + if (module_sp->RemapSourceFile(cu_file_spec.GetPath(), + remapped_file)) + cu_file_spec.SetFile(remapped_file, FileSpec::Style::native); + } - LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF( - cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); - - bool is_optimized = dwarf_cu->GetIsOptimized(); - cu_sp.reset(new CompileUnit( - module_sp, dwarf_cu, cu_file_spec, dwarf_cu->GetID(), - cu_language, is_optimized ? eLazyBoolYes : eLazyBoolNo)); - if (cu_sp) { - // If we just created a compile unit with an invalid file spec, - // try and get the first entry in the supports files from the - // line table as that should be the compile unit. - if (!cu_file_spec) { - cu_file_spec = cu_sp->GetSupportFiles().GetFileSpecAtIndex(1); - if (cu_file_spec) { - (FileSpec &)(*cu_sp) = cu_file_spec; - // Also fix the invalid file spec which was copied from the - // compile unit. - cu_sp->GetSupportFiles().Replace(0, cu_file_spec); - } - } + LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF( + cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); - dwarf_cu->SetUserData(cu_sp.get()); + bool is_optimized = dwarf_cu.GetIsOptimized(); + BuildCuTranslationTable(); + cu_sp = std::make_shared<CompileUnit>( + module_sp, &dwarf_cu, cu_file_spec, + *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language, + is_optimized ? eLazyBoolYes : eLazyBoolNo); - // Figure out the compile unit index if we weren't given one - if (cu_idx == UINT32_MAX) - DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx); + dwarf_cu.SetUserData(cu_sp.get()); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cu_idx, cu_sp); - } - } + m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( + dwarf_cu.GetID(), cu_sp); } } } @@ -866,23 +686,56 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu, return cu_sp; } +void SymbolFileDWARF::BuildCuTranslationTable() { + if (!m_lldb_cu_to_dwarf_unit.empty()) + return; + + DWARFDebugInfo *info = DebugInfo(); + if (!info) + return; + + if (!info->ContainsTypeUnits()) { + // We can use a 1-to-1 mapping. No need to build a translation table. + return; + } + for (uint32_t i = 0, num = info->GetNumUnits(); i < num; ++i) { + if (auto *cu = llvm::dyn_cast<DWARFCompileUnit>(info->GetUnitAtIndex(i))) { + cu->SetID(m_lldb_cu_to_dwarf_unit.size()); + m_lldb_cu_to_dwarf_unit.push_back(i); + } + } +} + +llvm::Optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { + BuildCuTranslationTable(); + if (m_lldb_cu_to_dwarf_unit.empty()) + return cu_idx; + if (cu_idx >= m_lldb_cu_to_dwarf_unit.size()) + return llvm::None; + return m_lldb_cu_to_dwarf_unit[cu_idx]; +} + uint32_t SymbolFileDWARF::GetNumCompileUnits() { DWARFDebugInfo *info = DebugInfo(); - if (info) - return info->GetNumCompileUnits(); - return 0; + if (!info) + return 0; + BuildCuTranslationTable(); + return m_lldb_cu_to_dwarf_unit.empty() ? info->GetNumUnits() + : m_lldb_cu_to_dwarf_unit.size(); } CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { ASSERT_MODULE_LOCK(this); - CompUnitSP cu_sp; DWARFDebugInfo *info = DebugInfo(); - if (info) { - DWARFUnit *dwarf_cu = info->GetCompileUnitAtIndex(cu_idx); - if (dwarf_cu) - cu_sp = ParseCompileUnit(dwarf_cu, cu_idx); + if (!info) + return {}; + + if (llvm::Optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) { + if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>( + info->GetUnitAtIndex(*dwarf_idx))) + return ParseCompileUnit(*dwarf_cu); } - return cu_sp; + return {}; } Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, @@ -920,50 +773,74 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { ASSERT_MODULE_LOCK(this); - size_t functions_added = 0; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); - if (dwarf_cu) { - DWARFDIECollection function_dies; - const size_t num_functions = - dwarf_cu->AppendDIEsWithTag(DW_TAG_subprogram, function_dies); - size_t func_idx; - for (func_idx = 0; func_idx < num_functions; ++func_idx) { - DWARFDIE die = function_dies.GetDIEAtIndex(func_idx); - if (comp_unit.FindFunctionByUID(die.GetID()).get() == NULL) { - if (ParseFunction(comp_unit, die)) - ++functions_added; - } - } - // FixupTypes(); + if (!dwarf_cu) + return 0; + + size_t functions_added = 0; + std::vector<DWARFDIE> function_dies; + dwarf_cu->AppendDIEsWithTag(DW_TAG_subprogram, function_dies); + for (const DWARFDIE &die : function_dies) { + if (comp_unit.FindFunctionByUID(die.GetID())) + continue; + if (ParseFunction(comp_unit, die)) + ++functions_added; } + // FixupTypes(); return functions_added; } bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { ASSERT_MODULE_LOCK(this); - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); - if (dwarf_cu) { - const DWARFBaseDIE cu_die = dwarf_cu->GetUnitDIEOnly(); - - if (cu_die) { - FileSpec cu_comp_dir = resolveCompDir( - cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)); - const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned( - DW_AT_stmt_list, DW_INVALID_OFFSET); - if (stmt_list != DW_INVALID_OFFSET) { - // All file indexes in DWARF are one based and a file of index zero is - // supposed to be the compile unit itself. - support_files.Append(comp_unit); - return DWARFDebugLine::ParseSupportFiles( - comp_unit.GetModule(), get_debug_line_data(), cu_comp_dir, - stmt_list, support_files, dwarf_cu); - } + if (DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit)) { + const dw_offset_t stmt_list = unit->GetLineTableOffset(); + if (stmt_list != DW_INVALID_OFFSET) { + // All file indexes in DWARF are one based and a file of index zero is + // supposed to be the compile unit itself. + support_files.Append(comp_unit); + return DWARFDebugLine::ParseSupportFiles(comp_unit.GetModule(), + m_context.getOrLoadLineData(), + stmt_list, support_files, unit); } } return false; } +FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { + if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit)) { + if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(*dwarf_cu)) + return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx); + return FileSpec(); + } + + auto &tu = llvm::cast<DWARFTypeUnit>(unit); + return GetTypeUnitSupportFiles(tu).GetFileSpecAtIndex(file_idx); +} + +const FileSpecList & +SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { + static FileSpecList empty_list; + + dw_offset_t offset = tu.GetLineTableOffset(); + if (offset == DW_INVALID_OFFSET || + offset == llvm::DenseMapInfo<dw_offset_t>::getEmptyKey() || + offset == llvm::DenseMapInfo<dw_offset_t>::getTombstoneKey()) + return empty_list; + + // Many type units can share a line table, so parse the support file list + // once, and cache it based on the offset field. + auto iter_bool = m_type_unit_support_files.try_emplace(offset); + FileSpecList &list = iter_bool.first->second; + if (iter_bool.second) { + list.Append(FileSpec()); + DWARFDebugLine::ParseSupportFiles(GetObjectFile()->GetModule(), + m_context.getOrLoadLineData(), offset, + list, &tu); + } + return list; +} + bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { ASSERT_MODULE_LOCK(this); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); @@ -974,54 +851,63 @@ bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { bool SymbolFileDWARF::ParseImportedModules( const lldb_private::SymbolContext &sc, - std::vector<lldb_private::ConstString> &imported_modules) { + std::vector<SourceModule> &imported_modules) { ASSERT_MODULE_LOCK(this); assert(sc.comp_unit); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); - if (dwarf_cu) { - if (ClangModulesDeclVendor::LanguageSupportsClangModules( - sc.comp_unit->GetLanguage())) { - UpdateExternalModuleListIfNeeded(); + if (!dwarf_cu) + return false; + if (!ClangModulesDeclVendor::LanguageSupportsClangModules( + sc.comp_unit->GetLanguage())) + return false; + UpdateExternalModuleListIfNeeded(); - if (sc.comp_unit) { - const DWARFDIE die = dwarf_cu->DIE(); + const DWARFDIE die = dwarf_cu->DIE(); + if (!die) + return false; - if (die) { - for (DWARFDIE child_die = die.GetFirstChild(); child_die; - child_die = child_die.GetSibling()) { - if (child_die.Tag() == DW_TAG_imported_declaration) { - if (DWARFDIE module_die = - child_die.GetReferencedDIE(DW_AT_import)) { - if (module_die.Tag() == DW_TAG_module) { - if (const char *name = module_die.GetAttributeValueAsString( - DW_AT_name, nullptr)) { - ConstString const_name(name); - imported_modules.push_back(const_name); - } - } - } - } - } - } - } else { - for (const auto &pair : m_external_type_modules) { - imported_modules.push_back(pair.first); - } + for (DWARFDIE child_die = die.GetFirstChild(); child_die; + child_die = child_die.GetSibling()) { + if (child_die.Tag() != DW_TAG_imported_declaration) + continue; + + DWARFDIE module_die = child_die.GetReferencedDIE(DW_AT_import); + if (module_die.Tag() != DW_TAG_module) + continue; + + if (const char *name = + module_die.GetAttributeValueAsString(DW_AT_name, nullptr)) { + SourceModule module; + module.path.push_back(ConstString(name)); + + DWARFDIE parent_die = module_die; + while ((parent_die = parent_die.GetParent())) { + if (parent_die.Tag() != DW_TAG_module) + break; + if (const char *name = + parent_die.GetAttributeValueAsString(DW_AT_name, nullptr)) + module.path.push_back(ConstString(name)); } + std::reverse(module.path.begin(), module.path.end()); + if (const char *include_path = module_die.GetAttributeValueAsString( + DW_AT_LLVM_include_path, nullptr)) + module.search_path = ConstString(include_path); + if (const char *sysroot = module_die.GetAttributeValueAsString( + DW_AT_LLVM_isysroot, nullptr)) + module.sysroot = ConstString(sysroot); + imported_modules.push_back(module); } } - return false; + return true; } struct ParseDWARFLineTableCallbackInfo { LineTable *line_table; - std::unique_ptr<LineSequence> sequence_ap; + std::unique_ptr<LineSequence> sequence_up; lldb::addr_t addr_mask; }; -//---------------------------------------------------------------------- // ParseStatementTableCallback -//---------------------------------------------------------------------- static void ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State &state, void *userData) { @@ -1035,26 +921,26 @@ static void ParseDWARFLineTableCallback(dw_offset_t offset, LineTable *line_table = info->line_table; // If this is our first time here, we need to create a sequence container. - if (!info->sequence_ap.get()) { - info->sequence_ap.reset(line_table->CreateLineSequenceContainer()); - assert(info->sequence_ap.get()); + if (!info->sequence_up) { + info->sequence_up.reset(line_table->CreateLineSequenceContainer()); + assert(info->sequence_up.get()); } line_table->AppendLineEntryToSequence( - info->sequence_ap.get(), state.address & info->addr_mask, state.line, + info->sequence_up.get(), state.address & info->addr_mask, state.line, state.column, state.file, state.is_stmt, state.basic_block, state.prologue_end, state.epilogue_begin, state.end_sequence); if (state.end_sequence) { // First, put the current sequence into the line table. - line_table->InsertSequence(info->sequence_ap.get()); + line_table->InsertSequence(info->sequence_up.get()); // Then, empty it to prepare for the next sequence. - info->sequence_ap->Clear(); + info->sequence_up->Clear(); } } } bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { ASSERT_MODULE_LOCK(this); - if (comp_unit.GetLineTable() != NULL) + if (comp_unit.GetLineTable() != nullptr) return true; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); @@ -1065,10 +951,10 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET); if (cu_line_offset != DW_INVALID_OFFSET) { - std::unique_ptr<LineTable> line_table_ap(new LineTable(&comp_unit)); - if (line_table_ap.get()) { + std::unique_ptr<LineTable> line_table_up(new LineTable(&comp_unit)); + if (line_table_up) { ParseDWARFLineTableCallbackInfo info; - info.line_table = line_table_ap.get(); + info.line_table = line_table_up.get(); /* * MIPS: @@ -1091,9 +977,9 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { } lldb::offset_t offset = cu_line_offset; - DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, - ParseDWARFLineTableCallback, - &info, dwarf_cu); + DWARFDebugLine::ParseStatementTable( + m_context.getOrLoadLineData(), &offset, + ParseDWARFLineTableCallback, &info, dwarf_cu); SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); if (debug_map_symfile) { // We have an object file that has a line table with addresses that @@ -1101,9 +987,9 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { // addresses that are relative to the .o file into addresses for // the main executable. comp_unit.SetLineTable( - debug_map_symfile->LinkOSOLineTable(this, line_table_ap.get())); + debug_map_symfile->LinkOSOLineTable(this, line_table_up.get())); } else { - comp_unit.SetLineTable(line_table_ap.release()); + comp_unit.SetLineTable(line_table_up.release()); return true; } } @@ -1119,7 +1005,7 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { if (iter != m_debug_macros_map.end()) return iter->second; - const DWARFDataExtractor &debug_macro_data = get_debug_macro_data(); + const DWARFDataExtractor &debug_macro_data = m_context.getOrLoadMacroData(); if (debug_macro_data.GetByteSize() == 0) return DebugMacrosSP(); @@ -1128,9 +1014,9 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { const DWARFDebugMacroHeader &header = DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset); - DWARFDebugMacroEntry::ReadMacroEntries(debug_macro_data, get_debug_str_data(), - header.OffsetIs64Bit(), offset, this, - debug_macros_sp); + DWARFDebugMacroEntry::ReadMacroEntries( + debug_macro_data, m_context.getOrLoadStrData(), header.OffsetIs64Bit(), + offset, this, debug_macros_sp); return debug_macros_sp; } @@ -1171,7 +1057,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: case DW_TAG_lexical_block: { - Block *block = NULL; + Block *block = nullptr; if (tag == DW_TAG_subprogram) { // Skip any DW_TAG_subprogram DIEs that are inside of a normal or // inlined functions. These will be parsed on their own as separate @@ -1187,8 +1073,8 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( block = block_sp.get(); } DWARFRangeList ranges; - const char *name = NULL; - const char *mangled_name = NULL; + const char *name = nullptr; + const char *mangled_name = nullptr; int decl_file = 0; int decl_line = 0; @@ -1236,21 +1122,21 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( block->FinalizeRanges(); if (tag != DW_TAG_subprogram && - (name != NULL || mangled_name != NULL)) { - std::unique_ptr<Declaration> decl_ap; + (name != nullptr || mangled_name != nullptr)) { + std::unique_ptr<Declaration> decl_up; if (decl_file != 0 || decl_line != 0 || decl_column != 0) - decl_ap.reset(new Declaration( + decl_up.reset(new Declaration( comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, decl_column)); - std::unique_ptr<Declaration> call_ap; + std::unique_ptr<Declaration> call_up; if (call_file != 0 || call_line != 0 || call_column != 0) - call_ap.reset(new Declaration( + call_up.reset(new Declaration( comp_unit.GetSupportFiles().GetFileSpecAtIndex(call_file), call_line, call_column)); - block->SetInlinedFunctionInfo(name, mangled_name, decl_ap.get(), - call_ap.get()); + block->SetInlinedFunctionInfo(name, mangled_name, decl_up.get(), + call_up.get()); } ++blocks_added; @@ -1313,7 +1199,17 @@ void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) { ast_parser->GetDeclForUIDFromDWARF(decl); } -SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) { +user_id_t SymbolFileDWARF::GetUID(DIERef ref) { + if (GetDebugMapSymfile()) + return GetID() | ref.die_offset(); + + return user_id_t(GetDwoNum().getValueOr(0x7fffffff)) << 32 | + ref.die_offset() | + (lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63); +} + +llvm::Optional<SymbolFileDWARF::DecodedUID> +SymbolFileDWARF::DecodeUID(lldb::user_id_t uid) { // This method can be called without going through the symbol vendor so we // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); @@ -1324,28 +1220,37 @@ SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) { // references to other DWARF objects and we must be ready to receive a // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF // instance. - SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile(); - if (debug_map) - return debug_map->GetSymbolFileByOSOIndex( + if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) { + SymbolFileDWARF *dwarf = debug_map->GetSymbolFileByOSOIndex( debug_map->GetOSOIndexFromUserID(uid)); - return this; + return DecodedUID{ + *dwarf, {llvm::None, DIERef::Section::DebugInfo, dw_offset_t(uid)}}; + } + dw_offset_t die_offset = uid; + if (die_offset == DW_INVALID_OFFSET) + return llvm::None; + + DIERef::Section section = + uid >> 63 ? DIERef::Section::DebugTypes : DIERef::Section::DebugInfo; + + llvm::Optional<uint32_t> dwo_num = uid >> 32 & 0x7fffffff; + if (*dwo_num == 0x7fffffff) + dwo_num = llvm::None; + + return DecodedUID{*this, {dwo_num, section, die_offset}}; } DWARFDIE -SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) { +SymbolFileDWARF::GetDIE(lldb::user_id_t uid) { // This method can be called without going through the symbol vendor so we // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we - // must make sure we use the correct DWARF file when resolving things. On - // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple - // SymbolFileDWARF classes, one for each .o file. We can often end up with - // references to other DWARF objects and we must be ready to receive a - // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF - // instance. - SymbolFileDWARF *dwarf = GetDWARFForUID(uid); - if (dwarf) - return dwarf->GetDIE(DIERef(uid, dwarf)); + + llvm::Optional<DecodedUID> decoded = DecodeUID(uid); + + if (decoded) + return decoded->dwarf.GetDIE(decoded->ref); + return DWARFDIE(); } @@ -1354,10 +1259,9 @@ CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) { // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling - // SymbolFileDWARF::GetDIEFromUID(). See comments inside the - // SymbolFileDWARF::GetDIEFromUID() for details. - DWARFDIE die = GetDIEFromUID(type_uid); - if (die) + // SymbolFileDWARF::GetDIE(). See comments inside the + // SymbolFileDWARF::GetDIE() for details. + if (DWARFDIE die = GetDIE(type_uid)) return die.GetDecl(); return CompilerDecl(); } @@ -1368,10 +1272,9 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) { // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling - // SymbolFileDWARF::GetDIEFromUID(). See comments inside the - // SymbolFileDWARF::GetDIEFromUID() for details. - DWARFDIE die = GetDIEFromUID(type_uid); - if (die) + // SymbolFileDWARF::GetDIE(). See comments inside the + // SymbolFileDWARF::GetDIE() for details. + if (DWARFDIE die = GetDIE(type_uid)) return die.GetDeclContext(); return CompilerDeclContext(); } @@ -1382,10 +1285,9 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling - // SymbolFileDWARF::GetDIEFromUID(). See comments inside the - // SymbolFileDWARF::GetDIEFromUID() for details. - DWARFDIE die = GetDIEFromUID(type_uid); - if (die) + // SymbolFileDWARF::GetDIE(). See comments inside the + // SymbolFileDWARF::GetDIE() for details. + if (DWARFDIE die = GetDIE(type_uid)) return die.GetContainingDeclContext(); return CompilerDeclContext(); } @@ -1395,10 +1297,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling - // SymbolFileDWARF::GetDIEFromUID(). See comments inside the - // SymbolFileDWARF::GetDIEFromUID() for details. - DWARFDIE type_die = GetDIEFromUID(type_uid); - if (type_die) + // SymbolFileDWARF::GetDIE(). See comments inside the + // SymbolFileDWARF::GetDIE() for details. + if (DWARFDIE type_die = GetDIE(type_uid)) return type_die.ResolveType(); else return nullptr; @@ -1408,8 +1309,7 @@ llvm::Optional<SymbolFile::ArrayInfo> SymbolFileDWARF::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - DWARFDIE type_die = GetDIEFromUID(type_uid); - if (type_die) + if (DWARFDIE type_die = GetDIE(type_uid)) return DWARFASTParser::ParseChildArrayInfo(type_die, exe_ctx); else return llvm::None; @@ -1454,7 +1354,7 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, } return ResolveType(die); } - return NULL; + return nullptr; } // This function is used when SymbolFileDWARFDebugMap owns a bunch of @@ -1548,15 +1448,14 @@ Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die, } CompileUnit * -SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu, - uint32_t cu_idx) { +SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu) { // Check if the symbol vendor already knows about this compile unit? - if (dwarf_cu->GetUserData() == NULL) { + if (dwarf_cu.GetUserData() == nullptr) { // The symbol vendor doesn't know about this compile unit, we need to parse // and add it to the symbol vendor object. - return ParseCompileUnit(dwarf_cu, cu_idx).get(); + return ParseCompileUnit(dwarf_cu).get(); } - return (CompileUnit *)dwarf_cu->GetUserData(); + return (CompileUnit *)dwarf_cu.GetUserData(); } size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name, @@ -1569,12 +1468,13 @@ size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name, bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) { sc.Clear(false); - if (die) { + if (die && llvm::isa<DWARFCompileUnit>(die.GetCU())) { // Check if the symbol vendor already knows about this compile unit? - sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); + sc.comp_unit = + GetCompUnitForDWARFCompUnit(llvm::cast<DWARFCompileUnit>(*die.GetCU())); sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get(); - if (sc.function == NULL) + if (sc.function == nullptr) sc.function = ParseFunction(*sc.comp_unit, die); if (sc.function) { @@ -1597,6 +1497,14 @@ lldb::ModuleSP SymbolFileDWARF::GetDWOModule(ConstString name) { DWARFDIE SymbolFileDWARF::GetDIE(const DIERef &die_ref) { + if (die_ref.dwo_num()) { + return DebugInfo() + ->GetUnitAtIndex(*die_ref.dwo_num()) + ->GetDwoSymbolFile() + ->GetDIE(die_ref); + } + + DWARFDebugInfo *debug_info = DebugInfo(); if (debug_info) return debug_info->GetDIE(die_ref); @@ -1606,24 +1514,29 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) { std::unique_ptr<SymbolFileDWARFDwo> SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( - DWARFUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) { + DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) { // If we are using a dSYM file, we never want the standard DWO files since // the -gmodules support uses the same DWO machanism to specify full debug // info files for modules. if (GetDebugMapSymfile()) return nullptr; - const char *dwo_name = cu_die.GetAttributeValueAsString( - this, &dwarf_cu, DW_AT_GNU_dwo_name, nullptr); + DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit); + // Only compile units can be split into two parts. + if (!dwarf_cu) + return nullptr; + + const char *dwo_name = + cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_GNU_dwo_name, nullptr); if (!dwo_name) return nullptr; SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile(); if (dwp_symfile) { - uint64_t dwo_id = cu_die.GetAttributeValueAsUnsigned(this, &dwarf_cu, - DW_AT_GNU_dwo_id, 0); + uint64_t dwo_id = + cu_die.GetAttributeValueAsUnsigned(dwarf_cu, DW_AT_GNU_dwo_id, 0); std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile = - dwp_symfile->GetSymbolFileForDwoId(&dwarf_cu, dwo_id); + dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id); if (dwo_symfile) return dwo_symfile; } @@ -1631,8 +1544,8 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( FileSpec dwo_file(dwo_name); FileSystem::Instance().Resolve(dwo_file); if (dwo_file.IsRelative()) { - const char *comp_dir = cu_die.GetAttributeValueAsString( - this, &dwarf_cu, DW_AT_comp_dir, nullptr); + const char *comp_dir = + cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr); if (!comp_dir) return nullptr; @@ -1654,7 +1567,7 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (dwo_obj_file == nullptr) return nullptr; - return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, &dwarf_cu); + return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); } void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -1666,7 +1579,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { const uint32_t num_compile_units = GetNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { - DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); + DWARFUnit *dwarf_cu = debug_info->GetUnitAtIndex(cu_idx); const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly(); if (die && !die.HasChildren()) { @@ -1708,16 +1621,14 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { // printed. However, as one can notice in this case we don't // actually need to try to load the already loaded module // (corresponding to .dwo) so we simply skip it. - if (m_obj_file->GetFileSpec() - .GetFileNameExtension() - .GetStringRef() == ".dwo" && + if (m_obj_file->GetFileSpec().GetFileNameExtension() == ".dwo" && llvm::StringRef(m_obj_file->GetFileSpec().GetPath()) .endswith(dwo_module_spec.GetFileSpec().GetPath())) { continue; } Status error = ModuleList::GetSharedModule( - dwo_module_spec, module_sp, NULL, NULL, NULL); + dwo_module_spec, module_sp, nullptr, nullptr, nullptr); if (!module_sp) { GetObjectFile()->GetModule()->ReportWarning( "0x%8.8x: unable to locate module needed for external types: " @@ -1737,8 +1648,8 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { } SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { - if (!m_global_aranges_ap) { - m_global_aranges_ap.reset(new GlobalVariableMap()); + if (!m_global_aranges_up) { + m_global_aranges_up.reset(new GlobalVariableMap()); ModuleSP module_sp = GetObjectFile()->GetModule(); if (module_sp) { @@ -1763,8 +1674,9 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { location_result.GetScalar().ULongLong(); lldb::addr_t byte_size = 1; if (var_sp->GetType()) - byte_size = var_sp->GetType()->GetByteSize(); - m_global_aranges_ap->Append(GlobalVariableMap::Entry( + byte_size = + var_sp->GetType()->GetByteSize().getValueOr(0); + m_global_aranges_up->Append(GlobalVariableMap::Entry( file_addr, byte_size, var_sp.get())); } } @@ -1774,9 +1686,9 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { } } } - m_global_aranges_ap->Sort(); + m_global_aranges_up->Sort(); } - return *m_global_aranges_ap; + return *m_global_aranges_up; } uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, @@ -1798,8 +1710,17 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, DWARFDebugInfo *debug_info = DebugInfo(); if (debug_info) { - const dw_offset_t cu_offset = - debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr); + llvm::Expected<DWARFDebugAranges &> aranges = + debug_info->GetCompileUnitAranges(); + if (!aranges) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG_ERROR(log, aranges.takeError(), + "SymbolFileDWARF::ResolveSymbolContext failed to get cu " + "aranges. {0}"); + return 0; + } + + const dw_offset_t cu_offset = aranges->FindAddress(file_vm_addr); if (cu_offset == DW_INVALID_OFFSET) { // Global variables are not in the compile unit address ranges. The // only way to currently find global variables is to iterate over the @@ -1822,10 +1743,10 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, } } else { uint32_t cu_idx = DW_INVALID_INDEX; - DWARFUnit *dwarf_cu = - debug_info->GetCompileUnit(cu_offset, &cu_idx); - if (dwarf_cu) { - sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); + if (auto *dwarf_cu = llvm::dyn_cast_or_null<DWARFCompileUnit>( + debug_info->GetUnitAtOffset(DIERef::Section::DebugInfo, + cu_offset, &cu_idx))) { + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); if (sc.comp_unit) { resolved |= eSymbolContextCompUnit; @@ -1837,7 +1758,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, if (function_die) { sc.function = sc.comp_unit->FindFunctionByUID(function_die.GetID()).get(); - if (sc.function == NULL) + if (sc.function == nullptr) sc.function = ParseFunction(*sc.comp_unit, function_die); if (sc.function && (resolve_scope & eSymbolContextBlock)) @@ -1852,7 +1773,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, force_check_line_table = true; } - if (sc.function != NULL) { + if (sc.function != nullptr) { resolved |= eSymbolContextFunction; if (resolve_scope & eSymbolContextBlock) { @@ -1871,7 +1792,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, if ((resolve_scope & eSymbolContextLineEntry) || force_check_line_table) { LineTable *line_table = sc.comp_unit->GetLineTable(); - if (line_table != NULL) { + if (line_table != nullptr) { // And address that makes it into this function should be in // terms of this debug file if there is no debug map, or it // will be an address in the .o file which needs to be fixed up @@ -1895,7 +1816,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, // only happen when there aren't other functions from other // compile units in these gaps. This helps keep the size of the // aranges down. - sc.comp_unit = NULL; + sc.comp_unit = nullptr; resolved &= ~eSymbolContextCompUnit; } } else { @@ -1918,110 +1839,100 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, SymbolContextList &sc_list) { const uint32_t prev_size = sc_list.GetSize(); if (resolve_scope & eSymbolContextCompUnit) { - DWARFDebugInfo *debug_info = DebugInfo(); - if (debug_info) { - uint32_t cu_idx; - DWARFUnit *dwarf_cu = NULL; - - for (cu_idx = 0; - (dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL; - ++cu_idx) { - CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); - const bool full_match = (bool)file_spec.GetDirectory(); - bool file_spec_matches_cu_file_spec = - dc_cu != NULL && FileSpec::Equal(file_spec, *dc_cu, full_match); - if (check_inlines || file_spec_matches_cu_file_spec) { - SymbolContext sc(m_obj_file->GetModule()); - sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); - if (sc.comp_unit) { - uint32_t file_idx = UINT32_MAX; + for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; + ++cu_idx) { + CompileUnit *dc_cu = ParseCompileUnitAtIndex(cu_idx).get(); + if (!dc_cu) + continue; + + const bool full_match = (bool)file_spec.GetDirectory(); + bool file_spec_matches_cu_file_spec = + FileSpec::Equal(file_spec, *dc_cu, full_match); + if (check_inlines || file_spec_matches_cu_file_spec) { + SymbolContext sc(m_obj_file->GetModule()); + sc.comp_unit = dc_cu; + uint32_t file_idx = UINT32_MAX; + + // If we are looking for inline functions only and we don't find it + // in the support files, we are done. + if (check_inlines) { + file_idx = + sc.comp_unit->GetSupportFiles().FindFileIndex(1, file_spec, true); + if (file_idx == UINT32_MAX) + continue; + } - // If we are looking for inline functions only and we don't find it - // in the support files, we are done. - if (check_inlines) { + if (line != 0) { + LineTable *line_table = sc.comp_unit->GetLineTable(); + + if (line_table != nullptr && line != 0) { + // We will have already looked up the file index if we are + // searching for inline entries. + if (!check_inlines) file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex( 1, file_spec, true); - if (file_idx == UINT32_MAX) - continue; - } - - if (line != 0) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - if (line_table != NULL && line != 0) { - // We will have already looked up the file index if we are - // searching for inline entries. - if (!check_inlines) - file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex( - 1, file_spec, true); - - if (file_idx != UINT32_MAX) { - uint32_t found_line; - uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex( - 0, file_idx, line, false, &sc.line_entry); - found_line = sc.line_entry.line; - - while (line_idx != UINT32_MAX) { - sc.function = NULL; - sc.block = NULL; - if (resolve_scope & - (eSymbolContextFunction | eSymbolContextBlock)) { - const lldb::addr_t file_vm_addr = - sc.line_entry.range.GetBaseAddress().GetFileAddress(); - if (file_vm_addr != LLDB_INVALID_ADDRESS) { - DWARFDIE function_die = - dwarf_cu->LookupAddress(file_vm_addr); - DWARFDIE block_die; - if (function_die) { - sc.function = - sc.comp_unit - ->FindFunctionByUID(function_die.GetID()) - .get(); - if (sc.function == NULL) - sc.function = - ParseFunction(*sc.comp_unit, function_die); - - if (sc.function && - (resolve_scope & eSymbolContextBlock)) - block_die = - function_die.LookupDeepestBlock(file_vm_addr); - } + if (file_idx != UINT32_MAX) { + uint32_t found_line; + uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex( + 0, file_idx, line, false, &sc.line_entry); + found_line = sc.line_entry.line; + + while (line_idx != UINT32_MAX) { + sc.function = nullptr; + sc.block = nullptr; + if (resolve_scope & + (eSymbolContextFunction | eSymbolContextBlock)) { + const lldb::addr_t file_vm_addr = + sc.line_entry.range.GetBaseAddress().GetFileAddress(); + if (file_vm_addr != LLDB_INVALID_ADDRESS) { + DWARFDIE function_die = + GetDWARFCompileUnit(dc_cu)->LookupAddress(file_vm_addr); + DWARFDIE block_die; + if (function_die) { + sc.function = + sc.comp_unit->FindFunctionByUID(function_die.GetID()) + .get(); + if (sc.function == nullptr) + sc.function = + ParseFunction(*sc.comp_unit, function_die); + + if (sc.function && (resolve_scope & eSymbolContextBlock)) + block_die = + function_die.LookupDeepestBlock(file_vm_addr); + } - if (sc.function != NULL) { - Block &block = sc.function->GetBlock(true); + if (sc.function != nullptr) { + Block &block = sc.function->GetBlock(true); - if (block_die) - sc.block = block.FindBlockByID(block_die.GetID()); - else if (function_die) - sc.block = - block.FindBlockByID(function_die.GetID()); - } - } + if (block_die) + sc.block = block.FindBlockByID(block_die.GetID()); + else if (function_die) + sc.block = block.FindBlockByID(function_die.GetID()); } - - sc_list.Append(sc); - line_idx = line_table->FindLineEntryIndexByFileIndex( - line_idx + 1, file_idx, found_line, true, - &sc.line_entry); } } - } else if (file_spec_matches_cu_file_spec && !check_inlines) { - // only append the context if we aren't looking for inline call - // sites by file and line and if the file spec matches that of - // the compile unit + sc_list.Append(sc); + line_idx = line_table->FindLineEntryIndexByFileIndex( + line_idx + 1, file_idx, found_line, true, &sc.line_entry); } - } else if (file_spec_matches_cu_file_spec && !check_inlines) { - // only append the context if we aren't looking for inline call - // sites by file and line and if the file spec matches that of - // the compile unit - sc_list.Append(sc); } - - if (!check_inlines) - break; + } else if (file_spec_matches_cu_file_spec && !check_inlines) { + // only append the context if we aren't looking for inline call + // sites by file and line and if the file spec matches that of + // the compile unit + sc_list.Append(sc); } + } else if (file_spec_matches_cu_file_spec && !check_inlines) { + // only append the context if we aren't looking for inline call + // sites by file and line and if the file spec matches that of + // the compile unit + sc_list.Append(sc); } + + if (!check_inlines) + break; } } } @@ -2066,7 +1977,7 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( } uint32_t SymbolFileDWARF::FindGlobalVariables( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -2082,7 +1993,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( return 0; DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; // Remember how many variables are in the list before we search. @@ -2090,6 +2001,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( llvm::StringRef basename; llvm::StringRef context; + bool name_is_mangled = (bool)Mangled(name); if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetCString(), context, basename)) @@ -2122,7 +2034,10 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( break; case DW_TAG_variable: { - sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); + auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); + if (!dwarf_cu) + continue; + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); if (parent_decl_ctx) { DWARFASTParser *dwarf_ast = die.GetDWARFParser(); @@ -2139,7 +2054,8 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( &variables); while (pruned_idx < variables.GetSize()) { VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx); - if (var_sp->GetName().GetStringRef().contains(name.GetStringRef())) + if (name_is_mangled || + var_sp->GetName().GetStringRef().contains(name.GetStringRef())) ++pruned_idx; else variables.RemoveVariableAtIndex(pruned_idx); @@ -2150,8 +2066,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( } break; } } else { - m_index->ReportInvalidDIEOffset(die_ref.die_offset, - name.GetStringRef()); + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); } } } @@ -2183,7 +2098,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, } DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; // Remember how many variables are in the list before we search. @@ -2203,14 +2118,18 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, DWARFDIE die = GetDIE(die_ref); if (die) { - sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); + DWARFCompileUnit *dwarf_cu = + llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); + if (!dwarf_cu) + continue; + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); if (variables.GetSize() - original_size >= max_matches) break; } else - m_index->ReportInvalidDIEOffset(die_ref.die_offset, regex.GetText()); + m_index->ReportInvalidDIERef(die_ref, regex.GetText()); } } @@ -2236,7 +2155,7 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, if (die.Tag() == DW_TAG_inlined_subroutine) { inlined_die = die; - while (1) { + while (true) { die = die.GetParent(); if (die) { @@ -2253,12 +2172,12 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, if (inlined_die) { Block &function_block = sc.function->GetBlock(true); sc.block = function_block.FindBlockByID(inlined_die.GetID()); - if (sc.block == NULL) + if (sc.block == nullptr) sc.block = function_block.FindBlockByID(inlined_die.GetOffset()); - if (sc.block == NULL || !sc.block->GetStartAddress(addr)) + if (sc.block == nullptr || !sc.block->GetStartAddress(addr)) addr.Clear(); } else { - sc.block = NULL; + sc.block = nullptr; addr = sc.function->GetAddressRange().GetBaseAddress(); } @@ -2285,14 +2204,14 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx, CompilerDeclContext actual_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); if (actual_decl_ctx) - return actual_decl_ctx == *decl_ctx; + return decl_ctx->IsContainedInLookup(actual_decl_ctx); } } return false; } uint32_t SymbolFileDWARF::FindFunctions( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, bool append, SymbolContextList &sc_list) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); @@ -2328,10 +2247,6 @@ uint32_t SymbolFileDWARF::FindFunctions( const uint32_t original_size = sc_list.GetSize(); - DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) - return 0; - llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies; DIEArray offsets; CompilerDeclContext empty_decl_ctx; @@ -2339,7 +2254,7 @@ uint32_t SymbolFileDWARF::FindFunctions( parent_decl_ctx = &empty_decl_ctx; std::vector<DWARFDIE> dies; - m_index->GetFunctions(name, *info, *parent_decl_ctx, name_type_mask, dies); + m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies); for (const DWARFDIE &die: dies) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); @@ -2394,7 +2309,7 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, for (DIERef ref : offsets) { DWARFDIE die = info->GetDIE(ref); if (!die) { - m_index->ReportInvalidDIEOffset(ref.die_offset, regex.GetText()); + m_index->ReportInvalidDIERef(ref, regex.GetText()); continue; } if (resolved_dies.insert(die.GetDIE()).second) @@ -2411,10 +2326,10 @@ void SymbolFileDWARF::GetMangledNamesForFunction( DWARFDebugInfo *info = DebugInfo(); uint32_t num_comp_units = 0; if (info) - num_comp_units = info->GetNumCompileUnits(); + num_comp_units = info->GetNumUnits(); for (uint32_t i = 0; i < num_comp_units; i++) { - DWARFUnit *cu = info->GetCompileUnitAtIndex(i); + DWARFUnit *cu = info->GetUnitAtIndex(i); if (cu == nullptr) continue; @@ -2423,21 +2338,15 @@ void SymbolFileDWARF::GetMangledNamesForFunction( dwo->GetMangledNamesForFunction(scope_qualified_name, mangled_names); } - NameToOffsetMap::iterator iter = - m_function_scope_qualified_name_map.find(scope_qualified_name); - if (iter == m_function_scope_qualified_name_map.end()) - return; - - DIERefSetSP set_sp = (*iter).second; - std::set<DIERef>::iterator set_iter; - for (set_iter = set_sp->begin(); set_iter != set_sp->end(); set_iter++) { - DWARFDIE die = DebugInfo()->GetDIE(*set_iter); + for (lldb::user_id_t uid : + m_function_scope_qualified_name_map.lookup(scope_qualified_name)) { + DWARFDIE die = GetDIE(uid); mangled_names.push_back(ConstString(die.GetMangledName())); } } uint32_t SymbolFileDWARF::FindTypes( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { @@ -2452,7 +2361,7 @@ uint32_t SymbolFileDWARF::FindTypes( searched_symbol_files.insert(this); DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -2497,8 +2406,7 @@ uint32_t SymbolFileDWARF::FindTypes( break; } } else { - m_index->ReportInvalidDIEOffset(die_ref.die_offset, - name.GetStringRef()); + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); } } const uint32_t num_matches = types.GetSize() - initial_types_size; @@ -2576,8 +2484,7 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, ++num_matches; } } else { - m_index->ReportInvalidDIEOffset(die_ref.die_offset, - name.GetStringRef()); + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); } } return num_matches; @@ -2586,7 +2493,7 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, } CompilerDeclContext -SymbolFileDWARF::FindNamespace(const ConstString &name, +SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext *parent_decl_ctx) { Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -2622,8 +2529,7 @@ SymbolFileDWARF::FindNamespace(const ConstString &name, break; } } else { - m_index->ReportInvalidDIEOffset(die_ref.die_offset, - name.GetStringRef()); + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); } } } @@ -2646,10 +2552,14 @@ TypeSP SymbolFileDWARF::GetTypeForDIE(const DWARFDIE &die, TypeSP type_sp; if (die) { Type *type_ptr = GetDIEToType().lookup(die.GetDIE()); - if (type_ptr == NULL) { - CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU()); - assert(lldb_cu); - SymbolContext sc(lldb_cu); + if (type_ptr == nullptr) { + SymbolContextScope *scope; + if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU())) + scope = GetCompUnitForDWARFCompUnit(*dwarf_cu); + else + scope = GetObjectFile()->GetModule().get(); + assert(scope); + SymbolContext sc(scope); const DWARFDebugInfoEntry *parent_die = die.GetParent().GetDIE(); while (parent_die != nullptr) { if (parent_die->Tag() == DW_TAG_subprogram) @@ -2661,7 +2571,7 @@ TypeSP SymbolFileDWARF::GetTypeForDIE(const DWARFDIE &die, !GetFunction(DWARFDIE(die.GetCU(), parent_die), sc)) sc = sc_backup; - type_sp = ParseType(sc, die, NULL); + type_sp = ParseType(sc, die, nullptr); } else if (type_ptr != DIE_IS_BEING_PARSED) { // Grab the existing type from the master types lists type_sp = type_ptr->shared_from_this(); @@ -2723,8 +2633,8 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) { } Symbol * -SymbolFileDWARF::GetObjCClassSymbol(const ConstString &objc_class_name) { - Symbol *objc_class_symbol = NULL; +SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { + Symbol *objc_class_symbol = nullptr; if (m_obj_file) { Symtab *symtab = m_obj_file->GetSymtab(); if (symtab) { @@ -2753,7 +2663,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( DWARFDebugInfo *debug_info = DebugInfo(); const uint32_t num_compile_units = GetNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { - DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); + DWARFUnit *dwarf_cu = debug_info->GetUnitAtIndex(cu_idx); if (dwarf_cu != cu && dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type()) { m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; @@ -2771,7 +2681,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( // 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::FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, const ConstString &type_name, + const DWARFDIE &die, ConstString type_name, bool must_be_implementation) { TypeSP type_sp; @@ -2829,15 +2739,13 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( } } } else { - m_index->ReportInvalidDIEOffset(die_ref.die_offset, - type_name.GetStringRef()); + m_index->ReportInvalidDIERef(die_ref, type_name.GetStringRef()); } } } return type_sp; } -//---------------------------------------------------------------------- // This function helps to ensure that the declaration contexts match for two // different DIEs. Often times debug information will refer to a forward // declaration of a type (the equivalent of "struct my_struct;". There will @@ -2847,14 +2755,13 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( // type was in the same declaration context as the original DIE. This function // can efficiently compare two DIEs and will return true when the declaration // context matches, and false when they don't. -//---------------------------------------------------------------------- bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1, const DWARFDIE &die2) { if (die1 == die2) return true; - DWARFDIECollection decl_ctx_1; - DWARFDIECollection decl_ctx_2; + std::vector<DWARFDIE> decl_ctx_1; + std::vector<DWARFDIE> decl_ctx_2; // The declaration DIE stack is a stack of the declaration context DIEs all // the way back to the compile unit. If a type "T" is declared inside a class // "B", and class "B" is declared inside a class "A" and class "A" is in a @@ -2870,11 +2777,11 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1, // back to the compiler unit. // First lets grab the decl contexts for both DIEs - die1.GetDeclContextDIEs(decl_ctx_1); - die2.GetDeclContextDIEs(decl_ctx_2); + decl_ctx_1 = die1.GetDeclContextDIEs(); + decl_ctx_2 = die2.GetDeclContextDIEs(); // Make sure the context arrays have the same size, otherwise we are done - const size_t count1 = decl_ctx_1.Size(); - const size_t count2 = decl_ctx_2.Size(); + const size_t count1 = decl_ctx_1.size(); + const size_t count2 = decl_ctx_2.size(); if (count1 != count2) return false; @@ -2884,18 +2791,18 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1, DWARFDIE decl_ctx_die2; size_t i; for (i = 0; i < count1; i++) { - decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex(i); - decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex(i); + decl_ctx_die1 = decl_ctx_1[i]; + decl_ctx_die2 = decl_ctx_2[i]; if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag()) return false; } -#if defined LLDB_CONFIGURATION_DEBUG +#ifndef NDEBUG // Make sure the top item in the decl context die array is always // DW_TAG_compile_unit or DW_TAG_partial_unit. If it isn't then // something went wrong in the DWARFDIE::GetDeclContextDIEs() // function. - dw_tag_t cu_tag = decl_ctx_1.GetDIEAtIndex(count1 - 1).Tag(); + dw_tag_t cu_tag = decl_ctx_1[count1 - 1].Tag(); UNUSED_IF_ASSERT_DISABLED(cu_tag); assert(cu_tag == DW_TAG_compile_unit || cu_tag == DW_TAG_partial_unit); @@ -2903,8 +2810,8 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1, // Always skip the compile unit when comparing by only iterating up to "count // - 1". Here we compare the names as we go. for (i = 0; i < count1 - 1; i++) { - decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex(i); - decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex(i); + decl_ctx_die1 = decl_ctx_1[i]; + decl_ctx_die2 = decl_ctx_2[i]; const char *name1 = decl_ctx_die1.GetName(); const char *name2 = decl_ctx_die2.GetName(); // If the string was from a DW_FORM_strp, then the pointer will often be @@ -3039,8 +2946,7 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( } } } else { - m_index->ReportInvalidDIEOffset(die_ref.die_offset, - type_name.GetStringRef()); + m_index->ReportInvalidDIERef(die_ref, type_name.GetStringRef()); } } } @@ -3051,42 +2957,32 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, bool *type_is_new_ptr) { - TypeSP type_sp; + if (!die) + return {}; - if (die) { - TypeSystem *type_system = - GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + TypeSystem *type_system = + GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + if (!type_system) + return {}; - if (type_system) { - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); - if (dwarf_ast) { - Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); - type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr); - if (type_sp) { - TypeList *type_list = GetTypeList(); - if (type_list) - type_list->Insert(type_sp); - - if (die.Tag() == DW_TAG_subprogram) { - DIERef die_ref = die.GetDIERef(); - std::string scope_qualified_name(GetDeclContextForUID(die.GetID()) - .GetScopeQualifiedName() - .AsCString("")); - if (scope_qualified_name.size()) { - NameToOffsetMap::iterator iter = - m_function_scope_qualified_name_map.find( - scope_qualified_name); - if (iter != m_function_scope_qualified_name_map.end()) - (*iter).second->insert(die_ref); - else { - DIERefSetSP new_set(new std::set<DIERef>); - new_set->insert(die_ref); - m_function_scope_qualified_name_map.emplace( - std::make_pair(scope_qualified_name, new_set)); - } - } - } - } + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (!dwarf_ast) + return {}; + + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr); + if (type_sp) { + TypeList *type_list = GetTypeList(); + if (type_list) + type_list->Insert(type_sp); + + if (die.Tag() == DW_TAG_subprogram) { + std::string scope_qualified_name(GetDeclContextForUID(die.GetID()) + .GetScopeQualifiedName() + .AsCString("")); + if (scope_qualified_name.size()) { + m_function_scope_qualified_name_map[scope_qualified_name].insert( + die.GetID()); } } } @@ -3161,13 +3057,13 @@ size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { ASSERT_MODULE_LOCK(this); - if (sc.comp_unit != NULL) { + if (sc.comp_unit != nullptr) { DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; if (sc.function) { - DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID(), this)); + DWARFDIE function_die = GetDIE(sc.function->GetID()); const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress( DW_AT_low_pc, LLDB_INVALID_ADDRESS); @@ -3180,20 +3076,21 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { return num_variables; } } else if (sc.comp_unit) { - DWARFUnit *dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()); + DWARFUnit *dwarf_cu = info->GetUnitAtIndex(sc.comp_unit->GetID()); - if (dwarf_cu == NULL) + if (dwarf_cu == nullptr) return 0; uint32_t vars_added = 0; VariableListSP variables(sc.comp_unit->GetVariableList(false)); - if (variables.get() == NULL) { - variables.reset(new VariableList()); + if (variables.get() == nullptr) { + variables = std::make_shared<VariableList>(); sc.comp_unit->SetVariableList(variables); DIEArray die_offsets; - m_index->GetGlobalVariables(*dwarf_cu, die_offsets); + m_index->GetGlobalVariables(dwarf_cu->GetNonSkeletonUnit(), + die_offsets); const size_t num_matches = die_offsets.size(); if (num_matches) { for (size_t i = 0; i < num_matches; ++i) { @@ -3207,7 +3104,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { ++vars_added; } } else - m_index->ReportInvalidDIEOffset(die_ref.die_offset, ""); + m_index->ReportInvalidDIERef(die_ref, ""); } } } @@ -3240,12 +3137,12 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, const size_t num_attributes = die.GetAttributes(attributes); DWARFDIE spec_die; if (num_attributes > 0) { - const char *name = NULL; - const char *mangled = NULL; + const char *name = nullptr; + const char *mangled = nullptr; Declaration decl; uint32_t i; DWARFFormValue type_die_form; - DWARFExpression location(die.GetCU()); + DWARFExpression location; bool is_external = false; bool is_artificial = false; bool location_is_const_value_data = false; @@ -3296,18 +3193,16 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location.CopyOpcodeData(module, debug_info_data, block_offset, - block_length); + location = DWARFExpression(module, debug_info_data, die.GetCU(), + block_offset, block_length); } else if (DWARFFormValue::IsDataForm(form_value.Form())) { // Retrieve the value as a data expression. - DWARFFormValue::FixedFormSizes fixed_form_sizes = - DWARFFormValue::GetFixedFormSizesForAddressSize( - attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), - attributes.CompileUnitAtIndex(i)->IsDWARF64()); uint32_t data_offset = attributes.DIEOffsetAtIndex(i); - uint32_t data_length = - fixed_form_sizes.GetSize(form_value.Form()); - if (data_length == 0) { + if (auto data_length = form_value.GetFixedSize()) + location = + DWARFExpression(module, debug_info_data, die.GetCU(), + data_offset, *data_length); + else { const uint8_t *data_pointer = form_value.BlockData(); if (data_pointer) { form_value.Unsigned(); @@ -3316,29 +3211,23 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, // create the variable const_value = form_value; } - } else - location.CopyOpcodeData(module, debug_info_data, data_offset, - data_length); + } } else { // Retrieve the value as a string expression. if (form_value.Form() == DW_FORM_strp) { - DWARFFormValue::FixedFormSizes fixed_form_sizes = - DWARFFormValue::GetFixedFormSizesForAddressSize( - attributes.CompileUnitAtIndex(i) - ->GetAddressByteSize(), - attributes.CompileUnitAtIndex(i)->IsDWARF64()); uint32_t data_offset = attributes.DIEOffsetAtIndex(i); - uint32_t data_length = - fixed_form_sizes.GetSize(form_value.Form()); - location.CopyOpcodeData(module, debug_info_data, data_offset, - data_length); + if (auto data_length = form_value.GetFixedSize()) + location = + DWARFExpression(module, debug_info_data, die.GetCU(), + data_offset, *data_length); } else { const char *str = form_value.AsCString(); uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart(); uint32_t string_length = strlen(str) + 1; - location.CopyOpcodeData(module, debug_info_data, - string_offset, string_length); + location = + DWARFExpression(module, debug_info_data, die.GetCU(), + string_offset, string_length); } } } @@ -3352,7 +3241,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location.CopyOpcodeData(module, data, block_offset, block_length); + location = DWARFExpression(module, data, die.GetCU(), + block_offset, block_length); } else { const DWARFDataExtractor &debug_loc_data = DebugLocData(); const dw_offset_t debug_loc_offset = form_value.Unsigned(); @@ -3360,8 +3250,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, size_t loc_list_length = DWARFExpression::LocationListSize( die.GetCU(), debug_loc_data, debug_loc_offset); if (loc_list_length > 0) { - location.CopyOpcodeData(module, debug_loc_data, - debug_loc_offset, loc_list_length); + location = DWARFExpression(module, debug_loc_data, die.GetCU(), + debug_loc_offset, loc_list_length); assert(func_low_pc != LLDB_INVALID_ADDRESS); location.SetLocationListSlide( func_low_pc - @@ -3370,31 +3260,11 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, } } break; case DW_AT_specification: - spec_die = GetDIE(DIERef(form_value)); + spec_die = form_value.Reference(); + break; + case DW_AT_start_scope: + // TODO: Implement this. break; - case DW_AT_start_scope: { - if (form_value.Form() == DW_FORM_sec_offset) { - DWARFRangeList dwarf_scope_ranges; - const DWARFDebugRangesBase *debug_ranges = DebugRanges(); - debug_ranges->FindRanges(die.GetCU(), - form_value.Unsigned(), - dwarf_scope_ranges); - } else { - // TODO: Handle the case when DW_AT_start_scope have form - // constant. The - // dwarf spec is a bit ambiguous about what is the expected - // behavior in case the enclosing block have a non coninious - // address range and the DW_AT_start_scope entry have a form - // constant. - GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 - ": DW_AT_start_scope has unsupported form type (0x%x)\n", - die.GetID(), form_value.Form()); - } - - scope_ranges.Sort(); - scope_ranges.CombineConsecutiveRanges(); - } break; case DW_AT_artificial: is_artificial = form_value.Boolean(); break; @@ -3425,7 +3295,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, ValueType scope = eValueTypeInvalid; const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die); - SymbolContextScope *symbol_context_scope = NULL; + SymbolContextScope *symbol_context_scope = nullptr; bool has_explicit_mangled = mangled != nullptr; if (!mangled) { @@ -3471,7 +3341,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (op_error) { StreamString strm; location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0, - NULL); + nullptr); GetObjectFile()->GetModule()->ReportError( "0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetData()); @@ -3574,7 +3444,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, } } - if (symbol_context_scope == NULL) { + if (symbol_context_scope == nullptr) { switch (parent_tag) { case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: @@ -3582,7 +3452,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (sc.function) { symbol_context_scope = sc.function->GetBlock(true).FindBlockByID( sc_parent_die.GetID()); - if (symbol_context_scope == NULL) + if (symbol_context_scope == nullptr) symbol_context_scope = sc.function; } break; @@ -3595,17 +3465,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (symbol_context_scope) { SymbolFileTypeSP type_sp( - new SymbolFileType(*this, DIERef(type_die_form).GetUID(this))); + new SymbolFileType(*this, GetUID(type_die_form.Reference()))); if (const_value.Form() && type_sp && type_sp->GetType()) - location.CopyOpcodeData(const_value.Unsigned(), - type_sp->GetType()->GetByteSize(), - die.GetCU()->GetAddressByteSize()); + location.UpdateValue(const_value.Unsigned(), + type_sp->GetType()->GetByteSize().getValueOr(0), + die.GetCU()->GetAddressByteSize()); - var_sp.reset(new Variable(die.GetID(), name, mangled, type_sp, scope, - symbol_context_scope, scope_ranges, &decl, - location, is_external, is_artificial, - is_static_member)); + var_sp = std::make_shared<Variable>( + die.GetID(), name, mangled, type_sp, scope, symbol_context_scope, + scope_ranges, &decl, location, is_external, is_artificial, + is_static_member); var_sp->SetLocationIsConstantValueData(location_is_const_value_data); } else { @@ -3644,12 +3514,11 @@ SymbolFileDWARF::FindBlockContainingSpecification( case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: case DW_TAG_lexical_block: { - if (die.GetAttributeValueAsReference( - DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset) + if (die.GetReferencedDIE(DW_AT_specification).GetOffset() == + spec_block_die_offset) return die; - if (die.GetAttributeValueAsReference(DW_AT_abstract_origin, - DW_INVALID_OFFSET) == + if (die.GetReferencedDIE(DW_AT_abstract_origin).GetOffset() == spec_block_die_offset) return die; } break; @@ -3694,16 +3563,16 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, // We haven't already parsed it, lets do that now. if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) || (tag == DW_TAG_formal_parameter && sc.function)) { - if (variable_list_sp.get() == NULL) { + if (variable_list_sp.get() == nullptr) { DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die); dw_tag_t parent_tag = sc_parent_die.Tag(); switch (parent_tag) { case DW_TAG_compile_unit: case DW_TAG_partial_unit: - if (sc.comp_unit != NULL) { + if (sc.comp_unit != nullptr) { variable_list_sp = sc.comp_unit->GetVariableList(false); - if (variable_list_sp.get() == NULL) { - variable_list_sp.reset(new VariableList()); + if (variable_list_sp.get() == nullptr) { + variable_list_sp = std::make_shared<VariableList>(); } } else { GetObjectFile()->GetModule()->ReportError( @@ -3718,31 +3587,31 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: case DW_TAG_lexical_block: - if (sc.function != NULL) { + if (sc.function != nullptr) { // Check to see if we already have parsed the variables for the // given scope Block *block = sc.function->GetBlock(true).FindBlockByID( sc_parent_die.GetID()); - if (block == NULL) { + if (block == nullptr) { // This must be a specification or abstract origin with a // concrete block counterpart in the current function. We need // to find the concrete block so we can correctly add the // variable to it const DWARFDIE concrete_block_die = FindBlockContainingSpecification( - DIERef(sc.function->GetID(), this), + GetDIE(sc.function->GetID()), sc_parent_die.GetOffset()); if (concrete_block_die) block = sc.function->GetBlock(true).FindBlockByID( concrete_block_die.GetID()); } - if (block != NULL) { + if (block != nullptr) { const bool can_create = false; variable_list_sp = block->GetBlockVariableList(can_create); - if (variable_list_sp.get() == NULL) { - variable_list_sp.reset(new VariableList()); + if (variable_list_sp.get() == nullptr) { + variable_list_sp = std::make_shared<VariableList>(); block->SetVariableList(variable_list_sp); } } @@ -3770,7 +3639,7 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, } } - bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram); + bool skip_children = (sc.function == nullptr && tag == DW_TAG_subprogram); if (!skip_children && parse_children && die.HasChildren()) { vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, @@ -3833,15 +3702,13 @@ CollectCallEdges(DWARFDIE function_die) { std::vector<lldb_private::CallEdge> SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) { - DWARFDIE func_die = GetDIEFromUID(func_id.GetID()); + DWARFDIE func_die = GetDIE(func_id.GetID()); if (func_die.IsValid()) return CollectCallEdges(func_die); return {}; } -//------------------------------------------------------------------ // PluginInterface protocol -//------------------------------------------------------------------ ConstString SymbolFileDWARF::GetPluginName() { return GetPluginNameStatic(); } uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; } @@ -3857,7 +3724,7 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { } SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { - if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) { + if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); if (module_sp) { SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); @@ -3882,7 +3749,10 @@ SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { module_spec.GetFileSpec() = m_obj_file->GetFileSpec(); module_spec.GetSymbolFileSpec() = FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp"); - FileSpec dwp_filespec = Symbols::LocateExecutableSymbolFile(module_spec); + + FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); + FileSpec dwp_filespec = + Symbols::LocateExecutableSymbolFile(module_spec, search_paths); if (FileSystem::Instance().Exists(dwp_filespec)) { m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(), dwp_filespec); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index d351289f8b51..018af47305f4 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -1,9 +1,8 @@ //===-- SymbolFileDWARF.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -20,9 +19,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Threading.h" -#include "lldb/Utility/Flags.h" - -#include "lldb/Core/RangeMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Core/dwarf.h" #include "lldb/Expression/DWARFExpression.h" @@ -30,20 +26,21 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Flags.h" +#include "lldb/Utility/RangeMap.h" #include "lldb/lldb-private.h" +#include "DWARFContext.h" #include "DWARFDataExtractor.h" #include "DWARFDefines.h" #include "DWARFIndex.h" #include "UniqueDWARFASTType.h" -//---------------------------------------------------------------------- // Forward Declarations for this DWARF plugin -//---------------------------------------------------------------------- class DebugMapModule; class DWARFAbbreviationDeclaration; class DWARFAbbreviationDeclarationSet; -class DWARFileUnit; +class DWARFCompileUnit; class DWARFDebugAbbrev; class DWARFDebugAranges; class DWARFDebugInfo; @@ -51,8 +48,8 @@ class DWARFDebugInfoEntry; class DWARFDebugLine; class DWARFDebugRangesBase; class DWARFDeclContext; -class DWARFDIECollection; class DWARFFormValue; +class DWARFTypeUnit; class SymbolFileDWARFDebugMap; class SymbolFileDWARFDwo; class SymbolFileDWARFDwp; @@ -65,14 +62,11 @@ public: friend class SymbolFileDWARFDebugMap; friend class SymbolFileDWARFDwo; friend class DebugMapModule; - friend struct DIERef; - friend class DWARFUnit; + friend class DWARFCompileUnit; friend class DWARFDIE; friend class DWARFASTParserClang; - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -86,11 +80,12 @@ public: static lldb_private::SymbolFile * CreateInstance(lldb_private::ObjectFile *obj_file); - //------------------------------------------------------------------ + static lldb_private::FileSpecList GetSymlinkPaths(); + // Constructors and Destructors - //------------------------------------------------------------------ - SymbolFileDWARF(lldb_private::ObjectFile *ofile); + SymbolFileDWARF(lldb_private::ObjectFile *ofile, + lldb_private::SectionList *dwo_section_list); ~SymbolFileDWARF() override; @@ -98,9 +93,7 @@ public: void InitializeObject() override; - //------------------------------------------------------------------ // Compile Unit function calls - //------------------------------------------------------------------ uint32_t GetNumCompileUnits() override; @@ -124,7 +117,7 @@ public: bool ParseImportedModules( const lldb_private::SymbolContext &sc, - std::vector<lldb_private::ConstString> &imported_modules) override; + std::vector<lldb_private::SourceModule> &imported_modules) override; size_t ParseBlocksRecursive(lldb_private::Function &func) override; @@ -142,11 +135,6 @@ public: bool assert_not_being_parsed = true, bool resolve_function_context = false); - SymbolFileDWARF *GetDWARFForUID(lldb::user_id_t uid); - - DWARFDIE - GetDIEFromUID(lldb::user_id_t uid); - lldb_private::CompilerDecl GetDeclForUID(lldb::user_id_t uid) override; lldb_private::CompilerDeclContext @@ -169,7 +157,7 @@ public: lldb_private::SymbolContextList &sc_list) override; uint32_t - FindGlobalVariables(const lldb_private::ConstString &name, + FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; @@ -179,7 +167,7 @@ public: lldb_private::VariableList &variables) override; uint32_t - FindFunctions(const lldb_private::ConstString &name, + FindFunctions(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, lldb::FunctionNameType name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list) override; @@ -193,7 +181,7 @@ public: std::vector<lldb_private::ConstString> &mangled_names) override; uint32_t - FindTypes(const lldb_private::ConstString &name, + FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, @@ -212,40 +200,20 @@ public: GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; void PreloadSymbols() override; std::recursive_mutex &GetModuleMutex() const override; - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ lldb_private::ConstString GetPluginName() override; uint32_t GetPluginVersion() override; - virtual const lldb_private::DWARFDataExtractor &get_debug_abbrev_data(); - virtual const lldb_private::DWARFDataExtractor &get_debug_addr_data(); - const lldb_private::DWARFDataExtractor &get_debug_aranges_data(); - const lldb_private::DWARFDataExtractor &get_debug_frame_data(); - virtual const lldb_private::DWARFDataExtractor &get_debug_info_data(); - const lldb_private::DWARFDataExtractor &get_debug_line_data(); - const lldb_private::DWARFDataExtractor &get_debug_line_str_data(); - const lldb_private::DWARFDataExtractor &get_debug_macro_data(); const lldb_private::DWARFDataExtractor &get_debug_loc_data(); const lldb_private::DWARFDataExtractor &get_debug_loclists_data(); - const lldb_private::DWARFDataExtractor &get_debug_ranges_data(); - const lldb_private::DWARFDataExtractor &get_debug_rnglists_data(); - virtual const lldb_private::DWARFDataExtractor &get_debug_str_data(); - virtual const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data(); - const lldb_private::DWARFDataExtractor &get_debug_types_data(); - const lldb_private::DWARFDataExtractor &get_apple_names_data(); - const lldb_private::DWARFDataExtractor &get_apple_types_data(); - const lldb_private::DWARFDataExtractor &get_apple_namespaces_data(); - const lldb_private::DWARFDataExtractor &get_apple_objc_data(); - const lldb_private::DWARFDataExtractor &get_gnu_debugaltlink(); DWARFDebugAbbrev *DebugAbbrev(); @@ -255,9 +223,8 @@ public: const DWARFDebugInfo *DebugInfo() const; - DWARFDebugRangesBase *DebugRanges(); - - const DWARFDebugRangesBase *DebugRanges() const; + DWARFDebugRangesBase *GetDebugRanges(); + DWARFDebugRangesBase *GetDebugRngLists(); const lldb_private::DWARFDataExtractor &DebugLocData(); @@ -270,8 +237,7 @@ public: HasForwardDeclForClangType(const lldb_private::CompilerType &compiler_type); lldb_private::CompileUnit * - GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu, - uint32_t cu_idx = UINT32_MAX); + GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu); virtual size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, DIEArray &method_die_offsets); @@ -282,8 +248,7 @@ public: static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die); - virtual lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu, - uint32_t cu_idx); + virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu); virtual lldb_private::DWARFExpression::LocationListFormat GetLocationListFormat() const; @@ -300,6 +265,18 @@ public: virtual DWARFDIE GetDIE(const DIERef &die_ref); + DWARFDIE GetDIE(lldb::user_id_t uid); + + lldb::user_id_t GetUID(const DWARFBaseDIE &die) { + return GetUID(die.GetDIERef()); + } + + lldb::user_id_t GetUID(const llvm::Optional<DIERef> &ref) { + return ref ? GetUID(*ref) : LLDB_INVALID_UID; + } + + lldb::user_id_t GetUID(DIERef ref); + virtual std::unique_ptr<SymbolFileDWARFDwo> GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die); @@ -307,7 +284,9 @@ public: // For regular SymbolFileDWARF instances the method returns nullptr, // for the instances of the subclass SymbolFileDWARFDwo // the method returns a pointer to the base compile unit. - virtual DWARFUnit *GetBaseCompileUnit(); + virtual DWARFCompileUnit *GetBaseCompileUnit() { return nullptr; } + + virtual llvm::Optional<uint32_t> GetDwoNum() { return llvm::None; } static bool DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx, @@ -320,6 +299,10 @@ public: void DumpClangAST(lldb_private::Stream &s) override; + lldb_private::DWARFContext &GetDWARFContext() { return m_context; } + + lldb_private::FileSpec GetFile(DWARFUnit &unit, size_t file_idx); + protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; @@ -328,7 +311,8 @@ protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::opaque_compiler_type_t> DIEToClangType; - typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> ClangTypeToDIE; + typedef llvm::DenseMap<lldb::opaque_compiler_type_t, lldb::user_id_t> + ClangTypeToDIE; struct DWARFDataSegment { llvm::once_flag m_flag; @@ -381,7 +365,7 @@ protected: const DWARFDIE &orig_die, const lldb::addr_t func_low_pc, bool parse_siblings, bool parse_children, - lldb_private::VariableList *cc_variable_list = NULL); + lldb_private::VariableList *cc_variable_list = nullptr); bool ClassOrStructIsVirtual(const DWARFDIE &die); @@ -393,11 +377,11 @@ protected: FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx); virtual lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, const lldb_private::ConstString &type_name, + const DWARFDIE &die, lldb_private::ConstString type_name, bool must_be_implementation); lldb_private::Symbol * - GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name); + GetObjCClassSymbol(lldb_private::ConstString objc_class_name); lldb::TypeSP GetTypeForDIE(const DWARFDIE &die, bool resolve_function_context = false); @@ -421,7 +405,7 @@ protected: bool DIEDeclContextsMatch(const DWARFDIE &die1, const DWARFDIE &die2); bool ClassContainsSelector(const DWARFDIE &class_die, - const lldb_private::ConstString &selector); + lldb_private::ConstString selector); bool FixupAddress(lldb_private::Address &addr); @@ -451,44 +435,35 @@ protected: return m_forward_decl_clang_type_to_die; } + void BuildCuTranslationTable(); + llvm::Optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx); + + struct DecodedUID { + SymbolFileDWARF &dwarf; + DIERef ref; + }; + llvm::Optional<DecodedUID> DecodeUID(lldb::user_id_t uid); + SymbolFileDWARFDwp *GetDwpSymbolFile(); + const lldb_private::FileSpecList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap *m_debug_map_symfile; llvm::once_flag m_dwp_symfile_once_flag; std::unique_ptr<SymbolFileDWARFDwp> m_dwp_symfile; - lldb_private::DWARFDataExtractor m_dwarf_data; + lldb_private::DWARFContext m_context; - DWARFDataSegment m_data_debug_abbrev; - DWARFDataSegment m_data_debug_addr; - DWARFDataSegment m_data_debug_aranges; - DWARFDataSegment m_data_debug_frame; - DWARFDataSegment m_data_debug_info; - DWARFDataSegment m_data_debug_line; - DWARFDataSegment m_data_debug_line_str; - DWARFDataSegment m_data_debug_macro; DWARFDataSegment m_data_debug_loc; DWARFDataSegment m_data_debug_loclists; - DWARFDataSegment m_data_debug_ranges; - DWARFDataSegment m_data_debug_rnglists; - DWARFDataSegment m_data_debug_str; - DWARFDataSegment m_data_debug_str_offsets; - DWARFDataSegment m_data_debug_types; - DWARFDataSegment m_data_apple_names; - DWARFDataSegment m_data_apple_types; - DWARFDataSegment m_data_apple_namespaces; - DWARFDataSegment m_data_apple_objc; - DWARFDataSegment m_data_gnu_debugaltlink; // The unique pointer items below are generated on demand if and when someone - // accesses - // them through a non const version of this class. + // accesses them through a non const version of this class. std::unique_ptr<DWARFDebugAbbrev> m_abbr; std::unique_ptr<DWARFDebugInfo> m_info; - std::unique_ptr<DWARFDebugLine> m_line; - std::unique_ptr<GlobalVariableMap> m_global_aranges_ap; + std::unique_ptr<GlobalVariableMap> m_global_aranges_up; typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP> DebugMacrosMap; @@ -499,15 +474,19 @@ protected: bool m_fetched_external_modules : 1; lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; - typedef std::shared_ptr<std::set<DIERef>> DIERefSetSP; - typedef std::unordered_map<std::string, DIERefSetSP> NameToOffsetMap; + typedef std::set<lldb::user_id_t> DIERefSet; + typedef llvm::StringMap<DIERefSet> NameToOffsetMap; NameToOffsetMap m_function_scope_qualified_name_map; std::unique_ptr<DWARFDebugRangesBase> m_ranges; + std::unique_ptr<DWARFDebugRangesBase> m_rnglists; UniqueDWARFASTTypeMap m_unique_ast_type_map; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; DIEToClangType m_forward_decl_die_to_clang_type; ClangTypeToDIE m_forward_decl_clang_type_to_die; + llvm::DenseMap<dw_offset_t, lldb_private::FileSpecList> + m_type_unit_support_files; + std::vector<uint32_t> m_lldb_cu_to_dwarf_unit; }; #endif // SymbolFileDWARF_SymbolFileDWARF_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 2c1e6416a935..8ec64dbaf764 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1,22 +1,20 @@ //===-- SymbolFileDWARFDebugMap.cpp -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "SymbolFileDWARFDebugMap.h" - #include "DWARFDebugAranges.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/RangeMap.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Utility/RangeMap.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Timer.h" @@ -36,6 +34,8 @@ #include "LogChannelDWARF.h" #include "SymbolFileDWARF.h" +#include <memory> + using namespace lldb; using namespace lldb_private; @@ -60,13 +60,11 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( return file_range_map; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); - if (log) { - ConstString object_name(oso_module->GetObjectName()); + if (log) log->Printf( "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')", static_cast<void *>(this), oso_module->GetSpecificationDescription().c_str()); - } std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos; if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) { @@ -177,10 +175,10 @@ public: SymbolVendor * GetSymbolVendor(bool can_create = true, - lldb_private::Stream *feedback_strm = NULL) override { + lldb_private::Stream *feedback_strm = nullptr) override { // Scope for locker - if (m_symfile_ap.get() || !can_create) - return m_symfile_ap.get(); + if (m_symfile_up.get() || !can_create) + return m_symfile_up.get(); ModuleSP exe_module_sp(m_exe_module_wp.lock()); if (exe_module_sp) { @@ -199,7 +197,7 @@ public: symbol_vendor->GetSymbolFile()); if (!oso_symfile) - return NULL; + return nullptr; ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor(); @@ -215,7 +213,7 @@ public: } } } - return NULL; + return nullptr; } protected: @@ -370,12 +368,12 @@ void SymbolFileDWARFDebugMap::InitOSO() { oso_symbol->GetName().GetCString()); } } else { - if (oso_symbol == NULL) + if (oso_symbol == nullptr) m_obj_file->GetModule()->ReportError( "N_OSO symbol[%u] can't be found, please file a bug and attach " "the binary listed in this error", oso_idx); - else if (so_symbol == NULL) + else if (so_symbol == nullptr) m_obj_file->GetModule()->ReportError( "N_SO not found for N_OSO symbol[%u], please file a bug and " "attach the binary listed in this error", @@ -400,7 +398,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx) { const uint32_t cu_count = GetNumCompileUnits(); if (oso_idx < cu_count) return GetModuleByCompUnitInfo(&m_compile_unit_infos[oso_idx]); - return NULL; + return nullptr; } Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( @@ -412,7 +410,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( comp_unit_info->oso_sp = pos->second; } else { ObjectFile *obj_file = GetObjectFile(); - comp_unit_info->oso_sp.reset(new OSOInfo()); + comp_unit_info->oso_sp = std::make_shared<OSOInfo>(); m_oso_map[{comp_unit_info->oso_path, comp_unit_info->oso_mod_time}] = comp_unit_info->oso_sp; const char *oso_path = comp_unit_info->oso_path.GetCString(); @@ -430,7 +428,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( ") since this executable was linked, file will be ignored", oso_file.GetPath().c_str(), llvm::to_string(oso_mod_time).c_str(), llvm::to_string(comp_unit_info->oso_mod_time).c_str()); - return NULL; + return nullptr; } } else { @@ -438,7 +436,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( if (!ObjectFile::SplitArchivePathWithObject(oso_path, oso_file, oso_object, must_exist)) { - return NULL; + return nullptr; } } // Always create a new module for .o files. Why? Because we use the debug @@ -456,16 +454,15 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( .getArchName() .str() .c_str()); - comp_unit_info->oso_sp->module_sp.reset(new DebugMapModule( + comp_unit_info->oso_sp->module_sp = std::make_shared<DebugMapModule>( obj_file->GetModule(), GetCompUnitInfoIndex(comp_unit_info), oso_file, - oso_arch, oso_object ? &oso_object : NULL, 0, - oso_object ? comp_unit_info->oso_mod_time - : llvm::sys::TimePoint<>())); + oso_arch, oso_object ? &oso_object : nullptr, 0, + oso_object ? comp_unit_info->oso_mod_time : llvm::sys::TimePoint<>()); } } if (comp_unit_info->oso_sp) return comp_unit_info->oso_sp->module_sp.get(); - return NULL; + return nullptr; } bool SymbolFileDWARFDebugMap::GetFileSpecForSO(uint32_t oso_idx, @@ -483,7 +480,7 @@ ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex(uint32_t oso_idx) { Module *oso_module = GetModuleByOSOIndex(oso_idx); if (oso_module) return oso_module->GetObjectFile(); - return NULL; + return nullptr; } SymbolFileDWARF * @@ -496,7 +493,7 @@ SymbolFileDWARFDebugMap::GetSymbolFile(const CompileUnit &comp_unit) { CompileUnitInfo *comp_unit_info = GetCompUnitInfo(comp_unit); if (comp_unit_info) return GetSymbolFileByCompUnitInfo(comp_unit_info); - return NULL; + return nullptr; } ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo( @@ -504,7 +501,7 @@ ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo( Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info); if (oso_module) return oso_module->GetObjectFile(); - return NULL; + return nullptr; } uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex( @@ -524,7 +521,7 @@ SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx) { unsigned size = m_compile_unit_infos.size(); if (oso_idx < size) return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[oso_idx]); - return NULL; + return nullptr; } SymbolFileDWARF * @@ -532,7 +529,7 @@ SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) { if (sym_file && sym_file->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic()) return (SymbolFileDWARF *)sym_file; - return NULL; + return nullptr; } SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo( @@ -543,7 +540,7 @@ SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo( if (sym_vendor) return GetSymbolFileAsSymbolFileDWARF(sym_vendor->GetSymbolFile()); } - return NULL; + return nullptr; } uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() { @@ -582,9 +579,10 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) { // User zero as the ID to match the compile unit at offset zero in each // .o file since each .o file can only have one compile unit for now. lldb::user_id_t cu_id = 0; - m_compile_unit_infos[cu_idx].compile_unit_sp.reset( - new CompileUnit(m_obj_file->GetModule(), NULL, so_file_spec, cu_id, - eLanguageTypeUnknown, eLazyBoolCalculate)); + m_compile_unit_infos[cu_idx].compile_unit_sp = + std::make_shared<CompileUnit>( + m_obj_file->GetModule(), nullptr, so_file_spec, cu_id, + eLanguageTypeUnknown, eLazyBoolCalculate); if (m_compile_unit_infos[cu_idx].compile_unit_sp) { // Let our symbol vendor know about this compile unit @@ -611,7 +609,7 @@ SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) { if (comp_unit == m_compile_unit_infos[i].compile_unit_sp.get()) return &m_compile_unit_infos[i]; } - return NULL; + return nullptr; } size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule( @@ -670,7 +668,7 @@ bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) { } bool SymbolFileDWARFDebugMap::ParseImportedModules( - const SymbolContext &sc, std::vector<ConstString> &imported_modules) { + const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); if (oso_dwarf) return oso_dwarf->ParseImportedModules(sc, imported_modules); @@ -708,7 +706,7 @@ Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) return oso_dwarf->ResolveTypeUID(type_uid); - return NULL; + return nullptr; } llvm::Optional<SymbolFile::ArrayInfo> @@ -752,7 +750,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, sc.symbol = symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex()); - if (sc.symbol != NULL) { + if (sc.symbol != nullptr) { resolved_flags |= eSymbolContextSymbol; uint32_t oso_idx = 0; @@ -810,7 +808,7 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( } uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &indexes, // Indexes into the symbol table that match "name" uint32_t max_matches, VariableList &variables) { @@ -834,7 +832,7 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( } uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { // Remember how many variables are in the list before we search. @@ -932,7 +930,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo * SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex( uint32_t symbol_idx, uint32_t *oso_idx_ptr) { const uint32_t oso_index_count = m_compile_unit_infos.size(); - CompileUnitInfo *comp_unit_info = NULL; + CompileUnitInfo *comp_unit_info = nullptr; if (oso_index_count) { comp_unit_info = (CompileUnitInfo *)bsearch( &symbol_idx, &m_compile_unit_infos[0], m_compile_unit_infos.size(), @@ -941,7 +939,7 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex( } if (oso_idx_ptr) { - if (comp_unit_info != NULL) + if (comp_unit_info != nullptr) *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0]; else *oso_idx_ptr = UINT32_MAX; @@ -953,7 +951,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo * SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID( user_id_t symbol_id, uint32_t *oso_idx_ptr) { const uint32_t oso_index_count = m_compile_unit_infos.size(); - CompileUnitInfo *comp_unit_info = NULL; + CompileUnitInfo *comp_unit_info = nullptr; if (oso_index_count) { comp_unit_info = (CompileUnitInfo *)::bsearch( &symbol_id, &m_compile_unit_infos[0], m_compile_unit_infos.size(), @@ -962,7 +960,7 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID( } if (oso_idx_ptr) { - if (comp_unit_info != NULL) + if (comp_unit_info != nullptr) *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0]; else *oso_idx_ptr = UINT32_MAX; @@ -996,7 +994,7 @@ static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp, } uint32_t SymbolFileDWARFDebugMap::FindFunctions( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, bool append, SymbolContextList &sc_list) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); @@ -1060,7 +1058,7 @@ size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, type_mask); uint32_t initial_size = type_list.GetSize(); - SymbolFileDWARF *oso_dwarf = NULL; + SymbolFileDWARF *oso_dwarf = nullptr; if (sc_scope) { SymbolContext sc; sc_scope->CalculateSymbolContext(&sc); @@ -1105,7 +1103,7 @@ bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type( m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { if (skip_dwarf_oso != oso_dwarf && - oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(NULL)) { + oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(nullptr)) { m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; return true; } @@ -1116,7 +1114,7 @@ bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type( } TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, const ConstString &type_name, + const DWARFDIE &die, ConstString type_name, bool must_be_implementation) { // If we have a debug map, we will have an Objective-C symbol whose name is // the type name and whose type is eSymbolTypeObjCClass. If we can find that @@ -1124,7 +1122,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( // contain the implementation definition since it will be scoped inside the // N_SO and we can then locate the SymbolFileDWARF that corresponds to that // N_SO. - SymbolFileDWARF *oso_dwarf = NULL; + SymbolFileDWARF *oso_dwarf = nullptr; TypeSP type_sp; ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile(); if (module_objfile) { @@ -1145,7 +1143,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( if (source_file_symbol_idx != UINT32_MAX) { CompileUnitInfo *compile_unit_info = GetCompileUnitInfoForSymbolWithIndex(source_file_symbol_idx, - NULL); + nullptr); if (compile_unit_info) { oso_dwarf = GetSymbolFileByCompUnitInfo(compile_unit_info); if (oso_dwarf) { @@ -1180,7 +1178,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( } uint32_t SymbolFileDWARFDebugMap::FindTypes( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { @@ -1212,7 +1210,7 @@ uint32_t SymbolFileDWARFDebugMap::FindTypes( //} CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const CompilerDeclContext *parent_decl_ctx) { CompilerDeclContext matching_namespace; @@ -1232,9 +1230,7 @@ void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) { }); } -//------------------------------------------------------------------ // PluginInterface protocol -//------------------------------------------------------------------ lldb_private::ConstString SymbolFileDWARFDebugMap::GetPluginName() { return GetPluginNameStatic(); } @@ -1272,7 +1268,7 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf) { } } } - return NULL; + return nullptr; } void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf, @@ -1418,7 +1414,7 @@ LineTable *SymbolFileDWARFDebugMap::LinkOSOLineTable(SymbolFileDWARF *oso_dwarf, CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_dwarf); if (cu_info) return line_table->LinkLineTable(cu_info->GetFileRangeMap(this)); - return NULL; + return nullptr; } size_t diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 176eadeeca71..afc6142e8231 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -1,23 +1,21 @@ //===-- SymbolFileDWARFDebugMap.h ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 SymbolFileDWARF_SymbolFileDWARFDebugMap_h_ #define SymbolFileDWARF_SymbolFileDWARFDebugMap_h_ +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Utility/RangeMap.h" +#include "llvm/Support/Chrono.h" #include <bitset> #include <map> #include <vector> -#include "lldb/Core/RangeMap.h" -#include "lldb/Symbol/SymbolFile.h" -#include "llvm/Support/Chrono.h" - #include "UniqueDWARFASTType.h" class SymbolFileDWARF; @@ -26,9 +24,7 @@ class DWARFDeclContext; class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile { public: - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -40,18 +36,14 @@ public: static lldb_private::SymbolFile * CreateInstance(lldb_private::ObjectFile *obj_file); - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ SymbolFileDWARFDebugMap(lldb_private::ObjectFile *ofile); ~SymbolFileDWARFDebugMap() override; uint32_t CalculateAbilities() override; void InitializeObject() override; - //------------------------------------------------------------------ // Compile Unit function calls - //------------------------------------------------------------------ uint32_t GetNumCompileUnits() override; lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; @@ -73,7 +65,7 @@ public: bool ParseImportedModules( const lldb_private::SymbolContext &sc, - std::vector<lldb_private::ConstString> &imported_modules) override; + std::vector<lldb_private::SourceModule> &imported_modules) override; size_t ParseBlocksRecursive(lldb_private::Function &func) override; size_t ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; @@ -100,7 +92,7 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; uint32_t - FindGlobalVariables(const lldb_private::ConstString &name, + FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; @@ -108,7 +100,7 @@ public: uint32_t max_matches, lldb_private::VariableList &variables) override; uint32_t - FindFunctions(const lldb_private::ConstString &name, + FindFunctions(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, lldb::FunctionNameType name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list) override; @@ -116,13 +108,13 @@ public: bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list) override; uint32_t - FindTypes(const lldb_private::ConstString &name, + FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; lldb_private::CompilerDeclContext FindNamespace( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, lldb::TypeClass type_mask, @@ -132,9 +124,7 @@ public: void DumpClangAST(lldb_private::Stream &s) override; - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ lldb_private::ConstString GetPluginName() override; uint32_t GetPluginVersion() override; @@ -143,9 +133,8 @@ protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; friend class DebugMapModule; - friend struct DIERef; friend class DWARFASTParserClang; - friend class DWARFUnit; + friend class DWARFCompileUnit; friend class SymbolFileDWARF; struct OSOInfo { lldb::ModuleSP module_sp; @@ -159,9 +148,7 @@ protected: lldb::addr_t> FileRangeMap; - //------------------------------------------------------------------ // Class specific types - //------------------------------------------------------------------ struct CompileUnitInfo { lldb_private::FileSpec so_file; lldb_private::ConstString oso_path; @@ -184,9 +171,7 @@ protected: const FileRangeMap &GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile); }; - //------------------------------------------------------------------ // Protected Member Functions - //------------------------------------------------------------------ void InitOSO(); static uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) { @@ -248,7 +233,7 @@ protected: const CompileUnitInfo *comp_unit_info); uint32_t PrivateFindGlobalVariables( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &name_symbol_indexes, uint32_t max_matches, lldb_private::VariableList &variables); @@ -266,16 +251,14 @@ protected: bool Supports_DW_AT_APPLE_objc_complete_type(SymbolFileDWARF *skip_dwarf_oso); lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, const lldb_private::ConstString &type_name, + const DWARFDIE &die, lldb_private::ConstString type_name, bool must_be_implementation); UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() { return m_unique_ast_type_map; } - //------------------------------------------------------------------ // OSOEntry - //------------------------------------------------------------------ class OSOEntry { public: OSOEntry() @@ -304,9 +287,7 @@ protected: typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry> DebugMap; - //------------------------------------------------------------------ // Member Variables - //------------------------------------------------------------------ std::bitset<kNumFlags> m_flags; std::vector<CompileUnitInfo> m_compile_unit_infos; std::vector<uint32_t> m_func_indexes; // Sorted by address @@ -318,68 +299,58 @@ protected: lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; DebugMap m_debug_map; - //------------------------------------------------------------------ // When an object file from the debug map gets parsed in // SymbolFileDWARF, it needs to tell the debug map about the object // files addresses by calling this function once for each N_FUN, // N_GSYM and N_STSYM and after all entries in the debug map have // been matched up, FinalizeOSOFileRanges() should be called. - //------------------------------------------------------------------ bool AddOSOFileRange(CompileUnitInfo *cu_info, lldb::addr_t exe_file_addr, lldb::addr_t exe_byte_size, lldb::addr_t oso_file_addr, lldb::addr_t oso_byte_size); - //------------------------------------------------------------------ // Called after calling AddOSOFileRange() for each object file debug // map entry to finalize the info for the unlinked compile unit. - //------------------------------------------------------------------ void FinalizeOSOFileRanges(CompileUnitInfo *cu_info); - //------------------------------------------------------------------ /// Convert \a addr from a .o file address, to an executable address. /// - /// @param[in] addr + /// \param[in] addr /// A section offset address from a .o file /// - /// @return + /// \return /// Returns true if \a addr was converted to be an executable /// section/offset address, false otherwise. - //------------------------------------------------------------------ bool LinkOSOAddress(lldb_private::Address &addr); - //------------------------------------------------------------------ /// Convert a .o file "file address" to an executable "file address". /// - /// @param[in] oso_symfile + /// \param[in] oso_symfile /// The DWARF symbol file that contains \a oso_file_addr /// - /// @param[in] oso_file_addr + /// \param[in] oso_file_addr /// A .o file "file address" to convert. /// - /// @return + /// \return /// LLDB_INVALID_ADDRESS if \a oso_file_addr is not in the /// linked executable, otherwise a valid "file address" from the /// linked executable that contains the debug map. - //------------------------------------------------------------------ lldb::addr_t LinkOSOFileAddress(SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr); - //------------------------------------------------------------------ /// Given a line table full of lines with "file addresses" that are /// for a .o file represented by \a oso_symfile, link a new line table /// and return it. /// - /// @param[in] oso_symfile + /// \param[in] oso_symfile /// The DWARF symbol file that produced the \a line_table /// - /// @param[in] addr + /// \param[in] addr /// A section offset address from a .o file /// - /// @return + /// \return /// Returns a valid line table full of linked addresses, or NULL /// if none of the line table addresses exist in the main /// executable. - //------------------------------------------------------------------ lldb_private::LineTable * LinkOSOLineTable(SymbolFileDWARF *oso_symfile, lldb_private::LineTable *line_table); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index 7881448535b8..c5b54b65ea29 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -1,9 +1,8 @@ //===-- SymbolFileDWARFDwo.cpp ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -13,18 +12,21 @@ #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/LLDBAssert.h" +#include "llvm/Support/Casting.h" -#include "DWARFUnit.h" +#include "DWARFCompileUnit.h" #include "DWARFDebugInfo.h" +#include "DWARFUnit.h" using namespace lldb; using namespace lldb_private; SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, - DWARFUnit *dwarf_cu) - : SymbolFileDWARF(objfile.get()), m_obj_file_sp(objfile), - m_base_dwarf_cu(dwarf_cu) { - SetID(((lldb::user_id_t)dwarf_cu->GetOffset()) << 32); + DWARFCompileUnit &dwarf_cu) + : SymbolFileDWARF(objfile.get(), objfile->GetSectionList( + /*update_module_section_list*/ false)), + m_obj_file_sp(objfile), m_base_dwarf_cu(dwarf_cu) { + SetID(((lldb::user_id_t)dwarf_cu.GetID()) << 32); } void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type, @@ -34,12 +36,6 @@ void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type, if (section_list) { SectionSP section_sp(section_list->FindSectionByType(sect_type, true)); if (section_sp) { - // See if we memory mapped the DWARF segment? - if (m_dwarf_data.GetByteSize()) { - data.SetData(m_dwarf_data, section_sp->GetOffset(), - section_sp->GetFileSize()); - return; - } if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) return; @@ -52,20 +48,41 @@ void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type, } lldb::CompUnitSP -SymbolFileDWARFDwo::ParseCompileUnit(DWARFUnit *dwarf_cu, - uint32_t cu_idx) { - assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit " - "called with incompatible compile " - "unit"); - return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu, UINT32_MAX); -} - -DWARFUnit *SymbolFileDWARFDwo::GetCompileUnit() { - // Only dwo files with 1 compile unit is supported - if (GetNumCompileUnits() == 1) - return DebugInfo()->GetCompileUnitAtIndex(0); - else +SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { + assert(GetCompileUnit() == &dwarf_cu && + "SymbolFileDWARFDwo::ParseCompileUnit called with incompatible " + "compile unit"); + return GetBaseSymbolFile().ParseCompileUnit(m_base_dwarf_cu); +} + +DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() { + if (!m_cu) + m_cu = ComputeCompileUnit(); + return m_cu; +} + +DWARFCompileUnit *SymbolFileDWARFDwo::ComputeCompileUnit() { + DWARFDebugInfo *debug_info = DebugInfo(); + if (!debug_info) return nullptr; + + // Right now we only support dwo files with one compile unit. If we don't have + // type units, we can just check for the unit count. + if (!debug_info->ContainsTypeUnits() && debug_info->GetNumUnits() == 1) + return llvm::cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(0)); + + // Otherwise, we have to run through all units, and find the compile unit that + // way. + DWARFCompileUnit *cu = nullptr; + for (size_t i = 0; i < debug_info->GetNumUnits(); ++i) { + if (auto *candidate = + llvm::dyn_cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(i))) { + if (cu) + return nullptr; // More that one CU found. + cu = candidate; + } + } + return cu; } DWARFUnit * @@ -74,83 +91,48 @@ SymbolFileDWARFDwo::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { } SymbolFileDWARF::DIEToTypePtr &SymbolFileDWARFDwo::GetDIEToType() { - return GetBaseSymbolFile()->GetDIEToType(); + return GetBaseSymbolFile().GetDIEToType(); } SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() { - return GetBaseSymbolFile()->GetDIEToVariable(); + return GetBaseSymbolFile().GetDIEToVariable(); } SymbolFileDWARF::DIEToClangType & SymbolFileDWARFDwo::GetForwardDeclDieToClangType() { - return GetBaseSymbolFile()->GetForwardDeclDieToClangType(); + return GetBaseSymbolFile().GetForwardDeclDieToClangType(); } SymbolFileDWARF::ClangTypeToDIE & SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie() { - return GetBaseSymbolFile()->GetForwardDeclClangTypeToDie(); + return GetBaseSymbolFile().GetForwardDeclClangTypeToDie(); } size_t SymbolFileDWARFDwo::GetObjCMethodDIEOffsets( lldb_private::ConstString class_name, DIEArray &method_die_offsets) { - return GetBaseSymbolFile()->GetObjCMethodDIEOffsets( - class_name, method_die_offsets); + return GetBaseSymbolFile().GetObjCMethodDIEOffsets(class_name, + method_die_offsets); } UniqueDWARFASTTypeMap &SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() { - return GetBaseSymbolFile()->GetUniqueDWARFASTTypeMap(); + return GetBaseSymbolFile().GetUniqueDWARFASTTypeMap(); } lldb::TypeSP SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext( const DWARFDeclContext &die_decl_ctx) { - return GetBaseSymbolFile()->FindDefinitionTypeForDWARFDeclContext( + return GetBaseSymbolFile().FindDefinitionTypeForDWARFDeclContext( die_decl_ctx); } lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, const lldb_private::ConstString &type_name, + const DWARFDIE &die, lldb_private::ConstString type_name, bool must_be_implementation) { - return GetBaseSymbolFile()->FindCompleteObjCDefinitionTypeForDIE( + return GetBaseSymbolFile().FindCompleteObjCDefinitionTypeForDIE( die, type_name, must_be_implementation); } -DWARFUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() { - return m_base_dwarf_cu; -} - -const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_abbrev_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugAbbrevDwo, - m_data_debug_abbrev); -} - -const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_addr_data() { - // For single file split dwarf case (when we have .dwo sections in a .o), - // we do not want to use the .debug_addr section from .o file, - // but want to get one from the final executable. - // For regular split debug case, .dwo file does not contain the - // .debug_addr, so we would always fall back to such lookup anyways. - llvm::call_once(m_data_debug_addr.m_flag, [this] { - SymbolFileDWARF::LoadSectionData(eSectionTypeDWARFDebugAddr, - std::ref(m_data_debug_addr.m_data)); - }); - return m_data_debug_addr.m_data; -} - -const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_info_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugInfoDwo, m_data_debug_info); -} - -const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_str_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugStrDwo, m_data_debug_str); -} - -const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_str_offsets_data() { - return GetCachedSectionData(eSectionTypeDWARFDebugStrOffsetsDwo, - m_data_debug_str_offsets); -} - -SymbolFileDWARF *SymbolFileDWARFDwo::GetBaseSymbolFile() { - return m_base_dwarf_cu->GetSymbolFileDWARF(); +SymbolFileDWARF &SymbolFileDWARFDwo::GetBaseSymbolFile() { + return m_base_dwarf_cu.GetSymbolFileDWARF(); } DWARFExpression::LocationListFormat @@ -160,11 +142,12 @@ SymbolFileDWARFDwo::GetLocationListFormat() const { TypeSystem * SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { - return GetBaseSymbolFile()->GetTypeSystemForLanguage(language); + return GetBaseSymbolFile().GetTypeSystemForLanguage(language); } DWARFDIE SymbolFileDWARFDwo::GetDIE(const DIERef &die_ref) { - lldbassert(m_base_dwarf_cu->GetOffset() == die_ref.cu_offset); - return DebugInfo()->GetDIEForDIEOffset(die_ref.die_offset); + if (*die_ref.dwo_num() == GetDwoNum()) + return DebugInfo()->GetDIE(die_ref); + return GetBaseSymbolFile().GetDIE(die_ref); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index b9ed37547aca..9b2f3bb84c4f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -1,9 +1,8 @@ //===-- SymbolFileDWARFDwo.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -14,14 +13,13 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF { public: - SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu); + SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu); ~SymbolFileDWARFDwo() override = default; - lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu, - uint32_t cu_idx) override; + lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu) override; - DWARFUnit *GetCompileUnit(); + DWARFCompileUnit *GetCompileUnit(); DWARFUnit * GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override; @@ -44,13 +42,9 @@ public: return nullptr; } - DWARFUnit *GetBaseCompileUnit() override; + DWARFCompileUnit *GetBaseCompileUnit() override { return &m_base_dwarf_cu; } - const lldb_private::DWARFDataExtractor &get_debug_abbrev_data() override; - const lldb_private::DWARFDataExtractor &get_debug_addr_data() override; - const lldb_private::DWARFDataExtractor &get_debug_info_data() override; - const lldb_private::DWARFDataExtractor &get_debug_str_data() override; - const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data() override; + llvm::Optional<uint32_t> GetDwoNum() override { return GetID() >> 32; } protected: void LoadSectionData(lldb::SectionType sect_type, @@ -70,13 +64,16 @@ protected: const DWARFDeclContext &die_decl_ctx) override; lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, const lldb_private::ConstString &type_name, + const DWARFDIE &die, lldb_private::ConstString type_name, bool must_be_implementation) override; - SymbolFileDWARF *GetBaseSymbolFile(); + SymbolFileDWARF &GetBaseSymbolFile(); + + DWARFCompileUnit *ComputeCompileUnit(); lldb::ObjectFileSP m_obj_file_sp; - DWARFUnit *m_base_dwarf_cu; + DWARFCompileUnit &m_base_dwarf_cu; + DWARFCompileUnit *m_cu = nullptr; }; #endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp index 403c10fe65ea..efea192b17ce 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp @@ -1,9 +1,8 @@ //===-- SymbolFileDWARFDwoDwp.cpp -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -22,7 +21,7 @@ using namespace lldb_private; SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, ObjectFileSP objfile, - DWARFUnit *dwarf_cu, + DWARFCompileUnit &dwarf_cu, uint64_t dwo_id) : SymbolFileDWARFDwo(objfile, dwarf_cu), m_dwp_symfile(dwp_symfile), m_dwo_id(dwo_id) {} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h index 905ba0a5c7b8..2105e1a8f6cb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h @@ -1,9 +1,8 @@ //===-- SymbolFileDWARFDwoDwp.h ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -16,7 +15,7 @@ class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo { public: SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, - lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu, + lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu, uint64_t dwo_id); protected: diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp index 73226dfc130f..08e6e1c8c2f3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp @@ -1,9 +1,8 @@ //===-- SymbolFileDWARFDwp.cpp ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -82,7 +81,7 @@ SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp, {} std::unique_ptr<SymbolFileDWARFDwo> -SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFUnit *dwarf_cu, +SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit &dwarf_cu, uint64_t dwo_id) { return std::unique_ptr<SymbolFileDWARFDwo>( new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id)); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h index 87f4d9402335..ef06b9dca8bb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h @@ -1,9 +1,8 @@ //===-- SymbolFileDWARFDwp.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -25,7 +24,7 @@ public: Create(lldb::ModuleSP module_sp, const lldb_private::FileSpec &file_spec); std::unique_ptr<SymbolFileDWARFDwo> - GetSymbolFileForDwoId(DWARFUnit *dwarf_cu, uint64_t dwo_id); + GetSymbolFileForDwoId(DWARFCompileUnit &dwarf_cu, uint64_t dwo_id); bool LoadSectionData(uint64_t dwo_id, lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index dd912aecf0d8..8da7e2226266 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -1,9 +1,8 @@ //===-- UniqueDWARFASTType.cpp ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -40,12 +39,12 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, case DW_TAG_namespace: { const char *parent_arg_die_name = parent_arg_die.GetName(); if (parent_arg_die_name == - NULL) // Anonymous (i.e. no-name) struct + nullptr) // Anonymous (i.e. no-name) struct { match = false; } else { const char *parent_pos_die_name = parent_pos_die.GetName(); - if (parent_pos_die_name == NULL || + if (parent_pos_die_name == nullptr || ((parent_arg_die_name != parent_pos_die_name) && strcmp(parent_arg_die_name, parent_pos_die_name))) match = false; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index 1e6b164e9457..1269dbac7126 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -1,9 +1,8 @@ //===-- UniqueDWARFASTType.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -19,9 +18,7 @@ class UniqueDWARFASTType { public: - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration(), m_byte_size( @@ -81,12 +78,12 @@ public: ~UniqueDWARFASTTypeMap() {} - void Insert(const lldb_private::ConstString &name, + void Insert(lldb_private::ConstString name, const UniqueDWARFASTType &entry) { m_collection[name.GetCString()].Append(entry); } - bool Find(const lldb_private::ConstString &name, const DWARFDIE &die, + bool Find(lldb_private::ConstString name, const DWARFDIE &die, const lldb_private::Declaration &decl, const int32_t byte_size, UniqueDWARFASTType &entry) const { const char *unique_name_cstr = name.GetCString(); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp new file mode 100644 index 000000000000..3834165c71c0 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp @@ -0,0 +1,457 @@ +//===-- CodeViewRegisterMapping.cpp -----------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "CodeViewRegisterMapping.h" + +#include "lldb/lldb-defines.h" + +#include "Plugins/Process/Utility/lldb-x86-register-enums.h" + +using namespace lldb_private; + +static const uint32_t g_code_view_to_lldb_registers_x86[] = { + LLDB_INVALID_REGNUM, // NONE + lldb_al_i386, // AL + lldb_cl_i386, // CL + lldb_dl_i386, // DL + lldb_bl_i386, // BL + lldb_ah_i386, // AH + lldb_ch_i386, // CH + lldb_dh_i386, // DH + lldb_bh_i386, // BH + lldb_ax_i386, // AX + lldb_cx_i386, // CX + lldb_dx_i386, // DX + lldb_bx_i386, // BX + lldb_sp_i386, // SP + lldb_bp_i386, // BP + lldb_si_i386, // SI + lldb_di_i386, // DI + lldb_eax_i386, // EAX + lldb_ecx_i386, // ECX + lldb_edx_i386, // EDX + lldb_ebx_i386, // EBX + lldb_esp_i386, // ESP + lldb_ebp_i386, // EBP + lldb_esi_i386, // ESI + lldb_edi_i386, // EDI + lldb_es_i386, // ES + lldb_cs_i386, // CS + lldb_ss_i386, // SS + lldb_ds_i386, // DS + lldb_fs_i386, // FS + lldb_gs_i386, // GS + LLDB_INVALID_REGNUM, // IP + LLDB_INVALID_REGNUM, // FLAGS + lldb_eip_i386, // EIP + lldb_eflags_i386, // EFLAGS + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // TEMP + LLDB_INVALID_REGNUM, // TEMPH + LLDB_INVALID_REGNUM, // QUOTE + LLDB_INVALID_REGNUM, // PCDR3 + LLDB_INVALID_REGNUM, // PCDR4 + LLDB_INVALID_REGNUM, // PCDR5 + LLDB_INVALID_REGNUM, // PCDR6 + LLDB_INVALID_REGNUM, // PCDR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // CR0 + LLDB_INVALID_REGNUM, // CR1 + LLDB_INVALID_REGNUM, // CR2 + LLDB_INVALID_REGNUM, // CR3 + LLDB_INVALID_REGNUM, // CR4 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_dr0_i386, // DR0 + lldb_dr1_i386, // DR1 + lldb_dr2_i386, // DR2 + lldb_dr3_i386, // DR3 + lldb_dr4_i386, // DR4 + lldb_dr5_i386, // DR5 + lldb_dr6_i386, // DR6 + lldb_dr7_i386, // DR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // GDTR + LLDB_INVALID_REGNUM, // GDTL + LLDB_INVALID_REGNUM, // IDTR + LLDB_INVALID_REGNUM, // IDTL + LLDB_INVALID_REGNUM, // LDTR + LLDB_INVALID_REGNUM, // TR + LLDB_INVALID_REGNUM, // PSEUDO1 + LLDB_INVALID_REGNUM, // PSEUDO2 + LLDB_INVALID_REGNUM, // PSEUDO3 + LLDB_INVALID_REGNUM, // PSEUDO4 + LLDB_INVALID_REGNUM, // PSEUDO5 + LLDB_INVALID_REGNUM, // PSEUDO6 + LLDB_INVALID_REGNUM, // PSEUDO7 + LLDB_INVALID_REGNUM, // PSEUDO8 + LLDB_INVALID_REGNUM, // PSEUDO9 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_st0_i386, // ST0 + lldb_st1_i386, // ST1 + lldb_st2_i386, // ST2 + lldb_st3_i386, // ST3 + lldb_st4_i386, // ST4 + lldb_st5_i386, // ST5 + lldb_st6_i386, // ST6 + lldb_st7_i386, // ST7 + LLDB_INVALID_REGNUM, // CTRL + LLDB_INVALID_REGNUM, // STAT + LLDB_INVALID_REGNUM, // TAG + LLDB_INVALID_REGNUM, // FPIP + LLDB_INVALID_REGNUM, // FPCS + LLDB_INVALID_REGNUM, // FPDO + LLDB_INVALID_REGNUM, // FPDS + LLDB_INVALID_REGNUM, // ISEM + LLDB_INVALID_REGNUM, // FPEIP + LLDB_INVALID_REGNUM, // FPEDO + lldb_mm0_i386, // MM0 + lldb_mm1_i386, // MM1 + lldb_mm2_i386, // MM2 + lldb_mm3_i386, // MM3 + lldb_mm4_i386, // MM4 + lldb_mm5_i386, // MM5 + lldb_mm6_i386, // MM6 + lldb_mm7_i386, // MM7 + lldb_xmm0_i386, // XMM0 + lldb_xmm1_i386, // XMM1 + lldb_xmm2_i386, // XMM2 + lldb_xmm3_i386, // XMM3 + lldb_xmm4_i386, // XMM4 + lldb_xmm5_i386, // XMM5 + lldb_xmm6_i386, // XMM6 + lldb_xmm7_i386 // XMM7 +}; + +static const uint32_t g_code_view_to_lldb_registers_x86_64[] = { + LLDB_INVALID_REGNUM, // NONE + lldb_al_x86_64, // AL + lldb_cl_x86_64, // CL + lldb_dl_x86_64, // DL + lldb_bl_x86_64, // BL + lldb_ah_x86_64, // AH + lldb_ch_x86_64, // CH + lldb_dh_x86_64, // DH + lldb_bh_x86_64, // BH + lldb_ax_x86_64, // AX + lldb_cx_x86_64, // CX + lldb_dx_x86_64, // DX + lldb_bx_x86_64, // BX + lldb_sp_x86_64, // SP + lldb_bp_x86_64, // BP + lldb_si_x86_64, // SI + lldb_di_x86_64, // DI + lldb_eax_x86_64, // EAX + lldb_ecx_x86_64, // ECX + lldb_edx_x86_64, // EDX + lldb_ebx_x86_64, // EBX + lldb_esp_x86_64, // ESP + lldb_ebp_x86_64, // EBP + lldb_esi_x86_64, // ESI + lldb_edi_x86_64, // EDI + lldb_es_x86_64, // ES + lldb_cs_x86_64, // CS + lldb_ss_x86_64, // SS + lldb_ds_x86_64, // DS + lldb_fs_x86_64, // FS + lldb_gs_x86_64, // GS + LLDB_INVALID_REGNUM, // IP + LLDB_INVALID_REGNUM, // FLAGS + LLDB_INVALID_REGNUM, // EIP + LLDB_INVALID_REGNUM, // EFLAGS + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // TEMP + LLDB_INVALID_REGNUM, // TEMPH + LLDB_INVALID_REGNUM, // QUOTE + LLDB_INVALID_REGNUM, // PCDR3 + LLDB_INVALID_REGNUM, // PCDR4 + LLDB_INVALID_REGNUM, // PCDR5 + LLDB_INVALID_REGNUM, // PCDR6 + LLDB_INVALID_REGNUM, // PCDR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // CR0 + LLDB_INVALID_REGNUM, // CR1 + LLDB_INVALID_REGNUM, // CR2 + LLDB_INVALID_REGNUM, // CR3 + LLDB_INVALID_REGNUM, // CR4 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_dr0_x86_64, // DR0 + lldb_dr1_x86_64, // DR1 + lldb_dr2_x86_64, // DR2 + lldb_dr3_x86_64, // DR3 + lldb_dr4_x86_64, // DR4 + lldb_dr5_x86_64, // DR5 + lldb_dr6_x86_64, // DR6 + lldb_dr7_x86_64, // DR7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // GDTR + LLDB_INVALID_REGNUM, // GDTL + LLDB_INVALID_REGNUM, // IDTR + LLDB_INVALID_REGNUM, // IDTL + LLDB_INVALID_REGNUM, // LDTR + LLDB_INVALID_REGNUM, // TR + LLDB_INVALID_REGNUM, // PSEUDO1 + LLDB_INVALID_REGNUM, // PSEUDO2 + LLDB_INVALID_REGNUM, // PSEUDO3 + LLDB_INVALID_REGNUM, // PSEUDO4 + LLDB_INVALID_REGNUM, // PSEUDO5 + LLDB_INVALID_REGNUM, // PSEUDO6 + LLDB_INVALID_REGNUM, // PSEUDO7 + LLDB_INVALID_REGNUM, // PSEUDO8 + LLDB_INVALID_REGNUM, // PSEUDO9 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_st0_x86_64, // ST0 + lldb_st1_x86_64, // ST1 + lldb_st2_x86_64, // ST2 + lldb_st3_x86_64, // ST3 + lldb_st4_x86_64, // ST4 + lldb_st5_x86_64, // ST5 + lldb_st6_x86_64, // ST6 + lldb_st7_x86_64, // ST7 + LLDB_INVALID_REGNUM, // CTRL + LLDB_INVALID_REGNUM, // STAT + LLDB_INVALID_REGNUM, // TAG + LLDB_INVALID_REGNUM, // FPIP + LLDB_INVALID_REGNUM, // FPCS + LLDB_INVALID_REGNUM, // FPDO + LLDB_INVALID_REGNUM, // FPDS + LLDB_INVALID_REGNUM, // ISEM + LLDB_INVALID_REGNUM, // FPEIP + LLDB_INVALID_REGNUM, // FPEDO + lldb_mm0_x86_64, // MM0 + lldb_mm1_x86_64, // MM1 + lldb_mm2_x86_64, // MM2 + lldb_mm3_x86_64, // MM3 + lldb_mm4_x86_64, // MM4 + lldb_mm5_x86_64, // MM5 + lldb_mm6_x86_64, // MM6 + lldb_mm7_x86_64, // MM7 + lldb_xmm0_x86_64, // XMM0 + lldb_xmm1_x86_64, // XMM1 + lldb_xmm2_x86_64, // XMM2 + lldb_xmm3_x86_64, // XMM3 + lldb_xmm4_x86_64, // XMM4 + lldb_xmm5_x86_64, // XMM5 + lldb_xmm6_x86_64, // XMM6 + lldb_xmm7_x86_64, // XMM7 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, + lldb_mxcsr_x86_64, // MXCSR + LLDB_INVALID_REGNUM, // EDXEAX + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, // EMM0L + LLDB_INVALID_REGNUM, // EMM1L + LLDB_INVALID_REGNUM, // EMM2L + LLDB_INVALID_REGNUM, // EMM3L + LLDB_INVALID_REGNUM, // EMM4L + LLDB_INVALID_REGNUM, // EMM5L + LLDB_INVALID_REGNUM, // EMM6L + LLDB_INVALID_REGNUM, // EMM7L + LLDB_INVALID_REGNUM, // EMM0H + LLDB_INVALID_REGNUM, // EMM1H + LLDB_INVALID_REGNUM, // EMM2H + LLDB_INVALID_REGNUM, // EMM3H + LLDB_INVALID_REGNUM, // EMM4H + LLDB_INVALID_REGNUM, // EMM5H + LLDB_INVALID_REGNUM, // EMM6H + LLDB_INVALID_REGNUM, // EMM7H + LLDB_INVALID_REGNUM, // MM00 + LLDB_INVALID_REGNUM, // MM01 + LLDB_INVALID_REGNUM, // MM10 + LLDB_INVALID_REGNUM, // MM11 + LLDB_INVALID_REGNUM, // MM20 + LLDB_INVALID_REGNUM, // MM21 + LLDB_INVALID_REGNUM, // MM30 + LLDB_INVALID_REGNUM, // MM31 + LLDB_INVALID_REGNUM, // MM40 + LLDB_INVALID_REGNUM, // MM41 + LLDB_INVALID_REGNUM, // MM50 + LLDB_INVALID_REGNUM, // MM51 + LLDB_INVALID_REGNUM, // MM60 + LLDB_INVALID_REGNUM, // MM61 + LLDB_INVALID_REGNUM, // MM70 + LLDB_INVALID_REGNUM, // MM71 + lldb_xmm8_x86_64, // XMM8 + lldb_xmm9_x86_64, // XMM9 + lldb_xmm10_x86_64, // XMM10 + lldb_xmm11_x86_64, // XMM11 + lldb_xmm12_x86_64, // XMM12 + lldb_xmm13_x86_64, // XMM13 + lldb_xmm14_x86_64, // XMM14 + lldb_xmm15_x86_64, // XMM15 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, + lldb_sil_x86_64, // SIL + lldb_dil_x86_64, // DIL + lldb_bpl_x86_64, // BPL + lldb_spl_x86_64, // SPL + lldb_rax_x86_64, // RAX + lldb_rbx_x86_64, // RBX + lldb_rcx_x86_64, // RCX + lldb_rdx_x86_64, // RDX + lldb_rsi_x86_64, // RSI + lldb_rdi_x86_64, // RDI + lldb_rbp_x86_64, // RBP + lldb_rsp_x86_64, // RSP + lldb_r8_x86_64, // R8 + lldb_r9_x86_64, // R9 + lldb_r10_x86_64, // R10 + lldb_r11_x86_64, // R11 + lldb_r12_x86_64, // R12 + lldb_r13_x86_64, // R13 + lldb_r14_x86_64, // R14 + lldb_r15_x86_64, // R15 + lldb_r8l_x86_64, // R8B + lldb_r9l_x86_64, // R9B + lldb_r10l_x86_64, // R10B + lldb_r11l_x86_64, // R11B + lldb_r12l_x86_64, // R12B + lldb_r13l_x86_64, // R13B + lldb_r14l_x86_64, // R14B + lldb_r15l_x86_64, // R15B + lldb_r8w_x86_64, // R8W + lldb_r9w_x86_64, // R9W + lldb_r10w_x86_64, // R10W + lldb_r11w_x86_64, // R11W + lldb_r12w_x86_64, // R12W + lldb_r13w_x86_64, // R13W + lldb_r14w_x86_64, // R14W + lldb_r15w_x86_64, // R15W + lldb_r8d_x86_64, // R8D + lldb_r9d_x86_64, // R9D + lldb_r10d_x86_64, // R10D + lldb_r11d_x86_64, // R11D + lldb_r12d_x86_64, // R12D + lldb_r13d_x86_64, // R13D + lldb_r14d_x86_64, // R14D + lldb_r15d_x86_64, // R15D + lldb_ymm0_x86_64, // AMD64_YMM0 + lldb_ymm1_x86_64, // AMD64_YMM1 + lldb_ymm2_x86_64, // AMD64_YMM2 + lldb_ymm3_x86_64, // AMD64_YMM3 + lldb_ymm4_x86_64, // AMD64_YMM4 + lldb_ymm5_x86_64, // AMD64_YMM5 + lldb_ymm6_x86_64, // AMD64_YMM6 + lldb_ymm7_x86_64, // AMD64_YMM7 + lldb_ymm8_x86_64, // AMD64_YMM8 + lldb_ymm9_x86_64, // AMD64_YMM9 + lldb_ymm10_x86_64, // AMD64_YMM10 + lldb_ymm11_x86_64, // AMD64_YMM11 + lldb_ymm12_x86_64, // AMD64_YMM12 + lldb_ymm13_x86_64, // AMD64_YMM13 + lldb_ymm14_x86_64, // AMD64_YMM14 + lldb_ymm15_x86_64, // AMD64_YMM15 + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + lldb_bnd0_x86_64, // BND0 + lldb_bnd1_x86_64, // BND1 + lldb_bnd2_x86_64 // BND2 +}; + +uint32_t lldb_private::npdb::GetLLDBRegisterNumber( + llvm::Triple::ArchType arch_type, llvm::codeview::RegisterId register_id) { + switch (arch_type) { + case llvm::Triple::x86: + if (static_cast<uint16_t>(register_id) < + sizeof(g_code_view_to_lldb_registers_x86) / + sizeof(g_code_view_to_lldb_registers_x86[0])) + return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>( + register_id)]; + + switch (register_id) { + case llvm::codeview::RegisterId::MXCSR: + return lldb_mxcsr_i386; + case llvm::codeview::RegisterId::BND0: + return lldb_bnd0_i386; + case llvm::codeview::RegisterId::BND1: + return lldb_bnd1_i386; + case llvm::codeview::RegisterId::BND2: + return lldb_bnd2_i386; + default: + return LLDB_INVALID_REGNUM; + } + case llvm::Triple::x86_64: + if (static_cast<uint16_t>(register_id) < + sizeof(g_code_view_to_lldb_registers_x86_64) / + sizeof(g_code_view_to_lldb_registers_x86_64[0])) + return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>( + register_id)]; + + return LLDB_INVALID_REGNUM; + default: + return LLDB_INVALID_REGNUM; + } +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h new file mode 100644 index 000000000000..b1c31e0c1785 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h @@ -0,0 +1,24 @@ +//===-- CodeViewRegisterMapping.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_Plugins_SymbolFile_PDB_CodeViewRegisterMapping_h_ +#define lldb_Plugins_SymbolFile_PDB_CodeViewRegisterMapping_h_ + +#include "llvm/ADT/Triple.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" + +namespace lldb_private { +namespace npdb { + +uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, + llvm::codeview::RegisterId register_id); + +} // namespace npdb +} // namespace lldb_private + +#endif diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp index 67ea05767fde..1838204e4ca6 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp @@ -1,9 +1,8 @@ //===-- CompileUnitIndex.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -125,11 +124,20 @@ CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) { uint16_t stream = descriptor.getModuleStreamIndex(); std::unique_ptr<llvm::msf::MappedBlockStream> stream_data = m_index.pdb().createIndexedStream(stream); + + + std::unique_ptr<CompilandIndexItem>& cci = result.first->second; + + if (!stream_data) { + llvm::pdb::ModuleDebugStreamRef debug_stream(descriptor, nullptr); + cci = llvm::make_unique<CompilandIndexItem>(PdbCompilandId{ modi }, debug_stream, std::move(descriptor)); + return *cci; + } + llvm::pdb::ModuleDebugStreamRef debug_stream(descriptor, std::move(stream_data)); - cantFail(debug_stream.reload()); - std::unique_ptr<CompilandIndexItem> &cci = result.first->second; + cantFail(debug_stream.reload()); cci = llvm::make_unique<CompilandIndexItem>( PdbCompilandId{modi}, std::move(debug_stream), std::move(descriptor)); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h index c965870da44b..44a1c8cdd9c2 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h @@ -1,9 +1,8 @@ //===-- CompileUnitIndex.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index 7b62530e4680..3d8bfb058721 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -1,15 +1,13 @@ //===-- DWARFLocationExpression.cpp -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "DWARFLocationExpression.h" -#include "Plugins/Process/Utility/lldb-x86-register-enums.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamBuffer.h" @@ -24,6 +22,8 @@ #include "llvm/Support/Endian.h" #include "PdbUtil.h" +#include "CodeViewRegisterMapping.h" +#include "PdbFPOProgramToDWARFExpression.h" using namespace lldb; using namespace lldb_private; @@ -31,448 +31,6 @@ using namespace lldb_private::npdb; using namespace llvm::codeview; using namespace llvm::pdb; -static const uint32_t g_code_view_to_lldb_registers_x86[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_i386, // AL - lldb_cl_i386, // CL - lldb_dl_i386, // DL - lldb_bl_i386, // BL - lldb_ah_i386, // AH - lldb_ch_i386, // CH - lldb_dh_i386, // DH - lldb_bh_i386, // BH - lldb_ax_i386, // AX - lldb_cx_i386, // CX - lldb_dx_i386, // DX - lldb_bx_i386, // BX - lldb_sp_i386, // SP - lldb_bp_i386, // BP - lldb_si_i386, // SI - lldb_di_i386, // DI - lldb_eax_i386, // EAX - lldb_ecx_i386, // ECX - lldb_edx_i386, // EDX - lldb_ebx_i386, // EBX - lldb_esp_i386, // ESP - lldb_ebp_i386, // EBP - lldb_esi_i386, // ESI - lldb_edi_i386, // EDI - lldb_es_i386, // ES - lldb_cs_i386, // CS - lldb_ss_i386, // SS - lldb_ds_i386, // DS - lldb_fs_i386, // FS - lldb_gs_i386, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - lldb_eip_i386, // EIP - lldb_eflags_i386, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_i386, // DR0 - lldb_dr1_i386, // DR1 - lldb_dr2_i386, // DR2 - lldb_dr3_i386, // DR3 - lldb_dr4_i386, // DR4 - lldb_dr5_i386, // DR5 - lldb_dr6_i386, // DR6 - lldb_dr7_i386, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_i386, // ST0 - lldb_st1_i386, // ST1 - lldb_st2_i386, // ST2 - lldb_st3_i386, // ST3 - lldb_st4_i386, // ST4 - lldb_st5_i386, // ST5 - lldb_st6_i386, // ST6 - lldb_st7_i386, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_i386, // MM0 - lldb_mm1_i386, // MM1 - lldb_mm2_i386, // MM2 - lldb_mm3_i386, // MM3 - lldb_mm4_i386, // MM4 - lldb_mm5_i386, // MM5 - lldb_mm6_i386, // MM6 - lldb_mm7_i386, // MM7 - lldb_xmm0_i386, // XMM0 - lldb_xmm1_i386, // XMM1 - lldb_xmm2_i386, // XMM2 - lldb_xmm3_i386, // XMM3 - lldb_xmm4_i386, // XMM4 - lldb_xmm5_i386, // XMM5 - lldb_xmm6_i386, // XMM6 - lldb_xmm7_i386 // XMM7 -}; - -static const uint32_t g_code_view_to_lldb_registers_x86_64[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_x86_64, // AL - lldb_cl_x86_64, // CL - lldb_dl_x86_64, // DL - lldb_bl_x86_64, // BL - lldb_ah_x86_64, // AH - lldb_ch_x86_64, // CH - lldb_dh_x86_64, // DH - lldb_bh_x86_64, // BH - lldb_ax_x86_64, // AX - lldb_cx_x86_64, // CX - lldb_dx_x86_64, // DX - lldb_bx_x86_64, // BX - lldb_sp_x86_64, // SP - lldb_bp_x86_64, // BP - lldb_si_x86_64, // SI - lldb_di_x86_64, // DI - lldb_eax_x86_64, // EAX - lldb_ecx_x86_64, // ECX - lldb_edx_x86_64, // EDX - lldb_ebx_x86_64, // EBX - lldb_esp_x86_64, // ESP - lldb_ebp_x86_64, // EBP - lldb_esi_x86_64, // ESI - lldb_edi_x86_64, // EDI - lldb_es_x86_64, // ES - lldb_cs_x86_64, // CS - lldb_ss_x86_64, // SS - lldb_ds_x86_64, // DS - lldb_fs_x86_64, // FS - lldb_gs_x86_64, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - LLDB_INVALID_REGNUM, // EIP - LLDB_INVALID_REGNUM, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_x86_64, // DR0 - lldb_dr1_x86_64, // DR1 - lldb_dr2_x86_64, // DR2 - lldb_dr3_x86_64, // DR3 - lldb_dr4_x86_64, // DR4 - lldb_dr5_x86_64, // DR5 - lldb_dr6_x86_64, // DR6 - lldb_dr7_x86_64, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_x86_64, // ST0 - lldb_st1_x86_64, // ST1 - lldb_st2_x86_64, // ST2 - lldb_st3_x86_64, // ST3 - lldb_st4_x86_64, // ST4 - lldb_st5_x86_64, // ST5 - lldb_st6_x86_64, // ST6 - lldb_st7_x86_64, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_x86_64, // MM0 - lldb_mm1_x86_64, // MM1 - lldb_mm2_x86_64, // MM2 - lldb_mm3_x86_64, // MM3 - lldb_mm4_x86_64, // MM4 - lldb_mm5_x86_64, // MM5 - lldb_mm6_x86_64, // MM6 - lldb_mm7_x86_64, // MM7 - lldb_xmm0_x86_64, // XMM0 - lldb_xmm1_x86_64, // XMM1 - lldb_xmm2_x86_64, // XMM2 - lldb_xmm3_x86_64, // XMM3 - lldb_xmm4_x86_64, // XMM4 - lldb_xmm5_x86_64, // XMM5 - lldb_xmm6_x86_64, // XMM6 - lldb_xmm7_x86_64, // XMM7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_mxcsr_x86_64, // MXCSR - LLDB_INVALID_REGNUM, // EDXEAX - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // EMM0L - LLDB_INVALID_REGNUM, // EMM1L - LLDB_INVALID_REGNUM, // EMM2L - LLDB_INVALID_REGNUM, // EMM3L - LLDB_INVALID_REGNUM, // EMM4L - LLDB_INVALID_REGNUM, // EMM5L - LLDB_INVALID_REGNUM, // EMM6L - LLDB_INVALID_REGNUM, // EMM7L - LLDB_INVALID_REGNUM, // EMM0H - LLDB_INVALID_REGNUM, // EMM1H - LLDB_INVALID_REGNUM, // EMM2H - LLDB_INVALID_REGNUM, // EMM3H - LLDB_INVALID_REGNUM, // EMM4H - LLDB_INVALID_REGNUM, // EMM5H - LLDB_INVALID_REGNUM, // EMM6H - LLDB_INVALID_REGNUM, // EMM7H - LLDB_INVALID_REGNUM, // MM00 - LLDB_INVALID_REGNUM, // MM01 - LLDB_INVALID_REGNUM, // MM10 - LLDB_INVALID_REGNUM, // MM11 - LLDB_INVALID_REGNUM, // MM20 - LLDB_INVALID_REGNUM, // MM21 - LLDB_INVALID_REGNUM, // MM30 - LLDB_INVALID_REGNUM, // MM31 - LLDB_INVALID_REGNUM, // MM40 - LLDB_INVALID_REGNUM, // MM41 - LLDB_INVALID_REGNUM, // MM50 - LLDB_INVALID_REGNUM, // MM51 - LLDB_INVALID_REGNUM, // MM60 - LLDB_INVALID_REGNUM, // MM61 - LLDB_INVALID_REGNUM, // MM70 - LLDB_INVALID_REGNUM, // MM71 - lldb_xmm8_x86_64, // XMM8 - lldb_xmm9_x86_64, // XMM9 - lldb_xmm10_x86_64, // XMM10 - lldb_xmm11_x86_64, // XMM11 - lldb_xmm12_x86_64, // XMM12 - lldb_xmm13_x86_64, // XMM13 - lldb_xmm14_x86_64, // XMM14 - lldb_xmm15_x86_64, // XMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_sil_x86_64, // SIL - lldb_dil_x86_64, // DIL - lldb_bpl_x86_64, // BPL - lldb_spl_x86_64, // SPL - lldb_rax_x86_64, // RAX - lldb_rbx_x86_64, // RBX - lldb_rcx_x86_64, // RCX - lldb_rdx_x86_64, // RDX - lldb_rsi_x86_64, // RSI - lldb_rdi_x86_64, // RDI - lldb_rbp_x86_64, // RBP - lldb_rsp_x86_64, // RSP - lldb_r8_x86_64, // R8 - lldb_r9_x86_64, // R9 - lldb_r10_x86_64, // R10 - lldb_r11_x86_64, // R11 - lldb_r12_x86_64, // R12 - lldb_r13_x86_64, // R13 - lldb_r14_x86_64, // R14 - lldb_r15_x86_64, // R15 - lldb_r8l_x86_64, // R8B - lldb_r9l_x86_64, // R9B - lldb_r10l_x86_64, // R10B - lldb_r11l_x86_64, // R11B - lldb_r12l_x86_64, // R12B - lldb_r13l_x86_64, // R13B - lldb_r14l_x86_64, // R14B - lldb_r15l_x86_64, // R15B - lldb_r8w_x86_64, // R8W - lldb_r9w_x86_64, // R9W - lldb_r10w_x86_64, // R10W - lldb_r11w_x86_64, // R11W - lldb_r12w_x86_64, // R12W - lldb_r13w_x86_64, // R13W - lldb_r14w_x86_64, // R14W - lldb_r15w_x86_64, // R15W - lldb_r8d_x86_64, // R8D - lldb_r9d_x86_64, // R9D - lldb_r10d_x86_64, // R10D - lldb_r11d_x86_64, // R11D - lldb_r12d_x86_64, // R12D - lldb_r13d_x86_64, // R13D - lldb_r14d_x86_64, // R14D - lldb_r15d_x86_64, // R15D - lldb_ymm0_x86_64, // AMD64_YMM0 - lldb_ymm1_x86_64, // AMD64_YMM1 - lldb_ymm2_x86_64, // AMD64_YMM2 - lldb_ymm3_x86_64, // AMD64_YMM3 - lldb_ymm4_x86_64, // AMD64_YMM4 - lldb_ymm5_x86_64, // AMD64_YMM5 - lldb_ymm6_x86_64, // AMD64_YMM6 - lldb_ymm7_x86_64, // AMD64_YMM7 - lldb_ymm8_x86_64, // AMD64_YMM8 - lldb_ymm9_x86_64, // AMD64_YMM9 - lldb_ymm10_x86_64, // AMD64_YMM10 - lldb_ymm11_x86_64, // AMD64_YMM11 - lldb_ymm12_x86_64, // AMD64_YMM12 - lldb_ymm13_x86_64, // AMD64_YMM13 - lldb_ymm14_x86_64, // AMD64_YMM14 - lldb_ymm15_x86_64, // AMD64_YMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_bnd0_x86_64, // BND0 - lldb_bnd1_x86_64, // BND1 - lldb_bnd2_x86_64 // BND2 -}; - -uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, - llvm::codeview::RegisterId register_id) { - switch (arch_type) { - case llvm::Triple::x86: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86) / - sizeof(g_code_view_to_lldb_registers_x86[0])) - return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>( - register_id)]; - - switch (register_id) { - case llvm::codeview::RegisterId::MXCSR: - return lldb_mxcsr_i386; - case llvm::codeview::RegisterId::BND0: - return lldb_bnd0_i386; - case llvm::codeview::RegisterId::BND1: - return lldb_bnd1_i386; - case llvm::codeview::RegisterId::BND2: - return lldb_bnd2_i386; - default: - return LLDB_INVALID_REGNUM; - } - case llvm::Triple::x86_64: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86_64) / - sizeof(g_code_view_to_lldb_registers_x86_64[0])) - return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>( - register_id)]; - - return LLDB_INVALID_REGNUM; - default: - return LLDB_INVALID_REGNUM; - } -} - uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) { if (register_id == llvm::codeview::RegisterId::VFRAME) return LLDB_REGNUM_GENERIC_FP; @@ -553,13 +111,13 @@ static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, uint32_t address_size = architecture.GetAddressByteSize(); uint32_t byte_size = architecture.GetDataByteSize(); if (byte_order == eByteOrderInvalid || address_size == 0) - return DWARFExpression(nullptr); + return DWARFExpression(); RegisterKind register_kind = eRegisterKindDWARF; StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); if (!writer(stream, register_kind)) - return DWARFExpression(nullptr); + return DWARFExpression(); DataBufferSP buffer = std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); @@ -610,6 +168,33 @@ DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression( return MakeRegisterBasedLocationExpressionInternal(reg, offset, module); } +static bool EmitVFrameEvaluationDWARFExpression( + llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) { + // VFrame value always stored in $TO pseudo-register + return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type, + stream); +} + +DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression( + llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) { + return MakeLocationExpressionInternal( + module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { + const ArchSpec &architecture = module->GetArchitecture(); + + if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(), + stream)) + return false; + + stream.PutHex8(llvm::dwarf::DW_OP_consts); + stream.PutSLEB128(offset); + stream.PutHex8(llvm::dwarf::DW_OP_plus); + + register_kind = eRegisterKindLLDB; + + return true; + }); +} + DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression( uint16_t section, uint32_t offset, ModuleSP module) { assert(section > 0); @@ -622,13 +207,7 @@ DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression( SectionList *section_list = module->GetSectionList(); assert(section_list); - // Section indices in PDB are 1-based, but in DWARF they are 0-based, so - // we need to subtract 1. - uint32_t section_idx = section - 1; - if (section_idx >= section_list->GetSize()) - return false; - - auto section_ptr = section_list->GetSectionAtIndex(section_idx); + auto section_ptr = section_list->FindSectionByID(section); if (!section_ptr) return false; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h index 670e95ee8e3c..c37d715babdc 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h @@ -1,9 +1,8 @@ //===-- DWARFLocationExpression.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -31,6 +30,9 @@ MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg, DWARFExpression MakeRegRelLocationExpression(llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module); +DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program, + int32_t offset, + lldb::ModuleSP module); DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset, lldb::ModuleSP module); DWARFExpression MakeConstantLocationExpression( diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 8917fd092385..4991be8e70ce 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -205,13 +205,17 @@ GetNestedTagDefinition(const NestedTypeRecord &Record, return std::move(child); } +static bool IsAnonymousNamespaceName(llvm::StringRef name) { + return name == "`anonymous namespace'" || name == "`anonymous-namespace'"; +} + PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index) : m_index(index), m_clang(GetClangASTContext(obj)) { BuildParentMap(); } -clang::DeclContext &PdbAstBuilder::GetTranslationUnitDecl() { - return *m_clang.GetTranslationUnitDecl(); +lldb_private::CompilerDeclContext PdbAstBuilder::GetTranslationUnitDecl() { + return ToCompilerDeclContext(*m_clang.GetTranslationUnitDecl()); } std::pair<clang::DeclContext *, std::string> @@ -256,7 +260,7 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) { for (llvm::ms_demangle::Node *scope : scopes) { auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope); std::string str = nii->toString(); - context = m_clang.GetUniqueNamespaceDeclaration(str.c_str(), context); + context = GetOrCreateNamespaceDecl(str.c_str(), *context); } return {context, uname}; } @@ -488,7 +492,7 @@ clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) { if (uid.kind() == PdbSymUidKind::CompilandSym) { if (uid.asCompilandSym().offset == 0) - return &GetTranslationUnitDecl(); + return FromCompilerDeclContext(GetTranslationUnitDecl()); } clang::Decl *decl = GetOrCreateDeclForUid(uid); @@ -503,7 +507,7 @@ PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) { MSVCUndecoratedNameParser parser(name); llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); - clang::DeclContext *context = &GetTranslationUnitDecl(); + auto context = FromCompilerDeclContext(GetTranslationUnitDecl()); llvm::StringRef uname = specs.back().GetBaseName(); specs = specs.drop_back(); @@ -525,7 +529,7 @@ PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) { // If that fails, treat it as a series of namespaces. for (const MSVCUndecoratedNameSpecifier &spec : specs) { std::string ns_name = spec.GetBaseName().str(); - context = m_clang.GetUniqueNamespaceDeclaration(ns_name.c_str(), context); + context = GetOrCreateNamespaceDecl(ns_name.c_str(), *context); } return {context, uname}; } @@ -544,7 +548,7 @@ PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) { StringView name{pub->Name.begin(), pub->Name.size()}; llvm::ms_demangle::SymbolNode *node = demangler.parse(name); if (!node) - return &GetTranslationUnitDecl(); + return FromCompilerDeclContext(GetTranslationUnitDecl()); llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{ node->Name->Components->Nodes, node->Name->Components->Count - 1}; @@ -565,10 +569,10 @@ PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) { } // It's not a type. It must be a series of namespaces. - clang::DeclContext *context = &GetTranslationUnitDecl(); + auto context = FromCompilerDeclContext(GetTranslationUnitDecl()); while (!name_components.empty()) { std::string ns = name_components.front()->toString(); - context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context); + context = GetOrCreateNamespaceDecl(ns.c_str(), *context); name_components = name_components.drop_front(); } return context; @@ -593,7 +597,7 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) { PdbTypeSymId type_id = uid.asTypeSym(); auto iter = m_parent_types.find(type_id.index); if (iter == m_parent_types.end()) - return &GetTranslationUnitDecl(); + return FromCompilerDeclContext(GetTranslationUnitDecl()); return GetOrCreateDeclContextForUid(PdbTypeSymId(iter->second)); } case PdbSymUidKind::FieldListMember: @@ -631,7 +635,7 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) { default: break; } - return &GetTranslationUnitDecl(); + return FromCompilerDeclContext(GetTranslationUnitDecl()); } bool PdbAstBuilder::CompleteType(clang::QualType qt) { @@ -805,9 +809,10 @@ clang::Decl *PdbAstBuilder::TryGetDecl(PdbSymUid uid) const { } clang::NamespaceDecl * -PdbAstBuilder::GetOrCreateNamespaceDecl(llvm::StringRef name, +PdbAstBuilder::GetOrCreateNamespaceDecl(const char *name, clang::DeclContext &context) { - return m_clang.GetUniqueNamespaceDeclaration(name.str().c_str(), &context); + return m_clang.GetUniqueNamespaceDeclaration( + IsAnonymousNamespaceName(name) ? nullptr : name, &context); } clang::BlockDecl * @@ -861,7 +866,8 @@ clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) { return llvm::dyn_cast<clang::VarDecl>(decl); CVSymbol sym = m_index.ReadSymbolRecord(var_id); - return CreateVariableDecl(PdbSymUid(var_id), sym, GetTranslationUnitDecl()); + auto context = FromCompilerDeclContext(GetTranslationUnitDecl()); + return CreateVariableDecl(PdbSymUid(var_id), sym, *context); } clang::TypedefNameDecl * @@ -933,7 +939,14 @@ clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) { if (cvt.kind() == LF_PROCEDURE) { ProcedureRecord pr; llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr)); - return CreateProcedureType(pr); + return CreateFunctionType(pr.ArgumentList, pr.ReturnType, pr.CallConv); + } + + if (cvt.kind() == LF_MFUNCTION) { + MemberFunctionRecord mfr; + llvm::cantFail( + TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr)); + return CreateFunctionType(mfr.ArgumentList, mfr.ReturnType, mfr.CallConv); } return {}; @@ -1117,10 +1130,11 @@ clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) { return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType()); } -clang::QualType -PdbAstBuilder::CreateProcedureType(const ProcedureRecord &proc) { +clang::QualType PdbAstBuilder::CreateFunctionType( + TypeIndex args_type_idx, TypeIndex return_type_idx, + llvm::codeview::CallingConvention calling_convention) { TpiStream &stream = m_index.tpi(); - CVType args_cvt = stream.getType(proc.ArgumentList); + CVType args_cvt = stream.getType(args_type_idx); ArgListRecord args; llvm::cantFail( TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args)); @@ -1138,10 +1152,10 @@ PdbAstBuilder::CreateProcedureType(const ProcedureRecord &proc) { arg_types.push_back(ToCompilerType(arg_type)); } - clang::QualType return_type = GetOrCreateType(proc.ReturnType); + clang::QualType return_type = GetOrCreateType(return_type_idx); llvm::Optional<clang::CallingConv> cc = - TranslateCallingConvention(proc.CallConv); + TranslateCallingConvention(calling_convention); if (!cc) return {}; @@ -1340,6 +1354,10 @@ PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) { return {&m_clang, &context}; } +clang::Decl * PdbAstBuilder::FromCompilerDecl(CompilerDecl decl) { + return static_cast<clang::Decl *>(decl.GetOpaqueDecl()); +} + clang::DeclContext * PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) { return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext()); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h index e3c0346f935e..67d024741e0d 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -1,9 +1,8 @@ //===-- PdbAstBuilder.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -51,19 +50,15 @@ struct DeclStatus { class PdbAstBuilder { public: - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ PdbAstBuilder(ObjectFile &obj, PdbIndex &index); - clang::DeclContext &GetTranslationUnitDecl(); + lldb_private::CompilerDeclContext GetTranslationUnitDecl(); clang::Decl *GetOrCreateDeclForUid(PdbSymUid uid); clang::DeclContext *GetOrCreateDeclContextForUid(PdbSymUid uid); clang::DeclContext *GetParentDeclContext(PdbSymUid uid); - clang::NamespaceDecl *GetOrCreateNamespaceDecl(llvm::StringRef name, - clang::DeclContext &context); clang::FunctionDecl *GetOrCreateFunctionDecl(PdbCompilandSymId func_id); clang::BlockDecl *GetOrCreateBlockDecl(PdbCompilandSymId block_id); clang::VarDecl *GetOrCreateVariableDecl(PdbCompilandSymId scope_id, @@ -81,6 +76,7 @@ public: CompilerDecl ToCompilerDecl(clang::Decl &decl); CompilerType ToCompilerType(clang::QualType qt); CompilerDeclContext ToCompilerDeclContext(clang::DeclContext &context); + clang::Decl * FromCompilerDecl(CompilerDecl decl); clang::DeclContext *FromCompilerDeclContext(CompilerDeclContext context); ClangASTContext &clang() { return m_clang; } @@ -103,7 +99,8 @@ private: clang::QualType CreateEnumType(PdbTypeSymId id, const llvm::codeview::EnumRecord &record); clang::QualType - CreateProcedureType(const llvm::codeview::ProcedureRecord &proc); + CreateFunctionType(TypeIndex args_type_idx, TypeIndex return_type_idx, + llvm::codeview::CallingConvention calling_convention); clang::QualType CreateType(PdbTypeSymId type); void CreateFunctionParameters(PdbCompilandSymId func_id, @@ -116,6 +113,9 @@ private: clang::DeclContext * GetParentDeclContextForSymbol(const llvm::codeview::CVSymbol &sym); + clang::NamespaceDecl *GetOrCreateNamespaceDecl(const char *name, + clang::DeclContext &context); + void ParseAllNamespacesPlusChildrenOf(llvm::Optional<llvm::StringRef> parent); void ParseDeclsForSimpleContext(clang::DeclContext &context); void ParseBlockChildren(PdbCompilandSymId block_id); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp new file mode 100644 index 000000000000..79dd010ff311 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp @@ -0,0 +1,137 @@ +//===-- PdbFPOProgramToDWARFExpression.cpp ----------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "PdbFPOProgramToDWARFExpression.h" +#include "CodeViewRegisterMapping.h" + +#include "lldb/Core/StreamBuffer.h" +#include "lldb/Symbol/PostfixExpression.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Stream.h" +#include "llvm/ADT/DenseMap.h" + +#include "llvm/ADT/StringExtras.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/EnumTables.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::postfix; + +static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) { + // lookup register name to get lldb register number + llvm::codeview::CPUType cpu_type; + switch (arch_type) { + case llvm::Triple::ArchType::aarch64: + cpu_type = llvm::codeview::CPUType::ARM64; + break; + + default: + cpu_type = llvm::codeview::CPUType::X64; + break; + } + + llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names = + llvm::codeview::getRegisterNames(cpu_type); + auto it = llvm::find_if( + register_names, + [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { + return reg_name.compare_lower(register_entry.Name) == 0; + }); + + if (it == register_names.end()) + return LLDB_INVALID_REGNUM; + + auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value); + return npdb::GetLLDBRegisterNumber(arch_type, reg_id); +} + +static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, + llvm::BumpPtrAllocator &alloc, + llvm::StringRef ®ister_name, + Node *&ast) { + // lvalue of assignment is always first token + // rvalue program goes next + std::tie(register_name, program) = getToken(program); + if (register_name.empty()) + return false; + + ast = Parse(program, alloc); + return ast != nullptr; +} + +static Node *ParseFPOProgram(llvm::StringRef program, + llvm::StringRef register_name, + llvm::Triple::ArchType arch_type, + llvm::BumpPtrAllocator &alloc) { + llvm::DenseMap<llvm::StringRef, Node *> dependent_programs; + + size_t cur = 0; + while (true) { + size_t assign_index = program.find('=', cur); + if (assign_index == llvm::StringRef::npos) { + llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos); + if (!tail.trim().empty()) { + // missing assign operator + return nullptr; + } + break; + } + llvm::StringRef assignment_program = program.slice(cur, assign_index); + + llvm::StringRef lvalue_name; + Node *rvalue_ast = nullptr; + if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name, + rvalue_ast)) { + return nullptr; + } + + lldbassert(rvalue_ast); + + // Emplace valid dependent subtrees to make target assignment independent + // from predecessors. Resolve all other SymbolNodes as registers. + bool success = + ResolveSymbols(rvalue_ast, [&](SymbolNode &symbol) -> Node * { + if (Node *node = dependent_programs.lookup(symbol.GetName())) + return node; + uint32_t reg_num = + ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type); + + if (reg_num == LLDB_INVALID_REGNUM) + return nullptr; + + return MakeNode<RegisterNode>(alloc, reg_num); + }); + if (!success) + return nullptr; + + if (lvalue_name == register_name) { + // found target assignment program - no need to parse further + return rvalue_ast; + } + + dependent_programs[lvalue_name] = rvalue_ast; + cur = assign_index + 1; + } + + return nullptr; +} + +bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( + llvm::StringRef program, llvm::StringRef register_name, + llvm::Triple::ArchType arch_type, Stream &stream) { + llvm::BumpPtrAllocator node_alloc; + Node *target_program = + ParseFPOProgram(program, register_name, arch_type, node_alloc); + if (target_program == nullptr) { + return false; + } + + ToDWARF(*target_program, stream); + return true; +} diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h new file mode 100644 index 000000000000..107e26fb04cb --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h @@ -0,0 +1,28 @@ +//===-- PdbFPOProgramToDWARFExpression.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_Plugins_SymbolFile_PDB_PDBFPOProgramToDWARFExpression_h_ +#define lldb_Plugins_SymbolFile_PDB_PDBFPOProgramToDWARFExpression_h_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" + +namespace lldb_private { +class Stream; + +namespace npdb { + +bool TranslateFPOProgramToDWARFExpression(llvm::StringRef program, + llvm::StringRef register_name, + llvm::Triple::ArchType arch_type, + lldb_private::Stream &stream); + +} // namespace npdb +} // namespace lldb_private + +#endif diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp index 9f5dab6c2e84..ba9a95b16e18 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp @@ -1,9 +1,8 @@ //===-- PdbIndex.cpp --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -133,9 +132,8 @@ void PdbIndex::BuildAddrToSymbolMap(CompilandIndexItem &cci) { PdbCompilandSymId cu_sym_id(modi, iter.offset()); - // If the debug info is incorrect, we could have multiple symbols with the - // same address. So use try_emplace instead of insert, and the first one - // will win. + // It's rare, but we could have multiple symbols with the same address + // because of identical comdat folding. Right now, the first one will win. cci.m_symbols_by_va.insert(std::make_pair(va, PdbSymUid(cu_sym_id))); } } @@ -187,8 +185,6 @@ std::vector<SymbolAndUid> PdbIndex::FindSymbolsByVa(lldb::addr_t va) { } CVSymbol PdbIndex::ReadSymbolRecord(PdbCompilandSymId cu_sym) const { - // We need to subtract 4 here to adjust for the codeview debug magic - // at the beginning of the debug info stream. const CompilandIndexItem *cci = compilands().GetCompiland(cu_sym.modi); auto iter = cci->m_debug_stream.getSymbolArray().at(cu_sym.offset); lldbassert(iter != cci->m_debug_stream.getSymbolArray().end()); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h index 839d4e6606e4..b30e7870bbdb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h @@ -1,9 +1,8 @@ //===-- PdbIndex.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -115,6 +114,7 @@ public: create(std::unique_ptr<llvm::pdb::PDBFile>); void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; } + lldb::addr_t GetLoadAddress() const { return m_load_address; } void ParseSectionContribs(); llvm::pdb::PDBFile &pdb() { return *m_file; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp index e5424568da47..e5ad23f813eb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp @@ -1,9 +1,8 @@ //===-- PdbSymUid.cpp -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h index 1166bee4e327..7252d63c1ab4 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h @@ -1,9 +1,8 @@ //===-- PdbSymUid.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // A unique identification scheme for Pdb records. diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 317725dd250e..1f5c97da81cf 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -1,9 +1,8 @@ //===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -15,9 +14,11 @@ #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" +#include "lldb/Symbol/Block.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-enumerations.h" @@ -43,7 +44,7 @@ MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, gaps = gaps.drop_front(); } - result.Append(start, end); + result.Append(start, end - start); return result; } @@ -507,8 +508,78 @@ VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) { return {}; } +static llvm::FixedStreamArray<FrameData>::Iterator +GetCorrespondingFrameData(lldb::addr_t load_addr, + const DebugFrameDataSubsectionRef &fpo_data, + const Variable::RangeList &ranges) { + lldbassert(!ranges.IsEmpty()); + + // assume that all variable ranges correspond to one frame data + using RangeListEntry = Variable::RangeList::Entry; + const RangeListEntry &range = ranges.GetEntryRef(0); + + auto it = fpo_data.begin(); + + // start by searching first frame data range containing variable range + for (; it != fpo_data.end(); ++it) { + RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize); + + if (fd_range.Contains(range)) { + break; + } + } + + // then first most nested entry that still contains variable range + auto found = it; + for (; it != fpo_data.end(); ++it) { + RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize); + + if (!fd_range.Contains(range)) { + break; + } + found = it; + } + + return found; +} + +static bool GetFrameDataProgram(PdbIndex &index, + const Variable::RangeList &ranges, + llvm::StringRef &out_program) { + const DebugFrameDataSubsectionRef &new_fpo_data = + index.dbi().getNewFpoRecords(); + + auto frame_data_it = + GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges); + if (frame_data_it == new_fpo_data.end()) + return false; + + PDBStringTable &strings = cantFail(index.pdb().getStringTable()); + out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc)); + return true; +} + +static RegisterId GetBaseFrameRegister(PdbIndex &index, + PdbCompilandSymId frame_proc_id, + bool is_parameter) { + CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id); + lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC); + + FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym); + cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs, + frame_proc)); + + CPUType cpu_type = index.compilands() + .GetCompiland(frame_proc_id.modi) + ->m_compile_opts->Machine; + + return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type) + : frame_proc.getLocalFramePtrReg(cpu_type); +} + VariableInfo lldb_private::npdb::GetVariableLocationInfo( - PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) { + PdbIndex &index, PdbCompilandSymId var_id, Block &block, + lldb::ModuleSP module) { CVSymbol sym = index.ReadSymbolRecord(var_id); @@ -543,13 +614,69 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( SymbolRecordKind::DefRangeFramePointerRelSym); cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>( loc_specifier_cvs, loc)); - // FIXME: The register needs to come from the S_FRAMEPROC symbol. - result.location = - MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module); - result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); - } else { - // FIXME: Handle other kinds + + Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); + + // TODO: may be better to pass function scope and not lookup it every + // time? find nearest parent function block + Block *cur = █ + while (cur->GetParent()) { + cur = cur->GetParent(); + } + PdbCompilandSymId func_scope_id = + PdbSymUid(cur->GetID()).asCompilandSym(); + CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id); + lldbassert(func_block_cvs.kind() == S_GPROC32 || + func_block_cvs.kind() == S_LPROC32); + + PdbCompilandSymId frame_proc_id( + func_scope_id.modi, func_scope_id.offset + func_block_cvs.length()); + + bool is_parameter = + ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None); + RegisterId base_reg = + GetBaseFrameRegister(index, frame_proc_id, is_parameter); + + if (base_reg == RegisterId::VFRAME) { + llvm::StringRef program; + if (GetFrameDataProgram(index, ranges, program)) { + result.location = + MakeVFrameRelLocationExpression(program, loc.Offset, module); + result.ranges = std::move(ranges); + } else { + // invalid variable + } + } else { + result.location = + MakeRegRelLocationExpression(base_reg, loc.Offset, module); + result.ranges = std::move(ranges); + } + } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) { + DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym); + cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>( + loc_specifier_cvs, loc)); + + Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); + + RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register; + + if (base_reg == RegisterId::VFRAME) { + llvm::StringRef program; + if (GetFrameDataProgram(index, ranges, program)) { + result.location = MakeVFrameRelLocationExpression( + program, loc.Hdr.BasePointerOffset, module); + result.ranges = std::move(ranges); + } else { + // invalid variable + } + } else { + result.location = MakeRegRelLocationExpression( + base_reg, loc.Hdr.BasePointerOffset, module); + result.ranges = std::move(ranges); + } } + + // FIXME: Handle other kinds return result; } llvm_unreachable("Symbol is not a local variable!"); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h index 570c300b6a2b..6f675b56dca4 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -1,9 +1,8 @@ //===-- PdbUtil.h -----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -142,7 +141,7 @@ LookThroughModifierRecord(llvm::codeview::CVType modifier); llvm::StringRef DropNameScope(llvm::StringRef name); VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol); -VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, +VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, Block& block, lldb::ModuleSP module); size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 7e97e2b37724..e27d4699ae2f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1,9 +1,8 @@ //===-- SymbolFileNativePDB.cpp ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -74,6 +73,8 @@ static lldb::LanguageType TranslateLanguage(PDB_Lang lang) { return lldb::LanguageType::eLanguageTypeC_plus_plus; case PDB_Lang::C: return lldb::LanguageType::eLanguageTypeC; + case PDB_Lang::Swift: + return lldb::LanguageType::eLanguageTypeSwift; default: return lldb::LanguageType::eLanguageTypeUnknown; } @@ -316,7 +317,7 @@ uint32_t SymbolFileNativePDB::CalculateAbilities() { } void SymbolFileNativePDB::InitializeObject() { - m_obj_load_address = m_obj_file->GetFileOffset(); + m_obj_load_address = m_obj_file->GetBaseAddress().GetFileAddress(); m_index->SetLoadAddress(m_obj_load_address); m_index->ParseSectionContribs(); @@ -594,6 +595,17 @@ TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, return array_sp; } + +TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id, + const MemberFunctionRecord &mfr, + CompilerType ct) { + Declaration decl; + return std::make_shared<lldb_private::Type>( + toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID, + lldb_private::Type::eEncodingIsUID, decl, ct, + lldb_private::Type::eResolveStateFull); +} + TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id, const ProcedureRecord &pr, CompilerType ct) { @@ -654,6 +666,11 @@ TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr)); return CreateProcedureType(type_id, pr, ct); } + if (cvt.kind() == LF_MFUNCTION) { + MemberFunctionRecord mfr; + llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr)); + return CreateFunctionType(type_id, mfr, ct); + } return nullptr; } @@ -1137,7 +1154,7 @@ bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, } bool SymbolFileNativePDB::ParseImportedModules( - const SymbolContext &sc, std::vector<ConstString> &imported_modules) { + const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { // PDB does not yet support module debug info return false; } @@ -1151,7 +1168,7 @@ size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); } uint32_t SymbolFileNativePDB::FindGlobalVariables( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; @@ -1178,7 +1195,7 @@ uint32_t SymbolFileNativePDB::FindGlobalVariables( } uint32_t SymbolFileNativePDB::FindFunctions( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, bool append, SymbolContextList &sc_list) { // For now we only support lookup by method name. @@ -1219,7 +1236,7 @@ uint32_t SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, } uint32_t SymbolFileNativePDB::FindTypes( - const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { if (!append) @@ -1316,7 +1333,9 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) { ModuleSP module = GetObjectFile()->GetModule(); - VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module); + Block &block = GetOrCreateBlock(scope_id); + VariableInfo var_info = + GetVariableLocationInfo(*m_index, var_id, block, module); if (!var_info.location || !var_info.ranges) return nullptr; @@ -1549,7 +1568,7 @@ size_t SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, } CompilerDeclContext -SymbolFileNativePDB::FindNamespace(const ConstString &name, +SymbolFileNativePDB::FindNamespace(ConstString name, const CompilerDeclContext *parent_decl_ctx) { return {}; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index dcf3fe365ef1..20daff219a0a 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -1,9 +1,8 @@ //===-- SymbolFileNativePDB.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -45,9 +44,7 @@ class SymbolFileNativePDB : public SymbolFile { friend class UdtRecordCompleter; public: - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -60,9 +57,7 @@ public: static SymbolFile *CreateInstance(ObjectFile *obj_file); - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ SymbolFileNativePDB(ObjectFile *ofile); ~SymbolFileNativePDB() override; @@ -71,9 +66,7 @@ public: void InitializeObject() override; - //------------------------------------------------------------------ // Compile Unit function calls - //------------------------------------------------------------------ uint32_t GetNumCompileUnits() override; @@ -95,13 +88,13 @@ public: FileSpecList &support_files) override; size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; - bool - ParseImportedModules(const SymbolContext &sc, - std::vector<ConstString> &imported_modules) override; + bool ParseImportedModules( + const SymbolContext &sc, + std::vector<lldb_private::SourceModule> &imported_modules) override; size_t ParseBlocksRecursive(Function &func) override; - uint32_t FindGlobalVariables(const ConstString &name, + uint32_t FindGlobalVariables(ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) override; @@ -130,7 +123,7 @@ public: size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, TypeList &type_list) override; - uint32_t FindFunctions(const ConstString &name, + uint32_t FindFunctions(ConstString name, const CompilerDeclContext *parent_decl_ctx, lldb::FunctionNameType name_type_mask, bool include_inlines, bool append, @@ -139,7 +132,7 @@ public: uint32_t FindFunctions(const RegularExpression ®ex, bool include_inlines, bool append, SymbolContextList &sc_list) override; - uint32_t FindTypes(const ConstString &name, + uint32_t FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, @@ -151,7 +144,7 @@ public: TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override; CompilerDeclContext - FindNamespace(const ConstString &name, + FindNamespace(ConstString name, const CompilerDeclContext *parent_decl_ctx) override; ConstString GetPluginName() override; @@ -187,6 +180,9 @@ private: lldb::TypeSP CreateArrayType(PdbTypeSymId type_id, const llvm::codeview::ArrayRecord &ar, CompilerType ct); + lldb::TypeSP CreateFunctionType(PdbTypeSymId type_id, + const llvm::codeview::MemberFunctionRecord &pr, + CompilerType ct); lldb::TypeSP CreateProcedureType(PdbTypeSymId type_id, const llvm::codeview::ProcedureRecord &pr, CompilerType ct); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 239dfbee625d..3c494dc83986 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -50,7 +50,8 @@ UdtRecordCompleter::UdtRecordCompleter(PdbTypeSymId id, } clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex( - llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access) { + llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access, + llvm::Optional<uint64_t> vtable_idx) { PdbTypeSymId type_id(ti); clang::QualType qt = m_ast_builder.GetOrCreateType(type_id); @@ -58,13 +59,32 @@ clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex( std::unique_ptr<clang::CXXBaseSpecifier> base_spec = m_ast_builder.clang().CreateBaseClassSpecifier( - qt.getAsOpaquePtr(), TranslateMemberAccess(access), false, - udt_cvt.kind() == LF_CLASS); + qt.getAsOpaquePtr(), TranslateMemberAccess(access), + vtable_idx.hasValue(), udt_cvt.kind() == LF_CLASS); lldbassert(base_spec); - m_bases.push_back(std::move(base_spec)); + + m_bases.push_back( + std::make_pair(vtable_idx.getValueOr(0), std::move(base_spec))); + return qt; } +void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, + MemberAccess access, MethodOptions options, + MemberAttributes attrs) { + clang::QualType method_qt = + m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx)); + m_ast_builder.CompleteType(method_qt); + + lldb::AccessType access_type = TranslateMemberAccess(access); + bool is_artificial = (options & MethodOptions::CompilerGenerated) == + MethodOptions::CompilerGenerated; + m_ast_builder.clang().AddMethodToCXXRecordType( + m_derived_ct.GetOpaqueQualType(), name.data(), nullptr, + m_ast_builder.ToCompilerType(method_qt), access_type, attrs.isVirtual(), + attrs.isStatic(), false, false, false, is_artificial); +} + Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, BaseClassRecord &base) { clang::QualType base_qt = @@ -82,9 +102,8 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, VirtualBaseClassRecord &base) { - AddBaseClassForTypeIndex(base.BaseType, base.getAccess()); + AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex); - // FIXME: Handle virtual base offsets. return Error::success(); } @@ -158,11 +177,27 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, OneMethodRecord &one_method) { + AddMethod(one_method.Name, one_method.Type, one_method.getAccess(), + one_method.getOptions(), one_method.Attrs); + return Error::success(); } Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, OverloadedMethodRecord &overloaded) { + TypeIndex method_list_idx = overloaded.MethodList; + + CVType method_list_type = m_tpi.getType(method_list_idx); + assert(method_list_type.kind() == LF_METHODLIST); + + MethodOverloadListRecord method_list; + llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>( + method_list_type, method_list)); + + for (const OneMethodRecord &method : method_list.Methods) + AddMethod(overloaded.Name, method.Type, method.getAccess(), + method.getOptions(), method.Attrs); + return Error::success(); } @@ -177,9 +212,19 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, } void UdtRecordCompleter::complete() { + // Ensure the correct order for virtual bases. + std::stable_sort(m_bases.begin(), m_bases.end(), + [](const IndexedBase &lhs, const IndexedBase &rhs) { + return lhs.first < rhs.first; + }); + + std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases; + bases.reserve(m_bases.size()); + for (auto &ib : m_bases) + bases.push_back(std::move(ib.second)); + ClangASTContext &clang = m_ast_builder.clang(); - clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), - std::move(m_bases)); + clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases)); clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType()); ClangASTContext::BuildIndirectFields(m_derived_ct); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h index 469685126e59..55397582209b 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h @@ -1,9 +1,8 @@ -//===-- SymbolFileNativePDB.h -----------------------------------*- C++ -*-===// +//===-- UdtRecordCompleter.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -36,6 +35,9 @@ namespace npdb { class PdbAstBuilder; class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks { + using IndexedBase = + std::pair<uint64_t, std::unique_ptr<clang::CXXBaseSpecifier>>; + union UdtTagRecord { UdtTagRecord() {} llvm::codeview::UnionRecord ur; @@ -48,7 +50,7 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks { clang::TagDecl &m_tag_decl; PdbAstBuilder &m_ast_builder; llvm::pdb::TpiStream &m_tpi; - std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> m_bases; + std::vector<IndexedBase> m_bases; ClangASTImporter::LayoutInfo m_layout; public: @@ -65,8 +67,13 @@ public: void complete(); private: - clang::QualType AddBaseClassForTypeIndex(llvm::codeview::TypeIndex ti, - llvm::codeview::MemberAccess access); + clang::QualType AddBaseClassForTypeIndex( + llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access, + llvm::Optional<uint64_t> vtable_idx = llvm::Optional<uint64_t>()); + void AddMethod(llvm::StringRef name, llvm::codeview::TypeIndex type_idx, + llvm::codeview::MemberAccess access, + llvm::codeview::MethodOptions options, + llvm::codeview::MemberAttributes attrs); }; } // namespace npdb diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 65e718bedaf1..82cfcfbb040f 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -1,9 +1,8 @@ //===-- PDBASTParser.cpp ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -568,9 +567,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { ast_typedef = ast_typedef.AddVolatileModifier(); GetDeclarationForSymbol(type, decl); + llvm::Optional<uint64_t> size; + if (type_def->getLength()) + size = type_def->getLength(); return std::make_shared<lldb_private::Type>( type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), - type_def->getLength(), nullptr, target_type->GetID(), + size, nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef, lldb_private::Type::eResolveStateFull); } break; @@ -637,16 +639,19 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { GetDeclarationForSymbol(type, decl); return std::make_shared<lldb_private::Type>( - type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), 0, - nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, - func_sig_ast_type, lldb_private::Type::eResolveStateFull); + type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), + llvm::None, nullptr, LLDB_INVALID_UID, + lldb_private::Type::eEncodingIsUID, decl, func_sig_ast_type, + lldb_private::Type::eResolveStateFull); } break; case PDB_SymType::ArrayType: { auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type); assert(array_type); uint32_t num_elements = array_type->getCount(); uint32_t element_uid = array_type->getElementTypeId(); - uint32_t bytes = array_type->getLength(); + llvm::Optional<uint64_t> bytes; + if (uint64_t size = array_type->getLength()) + bytes = size; // If array rank > 0, PDB gives the element type at N=0. So element type // will parsed in the order N=0, N=1,..., N=rank sequentially. @@ -682,10 +687,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { if (builtin_kind == PDB_BuiltinType::None) return nullptr; - uint64_t bytes = builtin_type->getLength(); + llvm::Optional<uint64_t> bytes; + if (uint64_t size = builtin_type->getLength()) + bytes = size; Encoding encoding = TranslateBuiltinEncoding(builtin_kind); CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize( - m_ast, *builtin_type, encoding, bytes * 8); + m_ast, *builtin_type, encoding, bytes.getValueOr(0) * 8); if (builtin_type->isConstType()) builtin_ast_type = builtin_ast_type.AddConstModifier(); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h index 02353870ab60..9221d42b2020 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h @@ -1,9 +1,8 @@ //===-- PDBASTParser.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index 9f398ef9b047..1c17bf6563b3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp @@ -1,9 +1,8 @@ //===-- PDBLocationToDWARFExpression.cpp ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -13,487 +12,64 @@ #include "lldb/Core/StreamBuffer.h" #include "lldb/Core/dwarf.h" #include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/Variable.h" #include "lldb/Utility/DataBufferHeap.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "Plugins/Process/Utility/lldb-x86-register-enums.h" +#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h" +#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h" using namespace lldb; using namespace lldb_private; +using namespace lldb_private::npdb; using namespace llvm::pdb; -namespace { -const uint32_t g_code_view_to_lldb_registers_x86[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_i386, // AL - lldb_cl_i386, // CL - lldb_dl_i386, // DL - lldb_bl_i386, // BL - lldb_ah_i386, // AH - lldb_ch_i386, // CH - lldb_dh_i386, // DH - lldb_bh_i386, // BH - lldb_ax_i386, // AX - lldb_cx_i386, // CX - lldb_dx_i386, // DX - lldb_bx_i386, // BX - lldb_sp_i386, // SP - lldb_bp_i386, // BP - lldb_si_i386, // SI - lldb_di_i386, // DI - lldb_eax_i386, // EAX - lldb_ecx_i386, // ECX - lldb_edx_i386, // EDX - lldb_ebx_i386, // EBX - lldb_esp_i386, // ESP - lldb_ebp_i386, // EBP - lldb_esi_i386, // ESI - lldb_edi_i386, // EDI - lldb_es_i386, // ES - lldb_cs_i386, // CS - lldb_ss_i386, // SS - lldb_ds_i386, // DS - lldb_fs_i386, // FS - lldb_gs_i386, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - lldb_eip_i386, // EIP - lldb_eflags_i386, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_i386, // DR0 - lldb_dr1_i386, // DR1 - lldb_dr2_i386, // DR2 - lldb_dr3_i386, // DR3 - lldb_dr4_i386, // DR4 - lldb_dr5_i386, // DR5 - lldb_dr6_i386, // DR6 - lldb_dr7_i386, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_i386, // ST0 - lldb_st1_i386, // ST1 - lldb_st2_i386, // ST2 - lldb_st3_i386, // ST3 - lldb_st4_i386, // ST4 - lldb_st5_i386, // ST5 - lldb_st6_i386, // ST6 - lldb_st7_i386, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_i386, // MM0 - lldb_mm1_i386, // MM1 - lldb_mm2_i386, // MM2 - lldb_mm3_i386, // MM3 - lldb_mm4_i386, // MM4 - lldb_mm5_i386, // MM5 - lldb_mm6_i386, // MM6 - lldb_mm7_i386, // MM7 - lldb_xmm0_i386, // XMM0 - lldb_xmm1_i386, // XMM1 - lldb_xmm2_i386, // XMM2 - lldb_xmm3_i386, // XMM3 - lldb_xmm4_i386, // XMM4 - lldb_xmm5_i386, // XMM5 - lldb_xmm6_i386, // XMM6 - lldb_xmm7_i386 // XMM7 -}; - -const uint32_t g_code_view_to_lldb_registers_x86_64[] = { - LLDB_INVALID_REGNUM, // NONE - lldb_al_x86_64, // AL - lldb_cl_x86_64, // CL - lldb_dl_x86_64, // DL - lldb_bl_x86_64, // BL - lldb_ah_x86_64, // AH - lldb_ch_x86_64, // CH - lldb_dh_x86_64, // DH - lldb_bh_x86_64, // BH - lldb_ax_x86_64, // AX - lldb_cx_x86_64, // CX - lldb_dx_x86_64, // DX - lldb_bx_x86_64, // BX - lldb_sp_x86_64, // SP - lldb_bp_x86_64, // BP - lldb_si_x86_64, // SI - lldb_di_x86_64, // DI - lldb_eax_x86_64, // EAX - lldb_ecx_x86_64, // ECX - lldb_edx_x86_64, // EDX - lldb_ebx_x86_64, // EBX - lldb_esp_x86_64, // ESP - lldb_ebp_x86_64, // EBP - lldb_esi_x86_64, // ESI - lldb_edi_x86_64, // EDI - lldb_es_x86_64, // ES - lldb_cs_x86_64, // CS - lldb_ss_x86_64, // SS - lldb_ds_x86_64, // DS - lldb_fs_x86_64, // FS - lldb_gs_x86_64, // GS - LLDB_INVALID_REGNUM, // IP - LLDB_INVALID_REGNUM, // FLAGS - LLDB_INVALID_REGNUM, // EIP - LLDB_INVALID_REGNUM, // EFLAGS - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // TEMP - LLDB_INVALID_REGNUM, // TEMPH - LLDB_INVALID_REGNUM, // QUOTE - LLDB_INVALID_REGNUM, // PCDR3 - LLDB_INVALID_REGNUM, // PCDR4 - LLDB_INVALID_REGNUM, // PCDR5 - LLDB_INVALID_REGNUM, // PCDR6 - LLDB_INVALID_REGNUM, // PCDR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CR0 - LLDB_INVALID_REGNUM, // CR1 - LLDB_INVALID_REGNUM, // CR2 - LLDB_INVALID_REGNUM, // CR3 - LLDB_INVALID_REGNUM, // CR4 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_x86_64, // DR0 - lldb_dr1_x86_64, // DR1 - lldb_dr2_x86_64, // DR2 - lldb_dr3_x86_64, // DR3 - lldb_dr4_x86_64, // DR4 - lldb_dr5_x86_64, // DR5 - lldb_dr6_x86_64, // DR6 - lldb_dr7_x86_64, // DR7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // GDTR - LLDB_INVALID_REGNUM, // GDTL - LLDB_INVALID_REGNUM, // IDTR - LLDB_INVALID_REGNUM, // IDTL - LLDB_INVALID_REGNUM, // LDTR - LLDB_INVALID_REGNUM, // TR - LLDB_INVALID_REGNUM, // PSEUDO1 - LLDB_INVALID_REGNUM, // PSEUDO2 - LLDB_INVALID_REGNUM, // PSEUDO3 - LLDB_INVALID_REGNUM, // PSEUDO4 - LLDB_INVALID_REGNUM, // PSEUDO5 - LLDB_INVALID_REGNUM, // PSEUDO6 - LLDB_INVALID_REGNUM, // PSEUDO7 - LLDB_INVALID_REGNUM, // PSEUDO8 - LLDB_INVALID_REGNUM, // PSEUDO9 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_x86_64, // ST0 - lldb_st1_x86_64, // ST1 - lldb_st2_x86_64, // ST2 - lldb_st3_x86_64, // ST3 - lldb_st4_x86_64, // ST4 - lldb_st5_x86_64, // ST5 - lldb_st6_x86_64, // ST6 - lldb_st7_x86_64, // ST7 - LLDB_INVALID_REGNUM, // CTRL - LLDB_INVALID_REGNUM, // STAT - LLDB_INVALID_REGNUM, // TAG - LLDB_INVALID_REGNUM, // FPIP - LLDB_INVALID_REGNUM, // FPCS - LLDB_INVALID_REGNUM, // FPDO - LLDB_INVALID_REGNUM, // FPDS - LLDB_INVALID_REGNUM, // ISEM - LLDB_INVALID_REGNUM, // FPEIP - LLDB_INVALID_REGNUM, // FPEDO - lldb_mm0_x86_64, // MM0 - lldb_mm1_x86_64, // MM1 - lldb_mm2_x86_64, // MM2 - lldb_mm3_x86_64, // MM3 - lldb_mm4_x86_64, // MM4 - lldb_mm5_x86_64, // MM5 - lldb_mm6_x86_64, // MM6 - lldb_mm7_x86_64, // MM7 - lldb_xmm0_x86_64, // XMM0 - lldb_xmm1_x86_64, // XMM1 - lldb_xmm2_x86_64, // XMM2 - lldb_xmm3_x86_64, // XMM3 - lldb_xmm4_x86_64, // XMM4 - lldb_xmm5_x86_64, // XMM5 - lldb_xmm6_x86_64, // XMM6 - lldb_xmm7_x86_64, // XMM7 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_mxcsr_x86_64, // MXCSR - LLDB_INVALID_REGNUM, // EDXEAX - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // EMM0L - LLDB_INVALID_REGNUM, // EMM1L - LLDB_INVALID_REGNUM, // EMM2L - LLDB_INVALID_REGNUM, // EMM3L - LLDB_INVALID_REGNUM, // EMM4L - LLDB_INVALID_REGNUM, // EMM5L - LLDB_INVALID_REGNUM, // EMM6L - LLDB_INVALID_REGNUM, // EMM7L - LLDB_INVALID_REGNUM, // EMM0H - LLDB_INVALID_REGNUM, // EMM1H - LLDB_INVALID_REGNUM, // EMM2H - LLDB_INVALID_REGNUM, // EMM3H - LLDB_INVALID_REGNUM, // EMM4H - LLDB_INVALID_REGNUM, // EMM5H - LLDB_INVALID_REGNUM, // EMM6H - LLDB_INVALID_REGNUM, // EMM7H - LLDB_INVALID_REGNUM, // MM00 - LLDB_INVALID_REGNUM, // MM01 - LLDB_INVALID_REGNUM, // MM10 - LLDB_INVALID_REGNUM, // MM11 - LLDB_INVALID_REGNUM, // MM20 - LLDB_INVALID_REGNUM, // MM21 - LLDB_INVALID_REGNUM, // MM30 - LLDB_INVALID_REGNUM, // MM31 - LLDB_INVALID_REGNUM, // MM40 - LLDB_INVALID_REGNUM, // MM41 - LLDB_INVALID_REGNUM, // MM50 - LLDB_INVALID_REGNUM, // MM51 - LLDB_INVALID_REGNUM, // MM60 - LLDB_INVALID_REGNUM, // MM61 - LLDB_INVALID_REGNUM, // MM70 - LLDB_INVALID_REGNUM, // MM71 - lldb_xmm8_x86_64, // XMM8 - lldb_xmm9_x86_64, // XMM9 - lldb_xmm10_x86_64, // XMM10 - lldb_xmm11_x86_64, // XMM11 - lldb_xmm12_x86_64, // XMM12 - lldb_xmm13_x86_64, // XMM13 - lldb_xmm14_x86_64, // XMM14 - lldb_xmm15_x86_64, // XMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, - lldb_sil_x86_64, // SIL - lldb_dil_x86_64, // DIL - lldb_bpl_x86_64, // BPL - lldb_spl_x86_64, // SPL - lldb_rax_x86_64, // RAX - lldb_rbx_x86_64, // RBX - lldb_rcx_x86_64, // RCX - lldb_rdx_x86_64, // RDX - lldb_rsi_x86_64, // RSI - lldb_rdi_x86_64, // RDI - lldb_rbp_x86_64, // RBP - lldb_rsp_x86_64, // RSP - lldb_r8_x86_64, // R8 - lldb_r9_x86_64, // R9 - lldb_r10_x86_64, // R10 - lldb_r11_x86_64, // R11 - lldb_r12_x86_64, // R12 - lldb_r13_x86_64, // R13 - lldb_r14_x86_64, // R14 - lldb_r15_x86_64, // R15 - lldb_r8l_x86_64, // R8B - lldb_r9l_x86_64, // R9B - lldb_r10l_x86_64, // R10B - lldb_r11l_x86_64, // R11B - lldb_r12l_x86_64, // R12B - lldb_r13l_x86_64, // R13B - lldb_r14l_x86_64, // R14B - lldb_r15l_x86_64, // R15B - lldb_r8w_x86_64, // R8W - lldb_r9w_x86_64, // R9W - lldb_r10w_x86_64, // R10W - lldb_r11w_x86_64, // R11W - lldb_r12w_x86_64, // R12W - lldb_r13w_x86_64, // R13W - lldb_r14w_x86_64, // R14W - lldb_r15w_x86_64, // R15W - lldb_r8d_x86_64, // R8D - lldb_r9d_x86_64, // R9D - lldb_r10d_x86_64, // R10D - lldb_r11d_x86_64, // R11D - lldb_r12d_x86_64, // R12D - lldb_r13d_x86_64, // R13D - lldb_r14d_x86_64, // R14D - lldb_r15d_x86_64, // R15D - lldb_ymm0_x86_64, // AMD64_YMM0 - lldb_ymm1_x86_64, // AMD64_YMM1 - lldb_ymm2_x86_64, // AMD64_YMM2 - lldb_ymm3_x86_64, // AMD64_YMM3 - lldb_ymm4_x86_64, // AMD64_YMM4 - lldb_ymm5_x86_64, // AMD64_YMM5 - lldb_ymm6_x86_64, // AMD64_YMM6 - lldb_ymm7_x86_64, // AMD64_YMM7 - lldb_ymm8_x86_64, // AMD64_YMM8 - lldb_ymm9_x86_64, // AMD64_YMM9 - lldb_ymm10_x86_64, // AMD64_YMM10 - lldb_ymm11_x86_64, // AMD64_YMM11 - lldb_ymm12_x86_64, // AMD64_YMM12 - lldb_ymm13_x86_64, // AMD64_YMM13 - lldb_ymm14_x86_64, // AMD64_YMM14 - lldb_ymm15_x86_64, // AMD64_YMM15 - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_bnd0_x86_64, // BND0 - lldb_bnd1_x86_64, // BND1 - lldb_bnd2_x86_64 // BND2 -}; - -uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, - llvm::codeview::RegisterId register_id) { - switch (arch_type) { - case llvm::Triple::x86: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86) / - sizeof(g_code_view_to_lldb_registers_x86[0])) - return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>( - register_id)]; - - switch (register_id) { - case llvm::codeview::RegisterId::MXCSR: - return lldb_mxcsr_i386; - case llvm::codeview::RegisterId::BND0: - return lldb_bnd0_i386; - case llvm::codeview::RegisterId::BND1: - return lldb_bnd1_i386; - case llvm::codeview::RegisterId::BND2: - return lldb_bnd2_i386; - default: - return LLDB_INVALID_REGNUM; +static std::unique_ptr<IPDBFrameData> +GetCorrespondingFrameData(const IPDBSession &session, + const Variable::RangeList &ranges) { + auto enumFrameData = session.getFrameData(); + if (!enumFrameData) + return nullptr; + + std::unique_ptr<IPDBFrameData> found; + while (auto fd = enumFrameData->getNext()) { + Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(), + fd->getLengthBlock()); + + for (size_t i = 0; i < ranges.GetSize(); i++) { + auto range = ranges.GetEntryAtIndex(i); + if (!range) + continue; + + if (!range->DoesIntersect(fdRange)) + continue; + + found = std::move(fd); + + break; } - case llvm::Triple::x86_64: - if (static_cast<uint16_t>(register_id) < - sizeof(g_code_view_to_lldb_registers_x86_64) / - sizeof(g_code_view_to_lldb_registers_x86_64[0])) - return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>( - register_id)]; - - return LLDB_INVALID_REGNUM; - default: - return LLDB_INVALID_REGNUM; } -} - -uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) { - if (register_id == llvm::codeview::RegisterId::VFRAME) - return LLDB_REGNUM_GENERIC_FP; - return LLDB_INVALID_REGNUM; + return found; } -uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type, - llvm::codeview::RegisterId register_id, - RegisterKind ®ister_kind) { - register_kind = eRegisterKindLLDB; - uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id); - if (reg_num != LLDB_INVALID_REGNUM) - return reg_num; - - register_kind = eRegisterKindGeneric; - return GetGenericRegisterNumber(register_id); +static bool EmitVFrameEvaluationDWARFExpression( + llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) { + // VFrame value always stored in $TO pseudo-register + return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type, + stream); } -} // namespace -DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, - const PDBSymbolData &symbol, - bool &is_constant) { +DWARFExpression ConvertPDBLocationToDWARFExpression( + ModuleSP module, const PDBSymbolData &symbol, + const Variable::RangeList &ranges, bool &is_constant) { is_constant = true; if (!module) - return DWARFExpression(nullptr); + return DWARFExpression(); const ArchSpec &architecture = module->GetArchitecture(); llvm::Triple::ArchType arch_type = architecture.GetMachine(); @@ -501,7 +77,7 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, uint32_t address_size = architecture.GetAddressByteSize(); uint32_t byte_size = architecture.GetDataByteSize(); if (byte_order == eByteOrderInvalid || address_size == 0) - return DWARFExpression(nullptr); + return DWARFExpression(); RegisterKind register_kind = eRegisterKindDWARF; StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); @@ -512,15 +88,13 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, SectionList *section_list = module->GetSectionList(); if (!section_list) - return DWARFExpression(nullptr); + return DWARFExpression(); - uint32_t section_idx = symbol.getAddressSection() - 1; - if (section_idx >= section_list->GetSize()) - return DWARFExpression(nullptr); + uint32_t section_id = symbol.getAddressSection(); - auto section = section_list->GetSectionAtIndex(section_idx); + auto section = section_list->FindSectionByID(section_id); if (!section) - return DWARFExpression(nullptr); + return DWARFExpression(); uint32_t offset = symbol.getAddressOffset(); stream.PutMaxHex64(section->GetFileAddress() + offset, address_size, @@ -531,10 +105,32 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, break; } case PDB_LocType::RegRel: { - uint32_t reg_num = - GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind); - if (reg_num == LLDB_INVALID_REGNUM) - return DWARFExpression(nullptr); + uint32_t reg_num; + auto reg_id = symbol.getRegisterId(); + if (reg_id == llvm::codeview::RegisterId::VFRAME) { + if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) { + if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type, + stream)) { + int32_t offset = symbol.getOffset(); + stream.PutHex8(DW_OP_consts); + stream.PutSLEB128(offset); + stream.PutHex8(DW_OP_plus); + + register_kind = eRegisterKindLLDB; + + is_constant = false; + break; + } + } + + register_kind = eRegisterKindGeneric; + reg_num = LLDB_REGNUM_GENERIC_FP; + } else { + register_kind = eRegisterKindLLDB; + reg_num = GetLLDBRegisterNumber(arch_type, reg_id); + if (reg_num == LLDB_INVALID_REGNUM) + return DWARFExpression(); + } if (reg_num > 31) { stream.PutHex8(DW_OP_bregx); @@ -550,10 +146,10 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, break; } case PDB_LocType::Enregistered: { - uint32_t reg_num = - GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind); + register_kind = eRegisterKindLLDB; + uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId()); if (reg_num == LLDB_INVALID_REGNUM) - return DWARFExpression(nullptr); + return DWARFExpression(); if (reg_num > 31) { stream.PutHex8(DW_OP_regx); @@ -572,7 +168,7 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module, break; } default: - return DWARFExpression(nullptr); + return DWARFExpression(); } DataBufferSP buffer = diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h index 37b80dfccb84..2e9d1386d537 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h @@ -1,9 +1,8 @@ //===-- PDBLocationToDWARFExpression.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,6 +10,7 @@ #define lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_ #include "lldb/Core/Module.h" +#include "lldb/Symbol/Variable.h" namespace lldb_private { class DWARFExpression; @@ -22,24 +22,26 @@ class PDBSymbolData; } } // namespace llvm -//------------------------------------------------------------------------------ /// Converts a location information from a PDB symbol to a DWARF expression /// -/// @param[in] module +/// \param[in] module /// The module \a symbol belongs to. /// -/// @param[in] symbol +/// \param[in] symbol /// The symbol with a location information to convert. /// -/// @param[out] is_constant +/// \param[in] ranges +/// Ranges where this variable is valid. +/// +/// \param[out] is_constant /// Set to \b true if the result expression is a constant value data, /// and \b false if it is a DWARF bytecode. /// -/// @return +/// \return /// The DWARF expression corresponding to the location data of \a symbol. -//------------------------------------------------------------------------------ lldb_private::DWARFExpression ConvertPDBLocationToDWARFExpression(lldb::ModuleSP module, const llvm::pdb::PDBSymbolData &symbol, + const lldb_private::Variable::RangeList &ranges, bool &is_constant); #endif diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index ad25842f4d05..17dfcdaceb9c 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1,9 +1,8 @@ //===-- SymbolFilePDB.cpp ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -65,6 +64,8 @@ lldb::LanguageType TranslateLanguage(PDB_Lang lang) { return lldb::LanguageType::eLanguageTypeC_plus_plus; case PDB_Lang::C: return lldb::LanguageType::eLanguageTypeC; + case PDB_Lang::Swift: + return lldb::LanguageType::eLanguageTypeSwift; default: return lldb::LanguageType::eLanguageTypeUnknown; } @@ -123,7 +124,7 @@ SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) { SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file) : SymbolFile(object_file), m_session_up(), m_global_scope_up(), - m_cached_compile_unit_count(0), m_tu_decl_ctx_up() {} + m_cached_compile_unit_count(0) {} SymbolFilePDB::~SymbolFilePDB() {} @@ -182,20 +183,12 @@ uint32_t SymbolFilePDB::CalculateAbilities() { } void SymbolFilePDB::InitializeObject() { - lldb::addr_t obj_load_address = m_obj_file->GetFileOffset(); + lldb::addr_t obj_load_address = m_obj_file->GetBaseAddress().GetFileAddress(); lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS); m_session_up->setLoadAddress(obj_load_address); if (!m_global_scope_up) m_global_scope_up = m_session_up->getGlobalScope(); lldbassert(m_global_scope_up.get()); - - TypeSystem *type_system = - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - ClangASTContext *clang_type_system = - llvm::dyn_cast_or_null<ClangASTContext>(type_system); - lldbassert(clang_type_system); - m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>( - type_system, clang_type_system->GetTranslationUnitDecl()); } uint32_t SymbolFilePDB::GetNumCompileUnits() { @@ -308,7 +301,8 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, comp_unit.AddFunction(func_sp); - TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + LanguageType lang = ParseLanguage(comp_unit); + TypeSystem *type_system = GetTypeSystemForLanguage(lang); if (!type_system) return nullptr; ClangASTContext *clang_type_system = @@ -378,7 +372,7 @@ bool SymbolFilePDB::ParseSupportFiles( bool SymbolFilePDB::ParseImportedModules( const lldb_private::SymbolContext &sc, - std::vector<lldb_private::ConstString> &imported_modules) { + std::vector<SourceModule> &imported_modules) { // PDB does not yet support module debug info return false; } @@ -934,12 +928,25 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( Variable::RangeList ranges; SymbolContextScope *context_scope = sc.comp_unit; - if (scope == eValueTypeVariableLocal) { + if (scope == eValueTypeVariableLocal || scope == eValueTypeVariableArgument) { if (sc.function) { - context_scope = sc.function->GetBlock(true).FindBlockByID( - pdb_data.getLexicalParentId()); - if (context_scope == nullptr) - context_scope = sc.function; + Block &function_block = sc.function->GetBlock(true); + Block *block = + function_block.FindBlockByID(pdb_data.getLexicalParentId()); + if (!block) + block = &function_block; + + context_scope = block; + + for (size_t i = 0, num_ranges = block->GetNumRanges(); i < num_ranges; + ++i) { + AddressRange range; + if (!block->GetRangeAtIndex(i, range)) + continue; + + ranges.Append(range.GetBaseAddress().GetFileAddress(), + range.GetByteSize()); + } } } @@ -952,7 +959,7 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( bool is_constant; DWARFExpression location = ConvertPDBLocationToDWARFExpression( - GetObjectFile()->GetModule(), pdb_data, is_constant); + GetObjectFile()->GetModule(), pdb_data, ranges, is_constant); var_sp = std::make_shared<Variable>( var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope, @@ -1034,7 +1041,7 @@ SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc, } uint32_t SymbolFilePDB::FindGlobalVariables( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) { if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) @@ -1234,7 +1241,7 @@ void SymbolFilePDB::CacheFunctionNames() { } uint32_t SymbolFilePDB::FindFunctions( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list) { @@ -1337,11 +1344,9 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { return; while (auto pub_symbol = results->getNext()) { - auto section_idx = pub_symbol->getAddressSection() - 1; - if (section_idx >= section_list->GetSize()) - continue; + auto section_id = pub_symbol->getAddressSection(); - auto section = section_list->GetSectionAtIndex(section_idx); + auto section = section_list->FindSectionByID(section_id); if (!section) continue; @@ -1376,7 +1381,7 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { } uint32_t SymbolFilePDB::FindTypes( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, @@ -1618,7 +1623,7 @@ PDBASTParser *SymbolFilePDB::GetPDBAstParser() { lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) { auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system); diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 81288093b7d8..ba3099aaec4d 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -1,9 +1,8 @@ //===-- SymbolFilePDB.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -24,9 +23,7 @@ class PDBASTParser; class SymbolFilePDB : public lldb_private::SymbolFile { public: - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -40,9 +37,7 @@ public: static lldb_private::SymbolFile * CreateInstance(lldb_private::ObjectFile *obj_file); - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ SymbolFilePDB(lldb_private::ObjectFile *ofile); ~SymbolFilePDB() override; @@ -51,9 +46,7 @@ public: void InitializeObject() override; - //------------------------------------------------------------------ // Compile Unit function calls - //------------------------------------------------------------------ uint32_t GetNumCompileUnits() override; @@ -75,7 +68,7 @@ public: bool ParseImportedModules( const lldb_private::SymbolContext &sc, - std::vector<lldb_private::ConstString> &imported_modules) override; + std::vector<lldb_private::SourceModule> &imported_modules) override; size_t ParseBlocksRecursive(lldb_private::Function &func) override; @@ -111,7 +104,7 @@ public: lldb_private::SymbolContextList &sc_list) override; uint32_t - FindGlobalVariables(const lldb_private::ConstString &name, + FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; @@ -121,7 +114,7 @@ public: lldb_private::VariableList &variables) override; uint32_t - FindFunctions(const lldb_private::ConstString &name, + FindFunctions(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, lldb::FunctionNameType name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list) override; @@ -137,7 +130,7 @@ public: void AddSymbols(lldb_private::Symtab &symtab) override; uint32_t - FindTypes(const lldb_private::ConstString &name, + FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, @@ -159,7 +152,7 @@ public: GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( - const lldb_private::ConstString &name, + lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; lldb_private::ConstString GetPluginName() override; @@ -253,7 +246,6 @@ private: std::unique_ptr<llvm::pdb::IPDBSession> m_session_up; std::unique_ptr<llvm::pdb::PDBSymbolExe> m_global_scope_up; uint32_t m_cached_compile_unit_count; - std::unique_ptr<lldb_private::CompilerDeclContext> m_tu_decl_ctx_up; lldb_private::UniqueCStringMap<uint32_t> m_func_full_names; lldb_private::UniqueCStringMap<uint32_t> m_func_base_names; diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 08778bd1ba70..a1b21e51b0fe 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -1,13 +1,13 @@ //===-- SymbolFileSymtab.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 "SymbolFileSymtab.h" + #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Symbol/CompileUnit.h" @@ -20,6 +20,8 @@ #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Timer.h" +#include <memory> + using namespace lldb; using namespace lldb_private; @@ -62,11 +64,9 @@ uint32_t SymbolFileSymtab::CalculateAbilities() { if (m_obj_file) { const Symtab *symtab = m_obj_file->GetSymtab(); if (symtab) { - //---------------------------------------------------------------------- // The snippet of code below will get the indexes the module symbol table // entries that are code, data, or function related (debug info), sort // them by value (address) and dump the sorted symbols. - //---------------------------------------------------------------------- if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile, m_source_indexes)) { abilities |= CompileUnits; @@ -124,9 +124,9 @@ CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) { const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) - cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, + cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, cu_symbol->GetName().AsCString(), 0, - eLanguageTypeUnknown, eLazyBoolNo)); + eLanguageTypeUnknown, eLazyBoolNo); } return cu_sp; } @@ -139,8 +139,8 @@ size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) { size_t num_added = 0; // We must at least have a valid compile unit const Symtab *symtab = m_obj_file->GetSymtab(); - const Symbol *curr_symbol = NULL; - const Symbol *next_symbol = NULL; + const Symbol *curr_symbol = nullptr; + const Symbol *next_symbol = nullptr; // const char *prefix = m_obj_file->SymbolPrefix(); // if (prefix == NULL) // prefix == ""; @@ -188,10 +188,10 @@ size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) { LLDB_INVALID_UID, // We don't have any type info // for this function curr_symbol->GetMangled(), // Linker/mangled name - NULL, // no return type for a code symbol... + nullptr, // no return type for a code symbol... func_range)); // first address range - if (func_sp.get() != NULL) { + if (func_sp.get() != nullptr) { comp_unit.AddFunction(func_sp); ++num_added; } @@ -219,7 +219,7 @@ bool SymbolFileSymtab::ParseSupportFiles(CompileUnit &comp_unit, } bool SymbolFileSymtab::ParseImportedModules( - const SymbolContext &sc, std::vector<ConstString> &imported_modules) { + const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { return false; } @@ -230,7 +230,7 @@ size_t SymbolFileSymtab::ParseVariablesForContext(const SymbolContext &sc) { } Type *SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) { - return NULL; + return nullptr; } llvm::Optional<SymbolFile::ArrayInfo> @@ -246,7 +246,7 @@ bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) { uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { - if (m_obj_file->GetSymtab() == NULL) + if (m_obj_file->GetSymtab() == nullptr) return 0; uint32_t resolved_flags = 0; @@ -259,9 +259,7 @@ uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr, return resolved_flags; } -//------------------------------------------------------------------ // PluginInterface protocol -//------------------------------------------------------------------ lldb_private::ConstString SymbolFileSymtab::GetPluginName() { return GetPluginNameStatic(); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index e4ec7a181333..bc9a531419ae 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -1,9 +1,8 @@ //===-- SymbolFileSymtab.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -18,16 +17,12 @@ class SymbolFileSymtab : public lldb_private::SymbolFile { public: - //------------------------------------------------------------------ // Constructors and Destructors - //------------------------------------------------------------------ SymbolFileSymtab(lldb_private::ObjectFile *obj_file); ~SymbolFileSymtab() override; - //------------------------------------------------------------------ // Static Functions - //------------------------------------------------------------------ static void Initialize(); static void Terminate(); @@ -41,9 +36,7 @@ public: uint32_t CalculateAbilities() override; - //------------------------------------------------------------------ // Compile Unit function calls - //------------------------------------------------------------------ uint32_t GetNumCompileUnits() override; lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; @@ -64,7 +57,7 @@ public: bool ParseImportedModules( const lldb_private::SymbolContext &sc, - std::vector<lldb_private::ConstString> &imported_modules) override; + std::vector<lldb_private::SourceModule> &imported_modules) override; size_t ParseBlocksRecursive(lldb_private::Function &func) override; @@ -86,9 +79,7 @@ public: lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override; - //------------------------------------------------------------------ // PluginInterface protocol - //------------------------------------------------------------------ lldb_private::ConstString GetPluginName() override; uint32_t GetPluginVersion() override; |