[llvm] r362484 - [llvm-ar] Reapply Fix relative thin archive path handling

Owen Reynolds via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 4 03:13:03 PDT 2019


Author: gbreynoo
Date: Tue Jun  4 03:13:03 2019
New Revision: 362484

URL: http://llvm.org/viewvc/llvm-project?rev=362484&view=rev
Log:
[llvm-ar] Reapply Fix relative thin archive path handling

Includes a fix for an introduced build failure due to a post c++11 use of std::mismatch. 

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

Added:
    llvm/trunk/test/tools/llvm-ar/reduce-thin-path.test
    llvm/trunk/test/tools/llvm-ar/thin-archive.test
Modified:
    llvm/trunk/include/llvm/Object/ArchiveWriter.h
    llvm/trunk/lib/Object/ArchiveWriter.cpp
    llvm/trunk/lib/ToolDrivers/llvm-lib/LibDriver.cpp
    llvm/trunk/test/tools/llvm-objcopy/ELF/archive-unknown-members.test
    llvm/trunk/test/tools/llvm-readobj/thin-archive-paths.test
    llvm/trunk/tools/llvm-ar/llvm-ar.cpp

Modified: llvm/trunk/include/llvm/Object/ArchiveWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ArchiveWriter.h?rev=362484&r1=362483&r2=362484&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ArchiveWriter.h (original)
+++ llvm/trunk/include/llvm/Object/ArchiveWriter.h Tue Jun  4 03:13:03 2019
@@ -36,7 +36,7 @@ struct NewArchiveMember {
                                             bool Deterministic);
 };
 
-std::string computeArchiveRelativePath(StringRef From, StringRef To);
+Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To);
 
 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
                    bool WriteSymtab, object::Archive::Kind Kind,

Modified: llvm/trunk/lib/Object/ArchiveWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ArchiveWriter.cpp?rev=362484&r1=362483&r2=362484&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ArchiveWriter.cpp (original)
+++ llvm/trunk/lib/Object/ArchiveWriter.cpp Tue Jun  4 03:13:03 2019
@@ -494,29 +494,46 @@ computeMemberData(raw_ostream &StringTab
 }
 
 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));
+  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,

