diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp | 173 |
1 files changed, 159 insertions, 14 deletions
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index b815ebb3c07a..b07674af3bd9 100644 --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -176,11 +176,6 @@ void SymbolFileBreakpad::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } -ConstString SymbolFileBreakpad::GetPluginNameStatic() { - static ConstString g_name("breakpad"); - return g_name; -} - uint32_t SymbolFileBreakpad::CalculateAbilities() { if (!m_objfile_sp || !llvm::isa<ObjectFileBreakpad>(*m_objfile_sp)) return 0; @@ -209,6 +204,10 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) { End(*m_objfile_sp); assert(Record::classify(*It) == Record::Func); ++It; // Skip FUNC record. + // Skip INLINE records. + while (It != End && Record::classify(*It) == Record::Inline) + ++It; + if (It != End) { auto record = LineRecord::parse(*It); if (record && record->FileNum < m_files->size()) @@ -224,9 +223,45 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) { return cu_sp; } +FunctionSP SymbolFileBreakpad::GetOrCreateFunction(CompileUnit &comp_unit) { + user_id_t id = comp_unit.GetID(); + if (FunctionSP func_sp = comp_unit.FindFunctionByUID(id)) + return func_sp; + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + FunctionSP func_sp; + addr_t base = GetBaseFileAddress(); + if (base == LLDB_INVALID_ADDRESS) { + LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping " + "symtab population."); + return func_sp; + } + + const SectionList *list = comp_unit.GetModule()->GetSectionList(); + CompUnitData &data = m_cu_data->GetEntryRef(id).data; + LineIterator It(*m_objfile_sp, Record::Func, data.bookmark); + assert(Record::classify(*It) == Record::Func); + + if (auto record = FuncRecord::parse(*It)) { + Mangled func_name; + func_name.SetValue(ConstString(record->Name), false); + addr_t address = record->Address + base; + SectionSP section_sp = list->FindSectionContainingFileAddress(address); + if (section_sp) { + AddressRange func_range( + section_sp, address - section_sp->GetFileAddress(), record->Size); + // Use the CU's id because every CU has only one function inside. + func_sp = std::make_shared<Function>(&comp_unit, id, 0, func_name, + nullptr, func_range); + comp_unit.AddFunction(func_sp); + } + } + return func_sp; +} + size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) { - // TODO - return 0; + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + return GetOrCreateFunction(comp_unit) ? 1 : 0; } bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { @@ -251,12 +286,88 @@ bool SymbolFileBreakpad::ParseSupportFiles(CompileUnit &comp_unit, return true; } +size_t SymbolFileBreakpad::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + CompileUnit *comp_unit = func.GetCompileUnit(); + lldbassert(comp_unit); + ParseInlineOriginRecords(); + // A vector of current each level's parent block. For example, when parsing + // "INLINE 0 ...", the current level is 0 and its parent block is the + // funciton block at index 0. + std::vector<Block *> blocks; + Block &block = func.GetBlock(false); + block.AddRange(Block::Range(0, func.GetAddressRange().GetByteSize())); + blocks.push_back(&block); + + size_t blocks_added = 0; + addr_t func_base = func.GetAddressRange().GetBaseAddress().GetOffset(); + CompUnitData &data = m_cu_data->GetEntryRef(comp_unit->GetID()).data; + LineIterator It(*m_objfile_sp, Record::Func, data.bookmark), + End(*m_objfile_sp); + ++It; // Skip the FUNC record. + size_t last_added_nest_level = 0; + while (It != End && Record::classify(*It) == Record::Inline) { + if (auto record = InlineRecord::parse(*It)) { + if (record->InlineNestLevel == 0 || + record->InlineNestLevel <= last_added_nest_level + 1) { + last_added_nest_level = record->InlineNestLevel; + BlockSP block_sp = std::make_shared<Block>(It.GetBookmark().offset); + FileSpec callsite_file; + if (record->CallSiteFileNum < m_files->size()) + callsite_file = (*m_files)[record->CallSiteFileNum]; + llvm::StringRef name; + if (record->OriginNum < m_inline_origins->size()) + name = (*m_inline_origins)[record->OriginNum]; + + Declaration callsite(callsite_file, record->CallSiteLineNum); + block_sp->SetInlinedFunctionInfo(name.str().c_str(), + /*mangled=*/nullptr, + /*decl_ptr=*/nullptr, &callsite); + for (const auto &range : record->Ranges) { + block_sp->AddRange( + Block::Range(range.first - func_base, range.second)); + } + block_sp->FinalizeRanges(); + + blocks[record->InlineNestLevel]->AddChild(block_sp); + if (record->InlineNestLevel + 1 >= blocks.size()) { + blocks.resize(blocks.size() + 1); + } + blocks[record->InlineNestLevel + 1] = block_sp.get(); + ++blocks_added; + } + } + ++It; + } + return blocks_added; +} + +void SymbolFileBreakpad::ParseInlineOriginRecords() { + if (m_inline_origins) + return; + m_inline_origins.emplace(); + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + for (llvm::StringRef line : lines(Record::InlineOrigin)) { + auto record = InlineOriginRecord::parse(line); + if (!record) { + LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", line); + continue; + } + + if (record->Number >= m_inline_origins->size()) + m_inline_origins->resize(record->Number + 1); + (*m_inline_origins)[record->Number] = record->Name; + } +} + uint32_t SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry))) + if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry | + eSymbolContextFunction | eSymbolContextBlock))) return 0; ParseCUData(); @@ -274,6 +385,22 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, } } + if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) { + FunctionSP func_sp = GetOrCreateFunction(*sc.comp_unit); + if (func_sp) { + sc.function = func_sp.get(); + result |= eSymbolContextFunction; + if (resolve_scope & eSymbolContextBlock) { + Block &block = func_sp->GetBlock(true); + sc.block = block.FindInnermostBlockByOffset( + so_addr.GetFileAddress() - + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress()); + if (sc.block) + result |= eSymbolContextBlock; + } + } + } + return result; } @@ -296,7 +423,20 @@ void SymbolFileBreakpad::FindFunctions( ConstString name, const CompilerDeclContext &parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { - // TODO + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + // TODO: Implement this with supported FunctionNameType. + + for (uint32_t i = 0; i < GetNumCompileUnits(); ++i) { + CompUnitSP cu_sp = GetCompileUnitAtIndex(i); + FunctionSP func_sp = GetOrCreateFunction(*cu_sp); + if (func_sp && name == func_sp->GetNameNoArguments()) { + SymbolContext sc; + sc.comp_unit = cu_sp.get(); + sc.function = func_sp.get(); + sc.module_sp = func_sp->CalculateSymbolContextModule(); + sc_list.Append(sc); + } + } } void SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, @@ -351,11 +491,6 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { 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); @@ -727,6 +862,10 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, End(*m_objfile_sp); assert(Record::classify(*It) == Record::Func); for (++It; It != End; ++It) { + // Skip INLINE records + if (Record::classify(*It) == Record::Inline) + continue; + auto record = LineRecord::parse(*It); if (!record) break; @@ -783,3 +922,9 @@ void SymbolFileBreakpad::ParseUnwindData() { } m_unwind_data->win.Sort(); } + +uint64_t SymbolFileBreakpad::GetDebugInfoSize() { + // Breakpad files are all debug info. + return m_objfile_sp->GetByteSize(); +} + |
