1343181Sdim//===-- SymbolFileBreakpad.h ------------------------------------*- C++ -*-===//
2343181Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343181Sdim//
7343181Sdim//===----------------------------------------------------------------------===//
8343181Sdim
9343181Sdim#ifndef LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
10343181Sdim#define LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
11343181Sdim
12353358Sdim#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
13353358Sdim#include "lldb/Core/FileSpecList.h"
14353358Sdim#include "lldb/Symbol/LineTable.h"
15360784Sdim#include "lldb/Symbol/PostfixExpression.h"
16343181Sdim#include "lldb/Symbol/SymbolFile.h"
17353358Sdim#include "lldb/Symbol/UnwindPlan.h"
18343181Sdim
19343181Sdimnamespace lldb_private {
20343181Sdim
21343181Sdimnamespace breakpad {
22343181Sdim
23343181Sdimclass SymbolFileBreakpad : public SymbolFile {
24360784Sdim  /// LLVM RTTI support.
25360784Sdim  static char ID;
26360784Sdim
27343181Sdimpublic:
28360784Sdim  /// LLVM RTTI support.
29360784Sdim  /// \{
30360784Sdim  bool isA(const void *ClassID) const override {
31360784Sdim    return ClassID == &ID || SymbolFile::isA(ClassID);
32360784Sdim  }
33360784Sdim  static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
34360784Sdim  /// \}
35360784Sdim
36343181Sdim  // Static Functions
37343181Sdim  static void Initialize();
38343181Sdim  static void Terminate();
39343181Sdim  static void DebuggerInitialize(Debugger &debugger) {}
40343181Sdim  static ConstString GetPluginNameStatic();
41343181Sdim
42343181Sdim  static const char *GetPluginDescriptionStatic() {
43343181Sdim    return "Breakpad debug symbol file reader.";
44343181Sdim  }
45343181Sdim
46360784Sdim  static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp) {
47360784Sdim    return new SymbolFileBreakpad(std::move(objfile_sp));
48343181Sdim  }
49343181Sdim
50343181Sdim  // Constructors and Destructors
51360784Sdim  SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp)
52360784Sdim      : SymbolFile(std::move(objfile_sp)) {}
53343181Sdim
54343181Sdim  ~SymbolFileBreakpad() override {}
55343181Sdim
56343181Sdim  uint32_t CalculateAbilities() override;
57343181Sdim
58343181Sdim  void InitializeObject() override {}
59343181Sdim
60343181Sdim  // Compile Unit function calls
61343181Sdim
62343181Sdim  lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override {
63343181Sdim    return lldb::eLanguageTypeUnknown;
64343181Sdim  }
65343181Sdim
66343181Sdim  size_t ParseFunctions(CompileUnit &comp_unit) override;
67343181Sdim
68343181Sdim  bool ParseLineTable(CompileUnit &comp_unit) override;
69343181Sdim
70343181Sdim  bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; }
71343181Sdim
72343181Sdim  bool ParseSupportFiles(CompileUnit &comp_unit,
73353358Sdim                         FileSpecList &support_files) override;
74343181Sdim  size_t ParseTypes(CompileUnit &cu) override { return 0; }
75343181Sdim
76353358Sdim  bool ParseImportedModules(
77353358Sdim      const SymbolContext &sc,
78353358Sdim      std::vector<lldb_private::SourceModule> &imported_modules) override {
79343181Sdim    return false;
80343181Sdim  }
81343181Sdim
82343181Sdim  size_t ParseBlocksRecursive(Function &func) override { return 0; }
83343181Sdim
84360784Sdim  void FindGlobalVariables(ConstString name,
85360784Sdim                           const CompilerDeclContext *parent_decl_ctx,
86360784Sdim                           uint32_t max_matches,
87360784Sdim                           VariableList &variables) override {}
88343181Sdim
89343181Sdim  size_t ParseVariablesForContext(const SymbolContext &sc) override {
90343181Sdim    return 0;
91343181Sdim  }
92343181Sdim  Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; }
93343181Sdim  llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
94343181Sdim      lldb::user_id_t type_uid,
95343181Sdim      const lldb_private::ExecutionContext *exe_ctx) override {
96343181Sdim    return llvm::None;
97343181Sdim  }
98343181Sdim
99343181Sdim  bool CompleteType(CompilerType &compiler_type) override { return false; }
100343181Sdim  uint32_t ResolveSymbolContext(const Address &so_addr,
101343181Sdim                                lldb::SymbolContextItem resolve_scope,
102343181Sdim                                SymbolContext &sc) override;
103343181Sdim
104353358Sdim  uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
105353358Sdim                                bool check_inlines,
106353358Sdim                                lldb::SymbolContextItem resolve_scope,
107353358Sdim                                SymbolContextList &sc_list) override;
108353358Sdim
109360784Sdim  void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
110360784Sdim                TypeList &type_list) override {}
111343181Sdim
112360784Sdim  void FindFunctions(ConstString name,
113360784Sdim                     const CompilerDeclContext *parent_decl_ctx,
114360784Sdim                     lldb::FunctionNameType name_type_mask,
115360784Sdim                     bool include_inlines, SymbolContextList &sc_list) override;
116343181Sdim
117360784Sdim  void FindFunctions(const RegularExpression &regex, bool include_inlines,
118360784Sdim                     SymbolContextList &sc_list) override;
119343181Sdim
120360784Sdim  void FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx,
121360784Sdim                 uint32_t max_matches,
122360784Sdim                 llvm::DenseSet<SymbolFile *> &searched_symbol_files,
123360784Sdim                 TypeMap &types) override;
124343181Sdim
125360784Sdim  void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
126360784Sdim                 llvm::DenseSet<SymbolFile *> &searched_symbol_files,
127360784Sdim                 TypeMap &types) override;
128343181Sdim
129360784Sdim  llvm::Expected<TypeSystem &>
130360784Sdim  GetTypeSystemForLanguage(lldb::LanguageType language) override {
131360784Sdim    return llvm::make_error<llvm::StringError>(
132360784Sdim        "SymbolFileBreakpad does not support GetTypeSystemForLanguage",
133360784Sdim        llvm::inconvertibleErrorCode());
134343181Sdim  }
135343181Sdim
136343181Sdim  CompilerDeclContext
137353358Sdim  FindNamespace(ConstString name,
138343181Sdim                const CompilerDeclContext *parent_decl_ctx) override {
139343181Sdim    return CompilerDeclContext();
140343181Sdim  }
141343181Sdim
142343181Sdim  void AddSymbols(Symtab &symtab) override;
143343181Sdim
144360784Sdim  llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) override;
145360784Sdim
146353358Sdim  lldb::UnwindPlanSP
147353358Sdim  GetUnwindPlan(const Address &address,
148353358Sdim                const RegisterInfoResolver &resolver) override;
149353358Sdim
150343181Sdim  ConstString GetPluginName() override { return GetPluginNameStatic(); }
151343181Sdim  uint32_t GetPluginVersion() override { return 1; }
152343181Sdim
153343181Sdimprivate:
154353358Sdim  // A class representing a position in the breakpad file. Useful for
155353358Sdim  // remembering the position so we can go back to it later and parse more data.
156353358Sdim  // Can be converted to/from a LineIterator, but it has a much smaller memory
157353358Sdim  // footprint.
158353358Sdim  struct Bookmark {
159353358Sdim    uint32_t section;
160353358Sdim    size_t offset;
161353358Sdim
162353358Sdim    friend bool operator<(const Bookmark &lhs, const Bookmark &rhs) {
163353358Sdim      return std::tie(lhs.section, lhs.offset) <
164353358Sdim             std::tie(rhs.section, rhs.offset);
165353358Sdim    }
166353358Sdim  };
167353358Sdim
168353358Sdim  // At iterator class for simplifying algorithms reading data from the breakpad
169353358Sdim  // file. It iterates over all records (lines) in the sections of a given type.
170353358Sdim  // It also supports saving a specific position (via the GetBookmark() method)
171353358Sdim  // and then resuming from it afterwards.
172353358Sdim  class LineIterator;
173353358Sdim
174353358Sdim  // Return an iterator range for all records in the given object file of the
175353358Sdim  // given type.
176353358Sdim  llvm::iterator_range<LineIterator> lines(Record::Kind section_type);
177353358Sdim
178353358Sdim  // Breakpad files do not contain sufficient information to correctly
179353358Sdim  // reconstruct compile units. The approach chosen here is to treat each
180353358Sdim  // function as a compile unit. The compile unit name is the name if the first
181353358Sdim  // line entry belonging to this function.
182353358Sdim  // This class is our internal representation of a compile unit. It stores the
183353358Sdim  // CompileUnit object and a bookmark pointing to the FUNC record of the
184353358Sdim  // compile unit function. It also lazily construct the list of support files
185353358Sdim  // and line table entries for the compile unit, when these are needed.
186353358Sdim  class CompUnitData {
187353358Sdim  public:
188353358Sdim    CompUnitData(Bookmark bookmark) : bookmark(bookmark) {}
189353358Sdim
190353358Sdim    CompUnitData() = default;
191353358Sdim    CompUnitData(const CompUnitData &rhs) : bookmark(rhs.bookmark) {}
192353358Sdim    CompUnitData &operator=(const CompUnitData &rhs) {
193353358Sdim      bookmark = rhs.bookmark;
194353358Sdim      support_files.reset();
195353358Sdim      line_table_up.reset();
196353358Sdim      return *this;
197353358Sdim    }
198353358Sdim    friend bool operator<(const CompUnitData &lhs, const CompUnitData &rhs) {
199353358Sdim      return lhs.bookmark < rhs.bookmark;
200353358Sdim    }
201353358Sdim
202353358Sdim    Bookmark bookmark;
203353358Sdim    llvm::Optional<FileSpecList> support_files;
204353358Sdim    std::unique_ptr<LineTable> line_table_up;
205353358Sdim
206353358Sdim  };
207353358Sdim
208360784Sdim  uint32_t CalculateNumCompileUnits() override;
209360784Sdim  lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
210360784Sdim
211353358Sdim  lldb::addr_t GetBaseFileAddress();
212353358Sdim  void ParseFileRecords();
213353358Sdim  void ParseCUData();
214353358Sdim  void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data);
215353358Sdim  void ParseUnwindData();
216360784Sdim  llvm::ArrayRef<uint8_t> SaveAsDWARF(postfix::Node &node);
217360784Sdim  lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark,
218360784Sdim                                        const RegisterInfoResolver &resolver);
219360784Sdim  bool ParseCFIUnwindRow(llvm::StringRef unwind_rules,
220360784Sdim                         const RegisterInfoResolver &resolver,
221360784Sdim                         UnwindPlan::Row &row);
222360784Sdim  lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark,
223360784Sdim                                        const RegisterInfoResolver &resolver);
224353358Sdim
225353358Sdim  using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>;
226353358Sdim
227353358Sdim  llvm::Optional<std::vector<FileSpec>> m_files;
228353358Sdim  llvm::Optional<CompUnitMap> m_cu_data;
229353358Sdim
230353358Sdim  using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>;
231360784Sdim  struct UnwindData {
232360784Sdim    UnwindMap cfi;
233360784Sdim    UnwindMap win;
234360784Sdim  };
235360784Sdim  llvm::Optional<UnwindData> m_unwind_data;
236353358Sdim  llvm::BumpPtrAllocator m_allocator;
237343181Sdim};
238343181Sdim
239343181Sdim} // namespace breakpad
240343181Sdim} // namespace lldb_private
241343181Sdim
242343181Sdim#endif
243