diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-02-14 18:35:13 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-02-14 18:35:13 +0000 |
commit | b7ae7297b94c4bfde45e210a335d9f18e3b5f19a (patch) | |
tree | 939904a78a8a702c71b082dc9ce996be72ae1975 /llvm/tools/llvm-ar | |
parent | 5ffdc43dc9bcf00158a764e11e45db836279d7e1 (diff) | |
download | bcm5719-llvm-b7ae7297b94c4bfde45e210a335d9f18e3b5f19a.tar.gz bcm5719-llvm-b7ae7297b94c4bfde45e210a335d9f18e3b5f19a.zip |
[llvm-ar] Implement the P modifier.
Summary:
GNU ar has a `P` modifier that changes filename comparisons to use full paths instead of the basename. As noted in the GNU docs, regular archives are not created with full path names, so P is used to deal with archives created by other archive programs (e.g. see the updated `absolute-paths.test` test case).
Since thin archives use full path names -- paths are relative to the archive -- it seems very error prone to not imply P when dealing with thin archives, so P is implied in those cases. (I think this is a deviation from GNU ar that makes sense).
This fixes PR37436 via https://github.com/ClangBuiltLinux/linux/issues/33.
Reviewers: mstorsjo, pcc, ruiu, davide, david2050, rnk
Subscribers: tpimh, llvm-commits, nickdesaulniers
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57927
llvm-svn: 354044
Diffstat (limited to 'llvm/tools/llvm-ar')
-rw-r--r-- | llvm/tools/llvm-ar/llvm-ar.cpp | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index 5fbbbf67f93..7d31103c688 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -98,6 +98,7 @@ MODIFIERS: [l] - ignored for compatibility [L] - add archive's contents [o] - preserve original dates + [P] - use full names when matching (implied for thin archives) [s] - create an archive index (cf. ranlib) [S] - do not build a symbol table [T] - create a thin archive @@ -168,16 +169,17 @@ enum ArchiveOperation { }; // Modifiers to follow operation to vary behavior -static bool AddAfter = false; ///< 'a' modifier -static bool AddBefore = false; ///< 'b' modifier -static bool Create = false; ///< 'c' modifier -static bool OriginalDates = false; ///< 'o' modifier -static bool OnlyUpdate = false; ///< 'u' modifier -static bool Verbose = false; ///< 'v' modifier -static bool Symtab = true; ///< 's' modifier -static bool Deterministic = true; ///< 'D' and 'U' modifiers -static bool Thin = false; ///< 'T' modifier -static bool AddLibrary = false; ///< 'L' modifier +static bool AddAfter = false; ///< 'a' modifier +static bool AddBefore = false; ///< 'b' modifier +static bool Create = false; ///< 'c' modifier +static bool OriginalDates = false; ///< 'o' modifier +static bool CompareFullPath = false; ///< 'P' modifier +static bool OnlyUpdate = false; ///< 'u' modifier +static bool Verbose = false; ///< 'v' modifier +static bool Symtab = true; ///< 's' modifier +static bool Deterministic = true; ///< 'D' and 'U' modifiers +static bool Thin = false; ///< 'T' modifier +static bool AddLibrary = false; ///< 'L' modifier // Relative Positional Argument (for insert/move). This variable holds // the name of the archive member to which the 'a', 'b' or 'i' modifier @@ -297,6 +299,9 @@ static ArchiveOperation parseCommandLine() { case 'o': OriginalDates = true; break; + case 'P': + CompareFullPath = true; + break; case 's': Symtab = true; MaybeJustCreateSymTab = true; @@ -333,6 +338,8 @@ static ArchiveOperation parseCommandLine() { break; case 'T': Thin = true; + // Thin archives store path names, so P should be forced. + CompareFullPath = true; break; case 'L': AddLibrary = true; @@ -439,6 +446,10 @@ static void doDisplayTable(StringRef Name, const object::Archive::Child &C) { outs() << Name << "\n"; } +static StringRef normalizePath(StringRef Path) { + return CompareFullPath ? Path : sys::path::filename(Path); +} + // Implement the 'x' operation. This function extracts files back to the file // system. static void doExtract(StringRef Name, const object::Archive::Child &C) { @@ -510,7 +521,9 @@ static void performReadOperation(ArchiveOperation Operation, StringRef Name = NameOrErr.get(); if (Filter) { - auto I = find(Members, Name); + auto I = find_if(Members, [Name](StringRef Path) { + return Name == normalizePath(Path); + }); if (I == Members.end()) continue; Members.erase(I); @@ -618,9 +631,8 @@ static InsertAction computeInsertAction(ArchiveOperation Operation, if (Operation == QuickAppend || Members.empty()) return IA_AddOldMember; - auto MI = find_if(Members, [Name](StringRef Path) { - return Name == sys::path::filename(Path); - }); + auto MI = find_if( + Members, [Name](StringRef Path) { return Name == normalizePath(Path); }); if (MI == Members.end()) return IA_AddOldMember; @@ -634,7 +646,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation, return IA_MoveOldMember; if (Operation == ReplaceOrInsert) { - StringRef PosName = sys::path::filename(RelPos); + StringRef PosName = normalizePath(RelPos); if (!OnlyUpdate) { if (PosName.empty()) return IA_AddNewMember; @@ -668,7 +680,7 @@ computeNewArchiveMembers(ArchiveOperation Operation, std::vector<NewArchiveMember> Ret; std::vector<NewArchiveMember> Moved; int InsertPos = -1; - StringRef PosName = sys::path::filename(RelPos); + StringRef PosName = normalizePath(RelPos); if (OldArchive) { Error Err = Error::success(); for (auto &Child : OldArchive->children(Err)) { @@ -860,6 +872,8 @@ static int performOperation(ArchiveOperation Operation, EC = errorToErrorCode(std::move(Err)); failIfError(EC, "error loading '" + ArchiveName + "': " + EC.message() + "!"); + if (Archive.isThin()) + CompareFullPath = true; performOperation(Operation, &Archive, std::move(Buf.get()), NewMembers); return 0; } @@ -933,7 +947,7 @@ static void runMRIScript() { ArchiveName = Rest; break; case MRICommand::Delete: { - StringRef Name = sys::path::filename(Rest); + StringRef Name = normalizePath(Rest); llvm::erase_if(NewMembers, [=](NewArchiveMember &M) { return M.MemberName == Name; }); break; |