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/llvm-ar/llvm-ar.cpp | |
| 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/llvm-ar/llvm-ar.cpp')
| -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) { | 

