Index: llvm/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/tools/dsymutil/DwarfLinker.cpp +++ llvm/tools/dsymutil/DwarfLinker.cpp @@ -100,6 +100,34 @@ namespace { +/// Small helper that resolves and caches file paths. This helps reduce the +/// number of calls to realpath which is expensive. +class CachedPathResolver { +public: + /// Resolve a path by calling realpath and cache its result. The returned + /// StringRef is interned in the given \p StringPool. + StringRef resolve(std::string Path, NonRelocatableStringpool &StringPool) { + StringRef FileName = sys::path::filename(Path); + SmallString<256> ParentPath = sys::path::parent_path(Path); + + // If the ParentPath has not yet been resolved, resolve and cache it for + // future look-ups. + if (!ResolvedPaths.count(ParentPath)) { + SmallString<256> RealPath; + sys::fs::real_path(ParentPath, RealPath); + ResolvedPaths.insert({ParentPath, StringRef(RealPath).str()}); + } + + // Join the file name again with the resolved path. + SmallString<256> ResolvedPath(ResolvedPaths[ParentPath]); + sys::path::append(ResolvedPath, FileName); + return StringPool.internString(ResolvedPath); + } + +private: + StringMap ResolvedPaths; +}; + /// Retrieve the section named \a SecName in \a Obj. /// /// To accommodate for platform discrepancies, the name passed should be @@ -234,6 +262,9 @@ DeclContext Root; DeclContext::Map Contexts; + /// Cache resolved paths from the line table. + CachedPathResolver PathResolver; + public: /// Get the child of \a Context described by \a DIE in \a Unit. The /// required strings will be interned in \a StringPool. @@ -428,21 +459,6 @@ const std::vector &getNamespaces() const { return Namespaces; } const std::vector &getObjC() const { return ObjC; } - /// Get the full path for file \a FileNum in the line table - StringRef getResolvedPath(unsigned FileNum) { - if (FileNum >= ResolvedPaths.size()) - return StringRef(); - return ResolvedPaths[FileNum]; - } - - /// Set the fully resolved path for the line-table's file \a FileNum - /// to \a Path. - void setResolvedPath(unsigned FileNum, StringRef Path) { - if (ResolvedPaths.size() <= FileNum) - ResolvedPaths.resize(FileNum + 1); - ResolvedPaths[FileNum] = Path; - } - private: DWARFUnit &OrigUnit; unsigned ID; @@ -493,12 +509,6 @@ std::vector ObjC; /// @} - /// Cached resolved paths from the line table. - /// Note, the StringRefs here point in to the intern (uniquing) string pool. - /// This means that a StringRef returned here doesn't need to then be uniqued - /// for the purposes of getting a unique address for each string. - std::vector ResolvedPaths; - /// Is this unit subject to the ODR rule? bool HasODR; @@ -1933,32 +1943,16 @@ if (!Name && Tag == dwarf::DW_TAG_namespace) FileNum = 1; - // FIXME: Passing U.getOrigUnit().getCompilationDir() - // instead of "" would allow more uniquing, but for now, do - // it this way to match dsymutil-classic. if (LT->hasFileAtIndex(FileNum)) { + std::string File; Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0); - // Cache the resolved paths, because calling realpath is expansive. - StringRef ResolvedPath = U.getResolvedPath(FileNum); - if (!ResolvedPath.empty()) { - FileRef = ResolvedPath; - } else { - std::string File; - bool gotFileName = - LT->getFileNameByIndex(FileNum, "", - DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, - File); - (void)gotFileName; - assert(gotFileName && "Must get file name from line table"); -#ifdef HAVE_REALPATH - char RealPath[PATH_MAX + 1]; - RealPath[PATH_MAX] = 0; - if (::realpath(File.c_str(), RealPath)) - File = RealPath; -#endif - FileRef = StringPool.internString(File); - U.setResolvedPath(FileNum, FileRef); - } + bool FoundFile = LT->getFileNameByIndex( + FileNum, U.getOrigUnit().getCompilationDir(), + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File); + (void)FoundFile; + assert(FoundFile && "Must get file name from line table"); + FileRef = + StringPool.internString(PathResolver.resolve(File, StringPool)); } } }