diff options
author | Owen Reynolds <gbreynoo@gmail.com> | 2019-06-03 15:26:07 +0000 |
---|---|---|
committer | Owen Reynolds <gbreynoo@gmail.com> | 2019-06-03 15:26:07 +0000 |
commit | fade9cbed76343c1e63657c4d425d3c47b0d73bf (patch) | |
tree | 69c8445c92630c2ad783aeacd08f18d71a45b038 /llvm/lib/Object/ArchiveWriter.cpp | |
parent | dab879d7c805562debea149e6d2c17839405c71b (diff) | |
download | bcm5719-llvm-fade9cbed76343c1e63657c4d425d3c47b0d73bf.tar.gz bcm5719-llvm-fade9cbed76343c1e63657c4d425d3c47b0d73bf.zip |
[llvm-ar] Fix relative thin archive path handling
This fixes some thin archive relative path issues, paths are shortened where possible and paths are output correctly when using the display table command.
Differential Revision: https://reviews.llvm.org/D59491
llvm-svn: 362407
Diffstat (limited to 'llvm/lib/Object/ArchiveWriter.cpp')
-rw-r--r-- | llvm/lib/Object/ArchiveWriter.cpp | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index 849d2835772..68c40054bb9 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -494,29 +494,46 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, } namespace llvm { + +static ErrorOr<SmallString<128>> canonicalizePath(StringRef P) { + SmallString<128> Ret = P; + std::error_code Err = sys::fs::make_absolute(Ret); + if (Err) + return Err; + sys::path::remove_dots(Ret, /*removedotdot*/ true); + return Ret; +} + // Compute the relative path from From to To. -std::string computeArchiveRelativePath(StringRef From, StringRef To) { - if (sys::path::is_absolute(From) || sys::path::is_absolute(To)) - return To; - - StringRef DirFrom = sys::path::parent_path(From); - auto FromI = sys::path::begin(DirFrom); - auto ToI = sys::path::begin(To); - while (*FromI == *ToI) { - ++FromI; - ++ToI; - } +Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) { + ErrorOr<SmallString<128>> PathToOrErr = canonicalizePath(To); + ErrorOr<SmallString<128>> DirFromOrErr = canonicalizePath(From); + if (!PathToOrErr || !DirFromOrErr) + return errorCodeToError(std::error_code(errno, std::generic_category())); + + const SmallString<128> &PathTo = *PathToOrErr; + const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr); + + // Can't construct a relative path between different roots + if (sys::path::root_name(PathTo) != sys::path::root_name(DirFrom)) + return sys::path::convert_to_slash(PathTo); + + // Skip common prefixes + auto FromTo = + std::mismatch(sys::path::begin(DirFrom), sys::path::end(DirFrom), + sys::path::begin(PathTo), sys::path::end(PathTo)); + auto FromI = FromTo.first; + auto ToI = FromTo.second; + // Construct relative path SmallString<128> Relative; for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) - sys::path::append(Relative, ".."); + sys::path::append(Relative, sys::path::Style::posix, ".."); - for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI) - sys::path::append(Relative, *ToI); + for (auto ToE = sys::path::end(PathTo); ToI != ToE; ++ToI) + sys::path::append(Relative, sys::path::Style::posix, *ToI); - // Replace backslashes with slashes so that the path is portable between *nix - // and Windows. - return sys::path::convert_to_slash(Relative); + return Relative.str(); } Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, |