blob: cb5ee5893162b9c4b96aa85b23f8d06637a36b56 [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"
Zachary Turner74e08ca2016-03-02 22:05:52 +000022
Pavel Labathb8d8c622016-05-09 11:07:43 +000023#include "llvm/DebugInfo/PDB/GenericError.h"
Zachary Turner74e08ca2016-03-02 22:05:52 +000024#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
25#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
26#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
27#include "llvm/DebugInfo/PDB/PDBSymbol.h"
28#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
29#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
30#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
31#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
32#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
33#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
Zachary Turner42dff792016-04-15 00:21:26 +000034#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
35#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
36#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
37
38#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
39
40#include <regex>
Zachary Turner74e08ca2016-03-02 22:05:52 +000041
42using namespace lldb_private;
Zachary Turner54fd7ff2016-05-04 20:33:53 +000043using namespace llvm::pdb;
Zachary Turner74e08ca2016-03-02 22:05:52 +000044
Kate Stoneb9c1b512016-09-06 20:57:50 +000045namespace {
46lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
47 switch (lang) {
48 case PDB_Lang::Cpp:
49 return lldb::LanguageType::eLanguageTypeC_plus_plus;
50 case PDB_Lang::C:
51 return lldb::LanguageType::eLanguageTypeC;
52 default:
53 return lldb::LanguageType::eLanguageTypeUnknown;
54 }
Zachary Turner74e08ca2016-03-02 22:05:52 +000055}
56
Kate Stoneb9c1b512016-09-06 20:57:50 +000057bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
58 uint32_t addr_length) {
59 return ((requested_line == 0 || actual_line == requested_line) &&
60 addr_length > 0);
61}
Zachary Turner74e08ca2016-03-02 22:05:52 +000062}
63
Kate Stoneb9c1b512016-09-06 20:57:50 +000064void SymbolFilePDB::Initialize() {
65 PluginManager::RegisterPlugin(GetPluginNameStatic(),
66 GetPluginDescriptionStatic(), CreateInstance,
67 DebuggerInitialize);
Zachary Turner74e08ca2016-03-02 22:05:52 +000068}
69
Kate Stoneb9c1b512016-09-06 20:57:50 +000070void SymbolFilePDB::Terminate() {
71 PluginManager::UnregisterPlugin(CreateInstance);
Zachary Turner74e08ca2016-03-02 22:05:52 +000072}
73
Kate Stoneb9c1b512016-09-06 20:57:50 +000074void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {}
75
76lldb_private::ConstString SymbolFilePDB::GetPluginNameStatic() {
77 static ConstString g_name("pdb");
78 return g_name;
Zachary Turner74e08ca2016-03-02 22:05:52 +000079}
80
Kate Stoneb9c1b512016-09-06 20:57:50 +000081const char *SymbolFilePDB::GetPluginDescriptionStatic() {
82 return "Microsoft PDB debug symbol file reader.";
Zachary Turner74e08ca2016-03-02 22:05:52 +000083}
84
85lldb_private::SymbolFile *
Kate Stoneb9c1b512016-09-06 20:57:50 +000086SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
87 return new SymbolFilePDB(obj_file);
Zachary Turner74e08ca2016-03-02 22:05:52 +000088}
89
90SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)
Kate Stoneb9c1b512016-09-06 20:57:50 +000091 : SymbolFile(object_file), m_cached_compile_unit_count(0) {}
Zachary Turner74e08ca2016-03-02 22:05:52 +000092
Kate Stoneb9c1b512016-09-06 20:57:50 +000093SymbolFilePDB::~SymbolFilePDB() {}
Zachary Turner74e08ca2016-03-02 22:05:52 +000094
Kate Stoneb9c1b512016-09-06 20:57:50 +000095uint32_t SymbolFilePDB::CalculateAbilities() {
96 if (!m_session_up) {
97 // Lazily load and match the PDB file, but only do this once.
98 std::string exePath = m_obj_file->GetFileSpec().GetPath();
99 auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath),
100 m_session_up);
101 if (error) {
102 llvm::consumeError(std::move(error));
103 return 0;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000104 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105 }
106 return CompileUnits | LineTables;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000107}
108
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109void SymbolFilePDB::InitializeObject() {
110 lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
111 m_session_up->setLoadAddress(obj_load_address);
Zachary Turner42dff792016-04-15 00:21:26 +0000112
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113 TypeSystem *type_system =
114 GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
115 ClangASTContext *clang_type_system =
116 llvm::dyn_cast_or_null<ClangASTContext>(type_system);
117 m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(
118 type_system, clang_type_system->GetTranslationUnitDecl());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000119}
120
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121uint32_t SymbolFilePDB::GetNumCompileUnits() {
122 if (m_cached_compile_unit_count == 0) {
Zachary Turner74e08ca2016-03-02 22:05:52 +0000123 auto global = m_session_up->getGlobalScope();
Zachary Turner54fd7ff2016-05-04 20:33:53 +0000124 auto compilands = global->findAllChildren<PDBSymbolCompiland>();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 m_cached_compile_unit_count = compilands->getChildCount();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000126
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127 // The linker can inject an additional "dummy" compilation unit into the
128 // PDB.
129 // Ignore this special compile unit for our purposes, if it is there. It is
130 // always the last one.
131 auto last_cu = compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
132 std::string name = last_cu->getName();
133 if (name == "* Linker *")
134 --m_cached_compile_unit_count;
135 }
136 return m_cached_compile_unit_count;
137}
Zachary Turner74e08ca2016-03-02 22:05:52 +0000138
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
140 auto global = m_session_up->getGlobalScope();
141 auto compilands = global->findAllChildren<PDBSymbolCompiland>();
142 auto cu = compilands->getChildAtIndex(index);
143
144 uint32_t id = cu->getSymIndexId();
145
146 return ParseCompileUnitForSymIndex(id);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000147}
148
149lldb::LanguageType
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) {
151 // What fields should I expect to be filled out on the SymbolContext? Is it
152 // safe to assume that `sc.comp_unit` is valid?
153 if (!sc.comp_unit)
154 return lldb::eLanguageTypeUnknown;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000155
Kate Stoneb9c1b512016-09-06 20:57:50 +0000156 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
157 sc.comp_unit->GetID());
158 if (!cu)
159 return lldb::eLanguageTypeUnknown;
160 auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
161 if (!details)
162 return lldb::eLanguageTypeUnknown;
163 return TranslateLanguage(details->getLanguage());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000164}
165
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166size_t SymbolFilePDB::ParseCompileUnitFunctions(
167 const lldb_private::SymbolContext &sc) {
168 // TODO: Implement this
169 return size_t();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000170}
171
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172bool SymbolFilePDB::ParseCompileUnitLineTable(
173 const lldb_private::SymbolContext &sc) {
174 return ParseCompileUnitLineTable(sc, 0);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000175}
176
Kate Stoneb9c1b512016-09-06 20:57:50 +0000177bool SymbolFilePDB::ParseCompileUnitDebugMacros(
178 const lldb_private::SymbolContext &sc) {
179 // PDB doesn't contain information about macros
180 return false;
181}
182
183bool SymbolFilePDB::ParseCompileUnitSupportFiles(
184 const lldb_private::SymbolContext &sc,
185 lldb_private::FileSpecList &support_files) {
186 if (!sc.comp_unit)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000187 return false;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000188
Kate Stoneb9c1b512016-09-06 20:57:50 +0000189 // In theory this is unnecessary work for us, because all of this information
190 // is easily
191 // (and quickly) accessible from DebugInfoPDB, so caching it a second time
192 // seems like a waste.
193 // Unfortunately, there's no good way around this short of a moderate
194 // refactor, since SymbolVendor
195 // depends on being able to cache this list.
196 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
197 sc.comp_unit->GetID());
198 if (!cu)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000199 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200 auto files = m_session_up->getSourceFilesForCompiland(*cu);
201 if (!files || files->getChildCount() == 0)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000202 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203
204 while (auto file = files->getNext()) {
205 FileSpec spec(file->getFileName(), false);
206 support_files.Append(spec);
207 }
208 return true;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000209}
210
Kate Stoneb9c1b512016-09-06 20:57:50 +0000211bool SymbolFilePDB::ParseImportedModules(
212 const lldb_private::SymbolContext &sc,
213 std::vector<lldb_private::ConstString> &imported_modules) {
214 // PDB does not yet support module debug info
215 return false;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000216}
217
218size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) {
220 // TODO: Implement this
221 return size_t();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000222}
223
Kate Stoneb9c1b512016-09-06 20:57:50 +0000224size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) {
225 // TODO: Implement this
226 return size_t();
227}
228
229size_t
230SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
231 // TODO: Implement this
232 return size_t();
233}
234
235lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
236 auto find_result = m_types.find(type_uid);
237 if (find_result != m_types.end())
238 return find_result->second.get();
239
240 TypeSystem *type_system =
241 GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
242 ClangASTContext *clang_type_system =
243 llvm::dyn_cast_or_null<ClangASTContext>(type_system);
244 if (!clang_type_system)
Zachary Turner74e08ca2016-03-02 22:05:52 +0000245 return nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246 PDBASTParser *pdb =
247 llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
248 if (!pdb)
249 return nullptr;
250
251 auto pdb_type = m_session_up->getSymbolById(type_uid);
252 if (pdb_type == nullptr)
253 return nullptr;
254
255 lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
256 m_types.insert(std::make_pair(type_uid, result));
257 return result.get();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000258}
259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) {
261 // TODO: Implement this
262 return false;
263}
264
265lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) {
266 return lldb_private::CompilerDecl();
267}
268
269lldb_private::CompilerDeclContext
270SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
271 // PDB always uses the translation unit decl context for everything. We can
272 // improve this later
273 // but it's not easy because PDB doesn't provide a high enough level of type
274 // fidelity in this area.
275 return *m_tu_decl_ctx_up;
276}
277
278lldb_private::CompilerDeclContext
279SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
280 return *m_tu_decl_ctx_up;
281}
282
283void SymbolFilePDB::ParseDeclsForContext(
284 lldb_private::CompilerDeclContext decl_ctx) {}
285
286uint32_t
287SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
288 uint32_t resolve_scope,
289 lldb_private::SymbolContext &sc) {
290 return uint32_t();
291}
292
293uint32_t SymbolFilePDB::ResolveSymbolContext(
294 const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
295 uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) {
296 if (resolve_scope & lldb::eSymbolContextCompUnit) {
297 // Locate all compilation units with line numbers referencing the specified
298 // file. For example, if
299 // `file_spec` is <vector>, then this should return all source files and
300 // header files that reference
301 // <vector>, either directly or indirectly.
302 auto compilands = m_session_up->findCompilandsForSourceFile(
303 file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive);
304
305 // For each one, either find get its previously parsed data, or parse it
306 // afresh and add it to
307 // the symbol context list.
308 while (auto compiland = compilands->getNext()) {
309 // If we're not checking inlines, then don't add line information for this
310 // file unless the FileSpec
311 // matches.
312 if (!check_inlines) {
313 // `getSourceFileName` returns the basename of the original source file
314 // used to generate this compiland.
315 // It does not return the full path. Currently the only way to get that
316 // is to do a basename lookup to
317 // get the IPDBSourceFile, but this is ambiguous in the case of two
318 // source files with the same name
319 // contributing to the same compiland. This is a moderately extreme
320 // edge case, so we consider this ok
321 // for now, although we need to find a long term solution.
322 std::string source_file = compiland->getSourceFileName();
323 auto pdb_file = m_session_up->findOneSourceFile(
324 compiland.get(), source_file,
325 PDB_NameSearchFlags::NS_CaseInsensitive);
326 source_file = pdb_file->getFileName();
327 FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows);
328 if (!file_spec.FileEquals(this_spec))
329 continue;
330 }
331
332 SymbolContext sc;
333 auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId());
334 sc.comp_unit = cu.get();
335 sc.module_sp = cu->GetModule();
336 sc_list.Append(sc);
337
338 // If we were asked to resolve line entries, add all entries to the line
339 // table that match the requested
340 // line (or all lines if `line` == 0)
341 if (resolve_scope & lldb::eSymbolContextLineEntry)
342 ParseCompileUnitLineTable(sc, line);
343 }
344 }
345 return sc_list.GetSize();
346}
347
348uint32_t SymbolFilePDB::FindGlobalVariables(
349 const lldb_private::ConstString &name,
350 const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
351 uint32_t max_matches, lldb_private::VariableList &variables) {
352 return uint32_t();
353}
354
355uint32_t
356SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex,
357 bool append, uint32_t max_matches,
358 lldb_private::VariableList &variables) {
359 return uint32_t();
360}
361
362uint32_t SymbolFilePDB::FindFunctions(
363 const lldb_private::ConstString &name,
364 const lldb_private::CompilerDeclContext *parent_decl_ctx,
365 uint32_t name_type_mask, bool include_inlines, bool append,
366 lldb_private::SymbolContextList &sc_list) {
367 return uint32_t();
368}
369
370uint32_t
371SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex,
372 bool include_inlines, bool append,
373 lldb_private::SymbolContextList &sc_list) {
374 return uint32_t();
375}
376
377void SymbolFilePDB::GetMangledNamesForFunction(
378 const std::string &scope_qualified_name,
379 std::vector<lldb_private::ConstString> &mangled_names) {}
380
381uint32_t SymbolFilePDB::FindTypes(
382 const lldb_private::SymbolContext &sc,
383 const lldb_private::ConstString &name,
384 const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
385 uint32_t max_matches,
386 llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
387 lldb_private::TypeMap &types) {
388 if (!append)
389 types.Clear();
390 if (!name)
391 return 0;
392
393 searched_symbol_files.clear();
394 searched_symbol_files.insert(this);
395
396 std::string name_str = name.AsCString();
397
398 // If this might be a regex, we have to return EVERY symbol and process them
399 // one by one, which is going
400 // to destroy performance on large PDB files. So try really hard not to use a
401 // regex match.
402 if (name_str.find_first_of("[]?*.-+\\") != std::string::npos)
403 FindTypesByRegex(name_str, max_matches, types);
404 else
405 FindTypesByName(name_str, max_matches, types);
406 return types.GetSize();
407}
408
409void SymbolFilePDB::FindTypesByRegex(const std::string &regex,
410 uint32_t max_matches,
411 lldb_private::TypeMap &types) {
412 // When searching by regex, we need to go out of our way to limit the search
413 // space as much as possible, since
414 // the way this is implemented is by searching EVERYTHING in the PDB and
415 // manually doing a regex compare. PDB
416 // library isn't optimized for regex searches or searches across multiple
417 // symbol types at the same time, so the
418 // best we can do is to search enums, then typedefs, then classes one by one,
419 // and do a regex compare against all
420 // of them.
421 PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
422 PDB_SymType::UDT};
423 auto global = m_session_up->getGlobalScope();
424 std::unique_ptr<IPDBEnumSymbols> results;
425
426 std::regex re(regex);
427
428 uint32_t matches = 0;
429
430 for (auto tag : tags_to_search) {
431 results = global->findAllChildren(tag);
432 while (auto result = results->getNext()) {
433 if (max_matches > 0 && matches >= max_matches)
434 break;
435
436 std::string type_name;
437 if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get()))
438 type_name = enum_type->getName();
439 else if (auto typedef_type =
440 llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get()))
441 type_name = typedef_type->getName();
442 else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get()))
443 type_name = class_type->getName();
444 else {
445 // We're only looking for types that have names. Skip symbols, as well
446 // as
447 // unnamed types such as arrays, pointers, etc.
448 continue;
449 }
450
451 if (!std::regex_match(type_name, re))
452 continue;
453
454 // This should cause the type to get cached and stored in the `m_types`
455 // lookup.
456 if (!ResolveTypeUID(result->getSymIndexId()))
457 continue;
458
459 auto iter = m_types.find(result->getSymIndexId());
460 if (iter == m_types.end())
461 continue;
462 types.Insert(iter->second);
463 ++matches;
464 }
465 }
466}
467
468void SymbolFilePDB::FindTypesByName(const std::string &name,
469 uint32_t max_matches,
470 lldb_private::TypeMap &types) {
471 auto global = m_session_up->getGlobalScope();
472 std::unique_ptr<IPDBEnumSymbols> results;
473 results = global->findChildren(PDB_SymType::None, name.c_str(),
474 PDB_NameSearchFlags::NS_Default);
475
476 uint32_t matches = 0;
477
478 while (auto result = results->getNext()) {
479 if (max_matches > 0 && matches >= max_matches)
480 break;
481 switch (result->getSymTag()) {
482 case PDB_SymType::Enum:
483 case PDB_SymType::UDT:
484 case PDB_SymType::Typedef:
485 break;
486 default:
487 // We're only looking for types that have names. Skip symbols, as well as
488 // unnamed types such as arrays, pointers, etc.
489 continue;
490 }
491
492 // This should cause the type to get cached and stored in the `m_types`
493 // lookup.
494 if (!ResolveTypeUID(result->getSymIndexId()))
495 continue;
496
497 auto iter = m_types.find(result->getSymIndexId());
498 if (iter == m_types.end())
499 continue;
500 types.Insert(iter->second);
501 ++matches;
502 }
503}
504
505size_t SymbolFilePDB::FindTypes(
506 const std::vector<lldb_private::CompilerContext> &contexts, bool append,
507 lldb_private::TypeMap &types) {
508 return 0;
509}
510
511lldb_private::TypeList *SymbolFilePDB::GetTypeList() { return nullptr; }
512
513size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
514 uint32_t type_mask,
515 lldb_private::TypeList &type_list) {
516 return size_t();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000517}
518
519lldb_private::TypeSystem *
Kate Stoneb9c1b512016-09-06 20:57:50 +0000520SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
521 auto type_system =
522 m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
523 if (type_system)
524 type_system->SetSymbolFile(this);
525 return type_system;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000526}
527
Kate Stoneb9c1b512016-09-06 20:57:50 +0000528lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace(
529 const lldb_private::SymbolContext &sc,
530 const lldb_private::ConstString &name,
531 const lldb_private::CompilerDeclContext *parent_decl_ctx) {
532 return lldb_private::CompilerDeclContext();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000533}
534
Kate Stoneb9c1b512016-09-06 20:57:50 +0000535lldb_private::ConstString SymbolFilePDB::GetPluginName() {
536 static ConstString g_name("pdb");
537 return g_name;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000538}
539
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540uint32_t SymbolFilePDB::GetPluginVersion() { return 1; }
541
542IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; }
543
544const IPDBSession &SymbolFilePDB::GetPDBSession() const {
545 return *m_session_up;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000546}
547
Kate Stoneb9c1b512016-09-06 20:57:50 +0000548lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id) {
549 auto found_cu = m_comp_units.find(id);
550 if (found_cu != m_comp_units.end())
551 return found_cu->second;
552
553 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(id);
554
555 // `getSourceFileName` returns the basename of the original source file used
556 // to generate this compiland. It does
557 // not return the full path. Currently the only way to get that is to do a
558 // basename lookup to get the
559 // IPDBSourceFile, but this is ambiguous in the case of two source files with
560 // the same name contributing to the
561 // same compiland. This is a moderately extreme edge case, so we consider this
562 // ok for now, although we need to find
563 // a long term solution.
564 auto file =
565 m_session_up->findOneSourceFile(cu.get(), cu->getSourceFileName(),
566 PDB_NameSearchFlags::NS_CaseInsensitive);
567 std::string path = file->getFileName();
568
569 lldb::LanguageType lang;
570 auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
571 if (!details)
572 lang = lldb::eLanguageTypeC_plus_plus;
573 else
574 lang = TranslateLanguage(details->getLanguage());
575
576 // Don't support optimized code for now, DebugInfoPDB does not return this
577 // information.
578 LazyBool optimized = eLazyBoolNo;
579 auto result = std::make_shared<CompileUnit>(
580 m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized);
581 m_comp_units.insert(std::make_pair(id, result));
582 return result;
Zachary Turner42dff792016-04-15 00:21:26 +0000583}
584
Kate Stoneb9c1b512016-09-06 20:57:50 +0000585bool SymbolFilePDB::ParseCompileUnitLineTable(
586 const lldb_private::SymbolContext &sc, uint32_t match_line) {
587 auto global = m_session_up->getGlobalScope();
588 auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
589 sc.comp_unit->GetID());
Zachary Turner42dff792016-04-15 00:21:26 +0000590
Kate Stoneb9c1b512016-09-06 20:57:50 +0000591 // LineEntry needs the *index* of the file into the list of support files
592 // returned by
593 // ParseCompileUnitSupportFiles. But the underlying SDK gives us a globally
594 // unique
595 // idenfitifier in the namespace of the PDB. So, we have to do a mapping so
596 // that we
597 // can hand out indices.
598 llvm::DenseMap<uint32_t, uint32_t> index_map;
599 BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);
600 auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000601
Kate Stoneb9c1b512016-09-06 20:57:50 +0000602 // Find contributions to `cu` from all source and header files.
603 std::string path = sc.comp_unit->GetPath();
604 auto files = m_session_up->getSourceFilesForCompiland(*cu);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000605
Kate Stoneb9c1b512016-09-06 20:57:50 +0000606 // For each source and header file, create a LineSequence for contributions to
607 // the cu
608 // from that file, and add the sequence.
609 while (auto file = files->getNext()) {
610 std::unique_ptr<LineSequence> sequence(
611 line_table->CreateLineSequenceContainer());
612 auto lines = m_session_up->findLineNumbers(*cu, *file);
613 int entry_count = lines->getChildCount();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000614
Kate Stoneb9c1b512016-09-06 20:57:50 +0000615 uint64_t prev_addr;
616 uint32_t prev_length;
617 uint32_t prev_line;
618 uint32_t prev_source_idx;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000619
Kate Stoneb9c1b512016-09-06 20:57:50 +0000620 for (int i = 0; i < entry_count; ++i) {
621 auto line = lines->getChildAtIndex(i);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000622
Kate Stoneb9c1b512016-09-06 20:57:50 +0000623 uint64_t lno = line->getLineNumber();
624 uint64_t addr = line->getVirtualAddress();
625 uint32_t length = line->getLength();
626 uint32_t source_id = line->getSourceFileId();
627 uint32_t col = line->getColumnNumber();
628 uint32_t source_idx = index_map[source_id];
Zachary Turner74e08ca2016-03-02 22:05:52 +0000629
Kate Stoneb9c1b512016-09-06 20:57:50 +0000630 // There was a gap between the current entry and the previous entry if the
631 // addresses don't perfectly line
632 // up.
633 bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000634
Kate Stoneb9c1b512016-09-06 20:57:50 +0000635 // Before inserting the current entry, insert a terminal entry at the end
636 // of the previous entry's address
637 // range if the current entry resulted in a gap from the previous entry.
638 if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) {
639 line_table->AppendLineEntryToSequence(
640 sequence.get(), prev_addr + prev_length, prev_line, 0,
641 prev_source_idx, false, false, false, false, true);
642 }
Zachary Turner74e08ca2016-03-02 22:05:52 +0000643
Kate Stoneb9c1b512016-09-06 20:57:50 +0000644 if (ShouldAddLine(match_line, lno, length)) {
645 bool is_statement = line->isStatement();
646 bool is_prologue = false;
647 bool is_epilogue = false;
648 auto func =
649 m_session_up->findSymbolByAddress(addr, PDB_SymType::Function);
650 if (func) {
651 auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>();
652 is_prologue = (addr == prologue->getVirtualAddress());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000653
Kate Stoneb9c1b512016-09-06 20:57:50 +0000654 auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>();
655 is_epilogue = (addr == epilogue->getVirtualAddress());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000656 }
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000657
Kate Stoneb9c1b512016-09-06 20:57:50 +0000658 line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col,
659 source_idx, is_statement, false,
660 is_prologue, is_epilogue, false);
661 }
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000662
Kate Stoneb9c1b512016-09-06 20:57:50 +0000663 prev_addr = addr;
664 prev_length = length;
665 prev_line = lno;
666 prev_source_idx = source_idx;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000667 }
668
Kate Stoneb9c1b512016-09-06 20:57:50 +0000669 if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) {
670 // The end is always a terminal entry, so insert it regardless.
671 line_table->AppendLineEntryToSequence(
672 sequence.get(), prev_addr + prev_length, prev_line, 0,
673 prev_source_idx, false, false, false, false, true);
674 }
675
676 line_table->InsertSequence(sequence.release());
677 }
678
679 sc.comp_unit->SetLineTable(line_table.release());
680 return true;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000681}
682
Kate Stoneb9c1b512016-09-06 20:57:50 +0000683void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
684 const PDBSymbolCompiland &cu,
685 llvm::DenseMap<uint32_t, uint32_t> &index_map) const {
686 // This is a hack, but we need to convert the source id into an index into the
687 // support
688 // files array. We don't want to do path comparisons to avoid basename / full
689 // path
690 // issues that may or may not even be a problem, so we use the globally unique
691 // source
692 // file identifiers. Ideally we could use the global identifiers everywhere,
693 // but LineEntry
694 // currently assumes indices.
695 auto source_files = m_session_up->getSourceFilesForCompiland(cu);
696 int index = 0;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000697
Kate Stoneb9c1b512016-09-06 20:57:50 +0000698 while (auto file = source_files->getNext()) {
699 uint32_t source_id = file->getUniqueId();
700 index_map[source_id] = index++;
701 }
Zachary Turner74e08ca2016-03-02 22:05:52 +0000702}