blob: 9a82f4d40fd8cfc4057179c37cfec64bae76f0cd [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
23#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
24#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
25#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
26#include "llvm/DebugInfo/PDB/PDBSymbol.h"
27#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
28#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
29#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
30#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
31#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
32#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
Zachary Turner42dff792016-04-15 00:21:26 +000033#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
34#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
35#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
36
37#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
38
39#include <regex>
Zachary Turner74e08ca2016-03-02 22:05:52 +000040
41using namespace lldb_private;
42
43namespace
44{
45 lldb::LanguageType TranslateLanguage(llvm::PDB_Lang lang)
46 {
47 switch (lang)
48 {
49 case llvm::PDB_Lang::Cpp:
50 return lldb::LanguageType::eLanguageTypeC_plus_plus;
51 case llvm::PDB_Lang::C:
52 return lldb::LanguageType::eLanguageTypeC;
53 default:
54 return lldb::LanguageType::eLanguageTypeUnknown;
55 }
56 }
Zachary Turner7e8c7be2016-03-10 00:06:26 +000057
58 bool
59 ShouldAddLine(uint32_t requested_line, uint32_t actual_line, uint32_t addr_length)
60 {
61 return ((requested_line == 0 || actual_line == requested_line) && addr_length > 0);
62 }
Zachary Turner74e08ca2016-03-02 22:05:52 +000063}
64
65void
66SymbolFilePDB::Initialize()
67{
68 PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
69 DebuggerInitialize);
70}
71
72void
73SymbolFilePDB::Terminate()
74{
75 PluginManager::UnregisterPlugin(CreateInstance);
76}
77
78void
79SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger)
80{
81}
82
83lldb_private::ConstString
84SymbolFilePDB::GetPluginNameStatic()
85{
86 static ConstString g_name("pdb");
87 return g_name;
88}
89
90const char *
91SymbolFilePDB::GetPluginDescriptionStatic()
92{
93 return "Microsoft PDB debug symbol file reader.";
94}
95
96lldb_private::SymbolFile *
97SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file)
98{
99 return new SymbolFilePDB(obj_file);
100}
101
102SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)
103 : SymbolFile(object_file), m_cached_compile_unit_count(0)
104{
105}
106
107SymbolFilePDB::~SymbolFilePDB()
108{
109}
110
111uint32_t
112SymbolFilePDB::CalculateAbilities()
113{
114 if (!m_session_up)
115 {
116 // Lazily load and match the PDB file, but only do this once.
117 std::string exePath = m_obj_file->GetFileSpec().GetPath();
118 auto error = llvm::loadDataForEXE(llvm::PDB_ReaderType::DIA, llvm::StringRef(exePath), m_session_up);
119 if (error != llvm::PDB_ErrorCode::Success)
120 return 0;
121 }
122 return CompileUnits | LineTables;
123}
124
125void
126SymbolFilePDB::InitializeObject()
127{
128 lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
129 m_session_up->setLoadAddress(obj_load_address);
Zachary Turner42dff792016-04-15 00:21:26 +0000130
131 TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
132 ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
133 m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(type_system, clang_type_system->GetTranslationUnitDecl());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000134}
135
136uint32_t
137SymbolFilePDB::GetNumCompileUnits()
138{
139 if (m_cached_compile_unit_count == 0)
140 {
141 auto global = m_session_up->getGlobalScope();
142 auto compilands = global->findAllChildren<llvm::PDBSymbolCompiland>();
143 m_cached_compile_unit_count = compilands->getChildCount();
144
145 // The linker can inject an additional "dummy" compilation unit into the PDB.
146 // Ignore this special compile unit for our purposes, if it is there. It is
147 // always the last one.
148 auto last_cu = compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
149 std::string name = last_cu->getName();
150 if (name == "* Linker *")
151 --m_cached_compile_unit_count;
152 }
153 return m_cached_compile_unit_count;
154}
155
156lldb::CompUnitSP
157SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index)
158{
159 auto global = m_session_up->getGlobalScope();
160 auto compilands = global->findAllChildren<llvm::PDBSymbolCompiland>();
161 auto cu = compilands->getChildAtIndex(index);
162
163 uint32_t id = cu->getSymIndexId();
164
165 return ParseCompileUnitForSymIndex(id);
166}
167
168lldb::LanguageType
169SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc)
170{
171 // What fields should I expect to be filled out on the SymbolContext? Is it
172 // safe to assume that `sc.comp_unit` is valid?
173 if (!sc.comp_unit)
174 return lldb::eLanguageTypeUnknown;
175
176 auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(sc.comp_unit->GetID());
177 if (!cu)
178 return lldb::eLanguageTypeUnknown;
179 auto details = cu->findOneChild<llvm::PDBSymbolCompilandDetails>();
180 if (!details)
181 return lldb::eLanguageTypeUnknown;
182 return TranslateLanguage(details->getLanguage());
183}
184
185size_t
186SymbolFilePDB::ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc)
187{
188 // TODO: Implement this
189 return size_t();
190}
191
192bool
193SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc)
194{
195 return ParseCompileUnitLineTable(sc, 0);
196}
197
198bool
199SymbolFilePDB::ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc)
200{
201 // PDB doesn't contain information about macros
202 return false;
203}
204
205bool
206SymbolFilePDB::ParseCompileUnitSupportFiles(const lldb_private::SymbolContext &sc,
207 lldb_private::FileSpecList &support_files)
208{
209 if (!sc.comp_unit)
210 return false;
211
212 // In theory this is unnecessary work for us, because all of this information is easily
213 // (and quickly) accessible from DebugInfoPDB, so caching it a second time seems like a waste.
214 // Unfortunately, there's no good way around this short of a moderate refactor, since SymbolVendor
215 // depends on being able to cache this list.
216 auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(sc.comp_unit->GetID());
217 if (!cu)
218 return false;
219 auto files = m_session_up->getSourceFilesForCompiland(*cu);
220 if (!files || files->getChildCount() == 0)
221 return false;
222
223 while (auto file = files->getNext())
224 {
225 FileSpec spec(file->getFileName(), false);
226 support_files.Append(spec);
227 }
228 return true;
229}
230
231bool
232SymbolFilePDB::ParseImportedModules(const lldb_private::SymbolContext &sc,
233 std::vector<lldb_private::ConstString> &imported_modules)
234{
235 // PDB does not yet support module debug info
236 return false;
237}
238
239size_t
240SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc)
241{
242 // TODO: Implement this
243 return size_t();
244}
245
246size_t
247SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc)
248{
249 // TODO: Implement this
250 return size_t();
251}
252
253size_t
254SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc)
255{
256 // TODO: Implement this
257 return size_t();
258}
259
260lldb_private::Type *
261SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid)
262{
Zachary Turner42dff792016-04-15 00:21:26 +0000263 auto find_result = m_types.find(type_uid);
264 if (find_result != m_types.end())
265 return find_result->second.get();
266
267 TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
268 ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
269 if (!clang_type_system)
270 return nullptr;
271 PDBASTParser *pdb = llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
272 if (!pdb)
273 return nullptr;
274
275 auto pdb_type = m_session_up->getSymbolById(type_uid);
276 if (pdb_type == nullptr)
277 return nullptr;
278
279 lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
280 m_types.insert(std::make_pair(type_uid, result));
281 return result.get();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000282}
283
284bool
285SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type)
286{
287 // TODO: Implement this
288 return false;
289}
290
291lldb_private::CompilerDecl
292SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid)
293{
294 return lldb_private::CompilerDecl();
295}
296
297lldb_private::CompilerDeclContext
298SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid)
299{
Zachary Turner42dff792016-04-15 00:21:26 +0000300 // PDB always uses the translation unit decl context for everything. We can improve this later
301 // but it's not easy because PDB doesn't provide a high enough level of type fidelity in this area.
302 return *m_tu_decl_ctx_up;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000303}
304
305lldb_private::CompilerDeclContext
306SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid)
307{
Zachary Turner42dff792016-04-15 00:21:26 +0000308 return *m_tu_decl_ctx_up;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000309}
310
311void
312SymbolFilePDB::ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)
313{
314}
315
316uint32_t
317SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, uint32_t resolve_scope,
318 lldb_private::SymbolContext &sc)
319{
320 return uint32_t();
321}
322
323uint32_t
324SymbolFilePDB::ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
325 uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list)
326{
327 if (resolve_scope & lldb::eSymbolContextCompUnit)
328 {
329 // Locate all compilation units with line numbers referencing the specified file. For example, if
330 // `file_spec` is <vector>, then this should return all source files and header files that reference
331 // <vector>, either directly or indirectly.
332 auto compilands =
333 m_session_up->findCompilandsForSourceFile(file_spec.GetPath(), llvm::PDB_NameSearchFlags::NS_CaseInsensitive);
334
335 // For each one, either find get its previously parsed data, or parse it afresh and add it to
336 // the symbol context list.
337 while (auto compiland = compilands->getNext())
338 {
339 // If we're not checking inlines, then don't add line information for this file unless the FileSpec
340 // matches.
341 if (!check_inlines)
342 {
343 // `getSourceFileName` returns the basename of the original source file used to generate this compiland.
344 // It does not return the full path. Currently the only way to get that is to do a basename lookup to
345 // get the IPDBSourceFile, but this is ambiguous in the case of two source files with the same name
346 // contributing to the same compiland. This is a moderately extreme edge case, so we consider this ok
347 // for now, although we need to find a long term solution.
348 std::string source_file = compiland->getSourceFileName();
349 auto pdb_file = m_session_up->findOneSourceFile(compiland.get(), source_file,
350 llvm::PDB_NameSearchFlags::NS_CaseInsensitive);
351 source_file = pdb_file->getFileName();
352 FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows);
353 if (!file_spec.FileEquals(this_spec))
354 continue;
355 }
356
357 SymbolContext sc;
358 auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId());
359 sc.comp_unit = cu.get();
360 sc.module_sp = cu->GetModule();
361 sc_list.Append(sc);
362
363 // If we were asked to resolve line entries, add all entries to the line table that match the requested
364 // line (or all lines if `line` == 0)
365 if (resolve_scope & lldb::eSymbolContextLineEntry)
366 ParseCompileUnitLineTable(sc, line);
367 }
368 }
369 return sc_list.GetSize();
370}
371
372uint32_t
373SymbolFilePDB::FindGlobalVariables(const lldb_private::ConstString &name,
374 const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
375 uint32_t max_matches, lldb_private::VariableList &variables)
376{
377 return uint32_t();
378}
379
380uint32_t
381SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex, bool append, uint32_t max_matches,
382 lldb_private::VariableList &variables)
383{
384 return uint32_t();
385}
386
387uint32_t
388SymbolFilePDB::FindFunctions(const lldb_private::ConstString &name,
389 const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask,
390 bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list)
391{
392 return uint32_t();
393}
394
395uint32_t
396SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex, bool include_inlines, bool append,
397 lldb_private::SymbolContextList &sc_list)
398{
399 return uint32_t();
400}
401
402void
403SymbolFilePDB::GetMangledNamesForFunction(const std::string &scope_qualified_name,
404 std::vector<lldb_private::ConstString> &mangled_names)
405{
406}
407
408uint32_t
409SymbolFilePDB::FindTypes(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name,
410 const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches,
411 llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
412 lldb_private::TypeMap &types)
413{
Zachary Turner42dff792016-04-15 00:21:26 +0000414 if (!append)
415 types.Clear();
416 if (!name)
417 return 0;
418
419 searched_symbol_files.clear();
420 searched_symbol_files.insert(this);
421
422 std::string name_str = name.AsCString();
423
424 // If this might be a regex, we have to return EVERY symbol and process them one by one, which is going
425 // to destroy performance on large PDB files. So try really hard not to use a regex match.
426 if (name_str.find_first_of("[]?*.-+\\") != std::string::npos)
427 FindTypesByRegex(name_str, max_matches, types);
428 else
429 FindTypesByName(name_str, max_matches, types);
430 return types.GetSize();
431}
432
433void
434SymbolFilePDB::FindTypesByRegex(const std::string &regex, uint32_t max_matches, lldb_private::TypeMap &types)
435{
436 // When searching by regex, we need to go out of our way to limit the search space as much as possible, since
437 // the way this is implemented is by searching EVERYTHING in the PDB and manually doing a regex compare. PDB
438 // library isn't optimized for regex searches or searches across multiple symbol types at the same time, so the
439 // best we can do is to search enums, then typedefs, then classes one by one, and do a regex compare against all
440 // of them.
441 llvm::PDB_SymType tags_to_search[] = {llvm::PDB_SymType::Enum, llvm::PDB_SymType::Typedef, llvm::PDB_SymType::UDT};
442 auto global = m_session_up->getGlobalScope();
443 std::unique_ptr<llvm::IPDBEnumSymbols> results;
444
445 std::regex re(regex);
446
447 uint32_t matches = 0;
448
449 for (auto tag : tags_to_search)
450 {
451 results = global->findAllChildren(tag);
452 while (auto result = results->getNext())
453 {
454 if (max_matches > 0 && matches >= max_matches)
455 break;
456
457 std::string type_name;
458 if (auto enum_type = llvm::dyn_cast<llvm::PDBSymbolTypeEnum>(result.get()))
459 type_name = enum_type->getName();
460 else if (auto typedef_type = llvm::dyn_cast<llvm::PDBSymbolTypeTypedef>(result.get()))
461 type_name = typedef_type->getName();
462 else if (auto class_type = llvm::dyn_cast<llvm::PDBSymbolTypeUDT>(result.get()))
463 type_name = class_type->getName();
464 else
465 {
466 // We're only looking for types that have names. Skip symbols, as well as
467 // unnamed types such as arrays, pointers, etc.
468 continue;
469 }
470
471 if (!std::regex_match(type_name, re))
472 continue;
473
474 // This should cause the type to get cached and stored in the `m_types` lookup.
475 if (!ResolveTypeUID(result->getSymIndexId()))
476 continue;
477
478 auto iter = m_types.find(result->getSymIndexId());
479 if (iter == m_types.end())
480 continue;
481 types.Insert(iter->second);
482 ++matches;
483 }
484 }
485}
486
487void
488SymbolFilePDB::FindTypesByName(const std::string &name, uint32_t max_matches, lldb_private::TypeMap &types)
489{
490 auto global = m_session_up->getGlobalScope();
491 std::unique_ptr<llvm::IPDBEnumSymbols> results;
492 results = global->findChildren(llvm::PDB_SymType::None, name.c_str(), llvm::PDB_NameSearchFlags::NS_Default);
493
494 uint32_t matches = 0;
495
496 while (auto result = results->getNext())
497 {
498 if (max_matches > 0 && matches >= max_matches)
499 break;
500 switch (result->getSymTag())
501 {
502 case llvm::PDB_SymType::Enum:
503 case llvm::PDB_SymType::UDT:
504 case llvm::PDB_SymType::Typedef:
505 break;
506 default:
507 // We're only looking for types that have names. Skip symbols, as well as
508 // unnamed types such as arrays, pointers, etc.
509 continue;
510 }
511
512 // This should cause the type to get cached and stored in the `m_types` lookup.
513 if (!ResolveTypeUID(result->getSymIndexId()))
514 continue;
515
516 auto iter = m_types.find(result->getSymIndexId());
517 if (iter == m_types.end())
518 continue;
519 types.Insert(iter->second);
520 ++matches;
521 }
Zachary Turner74e08ca2016-03-02 22:05:52 +0000522}
523
524size_t
Zachary Turner42dff792016-04-15 00:21:26 +0000525SymbolFilePDB::FindTypes(const std::vector<lldb_private::CompilerContext> &contexts, bool append,
Zachary Turner74e08ca2016-03-02 22:05:52 +0000526 lldb_private::TypeMap &types)
527{
Zachary Turner42dff792016-04-15 00:21:26 +0000528 return 0;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000529}
530
531lldb_private::TypeList *
532SymbolFilePDB::GetTypeList()
533{
534 return nullptr;
535}
536
537size_t
538SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, uint32_t type_mask,
539 lldb_private::TypeList &type_list)
540{
541 return size_t();
542}
543
544lldb_private::TypeSystem *
545SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language)
546{
547 auto type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
548 if (type_system)
549 type_system->SetSymbolFile(this);
550 return type_system;
551}
552
553lldb_private::CompilerDeclContext
554SymbolFilePDB::FindNamespace(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name,
555 const lldb_private::CompilerDeclContext *parent_decl_ctx)
556{
557 return lldb_private::CompilerDeclContext();
558}
559
560lldb_private::ConstString
561SymbolFilePDB::GetPluginName()
562{
563 static ConstString g_name("pdb");
564 return g_name;
565}
566
567uint32_t
568SymbolFilePDB::GetPluginVersion()
569{
570 return 1;
571}
572
Zachary Turner42dff792016-04-15 00:21:26 +0000573llvm::IPDBSession &
574SymbolFilePDB::GetPDBSession()
575{
576 return *m_session_up;
577}
578
579const llvm::IPDBSession &
580SymbolFilePDB::GetPDBSession() const
581{
582 return *m_session_up;
583}
584
Zachary Turner74e08ca2016-03-02 22:05:52 +0000585lldb::CompUnitSP
586SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id)
587{
588 auto found_cu = m_comp_units.find(id);
589 if (found_cu != m_comp_units.end())
590 return found_cu->second;
591
592 auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(id);
593
594 // `getSourceFileName` returns the basename of the original source file used to generate this compiland. It does
595 // not return the full path. Currently the only way to get that is to do a basename lookup to get the
596 // IPDBSourceFile, but this is ambiguous in the case of two source files with the same name contributing to the
597 // same compiland. This is a moderately extreme edge case, so we consider this ok for now, although we need to find
598 // a long term solution.
599 auto file = m_session_up->findOneSourceFile(cu.get(), cu->getSourceFileName(),
600 llvm::PDB_NameSearchFlags::NS_CaseInsensitive);
601 std::string path = file->getFileName();
602
603 lldb::LanguageType lang;
604 auto details = cu->findOneChild<llvm::PDBSymbolCompilandDetails>();
605 if (!details)
606 lang = lldb::eLanguageTypeC_plus_plus;
607 else
608 lang = TranslateLanguage(details->getLanguage());
609
610 // Don't support optimized code for now, DebugInfoPDB does not return this information.
611 bool optimized = false;
612 auto result = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized);
613 m_comp_units.insert(std::make_pair(id, result));
614 return result;
615}
616
617bool
618SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc, uint32_t match_line)
619{
620 auto global = m_session_up->getGlobalScope();
621 auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(sc.comp_unit->GetID());
622
623 // LineEntry needs the *index* of the file into the list of support files returned by
624 // ParseCompileUnitSupportFiles. But the underlying SDK gives us a globally unique
625 // idenfitifier in the namespace of the PDB. So, we have to do a mapping so that we
626 // can hand out indices.
Zachary Turner42dff792016-04-15 00:21:26 +0000627 llvm::DenseMap<uint32_t, uint32_t> index_map;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000628 BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);
629 auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
630
631 // Find contributions to `cu` from all source and header files.
632 std::string path = sc.comp_unit->GetPath();
633 auto files = m_session_up->getSourceFilesForCompiland(*cu);
634
635 // For each source and header file, create a LineSequence for contributions to the cu
636 // from that file, and add the sequence.
637 while (auto file = files->getNext())
638 {
639 std::unique_ptr<LineSequence> sequence(line_table->CreateLineSequenceContainer());
640 auto lines = m_session_up->findLineNumbers(*cu, *file);
641 int entry_count = lines->getChildCount();
642
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000643 uint64_t prev_addr;
644 uint32_t prev_length;
645 uint32_t prev_line;
646 uint32_t prev_source_idx;
647
Zachary Turner74e08ca2016-03-02 22:05:52 +0000648 for (int i = 0; i < entry_count; ++i)
649 {
650 auto line = lines->getChildAtIndex(i);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000651
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000652 uint64_t lno = line->getLineNumber();
653 uint64_t addr = line->getVirtualAddress();
654 uint32_t length = line->getLength();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000655 uint32_t source_id = line->getSourceFileId();
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000656 uint32_t col = line->getColumnNumber();
Zachary Turner74e08ca2016-03-02 22:05:52 +0000657 uint32_t source_idx = index_map[source_id];
658
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000659 // There was a gap between the current entry and the previous entry if the addresses don't perfectly line
660 // up.
661 bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
662
663 // Before inserting the current entry, insert a terminal entry at the end of the previous entry's address
664 // range if the current entry resulted in a gap from the previous entry.
665 if (is_gap && ShouldAddLine(match_line, prev_line, prev_length))
Zachary Turner74e08ca2016-03-02 22:05:52 +0000666 {
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000667 line_table->AppendLineEntryToSequence(sequence.get(), prev_addr + prev_length, prev_line, 0,
668 prev_source_idx, false, false, false, false, true);
Zachary Turner74e08ca2016-03-02 22:05:52 +0000669 }
670
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000671 if (ShouldAddLine(match_line, lno, length))
672 {
673 bool is_statement = line->isStatement();
674 bool is_prologue = false;
675 bool is_epilogue = false;
676 auto func = m_session_up->findSymbolByAddress(addr, llvm::PDB_SymType::Function);
677 if (func)
678 {
679 auto prologue = func->findOneChild<llvm::PDBSymbolFuncDebugStart>();
680 is_prologue = (addr == prologue->getVirtualAddress());
681
682 auto epilogue = func->findOneChild<llvm::PDBSymbolFuncDebugEnd>();
683 is_epilogue = (addr == epilogue->getVirtualAddress());
684 }
685
686 line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col, source_idx, is_statement, false,
687 is_prologue, is_epilogue, false);
688 }
689
690 prev_addr = addr;
691 prev_length = length;
692 prev_line = lno;
693 prev_source_idx = source_idx;
Zachary Turner74e08ca2016-03-02 22:05:52 +0000694 }
Zachary Turner7e8c7be2016-03-10 00:06:26 +0000695
696 if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length))
697 {
698 // The end is always a terminal entry, so insert it regardless.
699 line_table->AppendLineEntryToSequence(sequence.get(), prev_addr + prev_length, prev_line, 0,
700 prev_source_idx, false, false, false, false, true);
701 }
702
703 line_table->InsertSequence(sequence.release());
Zachary Turner74e08ca2016-03-02 22:05:52 +0000704 }
705
706 sc.comp_unit->SetLineTable(line_table.release());
707 return true;
708}
709
710void
711SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(const llvm::PDBSymbolCompiland &cu,
Zachary Turner42dff792016-04-15 00:21:26 +0000712 llvm::DenseMap<uint32_t, uint32_t> &index_map) const
Zachary Turner74e08ca2016-03-02 22:05:52 +0000713{
714 // This is a hack, but we need to convert the source id into an index into the support
715 // files array. We don't want to do path comparisons to avoid basename / full path
716 // issues that may or may not even be a problem, so we use the globally unique source
717 // file identifiers. Ideally we could use the global identifiers everywhere, but LineEntry
718 // currently assumes indices.
719 auto source_files = m_session_up->getSourceFilesForCompiland(cu);
720 int index = 0;
721
722 while (auto file = source_files->getNext())
723 {
724 uint32_t source_id = file->getUniqueId();
725 index_map[source_id] = index++;
726 }
727}