1 | //===-- SymbolFileNativePDB.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_NATIVEPDB_SYMBOLFILENATIVEPDB_H |
10 | #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H |
11 | |
12 | #include "lldb/Symbol/LineTable.h" |
13 | #include "lldb/Symbol/SymbolFile.h" |
14 | |
15 | #include "llvm/ADT/DenseMap.h" |
16 | #include "llvm/DebugInfo/CodeView/CVRecord.h" |
17 | #include "llvm/DebugInfo/CodeView/SymbolRecord.h" |
18 | #include "llvm/DebugInfo/PDB/PDBTypes.h" |
19 | |
20 | #include "CompileUnitIndex.h" |
21 | #include "PdbIndex.h" |
22 | #include "PdbAstBuilder.h" |
23 | #include <optional> |
24 | |
25 | namespace clang { |
26 | class TagDecl; |
27 | } |
28 | |
29 | namespace llvm { |
30 | namespace codeview { |
31 | class ClassRecord; |
32 | class EnumRecord; |
33 | class ModifierRecord; |
34 | class PointerRecord; |
35 | struct UnionRecord; |
36 | } // namespace codeview |
37 | } // namespace llvm |
38 | |
39 | namespace lldb_private { |
40 | |
41 | namespace npdb { |
42 | |
43 | class SymbolFileNativePDB : public SymbolFileCommon { |
44 | friend class UdtRecordCompleter; |
45 | |
46 | /// LLVM RTTI support. |
47 | static char ID; |
48 | |
49 | public: |
50 | /// LLVM RTTI support. |
51 | /// \{ |
52 | bool isA(const void *ClassID) const override { |
53 | return ClassID == &ID || SymbolFileCommon::isA(ClassID); |
54 | } |
55 | static bool classof(const SymbolFile *obj) { return obj->isA(ClassID: &ID); } |
56 | /// \} |
57 | |
58 | // Static Functions |
59 | static void Initialize(); |
60 | |
61 | static void Terminate(); |
62 | |
63 | static void DebuggerInitialize(Debugger &debugger); |
64 | |
65 | static llvm::StringRef GetPluginNameStatic() { return "native-pdb" ; } |
66 | |
67 | static llvm::StringRef GetPluginDescriptionStatic(); |
68 | |
69 | static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp); |
70 | |
71 | // Constructors and Destructors |
72 | SymbolFileNativePDB(lldb::ObjectFileSP objfile_sp); |
73 | |
74 | ~SymbolFileNativePDB() override; |
75 | |
76 | uint32_t CalculateAbilities() override; |
77 | |
78 | void InitializeObject() override; |
79 | |
80 | uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override; |
81 | |
82 | // Compile Unit function calls |
83 | |
84 | void |
85 | ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; |
86 | |
87 | lldb::LanguageType |
88 | ParseLanguage(lldb_private::CompileUnit &comp_unit) override; |
89 | |
90 | size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override; |
91 | |
92 | bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override; |
93 | |
94 | bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; |
95 | |
96 | bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, |
97 | SupportFileList &support_files) override; |
98 | size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; |
99 | |
100 | bool ParseImportedModules( |
101 | const SymbolContext &sc, |
102 | std::vector<lldb_private::SourceModule> &imported_modules) override; |
103 | |
104 | size_t ParseBlocksRecursive(Function &func) override; |
105 | |
106 | void FindGlobalVariables(ConstString name, |
107 | const CompilerDeclContext &parent_decl_ctx, |
108 | uint32_t max_matches, |
109 | VariableList &variables) override; |
110 | |
111 | size_t ParseVariablesForContext(const SymbolContext &sc) override; |
112 | |
113 | void AddSymbols(Symtab &symtab) override; |
114 | |
115 | CompilerDecl GetDeclForUID(lldb::user_id_t uid) override; |
116 | CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override; |
117 | CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override; |
118 | Type *ResolveTypeUID(lldb::user_id_t type_uid) override; |
119 | std::optional<ArrayInfo> GetDynamicArrayInfoForUID( |
120 | lldb::user_id_t type_uid, |
121 | const lldb_private::ExecutionContext *exe_ctx) override; |
122 | |
123 | bool CompleteType(CompilerType &compiler_type) override; |
124 | uint32_t ResolveSymbolContext(const Address &so_addr, |
125 | lldb::SymbolContextItem resolve_scope, |
126 | SymbolContext &sc) override; |
127 | uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, |
128 | lldb::SymbolContextItem resolve_scope, |
129 | SymbolContextList &sc_list) override; |
130 | |
131 | void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, |
132 | TypeList &type_list) override; |
133 | |
134 | void FindFunctions(const Module::LookupInfo &lookup_info, |
135 | const CompilerDeclContext &parent_decl_ctx, |
136 | bool include_inlines, SymbolContextList &sc_list) override; |
137 | |
138 | void FindFunctions(const RegularExpression ®ex, bool include_inlines, |
139 | SymbolContextList &sc_list) override; |
140 | |
141 | std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id); |
142 | |
143 | void FindTypes(const lldb_private::TypeQuery &match, |
144 | lldb_private::TypeResults &results) override; |
145 | |
146 | llvm::Expected<lldb::TypeSystemSP> |
147 | GetTypeSystemForLanguage(lldb::LanguageType language) override; |
148 | |
149 | CompilerDeclContext FindNamespace(ConstString name, |
150 | const CompilerDeclContext &parent_decl_ctx, |
151 | bool only_root_namespaces) override; |
152 | |
153 | llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } |
154 | |
155 | llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); } |
156 | const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); } |
157 | |
158 | PdbIndex &GetIndex() { return *m_index; }; |
159 | |
160 | void DumpClangAST(Stream &s) override; |
161 | |
162 | std::optional<llvm::codeview::TypeIndex> |
163 | GetParentType(llvm::codeview::TypeIndex ti); |
164 | |
165 | private: |
166 | struct LineTableEntryComparator { |
167 | bool operator()(const lldb_private::LineTable::Entry &lhs, |
168 | const lldb_private::LineTable::Entry &rhs) const { |
169 | return lhs.file_addr < rhs.file_addr; |
170 | } |
171 | }; |
172 | |
173 | // From address range relative to function base to source line number. |
174 | using RangeSourceLineVector = |
175 | lldb_private::RangeDataVector<uint32_t, uint32_t, int32_t>; |
176 | // InlineSite contains information in a S_INLINESITE record. |
177 | struct InlineSite { |
178 | PdbCompilandSymId parent_id; |
179 | std::shared_ptr<InlineFunctionInfo> inline_function_info; |
180 | RangeSourceLineVector ranges; |
181 | std::vector<lldb_private::LineTable::Entry> line_entries; |
182 | InlineSite(PdbCompilandSymId parent_id) : parent_id(parent_id){}; |
183 | }; |
184 | |
185 | void BuildParentMap(); |
186 | |
187 | uint32_t CalculateNumCompileUnits() override; |
188 | |
189 | lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; |
190 | |
191 | void FindTypesByName(llvm::StringRef name, uint32_t max_matches, |
192 | TypeMap &types); |
193 | |
194 | lldb::TypeSP CreateModifierType(PdbTypeSymId type_id, |
195 | const llvm::codeview::ModifierRecord &mr, |
196 | CompilerType ct); |
197 | lldb::TypeSP CreatePointerType(PdbTypeSymId type_id, |
198 | const llvm::codeview::PointerRecord &pr, |
199 | CompilerType ct); |
200 | lldb::TypeSP CreateSimpleType(llvm::codeview::TypeIndex ti, CompilerType ct); |
201 | lldb::TypeSP CreateTagType(PdbTypeSymId type_id, |
202 | const llvm::codeview::ClassRecord &cr, |
203 | CompilerType ct); |
204 | lldb::TypeSP CreateTagType(PdbTypeSymId type_id, |
205 | const llvm::codeview::EnumRecord &er, |
206 | CompilerType ct); |
207 | lldb::TypeSP CreateTagType(PdbTypeSymId type_id, |
208 | const llvm::codeview::UnionRecord &ur, |
209 | CompilerType ct); |
210 | lldb::TypeSP CreateArrayType(PdbTypeSymId type_id, |
211 | const llvm::codeview::ArrayRecord &ar, |
212 | CompilerType ct); |
213 | lldb::TypeSP CreateFunctionType(PdbTypeSymId type_id, |
214 | const llvm::codeview::MemberFunctionRecord &pr, |
215 | CompilerType ct); |
216 | lldb::TypeSP CreateProcedureType(PdbTypeSymId type_id, |
217 | const llvm::codeview::ProcedureRecord &pr, |
218 | CompilerType ct); |
219 | lldb::TypeSP CreateClassStructUnion(PdbTypeSymId type_id, |
220 | const llvm::codeview::TagRecord &record, |
221 | size_t size, CompilerType ct); |
222 | |
223 | lldb::FunctionSP GetOrCreateFunction(PdbCompilandSymId func_id, |
224 | CompileUnit &comp_unit); |
225 | lldb::CompUnitSP GetOrCreateCompileUnit(const CompilandIndexItem &cci); |
226 | lldb::TypeSP GetOrCreateType(PdbTypeSymId type_id); |
227 | lldb::TypeSP GetOrCreateType(llvm::codeview::TypeIndex ti); |
228 | lldb::VariableSP GetOrCreateGlobalVariable(PdbGlobalSymId var_id); |
229 | Block &GetOrCreateBlock(PdbCompilandSymId block_id); |
230 | lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id, |
231 | PdbCompilandSymId var_id, |
232 | bool is_param); |
233 | lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id); |
234 | |
235 | lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id, |
236 | CompileUnit &comp_unit); |
237 | Block &CreateBlock(PdbCompilandSymId block_id); |
238 | lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id, |
239 | PdbCompilandSymId var_id, bool is_param); |
240 | lldb::TypeSP CreateTypedef(PdbGlobalSymId id); |
241 | lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci); |
242 | lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct); |
243 | lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id); |
244 | lldb::VariableSP CreateGlobalVariable(PdbGlobalSymId var_id); |
245 | lldb::VariableSP CreateConstantSymbol(PdbGlobalSymId var_id, |
246 | const llvm::codeview::CVSymbol &cvs); |
247 | size_t ParseVariablesForCompileUnit(CompileUnit &comp_unit, |
248 | VariableList &variables); |
249 | size_t ParseVariablesForBlock(PdbCompilandSymId block_id); |
250 | |
251 | llvm::Expected<uint32_t> GetFileIndex(const CompilandIndexItem &cii, |
252 | uint32_t file_id); |
253 | |
254 | size_t ParseSymbolArrayInScope( |
255 | PdbCompilandSymId parent, |
256 | llvm::function_ref<bool(llvm::codeview::SymbolKind, PdbCompilandSymId)> |
257 | fn); |
258 | |
259 | void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr); |
260 | |
261 | llvm::BumpPtrAllocator m_allocator; |
262 | |
263 | lldb::addr_t m_obj_load_address = 0; |
264 | bool m_done_full_type_scan = false; |
265 | // UID for anonymous union and anonymous struct as they don't have entities in |
266 | // pdb debug info. |
267 | lldb::user_id_t anonymous_id = LLDB_INVALID_UID - 1; |
268 | |
269 | std::unique_ptr<llvm::pdb::PDBFile> m_file_up; |
270 | std::unique_ptr<PdbIndex> m_index; |
271 | |
272 | llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_global_vars; |
273 | llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_local_variables; |
274 | llvm::DenseMap<lldb::user_id_t, lldb::BlockSP> m_blocks; |
275 | llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions; |
276 | llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands; |
277 | llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types; |
278 | llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites; |
279 | llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex> |
280 | m_parent_types; |
281 | }; |
282 | |
283 | } // namespace npdb |
284 | } // namespace lldb_private |
285 | |
286 | #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H |
287 | |