blob: de9b9f024fc73a90eaf6324a5c9ec60426e5ded5 [file] [log] [blame]
Zachary Turner74e08ca2016-03-02 22:05:52 +00001//===-- SymbolFilePDB.cpp ---------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "SymbolFilePDB.h"
11
Zachary Turner42dff792016-04-15 00:21:26 +000012#include "clang/Lex/Lexer.h"
13
Zachary Turner74e08ca2016-03-02 22:05:52 +000014#include "lldb/Core/Module.h"
15#include "lldb/Core/PluginManager.h"
Zachary Turner42dff792016-04-15 00:21:26 +000016#include "lldb/Symbol/ClangASTContext.h"
Zachary Turner74e08ca2016-03-02 22:05:52 +000017#include "lldb/Symbol/CompileUnit.h"
18#include "lldb/Symbol/LineTable.h"
19#include "lldb/Symbol/ObjectFile.h"
20#include "lldb/Symbol/SymbolContext.h"
Zachary Turner42dff792016-04-15 00:21:26 +000021#include "lldb/Symbol/TypeMap.h"
Aaron Smith86e94342017-12-22 05:26:50 +000022#include "lldb/Utility/RegularExpression.h"
Zachary Turner74e08ca2016-03-02 22:05:52 +000023
Pavel Labathb8d8c622016-05-09 11:07:43 +000024#include "llvm/DebugInfo/PDB/GenericError.h"
Aaron Smith1f8552a2017-12-22 00:04:36 +000025#include "llvm/DebugInfo/PDB/IPDBDataStream.h"
Zachary Turner74e08ca2016-03-02 22:05:52 +000026#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
27#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
28#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
Aaron Smith1f8552a2017-12-22 00:04:36 +000029#include "llvm/DebugInfo/PDB/IPDBTable.h"
Zachary Turner74e08ca2016-03-02 22:05:52 +000030#include "llvm/DebugInfo/PDB/PDBSymbol.h"
31#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
32#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
Aaron Smith1f8552a2017-12-22 00:04:36 +000033#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
Zachary Turner74e08ca2016-03-02 22:05:52 +000034#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
35#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
36#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
37#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
Zachary Turner42dff792016-04-15 00:21:26 +000038#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
39#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
40#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
41
42#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
43
44#include <regex>
Zachary Turner74e08ca2016-03-02 22:05:52 +000045
46using namespace lldb_private;
Zachary Turner54fd7ff2016-05-04 20:33:53 +000047using namespace llvm::pdb;
Zachary Turner74e08ca2016-03-02 22:05:52 +000048
Kate Stoneb9c1b512016-09-06 20:57:50 +000049namespace {
50lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
51 switch (lang) {
52 case PDB_Lang::Cpp:
53 return lldb::LanguageType::eLanguageTypeC_plus_plus;
54 case PDB_Lang::C:
55 return lldb::LanguageType::eLanguageTypeC;
56 default:
57 return lldb::LanguageType::eLanguageTypeUnknown;
58 }
Zachary Turner74e08ca2016-03-02 22:05:52 +000059}
60
Kate Stoneb9c1b512016-09-06 20:57:50 +000061bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
62 uint32_t addr_length) {
63 return ((requested_line == 0 || actual_line == requested_line) &&
64 addr_length > 0);
65}
Zachary Turner74e08ca2016-03-02 22:05:52 +000066}
67
Kate Stoneb9c1b512016-09-06 20:57:50 +000068void SymbolFilePDB::Initialize() {
69 PluginManager::RegisterPlugin(GetPluginNameStatic(),
70 GetPluginDescriptionStatic(), CreateInstance,
71 DebuggerInitialize);
Zachary Turner74e08ca2016-03-02 22:05:52 +000072}
73
Kate Stoneb9c1b512016-09-06 20:57:50 +000074void SymbolFilePDB::Terminate() {
75 PluginManager::UnregisterPlugin(CreateInstance);
Zachary Turner74e08ca2016-03-02 22:05:52 +000076}
77
Kate Stoneb9c1b512016-09-06 20:57:50 +000078void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {}
79
80lldb_private::ConstString SymbolFilePDB::GetPluginNameStatic() {
81 static ConstString g_name("pdb");
82 return g_name;
Zachary Turner74e08ca2016-03-02 22:05:52 +000083}
84
Kate Stoneb9c1b512016-09-06 20:57:50 +000085const char *SymbolFilePDB::GetPluginDescriptionStatic() {
86 return "Microsoft PDB debug symbol file reader.";
Zachary Turner74e08ca2016-03-02 22:05:52 +000087}
88
89lldb_private::SymbolFile *
Kate Stoneb9c1b512016-09-06 20:57:50 +000090SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
91 return new SymbolFilePDB(obj_file);
Zachary Turner74e08ca2016-03-02 22:05:52 +000092}
93
94SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 : SymbolFile(object_file), m_cached_compile_unit_count(0) {}
Zachary Turner74e08ca2016-03-02 22:05:52 +000096
Kate Stoneb9c1b512016-09-06 20:57:50 +000097SymbolFilePDB::~SymbolFilePDB() {}
Zachary Turner74e08ca2016-03-02 22:05:52 +000098
Kate Stoneb9c1b512016-09-06 20:57:50 +000099uint32_t SymbolFilePDB::CalculateAbilities() {
Aaron Smith1f8552a2017-12-22 00:04:36 +0000100 uint32_t abilities = 0;
101 if (!m_obj_file)
102 return 0;
103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 if (!m_session_up) {
105 // Lazily load and match the PDB file, but only do this once.
106 std::string exePath = m_obj_file->GetFileSpec().GetPath();
107 auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath),
108 m_session_up);
109 if (error) {
110 llvm::consumeError(std::move(error));
Aaron Smith1f8552a2017-12-22 00:04:36 +0000111 auto module_sp = m_obj_file->GetModule();
112 if (!module_sp)
113 return 0;
114 // See if any symbol file is specified through `--symfile` option.
115 FileSpec symfile = module_sp->GetSymbolFileFileSpec();
116 if (!symfile)
117 return 0;
118 error = loadDataForPDB(PDB_ReaderType::DIA,
119 llvm::StringRef(symfile.GetPath()),
120 m_session_up);
121 if (error) {
122 llvm::consumeError(std::move(error));
123 return 0;
124 }
Zachary Turner74e08ca2016-03-02 22:05:52 +0000125 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 }
Aaron Smith1f8552a2017-12-22 00:04:36 +0000127 if (!m_session_up.get())
128 return 0;
129
130 auto enum_tables_up = m_session_up->getEnumTables();
131 if (!enum_tables_up)
132 return 0;
133 while (auto table_up = enum_tables_up->getNext()) {
134 if (table_up->getItemCount() == 0)
135 continue;
136 auto type = table_up->getTableType();
137 switch (type) {
138 case PDB_TableType::Symbols:
139 // This table represents a store of symbols with types listed in
140 // PDBSym_Type
141 abilities |= (CompileUnits | Functions | Blocks |
142 GlobalVariables | LocalVariables | VariableTypes);
143 break;
144 case PDB_TableType::LineNumbers:
145 abilities |= LineTables;
146 break;
147 default: break;
148 }
149 }
150 return abilities;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000151}
152
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153void SymbolFilePDB::InitializeObject() {
154 lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
155 m_session_up->setLoadAddress(obj_load_address);
Zachary Turner42dff792016-04-15 00:21:26 +0000156
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 TypeSystem *type_system =
158 GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
159 ClangASTContext *clang_type_system =
160 llvm::dyn_cast_or_null<ClangASTContext>(type_system);
161 m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(
162 type_system, clang_type_system->GetTranslationUnitDecl());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000163}
164
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165uint32_t SymbolFilePDB::GetNumCompileUnits() {
166 if (m_cached_compile_unit_count == 0) {
Zachary Turner74e08ca2016-03-02 22:05:52 +0000167 auto global = m_session_up->getGlobalScope();
Zachary Turner54fd7ff2016-05-04 20:33:53 +0000168 auto compilands = global->findAllChildren<PDBSymbolCompiland>();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000169 m_cached_compile_unit_count = compilands->getChildCount();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000170
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171 // The linker can inject an additional "dummy" compilation unit into the
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000172 // PDB. Ignore this special compile unit for our purposes, if it is there.
173 // It is always the last one.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174 auto last_cu = compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
175 std::string name = last_cu->getName();
176 if (name == "* Linker *")
177 --m_cached_compile_unit_count;
178 }
179 return m_cached_compile_unit_count;
180}
Zachary Turner74e08ca2016-03-02 22:05:52 +0000181
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
183 auto global = m_session_up->getGlobalScope();
184 auto compilands = global->findAllChildren<PDBSymbolCompiland>();
185 auto cu = compilands->getChildAtIndex(index);
186
187 uint32_t id = cu->getSymIndexId();
188
189 return ParseCompileUnitForSymIndex(id);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000190}
191
192lldb::LanguageType
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) {
194 // What fields should I expect to be filled out on the SymbolContext? Is it
195 // safe to assume that `sc.comp_unit` is valid?
196 if (!sc.comp_unit)
197 return lldb::eLanguageTypeUnknown;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000198
Kate Stoneb9c1b512016-09-06 20:57:50 +0000199 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
200 sc.comp_unit->GetID());
201 if (!cu)
202 return lldb::eLanguageTypeUnknown;
203 auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
204 if (!details)
205 return lldb::eLanguageTypeUnknown;
206 return TranslateLanguage(details->getLanguage());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000207}
208
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209size_t SymbolFilePDB::ParseCompileUnitFunctions(
210 const lldb_private::SymbolContext &sc) {
211 // TODO: Implement this
212 return size_t();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000213}
214
Kate Stoneb9c1b512016-09-06 20:57:50 +0000215bool SymbolFilePDB::ParseCompileUnitLineTable(
216 const lldb_private::SymbolContext &sc) {
217 return ParseCompileUnitLineTable(sc, 0);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000218}
219
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220bool SymbolFilePDB::ParseCompileUnitDebugMacros(
221 const lldb_private::SymbolContext &sc) {
222 // PDB doesn't contain information about macros
223 return false;
224}
225
226bool SymbolFilePDB::ParseCompileUnitSupportFiles(
227 const lldb_private::SymbolContext &sc,
228 lldb_private::FileSpecList &support_files) {
229 if (!sc.comp_unit)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000230 return false;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232 // In theory this is unnecessary work for us, because all of this information
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000233 // is easily (and quickly) accessible from DebugInfoPDB, so caching it a
234 // second time seems like a waste. Unfortunately, there's no good way around
235 // this short of a moderate refactor since SymbolVendor depends on being able
236 // to cache this list.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
238 sc.comp_unit->GetID());
239 if (!cu)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000240 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000241 auto files = m_session_up->getSourceFilesForCompiland(*cu);
242 if (!files || files->getChildCount() == 0)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000243 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244
245 while (auto file = files->getNext()) {
246 FileSpec spec(file->getFileName(), false);
247 support_files.Append(spec);
248 }
249 return true;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000250}
251
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252bool SymbolFilePDB::ParseImportedModules(
253 const lldb_private::SymbolContext &sc,
254 std::vector<lldb_private::ConstString> &imported_modules) {
255 // PDB does not yet support module debug info
256 return false;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000257}
258
259size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) {
261 // TODO: Implement this
262 return size_t();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000263}
264
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) {
266 // TODO: Implement this
267 return size_t();
268}
269
270size_t
271SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
272 // TODO: Implement this
273 return size_t();
274}
275
276lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
277 auto find_result = m_types.find(type_uid);
278 if (find_result != m_types.end())
279 return find_result->second.get();
280
281 TypeSystem *type_system =
282 GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
283 ClangASTContext *clang_type_system =
284 llvm::dyn_cast_or_null<ClangASTContext>(type_system);
285 if (!clang_type_system)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000286 return nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287 PDBASTParser *pdb =
288 llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
289 if (!pdb)
290 return nullptr;
291
292 auto pdb_type = m_session_up->getSymbolById(type_uid);
293 if (pdb_type == nullptr)
294 return nullptr;
295
296 lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
Aaron Smith86e94342017-12-22 05:26:50 +0000297 if (result.get())
298 m_types.insert(std::make_pair(type_uid, result));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299 return result.get();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000300}
301
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) {
303 // TODO: Implement this
304 return false;
305}
306
307lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) {
308 return lldb_private::CompilerDecl();
309}
310
311lldb_private::CompilerDeclContext
312SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
313 // PDB always uses the translation unit decl context for everything. We can
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000314 // improve this later but it's not easy because PDB doesn't provide a high
315 // enough level of type fidelity in this area.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316 return *m_tu_decl_ctx_up;
317}
318
319lldb_private::CompilerDeclContext
320SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
321 return *m_tu_decl_ctx_up;
322}
323
324void SymbolFilePDB::ParseDeclsForContext(
325 lldb_private::CompilerDeclContext decl_ctx) {}
326
327uint32_t
328SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
329 uint32_t resolve_scope,
330 lldb_private::SymbolContext &sc) {
331 return uint32_t();
332}
333
334uint32_t SymbolFilePDB::ResolveSymbolContext(
335 const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
336 uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) {
337 if (resolve_scope & lldb::eSymbolContextCompUnit) {
338 // Locate all compilation units with line numbers referencing the specified
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000339 // file. For example, if `file_spec` is <vector>, then this should return
340 // all source files and header files that reference <vector>, either
341 // directly or indirectly.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000342 auto compilands = m_session_up->findCompilandsForSourceFile(
343 file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive);
344
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000345 // For each one, either find its previously parsed data or parse it afresh
346 // and add it to the symbol context list.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347 while (auto compiland = compilands->getNext()) {
348 // If we're not checking inlines, then don't add line information for this
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000349 // file unless the FileSpec matches.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350 if (!check_inlines) {
351 // `getSourceFileName` returns the basename of the original source file
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000352 // used to generate this compiland. It does not return the full path.
353 // Currently the only way to get that is to do a basename lookup to get
354 // the IPDBSourceFile, but this is ambiguous in the case of two source
355 // files with the same name contributing to the same compiland. This is
356 // a moderately extreme edge case, so we consider this OK for now,
357 // although we need to find a long-term solution.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358 std::string source_file = compiland->getSourceFileName();
359 auto pdb_file = m_session_up->findOneSourceFile(
360 compiland.get(), source_file,
361 PDB_NameSearchFlags::NS_CaseInsensitive);
362 source_file = pdb_file->getFileName();
363 FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows);
364 if (!file_spec.FileEquals(this_spec))
365 continue;
366 }
367
368 SymbolContext sc;
369 auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId());
370 sc.comp_unit = cu.get();
371 sc.module_sp = cu->GetModule();
372 sc_list.Append(sc);
373
374 // If we were asked to resolve line entries, add all entries to the line
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000375 // table that match the requested line (or all lines if `line` == 0).
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376 if (resolve_scope & lldb::eSymbolContextLineEntry)
377 ParseCompileUnitLineTable(sc, line);
378 }
379 }
380 return sc_list.GetSize();
381}
382
383uint32_t SymbolFilePDB::FindGlobalVariables(
384 const lldb_private::ConstString &name,
385 const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
386 uint32_t max_matches, lldb_private::VariableList &variables) {
387 return uint32_t();
388}
389
390uint32_t
391SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex,
392 bool append, uint32_t max_matches,
393 lldb_private::VariableList &variables) {
394 return uint32_t();
395}
396
397uint32_t SymbolFilePDB::FindFunctions(
398 const lldb_private::ConstString &name,
399 const lldb_private::CompilerDeclContext *parent_decl_ctx,
400 uint32_t name_type_mask, bool include_inlines, bool append,
401 lldb_private::SymbolContextList &sc_list) {
402 return uint32_t();
403}
404
405uint32_t
406SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex,
407 bool include_inlines, bool append,
408 lldb_private::SymbolContextList &sc_list) {
409 return uint32_t();
410}
411
412void SymbolFilePDB::GetMangledNamesForFunction(
413 const std::string &scope_qualified_name,
414 std::vector<lldb_private::ConstString> &mangled_names) {}
415
416uint32_t SymbolFilePDB::FindTypes(
417 const lldb_private::SymbolContext &sc,
418 const lldb_private::ConstString &name,
419 const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
420 uint32_t max_matches,
421 llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
422 lldb_private::TypeMap &types) {
423 if (!append)
424 types.Clear();
425 if (!name)
426 return 0;
427
428 searched_symbol_files.clear();
429 searched_symbol_files.insert(this);
430
431 std::string name_str = name.AsCString();
432
Aaron Smith86e94342017-12-22 05:26:50 +0000433 // There is an assumption 'name' is not a regex
434 FindTypesByName(name_str, max_matches, types);
435
Kate Stoneb9c1b512016-09-06 20:57:50 +0000436 return types.GetSize();
437}
438
Aaron Smith86e94342017-12-22 05:26:50 +0000439void
440SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression &regex,
441 uint32_t max_matches,
442 lldb_private::TypeMap &types) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000443 // When searching by regex, we need to go out of our way to limit the search
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000444 // space as much as possible since this searches EVERYTHING in the PDB,
445 // manually doing regex comparisons. PDB library isn't optimized for regex
446 // searches or searches across multiple symbol types at the same time, so the
Kate Stoneb9c1b512016-09-06 20:57:50 +0000447 // best we can do is to search enums, then typedefs, then classes one by one,
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000448 // and do a regex comparison against each of them.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000449 PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
450 PDB_SymType::UDT};
451 auto global = m_session_up->getGlobalScope();
452 std::unique_ptr<IPDBEnumSymbols> results;
453
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454 uint32_t matches = 0;
455
456 for (auto tag : tags_to_search) {
457 results = global->findAllChildren(tag);
458 while (auto result = results->getNext()) {
459 if (max_matches > 0 && matches >= max_matches)
460 break;
461
462 std::string type_name;
463 if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get()))
464 type_name = enum_type->getName();
465 else if (auto typedef_type =
466 llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get()))
467 type_name = typedef_type->getName();
468 else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get()))
469 type_name = class_type->getName();
470 else {
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000471 // We're looking only for types that have names. Skip symbols, as well
472 // as unnamed types such as arrays, pointers, etc.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473 continue;
474 }
475
Aaron Smith86e94342017-12-22 05:26:50 +0000476 if (!regex.Execute(type_name))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000477 continue;
478
479 // This should cause the type to get cached and stored in the `m_types`
480 // lookup.
481 if (!ResolveTypeUID(result->getSymIndexId()))
482 continue;
483
484 auto iter = m_types.find(result->getSymIndexId());
485 if (iter == m_types.end())
486 continue;
487 types.Insert(iter->second);
488 ++matches;
489 }
490 }
491}
492
493void SymbolFilePDB::FindTypesByName(const std::string &name,
494 uint32_t max_matches,
495 lldb_private::TypeMap &types) {
496 auto global = m_session_up->getGlobalScope();
497 std::unique_ptr<IPDBEnumSymbols> results;
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000498 results = global->findChildren(PDB_SymType::None, name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000499 PDB_NameSearchFlags::NS_Default);
500
501 uint32_t matches = 0;
502
503 while (auto result = results->getNext()) {
504 if (max_matches > 0 && matches >= max_matches)
505 break;
506 switch (result->getSymTag()) {
507 case PDB_SymType::Enum:
508 case PDB_SymType::UDT:
509 case PDB_SymType::Typedef:
510 break;
511 default:
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000512 // We're looking only for types that have names. Skip symbols, as well as
Kate Stoneb9c1b512016-09-06 20:57:50 +0000513 // unnamed types such as arrays, pointers, etc.
514 continue;
515 }
516
517 // This should cause the type to get cached and stored in the `m_types`
518 // lookup.
519 if (!ResolveTypeUID(result->getSymIndexId()))
520 continue;
521
522 auto iter = m_types.find(result->getSymIndexId());
523 if (iter == m_types.end())
524 continue;
525 types.Insert(iter->second);
526 ++matches;
527 }
528}
529
530size_t SymbolFilePDB::FindTypes(
531 const std::vector<lldb_private::CompilerContext> &contexts, bool append,
532 lldb_private::TypeMap &types) {
533 return 0;
534}
535
536lldb_private::TypeList *SymbolFilePDB::GetTypeList() { return nullptr; }
537
538size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
539 uint32_t type_mask,
540 lldb_private::TypeList &type_list) {
541 return size_t();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000542}
543
544lldb_private::TypeSystem *
Kate Stoneb9c1b512016-09-06 20:57:50 +0000545SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
546 auto type_system =
547 m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
548 if (type_system)
549 type_system->SetSymbolFile(this);
550 return type_system;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000551}
552
Kate Stoneb9c1b512016-09-06 20:57:50 +0000553lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace(
554 const lldb_private::SymbolContext &sc,
555 const lldb_private::ConstString &name,
556 const lldb_private::CompilerDeclContext *parent_decl_ctx) {
557 return lldb_private::CompilerDeclContext();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000558}
559
Kate Stoneb9c1b512016-09-06 20:57:50 +0000560lldb_private::ConstString SymbolFilePDB::GetPluginName() {
561 static ConstString g_name("pdb");
562 return g_name;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000563}
564
Kate Stoneb9c1b512016-09-06 20:57:50 +0000565uint32_t SymbolFilePDB::GetPluginVersion() { return 1; }
566
567IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; }
568
569const IPDBSession &SymbolFilePDB::GetPDBSession() const {
570 return *m_session_up;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000571}
572
Kate Stoneb9c1b512016-09-06 20:57:50 +0000573lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id) {
574 auto found_cu = m_comp_units.find(id);
575 if (found_cu != m_comp_units.end())
576 return found_cu->second;
577
578 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(id);
579
580 // `getSourceFileName` returns the basename of the original source file used
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000581 // to generate this compiland. It does not return the full path. Currently
582 // the only way to get that is to do a basename lookup to get the
Kate Stoneb9c1b512016-09-06 20:57:50 +0000583 // IPDBSourceFile, but this is ambiguous in the case of two source files with
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000584 // the same name contributing to the same compiland. This is a moderately
585 // extreme edge case, so we consider this OK for now, although we need to find
586 // a long-term solution.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000587 auto file =
588 m_session_up->findOneSourceFile(cu.get(), cu->getSourceFileName(),
589 PDB_NameSearchFlags::NS_CaseInsensitive);
590 std::string path = file->getFileName();
591
592 lldb::LanguageType lang;
593 auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
594 if (!details)
595 lang = lldb::eLanguageTypeC_plus_plus;
596 else
597 lang = TranslateLanguage(details->getLanguage());
598
599 // Don't support optimized code for now, DebugInfoPDB does not return this
600 // information.
601 LazyBool optimized = eLazyBoolNo;
602 auto result = std::make_shared<CompileUnit>(
603 m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized);
604 m_comp_units.insert(std::make_pair(id, result));
605 return result;
Zachary Turner42dff792016-04-15 00:21:26 +0000606}
607
Kate Stoneb9c1b512016-09-06 20:57:50 +0000608bool SymbolFilePDB::ParseCompileUnitLineTable(
609 const lldb_private::SymbolContext &sc, uint32_t match_line) {
610 auto global = m_session_up->getGlobalScope();
611 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
612 sc.comp_unit->GetID());
Zachary Turner42dff792016-04-15 00:21:26 +0000613
Kate Stoneb9c1b512016-09-06 20:57:50 +0000614 // LineEntry needs the *index* of the file into the list of support files
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000615 // returned by ParseCompileUnitSupportFiles. But the underlying SDK gives us
616 // a globally unique idenfitifier in the namespace of the PDB. So, we have to
617 // do a mapping so that we can hand out indices.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000618 llvm::DenseMap<uint32_t, uint32_t> index_map;
619 BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);
620 auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000621
Kate Stoneb9c1b512016-09-06 20:57:50 +0000622 // Find contributions to `cu` from all source and header files.
623 std::string path = sc.comp_unit->GetPath();
624 auto files = m_session_up->getSourceFilesForCompiland(*cu);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000625
Kate Stoneb9c1b512016-09-06 20:57:50 +0000626 // For each source and header file, create a LineSequence for contributions to
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000627 // the cu from that file, and add the sequence.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000628 while (auto file = files->getNext()) {
629 std::unique_ptr<LineSequence> sequence(
630 line_table->CreateLineSequenceContainer());
631 auto lines = m_session_up->findLineNumbers(*cu, *file);
632 int entry_count = lines->getChildCount();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000633
Kate Stoneb9c1b512016-09-06 20:57:50 +0000634 uint64_t prev_addr;
635 uint32_t prev_length;
636 uint32_t prev_line;
637 uint32_t prev_source_idx;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000638
Kate Stoneb9c1b512016-09-06 20:57:50 +0000639 for (int i = 0; i < entry_count; ++i) {
640 auto line = lines->getChildAtIndex(i);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000641
Kate Stoneb9c1b512016-09-06 20:57:50 +0000642 uint64_t lno = line->getLineNumber();
643 uint64_t addr = line->getVirtualAddress();
644 uint32_t length = line->getLength();
645 uint32_t source_id = line->getSourceFileId();
646 uint32_t col = line->getColumnNumber();
647 uint32_t source_idx = index_map[source_id];
Zachary Turner74e08ca2016-03-02 22:05:52 +0000648
Kate Stoneb9c1b512016-09-06 20:57:50 +0000649 // There was a gap between the current entry and the previous entry if the
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000650 // addresses don't perfectly line up.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000651 bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000652
Kate Stoneb9c1b512016-09-06 20:57:50 +0000653 // Before inserting the current entry, insert a terminal entry at the end
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000654 // of the previous entry's address range if the current entry resulted in
655 // a gap from the previous entry.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) {
657 line_table->AppendLineEntryToSequence(
658 sequence.get(), prev_addr + prev_length, prev_line, 0,
659 prev_source_idx, false, false, false, false, true);
660 }
Zachary Turner74e08ca2016-03-02 22:05:52 +0000661
Kate Stoneb9c1b512016-09-06 20:57:50 +0000662 if (ShouldAddLine(match_line, lno, length)) {
663 bool is_statement = line->isStatement();
664 bool is_prologue = false;
665 bool is_epilogue = false;
666 auto func =
667 m_session_up->findSymbolByAddress(addr, PDB_SymType::Function);
668 if (func) {
669 auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>();
670 is_prologue = (addr == prologue->getVirtualAddress());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000671
Kate Stoneb9c1b512016-09-06 20:57:50 +0000672 auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>();
673 is_epilogue = (addr == epilogue->getVirtualAddress());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000674 }
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000675
Kate Stoneb9c1b512016-09-06 20:57:50 +0000676 line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col,
677 source_idx, is_statement, false,
678 is_prologue, is_epilogue, false);
679 }
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000680
Kate Stoneb9c1b512016-09-06 20:57:50 +0000681 prev_addr = addr;
682 prev_length = length;
683 prev_line = lno;
684 prev_source_idx = source_idx;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000685 }
686
Kate Stoneb9c1b512016-09-06 20:57:50 +0000687 if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) {
688 // The end is always a terminal entry, so insert it regardless.
689 line_table->AppendLineEntryToSequence(
690 sequence.get(), prev_addr + prev_length, prev_line, 0,
691 prev_source_idx, false, false, false, false, true);
692 }
693
694 line_table->InsertSequence(sequence.release());
695 }
696
697 sc.comp_unit->SetLineTable(line_table.release());
698 return true;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000699}
700
Kate Stoneb9c1b512016-09-06 20:57:50 +0000701void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
702 const PDBSymbolCompiland &cu,
703 llvm::DenseMap<uint32_t, uint32_t> &index_map) const {
704 // This is a hack, but we need to convert the source id into an index into the
Adrian McCarthy9d0eb9962017-01-27 21:42:28 +0000705 // support files array. We don't want to do path comparisons to avoid
706 // basename / full path issues that may or may not even be a problem, so we
707 // use the globally unique source file identifiers. Ideally we could use the
708 // global identifiers everywhere, but LineEntry currently assumes indices.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000709 auto source_files = m_session_up->getSourceFilesForCompiland(cu);
710 int index = 0;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000711
Kate Stoneb9c1b512016-09-06 20:57:50 +0000712 while (auto file = source_files->getNext()) {
713 uint32_t source_id = file->getUniqueId();
714 index_map[source_id] = index++;
715 }
Zachary Turner74e08ca2016-03-02 22:05:52 +0000716}