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