summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp173
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 &regex,
@@ -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();
+}
+