diff options
| author | Jordan Rupprecht <rupprecht@google.com> | 2019-02-07 16:41:06 +0000 |
|---|---|---|
| committer | Jordan Rupprecht <rupprecht@google.com> | 2019-02-07 16:41:06 +0000 |
| commit | bf990ab5aab03aa0aac53c9ef47ef264307804ed (patch) | |
| tree | 2741b685b47afa28bba455256956be1f837cca75 /llvm/tools | |
| parent | b88144e4babdb1acc2694010de377f826242e731 (diff) | |
| download | bcm5719-llvm-bf990ab5aab03aa0aac53c9ef47ef264307804ed.tar.gz bcm5719-llvm-bf990ab5aab03aa0aac53c9ef47ef264307804ed.zip | |
[llvm-ar][libObject] Fix relative paths when nesting thin archives.
Summary:
When adding one thin archive to another, we currently chop off the relative path to the flattened members. For instance, when adding `foo/child.a` (which contains `x.txt`) to `parent.a`, when flattening it we should add it as `foo/x.txt` (which exists) instead of `x.txt` (which does not exist).
As a note, this also undoes the `IsNew` parameter of handling relative paths in r288280. The unit test there still passes.
This was reported as part of testing the kernel build with llvm-ar: https://patchwork.kernel.org/patch/10767545/ (see the second point).
Reviewers: mstorsjo, pcc, ruiu, davide, david2050
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57842
llvm-svn: 353424
Diffstat (limited to 'llvm/tools')
| -rw-r--r-- | llvm/tools/llvm-ar/llvm-ar.cpp | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index 0119ec502e5..6e0be0a8158 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -193,6 +193,9 @@ static std::string ArchiveName; // on the command line. static std::vector<StringRef> Members; +// Static buffer to hold StringRefs. +static BumpPtrAllocator Alloc; + // Extract the member filename from the command line for the [relpos] argument // associated with a, b, and i modifiers static void getRelPos() { @@ -537,6 +540,35 @@ static void performReadOperation(ArchiveOperation Operation, exit(1); } +// Compute the relative path from From to To. +static std::string computeRelativePath(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; + } + + SmallString<128> Relative; + for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) + sys::path::append(Relative, ".."); + + for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI) + sys::path::append(Relative, *ToI); + +#ifdef _WIN32 + // Replace backslashes with slashes so that the path is portable between *nix + // and Windows. + std::replace(Relative.begin(), Relative.end(), '\\', '/'); +#endif + + return Relative.str(); +} + static void addChildMember(std::vector<NewArchiveMember> &Members, const object::Archive::Child &M, bool FlattenArchive = false) { @@ -545,6 +577,15 @@ static void addChildMember(std::vector<NewArchiveMember> &Members, Expected<NewArchiveMember> NMOrErr = NewArchiveMember::getOldMember(M, Deterministic); failIfError(NMOrErr.takeError()); + // If the child member we're trying to add is thin, use the path relative to + // the archive it's in, so the file resolves correctly. + if (Thin && FlattenArchive) { + StringSaver Saver(Alloc); + Expected<std::string> FileNameOrErr = M.getFullName(); + failIfError(FileNameOrErr.takeError()); + NMOrErr->MemberName = + Saver.save(computeRelativePath(ArchiveName, *FileNameOrErr)); + } if (FlattenArchive && identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) { Expected<std::string> FileNameOrErr = M.getFullName(); @@ -568,6 +609,13 @@ static void addMember(std::vector<NewArchiveMember> &Members, Expected<NewArchiveMember> NMOrErr = NewArchiveMember::getFile(FileName, Deterministic); failIfError(NMOrErr.takeError(), FileName); + StringSaver Saver(Alloc); + // For regular archives, use the basename of the object path for the member + // name. For thin archives, use the full relative paths so the file resolves + // correctly. + NMOrErr->MemberName = + Thin ? Saver.save(computeRelativePath(ArchiveName, FileName)) + : sys::path::filename(NMOrErr->MemberName); if (FlattenArchive && identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) { object::Archive &Lib = readLibrary(FileName); @@ -581,8 +629,6 @@ static void addMember(std::vector<NewArchiveMember> &Members, return; } } - // Use the basename of the object path for the member name. - NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName); Members.push_back(std::move(*NMOrErr)); } @@ -672,7 +718,7 @@ computeNewArchiveMembers(ArchiveOperation Operation, computeInsertAction(Operation, Child, Name, MemberI); switch (Action) { case IA_AddOldMember: - addChildMember(Ret, Child); + addChildMember(Ret, Child, /*FlattenArchive=*/Thin); break; case IA_AddNewMember: addMember(Ret, *MemberI); @@ -680,7 +726,7 @@ computeNewArchiveMembers(ArchiveOperation Operation, case IA_Delete: break; case IA_MoveOldMember: - addChildMember(Moved, Child); + addChildMember(Moved, Child, /*FlattenArchive=*/Thin); break; case IA_MoveNewMember: addMember(Moved, *MemberI); @@ -899,7 +945,7 @@ static void runMRIScript() { { Error Err = Error::success(); for (auto &Member : Lib.children(Err)) - addChildMember(NewMembers, Member); + addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin); failIfError(std::move(Err)); } break; @@ -951,7 +997,6 @@ static bool handleGenericOption(StringRef arg) { static int ar_main(int argc, char **argv) { SmallVector<const char *, 0> Argv(argv, argv + argc); - BumpPtrAllocator Alloc; StringSaver Saver(Alloc); cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv); for (size_t i = 1; i < Argv.size(); ++i) { |

