You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
8.6 KiB
243 lines
8.6 KiB
4 months ago
|
//===-- SymbolFileBreakpad.h ------------------------------------*- C++ -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
|
||
|
#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
|
||
|
|
||
|
#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
|
||
|
#include "lldb/Core/FileSpecList.h"
|
||
|
#include "lldb/Symbol/LineTable.h"
|
||
|
#include "lldb/Symbol/PostfixExpression.h"
|
||
|
#include "lldb/Symbol/SymbolFile.h"
|
||
|
#include "lldb/Symbol/UnwindPlan.h"
|
||
|
|
||
|
namespace lldb_private {
|
||
|
|
||
|
namespace breakpad {
|
||
|
|
||
|
class SymbolFileBreakpad : public SymbolFile {
|
||
|
/// LLVM RTTI support.
|
||
|
static char ID;
|
||
|
|
||
|
public:
|
||
|
/// LLVM RTTI support.
|
||
|
/// \{
|
||
|
bool isA(const void *ClassID) const override {
|
||
|
return ClassID == &ID || SymbolFile::isA(ClassID);
|
||
|
}
|
||
|
static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
|
||
|
/// \}
|
||
|
|
||
|
// Static Functions
|
||
|
static void Initialize();
|
||
|
static void Terminate();
|
||
|
static void DebuggerInitialize(Debugger &debugger) {}
|
||
|
static ConstString GetPluginNameStatic();
|
||
|
|
||
|
static const char *GetPluginDescriptionStatic() {
|
||
|
return "Breakpad debug symbol file reader.";
|
||
|
}
|
||
|
|
||
|
static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp) {
|
||
|
return new SymbolFileBreakpad(std::move(objfile_sp));
|
||
|
}
|
||
|
|
||
|
// Constructors and Destructors
|
||
|
SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp)
|
||
|
: SymbolFile(std::move(objfile_sp)) {}
|
||
|
|
||
|
~SymbolFileBreakpad() override {}
|
||
|
|
||
|
uint32_t CalculateAbilities() override;
|
||
|
|
||
|
void InitializeObject() override {}
|
||
|
|
||
|
// Compile Unit function calls
|
||
|
|
||
|
lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override {
|
||
|
return lldb::eLanguageTypeUnknown;
|
||
|
}
|
||
|
|
||
|
size_t ParseFunctions(CompileUnit &comp_unit) override;
|
||
|
|
||
|
bool ParseLineTable(CompileUnit &comp_unit) override;
|
||
|
|
||
|
bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; }
|
||
|
|
||
|
bool ParseSupportFiles(CompileUnit &comp_unit,
|
||
|
FileSpecList &support_files) override;
|
||
|
size_t ParseTypes(CompileUnit &cu) override { return 0; }
|
||
|
|
||
|
bool ParseImportedModules(
|
||
|
const SymbolContext &sc,
|
||
|
std::vector<lldb_private::SourceModule> &imported_modules) override {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
size_t ParseBlocksRecursive(Function &func) override { return 0; }
|
||
|
|
||
|
void FindGlobalVariables(ConstString name,
|
||
|
const CompilerDeclContext &parent_decl_ctx,
|
||
|
uint32_t max_matches,
|
||
|
VariableList &variables) override {}
|
||
|
|
||
|
size_t ParseVariablesForContext(const SymbolContext &sc) override {
|
||
|
return 0;
|
||
|
}
|
||
|
Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; }
|
||
|
llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
|
||
|
lldb::user_id_t type_uid,
|
||
|
const lldb_private::ExecutionContext *exe_ctx) override {
|
||
|
return llvm::None;
|
||
|
}
|
||
|
|
||
|
bool CompleteType(CompilerType &compiler_type) override { return false; }
|
||
|
uint32_t ResolveSymbolContext(const Address &so_addr,
|
||
|
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;
|
||
|
|
||
|
void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
|
||
|
TypeList &type_list) override {}
|
||
|
|
||
|
void FindFunctions(ConstString name,
|
||
|
const CompilerDeclContext &parent_decl_ctx,
|
||
|
lldb::FunctionNameType name_type_mask,
|
||
|
bool include_inlines, SymbolContextList &sc_list) override;
|
||
|
|
||
|
void FindFunctions(const RegularExpression ®ex, bool include_inlines,
|
||
|
SymbolContextList &sc_list) override;
|
||
|
|
||
|
void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx,
|
||
|
uint32_t max_matches,
|
||
|
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
|
||
|
TypeMap &types) override;
|
||
|
|
||
|
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
|
||
|
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
|
||
|
TypeMap &types) override;
|
||
|
|
||
|
llvm::Expected<TypeSystem &>
|
||
|
GetTypeSystemForLanguage(lldb::LanguageType language) override {
|
||
|
return llvm::make_error<llvm::StringError>(
|
||
|
"SymbolFileBreakpad does not support GetTypeSystemForLanguage",
|
||
|
llvm::inconvertibleErrorCode());
|
||
|
}
|
||
|
|
||
|
CompilerDeclContext
|
||
|
FindNamespace(ConstString name,
|
||
|
const CompilerDeclContext &parent_decl_ctx) override {
|
||
|
return CompilerDeclContext();
|
||
|
}
|
||
|
|
||
|
void AddSymbols(Symtab &symtab) override;
|
||
|
|
||
|
llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) 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;
|
||
|
|
||
|
};
|
||
|
|
||
|
uint32_t CalculateNumCompileUnits() override;
|
||
|
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
|
||
|
|
||
|
lldb::addr_t GetBaseFileAddress();
|
||
|
void ParseFileRecords();
|
||
|
void ParseCUData();
|
||
|
void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data);
|
||
|
void ParseUnwindData();
|
||
|
llvm::ArrayRef<uint8_t> SaveAsDWARF(postfix::Node &node);
|
||
|
lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark,
|
||
|
const RegisterInfoResolver &resolver);
|
||
|
bool ParseCFIUnwindRow(llvm::StringRef unwind_rules,
|
||
|
const RegisterInfoResolver &resolver,
|
||
|
UnwindPlan::Row &row);
|
||
|
lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark,
|
||
|
const RegisterInfoResolver &resolver);
|
||
|
|
||
|
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>;
|
||
|
struct UnwindData {
|
||
|
UnwindMap cfi;
|
||
|
UnwindMap win;
|
||
|
};
|
||
|
llvm::Optional<UnwindData> m_unwind_data;
|
||
|
llvm::BumpPtrAllocator m_allocator;
|
||
|
};
|
||
|
|
||
|
} // namespace breakpad
|
||
|
} // namespace lldb_private
|
||
|
|
||
|
#endif
|