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