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