Modified: llvm/trunk/lib/ToolDrivers/llvm-lib/LibDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ToolDrivers/llvm-lib/LibDriver.cpp?rev=362484&r1=362483&r2=362484&view=diff
==============================================================================
--- llvm/trunk/lib/ToolDrivers/llvm-lib/LibDriver.cpp (original)
+++ llvm/trunk/lib/ToolDrivers/llvm-lib/LibDriver.cpp Tue Jun  4 03:13:03 2019
@@ -211,9 +211,14 @@ int llvm::libDriverMain(ArrayRef<const c
   // llvm-lib uses relative paths for both regular and thin archives, unlike
   // standard GNU ar, which only uses relative paths for thin archives and
   // basenames for regular archives.
-  for (NewArchiveMember &Member : Members)
-    Member.MemberName =
-        Saver.save(computeArchiveRelativePath(OutputPath, Member.MemberName));
+  for (NewArchiveMember &Member : Members) {
+    if (sys::path::is_relative(Member.MemberName)) {
+      Expected<std::string> PathOrErr =
+          computeArchiveRelativePath(OutputPath, Member.MemberName);
+      if (PathOrErr)
+        Member.MemberName = Saver.save(*PathOrErr);
+    }
+  }
 
   if (Error E =
           writeArchive(OutputPath, Members,

Added: llvm/trunk/test/tools/llvm-ar/reduce-thin-path.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/reduce-thin-path.test?rev=362484&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/reduce-thin-path.test (added)
+++ llvm/trunk/test/tools/llvm-ar/reduce-thin-path.test Tue Jun  4 03:13:03 2019
@@ -0,0 +1,10 @@
+RUN: rm -rf %t && mkdir -p %t/foo/bar/
+RUN: mkdir -p %t/baz/
+RUN: yaml2obj %S/Inputs/elf.yaml -o %t/elf.o
+
+RUN: cd %t && llvm-ar rTc %t/baz/internal.ar elf.o
+RUN: cd %t/foo && llvm-ar rTc %t/foo/bar/external.ar ../baz/internal.ar
+
+RUN: FileCheck -input-file=%t/foo/bar/external.ar %s
+
+CHECK: {{^}}../../elf.o/

Added: llvm/trunk/test/tools/llvm-ar/thin-archive.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/thin-archive.test?rev=362484&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/thin-archive.test (added)
+++ llvm/trunk/test/tools/llvm-ar/thin-archive.test Tue Jun  4 03:13:03 2019
@@ -0,0 +1,45 @@
+RUN: rm -rf %t && mkdir -p %t/foo/bar/
+
+RUN: yaml2obj %S/Inputs/elf.yaml -o %t/foo/elf.o
+RUN: cp %t/foo/elf.o %t/foo/bar/elf.o
+RUN: cp %t/foo/bar/elf.o %t/delete.o
+
+Test that modules can be added with absolute paths when the archive is created using an absolute path
+
+RUN: llvm-ar rTc %t/absolute-1.ar %t/foo/elf.o %t/delete.o %t/foo/bar/elf.o
+RUN: llvm-ar dT %t/absolute-1.ar delete.o
+
+RUN: FileCheck -input-file=%t/absolute-1.ar --check-prefixes=THIN,CHECK %s -DPATH=%/t/
+RUN: llvm-ar t %t/absolute-1.ar | FileCheck %s -DPATH=%/t/
+
+Test that modules can be added with absolute paths when the archive is created using a relative path
+
+RUN: llvm-ar rTc Output/%basename_t.tmp/absolute-2.ar %t/foo/elf.o %t/delete.o %t/foo/bar/elf.o
+RUN: llvm-ar dT Output/%basename_t.tmp/absolute-2.ar %t/delete.o
+
+RUN: FileCheck -input-file=%t/absolute-2.ar --check-prefixes=THIN,CHECK %s -DPATH=%/t/
+RUN: llvm-ar t %t/absolute-2.ar | FileCheck %s -DPATH=%/t/
+
+These tests must be run in %t/foo. cd %t is included on each line to make debugging this test case easier.
+
+Test that modules can be added with relative paths when the archive is created using a relative path
+
+RUN: cd %t/foo && llvm-ar rTc ../relative-1.ar elf.o ../delete.o bar/elf.o
+RUN: cd %t/foo && llvm-ar dT ../relative-1.ar delete.o
+
+RUN: FileCheck -input-file=%t/relative-1.ar --check-prefixes=THIN,CHECK %s -DPATH=
+RUN: llvm-ar t %t/relative-1.ar | FileCheck %s -DPATH=%/t/
+
+Test that modules can be added with relative paths when the archive is created using a absolute path
+
+RUN: cd %t/foo && llvm-ar rTc %t/relative-2.ar elf.o ../delete.o bar/elf.o
+RUN: cd %t/foo && llvm-ar dT %t/relative-2.ar delete.o
+
+RUN: FileCheck -input-file=%t/relative-2.ar --check-prefixes=THIN,CHECK %s -DPATH=
+RUN: llvm-ar t %t/relative-2.ar | FileCheck %s -DPATH=%/t/
+
+THIN: !<thin>
+
+CHECK-NOT: delete.o
+CHECK: {{^}}[[PATH]]foo/elf.o
+CHECK: {{^}}[[PATH]]foo/bar/elf.o

Modified: llvm/trunk/test/tools/llvm-objcopy/ELF/archive-unknown-members.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/archive-unknown-members.test?rev=362484&r1=362483&r2=362484&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/ELF/archive-unknown-members.test (original)
+++ llvm/trunk/test/tools/llvm-objcopy/ELF/archive-unknown-members.test Tue Jun  4 03:13:03 2019
@@ -23,10 +23,10 @@
 # RUN: llvm-ar rcT %t.thin1.a %t1.o %s
 # RUN: llvm-ar rcT %t.thin2.a %t2.o %s
 
-# RUN: not llvm-objcopy --strip-debug %t.thin1.a 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=THIN -DARCHIVE=%t.thin1.a -DMEMBER=%s
-# RUN: not llvm-strip --strip-debug %t.thin2.a 2>&1 \
-# RUN:   | FileCheck %s --check-prefix=THIN -DARCHIVE=%t.thin2.a -DMEMBER=%s
+# RUN: not llvm-objcopy --strip-debug %/t.thin1.a 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=THIN -DARCHIVE=%/t.thin1.a -DMEMBER=%/s
+# RUN: not llvm-strip --strip-debug %/t.thin2.a 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=THIN -DARCHIVE=%/t.thin2.a -DMEMBER=%/s
 ## Verify that the first member was not modified, if a later member could not
 ## be recognized.
 # RUN: cmp %t.o %t1.o

Modified: llvm/trunk/test/tools/llvm-readobj/thin-archive-paths.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/thin-archive-paths.test?rev=362484&r1=362483&r2=362484&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/thin-archive-paths.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/thin-archive-paths.test Tue Jun  4 03:13:03 2019
@@ -23,11 +23,11 @@
 # RUN: llvm-ar rcT c/absolute.a %t/a/b/1.o
 
 # Show that absolute paths in the file header printing are correct.
-# RUN: llvm-readobj --file-headers c/absolute.a | FileCheck %s --check-prefix=ABS -DDIR=%t
+# RUN: llvm-readobj --file-headers c/absolute.a | FileCheck %s --check-prefix=ABS -DDIR=%/t
 # ABS: File: [[DIR]]/a/b/1.o
 
 # Show that absolute paths in an error message for both archive and member are correct.
 # RUN: rm a/b/1.o
-# RUN: not llvm-readobj --file-headers %t/c/absolute.a 2>&1 | FileCheck %s --check-prefix=ERR2 -DDIR=%t
-# RUN: not llvm-readelf --file-headers %t/c/absolute.a 2>&1 | FileCheck %s --check-prefix=ERR2 -DDIR=%t
+# RUN: not llvm-readobj --file-headers %/t/c/absolute.a 2>&1 | FileCheck %s --check-prefix=ERR2 -DDIR=%/t
+# RUN: not llvm-readelf --file-headers %/t/c/absolute.a 2>&1 | FileCheck %s --check-prefix=ERR2 -DDIR=%/t
 # ERR2: error: '[[DIR]]/c/absolute.a': '[[DIR]]/a/b/1.o': {{[Nn]}}o such file or directory

Modified: llvm/trunk/tools/llvm-ar/llvm-ar.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-ar/llvm-ar.cpp?rev=362484&r1=362483&r2=362484&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-ar/llvm-ar.cpp (original)
+++ llvm/trunk/tools/llvm-ar/llvm-ar.cpp Tue Jun  4 03:13:03 2019
@@ -464,9 +464,11 @@ static void doDisplayTable(StringRef Nam
   }
 
   if (C.getParent()->isThin()) {
-    StringRef ParentDir = sys::path::parent_path(ArchiveName);
-    if (!ParentDir.empty())
-      outs() << ParentDir << '/';
+    if (!sys::path::is_absolute(Name)) {
+      StringRef ParentDir = sys::path::parent_path(ArchiveName);
+      if (!ParentDir.empty())
+        outs() << sys::path::convert_to_slash(ParentDir) << '/';
+    }
   }
   outs() << Name << "\n";
 }
@@ -593,10 +595,18 @@ static void addChildMember(std::vector<N
   // the archive it's in, so the file resolves correctly.
   if (Thin && FlattenArchive) {
     StringSaver Saver(Alloc);
-    Expected<std::string> FileNameOrErr = M.getFullName();
+    Expected<std::string> FileNameOrErr = M.getName();
     failIfError(FileNameOrErr.takeError());
-    NMOrErr->MemberName =
-        Saver.save(computeArchiveRelativePath(ArchiveName, *FileNameOrErr));
+    if (sys::path::is_absolute(*FileNameOrErr)) {
+      NMOrErr->MemberName = Saver.save(sys::path::convert_to_slash(*FileNameOrErr));
+    } else {
+      FileNameOrErr = M.getFullName();
+      failIfError(FileNameOrErr.takeError());
+      Expected<std::string> PathOrErr =
+          computeArchiveRelativePath(ArchiveName, *FileNameOrErr);
+      NMOrErr->MemberName = Saver.save(
+          PathOrErr ? *PathOrErr : sys::path::convert_to_slash(*FileNameOrErr));
+    }
   }
   if (FlattenArchive &&
       identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
@@ -625,9 +635,19 @@ static void addMember(std::vector<NewArc
   // 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(computeArchiveRelativePath(ArchiveName, FileName))
-           : sys::path::filename(NMOrErr->MemberName);
+  if (!Thin) {
+    NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
+  } else {
+    if (sys::path::is_absolute(FileName))
+      NMOrErr->MemberName = Saver.save(sys::path::convert_to_slash(FileName));
+    else {
+      Expected<std::string> PathOrErr =
+          computeArchiveRelativePath(ArchiveName, FileName);
+      NMOrErr->MemberName = Saver.save(
+          PathOrErr ? *PathOrErr : sys::path::convert_to_slash(FileName));
+    }
+  }
+
   if (FlattenArchive &&
       identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
     object::Archive &Lib = readLibrary(FileName);




More information about the llvm-commits mailing list