1061da546Spatrick //===-- SymbolFileBreakpad.h ------------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H 11061da546Spatrick 12061da546Spatrick #include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h" 13061da546Spatrick #include "lldb/Core/FileSpecList.h" 14061da546Spatrick #include "lldb/Symbol/LineTable.h" 15061da546Spatrick #include "lldb/Symbol/PostfixExpression.h" 16061da546Spatrick #include "lldb/Symbol/SymbolFile.h" 17061da546Spatrick #include "lldb/Symbol/UnwindPlan.h" 18*f6aab3d8Srobert #include <optional> 19061da546Spatrick 20061da546Spatrick namespace lldb_private { 21061da546Spatrick 22061da546Spatrick namespace breakpad { 23061da546Spatrick 24*f6aab3d8Srobert class SymbolFileBreakpad : public SymbolFileCommon { 25061da546Spatrick /// LLVM RTTI support. 26061da546Spatrick static char ID; 27061da546Spatrick 28061da546Spatrick public: 29061da546Spatrick /// LLVM RTTI support. 30061da546Spatrick /// \{ isA(const void * ClassID)31061da546Spatrick bool isA(const void *ClassID) const override { 32*f6aab3d8Srobert return ClassID == &ID || SymbolFileCommon::isA(ClassID); 33061da546Spatrick } classof(const SymbolFile * obj)34061da546Spatrick static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } 35061da546Spatrick /// \} 36061da546Spatrick 37061da546Spatrick // Static Functions 38061da546Spatrick static void Initialize(); 39061da546Spatrick static void Terminate(); DebuggerInitialize(Debugger & debugger)40061da546Spatrick static void DebuggerInitialize(Debugger &debugger) {} GetPluginNameStatic()41*f6aab3d8Srobert static llvm::StringRef GetPluginNameStatic() { return "breakpad"; } 42061da546Spatrick GetPluginDescriptionStatic()43*f6aab3d8Srobert static llvm::StringRef GetPluginDescriptionStatic() { 44061da546Spatrick return "Breakpad debug symbol file reader."; 45061da546Spatrick } 46061da546Spatrick CreateInstance(lldb::ObjectFileSP objfile_sp)47061da546Spatrick static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp) { 48061da546Spatrick return new SymbolFileBreakpad(std::move(objfile_sp)); 49061da546Spatrick } 50061da546Spatrick 51061da546Spatrick // Constructors and Destructors SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp)52061da546Spatrick SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp) 53*f6aab3d8Srobert : SymbolFileCommon(std::move(objfile_sp)) {} 54061da546Spatrick 55be691f3bSpatrick ~SymbolFileBreakpad() override = default; 56061da546Spatrick 57061da546Spatrick uint32_t CalculateAbilities() override; 58061da546Spatrick InitializeObject()59061da546Spatrick void InitializeObject() override {} 60061da546Spatrick 61061da546Spatrick // Compile Unit function calls 62061da546Spatrick ParseLanguage(CompileUnit & comp_unit)63061da546Spatrick lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override { 64061da546Spatrick return lldb::eLanguageTypeUnknown; 65061da546Spatrick } 66061da546Spatrick 67*f6aab3d8Srobert lldb::FunctionSP GetOrCreateFunction(CompileUnit &comp_unit); 68*f6aab3d8Srobert 69061da546Spatrick size_t ParseFunctions(CompileUnit &comp_unit) override; 70061da546Spatrick 71061da546Spatrick bool ParseLineTable(CompileUnit &comp_unit) override; 72061da546Spatrick ParseDebugMacros(CompileUnit & comp_unit)73061da546Spatrick bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; } 74061da546Spatrick 75061da546Spatrick bool ParseSupportFiles(CompileUnit &comp_unit, 76061da546Spatrick FileSpecList &support_files) override; ParseTypes(CompileUnit & cu)77061da546Spatrick size_t ParseTypes(CompileUnit &cu) override { return 0; } 78061da546Spatrick ParseImportedModules(const SymbolContext & sc,std::vector<lldb_private::SourceModule> & imported_modules)79061da546Spatrick bool ParseImportedModules( 80061da546Spatrick const SymbolContext &sc, 81061da546Spatrick std::vector<lldb_private::SourceModule> &imported_modules) override { 82061da546Spatrick return false; 83061da546Spatrick } 84061da546Spatrick 85*f6aab3d8Srobert size_t ParseBlocksRecursive(Function &func) override; 86061da546Spatrick FindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,VariableList & variables)87061da546Spatrick void FindGlobalVariables(ConstString name, 88dda28197Spatrick const CompilerDeclContext &parent_decl_ctx, 89061da546Spatrick uint32_t max_matches, 90061da546Spatrick VariableList &variables) override {} 91061da546Spatrick ParseVariablesForContext(const SymbolContext & sc)92061da546Spatrick size_t ParseVariablesForContext(const SymbolContext &sc) override { 93061da546Spatrick return 0; 94061da546Spatrick } ResolveTypeUID(lldb::user_id_t type_uid)95061da546Spatrick Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; } GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)96*f6aab3d8Srobert std::optional<ArrayInfo> GetDynamicArrayInfoForUID( 97061da546Spatrick lldb::user_id_t type_uid, 98061da546Spatrick const lldb_private::ExecutionContext *exe_ctx) override { 99*f6aab3d8Srobert return std::nullopt; 100061da546Spatrick } 101061da546Spatrick CompleteType(CompilerType & compiler_type)102061da546Spatrick bool CompleteType(CompilerType &compiler_type) override { return false; } 103061da546Spatrick uint32_t ResolveSymbolContext(const Address &so_addr, 104061da546Spatrick lldb::SymbolContextItem resolve_scope, 105061da546Spatrick SymbolContext &sc) override; 106061da546Spatrick 107be691f3bSpatrick uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, 108061da546Spatrick lldb::SymbolContextItem resolve_scope, 109061da546Spatrick SymbolContextList &sc_list) override; 110061da546Spatrick GetTypes(SymbolContextScope * sc_scope,lldb::TypeClass type_mask,TypeList & type_list)111061da546Spatrick void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, 112061da546Spatrick TypeList &type_list) override {} 113061da546Spatrick 114*f6aab3d8Srobert void FindFunctions(const Module::LookupInfo &lookup_info, 115dda28197Spatrick const CompilerDeclContext &parent_decl_ctx, 116061da546Spatrick bool include_inlines, SymbolContextList &sc_list) override; 117061da546Spatrick 118061da546Spatrick void FindFunctions(const RegularExpression ®ex, bool include_inlines, 119061da546Spatrick SymbolContextList &sc_list) override; 120061da546Spatrick 121dda28197Spatrick void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, 122061da546Spatrick uint32_t max_matches, 123061da546Spatrick llvm::DenseSet<SymbolFile *> &searched_symbol_files, 124061da546Spatrick TypeMap &types) override; 125061da546Spatrick 126061da546Spatrick void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, 127061da546Spatrick llvm::DenseSet<SymbolFile *> &searched_symbol_files, 128061da546Spatrick TypeMap &types) override; 129061da546Spatrick 130*f6aab3d8Srobert llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language)131061da546Spatrick GetTypeSystemForLanguage(lldb::LanguageType language) override { 132061da546Spatrick return llvm::make_error<llvm::StringError>( 133061da546Spatrick "SymbolFileBreakpad does not support GetTypeSystemForLanguage", 134061da546Spatrick llvm::inconvertibleErrorCode()); 135061da546Spatrick } 136061da546Spatrick 137061da546Spatrick CompilerDeclContext FindNamespace(ConstString name,const CompilerDeclContext & parent_decl_ctx)138061da546Spatrick FindNamespace(ConstString name, 139dda28197Spatrick const CompilerDeclContext &parent_decl_ctx) override { 140061da546Spatrick return CompilerDeclContext(); 141061da546Spatrick } 142061da546Spatrick 143061da546Spatrick void AddSymbols(Symtab &symtab) override; 144061da546Spatrick 145061da546Spatrick llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) override; 146061da546Spatrick 147061da546Spatrick lldb::UnwindPlanSP 148061da546Spatrick GetUnwindPlan(const Address &address, 149061da546Spatrick const RegisterInfoResolver &resolver) override; 150061da546Spatrick GetPluginName()151*f6aab3d8Srobert llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 152*f6aab3d8Srobert 153*f6aab3d8Srobert uint64_t GetDebugInfoSize() override; 154061da546Spatrick 155061da546Spatrick private: 156061da546Spatrick // A class representing a position in the breakpad file. Useful for 157061da546Spatrick // remembering the position so we can go back to it later and parse more data. 158061da546Spatrick // Can be converted to/from a LineIterator, but it has a much smaller memory 159061da546Spatrick // footprint. 160061da546Spatrick struct Bookmark { 161061da546Spatrick uint32_t section; 162061da546Spatrick size_t offset; 163061da546Spatrick 164061da546Spatrick friend bool operator<(const Bookmark &lhs, const Bookmark &rhs) { 165061da546Spatrick return std::tie(lhs.section, lhs.offset) < 166061da546Spatrick std::tie(rhs.section, rhs.offset); 167061da546Spatrick } 168061da546Spatrick }; 169061da546Spatrick 170061da546Spatrick // At iterator class for simplifying algorithms reading data from the breakpad 171061da546Spatrick // file. It iterates over all records (lines) in the sections of a given type. 172061da546Spatrick // It also supports saving a specific position (via the GetBookmark() method) 173061da546Spatrick // and then resuming from it afterwards. 174061da546Spatrick class LineIterator; 175061da546Spatrick 176061da546Spatrick // Return an iterator range for all records in the given object file of the 177061da546Spatrick // given type. 178061da546Spatrick llvm::iterator_range<LineIterator> lines(Record::Kind section_type); 179061da546Spatrick 180061da546Spatrick // Breakpad files do not contain sufficient information to correctly 181061da546Spatrick // reconstruct compile units. The approach chosen here is to treat each 182061da546Spatrick // function as a compile unit. The compile unit name is the name if the first 183061da546Spatrick // line entry belonging to this function. 184061da546Spatrick // This class is our internal representation of a compile unit. It stores the 185061da546Spatrick // CompileUnit object and a bookmark pointing to the FUNC record of the 186061da546Spatrick // compile unit function. It also lazily construct the list of support files 187061da546Spatrick // and line table entries for the compile unit, when these are needed. 188061da546Spatrick class CompUnitData { 189061da546Spatrick public: CompUnitData(Bookmark bookmark)190061da546Spatrick CompUnitData(Bookmark bookmark) : bookmark(bookmark) {} 191061da546Spatrick 192061da546Spatrick CompUnitData() = default; CompUnitData(const CompUnitData & rhs)193061da546Spatrick CompUnitData(const CompUnitData &rhs) : bookmark(rhs.bookmark) {} 194061da546Spatrick CompUnitData &operator=(const CompUnitData &rhs) { 195061da546Spatrick bookmark = rhs.bookmark; 196061da546Spatrick support_files.reset(); 197061da546Spatrick line_table_up.reset(); 198061da546Spatrick return *this; 199061da546Spatrick } 200061da546Spatrick friend bool operator<(const CompUnitData &lhs, const CompUnitData &rhs) { 201061da546Spatrick return lhs.bookmark < rhs.bookmark; 202061da546Spatrick } 203061da546Spatrick 204061da546Spatrick Bookmark bookmark; 205*f6aab3d8Srobert std::optional<FileSpecList> support_files; 206061da546Spatrick std::unique_ptr<LineTable> line_table_up; 207061da546Spatrick 208061da546Spatrick }; 209061da546Spatrick 210061da546Spatrick uint32_t CalculateNumCompileUnits() override; 211061da546Spatrick lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; 212061da546Spatrick 213061da546Spatrick lldb::addr_t GetBaseFileAddress(); 214061da546Spatrick void ParseFileRecords(); 215061da546Spatrick void ParseCUData(); 216061da546Spatrick void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data); 217061da546Spatrick void ParseUnwindData(); 218061da546Spatrick llvm::ArrayRef<uint8_t> SaveAsDWARF(postfix::Node &node); 219061da546Spatrick lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark, 220061da546Spatrick const RegisterInfoResolver &resolver); 221061da546Spatrick bool ParseCFIUnwindRow(llvm::StringRef unwind_rules, 222061da546Spatrick const RegisterInfoResolver &resolver, 223061da546Spatrick UnwindPlan::Row &row); 224061da546Spatrick lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark, 225061da546Spatrick const RegisterInfoResolver &resolver); 226*f6aab3d8Srobert void ParseInlineOriginRecords(); 227061da546Spatrick 228061da546Spatrick using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>; 229061da546Spatrick 230*f6aab3d8Srobert std::optional<std::vector<FileSpec>> m_files; 231*f6aab3d8Srobert std::optional<CompUnitMap> m_cu_data; 232*f6aab3d8Srobert std::optional<std::vector<llvm::StringRef>> m_inline_origins; 233061da546Spatrick 234061da546Spatrick using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>; 235061da546Spatrick struct UnwindData { 236061da546Spatrick UnwindMap cfi; 237061da546Spatrick UnwindMap win; 238061da546Spatrick }; 239*f6aab3d8Srobert std::optional<UnwindData> m_unwind_data; 240061da546Spatrick llvm::BumpPtrAllocator m_allocator; 241061da546Spatrick }; 242061da546Spatrick 243061da546Spatrick } // namespace breakpad 244061da546Spatrick } // namespace lldb_private 245061da546Spatrick 246061da546Spatrick #endif 247