Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -319,6 +319,9 @@ static lldb::LanguageType GetLanguage(DWARFUnit &unit); + typedef std::pair FileSpecMapKey; + typedef std::map FileSpecMap; + protected: typedef llvm::DenseMap DIEToTypePtr; @@ -517,6 +520,7 @@ llvm::DenseMap m_type_unit_support_files; std::vector m_lldb_cu_to_dwarf_unit; + FileSpecMap m_file_spec_map; }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARF_H Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -224,6 +224,7 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style, + SymbolFileDWARF::FileSpecMap &file_spec_map, llvm::StringRef compile_dir = {}) { FileSpecList support_files; size_t first_file = 0; @@ -237,13 +238,32 @@ const size_t number_of_files = prologue.FileNames.size(); for (size_t idx = first_file; idx <= number_of_files; ++idx) { - std::string remapped_file; - if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) - if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file)) - remapped_file = std::move(*file_path); + FileSpec remapped_file; + // Constructing the paths and then validating when constructing the FileSpec + // has proven to be expensive in large C++ projects with lots of include + // files, so first we check if we've cached the FileSpec. + auto entry = prologue.getFileNameEntry(idx); + std::string includeDir; + includeDir += prologue.getIncludeDirectoryFromEntry( + entry, llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); + SymbolFileDWARF::FileSpecMapKey key = {includeDir, + *(entry.Name.getAsCString())}; + auto map_entry = file_spec_map.find(key); + if (map_entry != file_spec_map.end()) { + remapped_file = map_entry->second; + } else if (auto file_path = + GetFileByIndex(prologue, idx, compile_dir, style)) { + std::string remapped_file_name; + if (module->RemapSourceFile(llvm::StringRef(*file_path), + remapped_file_name)) + remapped_file = FileSpec(remapped_file_name, style); + else + remapped_file = FileSpec(std::move(*file_path), style); + file_spec_map.emplace(key, remapped_file); + } // Unconditionally add an entry, so the indices match up. - support_files.EmplaceBack(remapped_file, style); + support_files.EmplaceBack(remapped_file); } return support_files; @@ -896,7 +916,7 @@ comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue( comp_unit.GetModule(), prologue, dwarf_cu->GetPathStyle(), - dwarf_cu->GetCompilationDirectory().GetCString())); + m_file_spec_map, dwarf_cu->GetCompilationDirectory().GetCString())); return true; } @@ -941,8 +961,9 @@ if (error) { report(std::move(error)); } else { - list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), - prologue, tu.GetPathStyle()); + list = + ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), prologue, + tu.GetPathStyle(), m_file_spec_map); } } return list; Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -118,6 +118,9 @@ /// index. const llvm::DWARFDebugLine::FileNameEntry & getFileNameEntry(uint64_t Index) const; + StringRef getIncludeDirectoryFromEntry( + const llvm::DWARFDebugLine::FileNameEntry &Entry, + DILineInfoSpecifier::FileLineInfoKind Kind) const; bool hasFileAtIndex(uint64_t FileIndex) const; Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -1365,19 +1365,7 @@ } SmallString<16> FilePath; - StringRef IncludeDir; - // Be defensive about the contents of Entry. - if (getVersion() >= 5) { - // DirIdx 0 is the compilation directory, so don't include it for - // relative names. - if ((Entry.DirIdx != 0 || Kind != FileLineInfoKind::RelativeFilePath) && - Entry.DirIdx < IncludeDirectories.size()) - IncludeDir = IncludeDirectories[Entry.DirIdx].getAsCString().getValue(); - } else { - if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size()) - IncludeDir = - IncludeDirectories[Entry.DirIdx - 1].getAsCString().getValue(); - } + StringRef IncludeDir = getIncludeDirectoryFromEntry(Entry, Kind); // For absolute paths only, include the compilation directory of compile unit. // We know that FileName is not absolute, the only way to have an absolute @@ -1396,6 +1384,25 @@ return true; } +StringRef DWARFDebugLine::Prologue::getIncludeDirectoryFromEntry( + const llvm::DWARFDebugLine::FileNameEntry &Entry, + FileLineInfoKind Kind) const { + StringRef IncludeDir; + // Be defensive about the contents of Entry. + if (getVersion() >= 5) { + // DirIdx 0 is the compilation directory, so don't include it for + // relative names. + if ((Entry.DirIdx != 0 || Kind != FileLineInfoKind::RelativeFilePath) && + Entry.DirIdx < IncludeDirectories.size()) + IncludeDir = IncludeDirectories[Entry.DirIdx].getAsCString().getValue(); + } else { + if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size()) + IncludeDir = + IncludeDirectories[Entry.DirIdx - 1].getAsCString().getValue(); + } + return IncludeDir; +} + bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( object::SectionedAddress Address, const char *CompDir, FileLineInfoKind Kind, DILineInfo &Result) const {