1 //===-- SymbolFileBreakpad.h ------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H 10 #define LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H 11 12 #include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h" 13 #include "lldb/Core/FileSpecList.h" 14 #include "lldb/Symbol/LineTable.h" 15 #include "lldb/Symbol/PostfixExpression.h" 16 #include "lldb/Symbol/SymbolFile.h" 17 #include "lldb/Symbol/UnwindPlan.h" 18 19 namespace lldb_private { 20 21 namespace breakpad { 22 23 class SymbolFileBreakpad : public SymbolFile { 24 /// LLVM RTTI support. 25 static char ID; 26 27 public: 28 /// LLVM RTTI support. 29 /// \{ 30 bool isA(const void *ClassID) const override { 31 return ClassID == &ID || SymbolFile::isA(ClassID); 32 } 33 static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } 34 /// \} 35 36 // Static Functions 37 static void Initialize(); 38 static void Terminate(); 39 static void DebuggerInitialize(Debugger &debugger) {} 40 static ConstString GetPluginNameStatic(); 41 42 static const char *GetPluginDescriptionStatic() { 43 return "Breakpad debug symbol file reader."; 44 } 45 46 static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp) { 47 return new SymbolFileBreakpad(std::move(objfile_sp)); 48 } 49 50 // Constructors and Destructors 51 SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp) 52 : SymbolFile(std::move(objfile_sp)) {} 53 54 ~SymbolFileBreakpad() override {} 55 56 uint32_t CalculateAbilities() override; 57 58 void InitializeObject() override {} 59 60 // Compile Unit function calls 61 62 lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override { 63 return lldb::eLanguageTypeUnknown; 64 } 65 66 size_t ParseFunctions(CompileUnit &comp_unit) override; 67 68 bool ParseLineTable(CompileUnit &comp_unit) override; 69 70 bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; } 71 72 bool ParseSupportFiles(CompileUnit &comp_unit, 73 FileSpecList &support_files) override; 74 size_t ParseTypes(CompileUnit &cu) override { return 0; } 75 76 bool ParseImportedModules( 77 const SymbolContext &sc, 78 std::vector<lldb_private::SourceModule> &imported_modules) override { 79 return false; 80 } 81 82 size_t ParseBlocksRecursive(Function &func) override { return 0; } 83 84 void FindGlobalVariables(ConstString name, 85 const CompilerDeclContext *parent_decl_ctx, 86 uint32_t max_matches, 87 VariableList &variables) override {} 88 89 size_t ParseVariablesForContext(const SymbolContext &sc) override { 90 return 0; 91 } 92 Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; } 93 llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( 94 lldb::user_id_t type_uid, 95 const lldb_private::ExecutionContext *exe_ctx) override { 96 return llvm::None; 97 } 98 99 bool CompleteType(CompilerType &compiler_type) override { return false; } 100 uint32_t ResolveSymbolContext(const Address &so_addr, 101 lldb::SymbolContextItem resolve_scope, 102 SymbolContext &sc) override; 103 104 uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, 105 bool check_inlines, 106 lldb::SymbolContextItem resolve_scope, 107 SymbolContextList &sc_list) override; 108 109 void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, 110 TypeList &type_list) override {} 111 112 void FindFunctions(ConstString name, 113 const CompilerDeclContext *parent_decl_ctx, 114 lldb::FunctionNameType name_type_mask, 115 bool include_inlines, SymbolContextList &sc_list) override; 116 117 void FindFunctions(const RegularExpression ®ex, bool include_inlines, 118 SymbolContextList &sc_list) override; 119 120 void FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx, 121 uint32_t max_matches, 122 llvm::DenseSet<SymbolFile *> &searched_symbol_files, 123 TypeMap &types) override; 124 125 void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, 126 llvm::DenseSet<SymbolFile *> &searched_symbol_files, 127 TypeMap &types) override; 128 129 llvm::Expected<TypeSystem &> 130 GetTypeSystemForLanguage(lldb::LanguageType language) override { 131 return llvm::make_error<llvm::StringError>( 132 "SymbolFileBreakpad does not support GetTypeSystemForLanguage", 133 llvm::inconvertibleErrorCode()); 134 } 135 136 CompilerDeclContext 137 FindNamespace(ConstString name, 138 const CompilerDeclContext *parent_decl_ctx) override { 139 return CompilerDeclContext(); 140 } 141 142 void AddSymbols(Symtab &symtab) override; 143 144 llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) override; 145 146 lldb::UnwindPlanSP 147 GetUnwindPlan(const Address &address, 148 const RegisterInfoResolver &resolver) override; 149 150 ConstString GetPluginName() override { return GetPluginNameStatic(); } 151 uint32_t GetPluginVersion() override { return 1; } 152 153 private: 154 // A class representing a position in the breakpad file. Useful for 155 // remembering the position so we can go back to it later and parse more data. 156 // Can be converted to/from a LineIterator, but it has a much smaller memory 157 // footprint. 158 struct Bookmark { 159 uint32_t section; 160 size_t offset; 161 162 friend bool operator<(const Bookmark &lhs, const Bookmark &rhs) { 163 return std::tie(lhs.section, lhs.offset) < 164 std::tie(rhs.section, rhs.offset); 165 } 166 }; 167 168 // At iterator class for simplifying algorithms reading data from the breakpad 169 // file. It iterates over all records (lines) in the sections of a given type. 170 // It also supports saving a specific position (via the GetBookmark() method) 171 // and then resuming from it afterwards. 172 class LineIterator; 173 174 // Return an iterator range for all records in the given object file of the 175 // given type. 176 llvm::iterator_range<LineIterator> lines(Record::Kind section_type); 177 178 // Breakpad files do not contain sufficient information to correctly 179 // reconstruct compile units. The approach chosen here is to treat each 180 // function as a compile unit. The compile unit name is the name if the first 181 // line entry belonging to this function. 182 // This class is our internal representation of a compile unit. It stores the 183 // CompileUnit object and a bookmark pointing to the FUNC record of the 184 // compile unit function. It also lazily construct the list of support files 185 // and line table entries for the compile unit, when these are needed. 186 class CompUnitData { 187 public: 188 CompUnitData(Bookmark bookmark) : bookmark(bookmark) {} 189 190 CompUnitData() = default; 191 CompUnitData(const CompUnitData &rhs) : bookmark(rhs.bookmark) {} 192 CompUnitData &operator=(const CompUnitData &rhs) { 193 bookmark = rhs.bookmark; 194 support_files.reset(); 195 line_table_up.reset(); 196 return *this; 197 } 198 friend bool operator<(const CompUnitData &lhs, const CompUnitData &rhs) { 199 return lhs.bookmark < rhs.bookmark; 200 } 201 202 Bookmark bookmark; 203 llvm::Optional<FileSpecList> support_files; 204 std::unique_ptr<LineTable> line_table_up; 205 206 }; 207 208 uint32_t CalculateNumCompileUnits() override; 209 lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; 210 211 lldb::addr_t GetBaseFileAddress(); 212 void ParseFileRecords(); 213 void ParseCUData(); 214 void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data); 215 void ParseUnwindData(); 216 llvm::ArrayRef<uint8_t> SaveAsDWARF(postfix::Node &node); 217 lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark, 218 const RegisterInfoResolver &resolver); 219 bool ParseCFIUnwindRow(llvm::StringRef unwind_rules, 220 const RegisterInfoResolver &resolver, 221 UnwindPlan::Row &row); 222 lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark, 223 const RegisterInfoResolver &resolver); 224 225 using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>; 226 227 llvm::Optional<std::vector<FileSpec>> m_files; 228 llvm::Optional<CompUnitMap> m_cu_data; 229 230 using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>; 231 struct UnwindData { 232 UnwindMap cfi; 233 UnwindMap win; 234 }; 235 llvm::Optional<UnwindData> m_unwind_data; 236 llvm::BumpPtrAllocator m_allocator; 237 }; 238 239 } // namespace breakpad 240 } // namespace lldb_private 241 242 #endif 243