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