llvm.org GIT mirror llvm / ce7f3f7
Revert r353424 "[llvm-ar][libObject] Fix relative paths when nesting thin archives." This broke the Chromium build on Windows, see https://crbug.com/930058 > 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`, whe > lattening 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 This reverts commit bf990ab5aab03aa0aac53c9ef47ef264307804ed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353507 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 6 months ago
5 changed file(s) with 67 addition(s) and 79 deletion(s). Raw diff Collapse all Expand all
2525 sys::TimePoint ModTime;
2626 unsigned UID = 0, GID = 0, Perms = 0644;
2727
28 bool IsNew = false;
2829 NewArchiveMember() = default;
2930 NewArchiveMember(MemoryBufferRef BufRef);
3031
4747 return BufOrErr.takeError();
4848
4949 NewArchiveMember M;
50 assert(M.IsNew == false);
5051 M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
5152 M.MemberName = M.Buf->getBufferIdentifier();
5253 if (!Deterministic) {
9697 return errorCodeToError(std::error_code(errno, std::generic_category()));
9798
9899 NewArchiveMember M;
100 M.IsNew = true;
99101 M.Buf = std::move(*MemberBufferOrErr);
100102 M.MemberName = M.Buf->getBufferIdentifier();
101103 if (!Deterministic) {
188190 return Thin || Name.size() >= 16 || Name.contains('/');
189191 }
190192
193 // Compute the relative path from From to To.
194 static std::string computeRelativePath(StringRef From, StringRef To) {
195 if (sys::path::is_absolute(From) || sys::path::is_absolute(To))
196 return To;
197
198 StringRef DirFrom = sys::path::parent_path(From);
199 auto FromI = sys::path::begin(DirFrom);
200 auto ToI = sys::path::begin(To);
201 while (*FromI == *ToI) {
202 ++FromI;
203 ++ToI;
204 }
205
206 SmallString<128> Relative;
207 for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
208 sys::path::append(Relative, "..");
209
210 for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI)
211 sys::path::append(Relative, *ToI);
212
213 #ifdef _WIN32
214 // Replace backslashes with slashes so that the path is portable between *nix
215 // and Windows.
216 std::replace(Relative.begin(), Relative.end(), '\\', '/');
217 #endif
218
219 return Relative.str();
220 }
221
191222 static bool is64BitKind(object::Archive::Kind Kind) {
192223 switch (Kind) {
193224 case object::Archive::K_GNU:
202233 llvm_unreachable("not supported for writting");
203234 }
204235
205 static void
206 printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable,
207 StringMap &MemberNames, object::Archive::Kind Kind,
208 bool Thin, const NewArchiveMember &M,
209 sys::TimePoint ModTime, unsigned Size) {
236 static void addToStringTable(raw_ostream &Out, StringRef ArcName,
237 const NewArchiveMember &M, bool Thin) {
238 StringRef ID = M.Buf->getBufferIdentifier();
239 if (Thin) {
240 if (M.IsNew)
241 Out << computeRelativePath(ArcName, ID);
242 else
243 Out << ID;
244 } else
245 Out << M.MemberName;
246 Out << "/\n";
247 }
248
249 static void printMemberHeader(raw_ostream &Out, uint64_t Pos,
250 raw_ostream &StringTable,
251 StringMap &MemberNames,
252 object::Archive::Kind Kind, bool Thin,
253 StringRef ArcName, const NewArchiveMember &M,
254 sys::TimePoint ModTime,
255 unsigned Size) {
256
210257 if (isBSDLike(Kind))
211258 return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
212259 M.Perms, Size);
217264 uint64_t NamePos;
218265 if (Thin) {
219266 NamePos = StringTable.tell();
220 StringTable << M.MemberName << "/\n";
267 addToStringTable(StringTable, ArcName, M, Thin);
221268 } else {
222269 auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});
223270 if (Insertion.second) {
224271 Insertion.first->second = StringTable.tell();
225 StringTable << M.MemberName << "/\n";
272 addToStringTable(StringTable, ArcName, M, Thin);
226273 }
227274 NamePos = Insertion.first->second;
228275 }
384431
385432 static Expected>
386433 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
387 object::Archive::Kind Kind, bool Thin, bool Deterministic,
388 ArrayRef NewMembers) {
434 object::Archive::Kind Kind, bool Thin, StringRef ArcName,
435 bool Deterministic, ArrayRef NewMembers) {
389436 static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
390437
391438 // This ignores the symbol table, but we only need the value mod 8 and the
472519 ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
473520 else
474521 ModTime = M.ModTime;
475 printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
476 ModTime, Buf.getBufferSize() + MemberPadding);
522 printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, ArcName,
523 M, ModTime, Buf.getBufferSize() + MemberPadding);
477524 Out.flush();
478525
479526 Expected> Symbols =
505552 raw_svector_ostream StringTable(StringTableBuf);
506553
507554 Expected> DataOrErr = computeMemberData(
508 StringTable, SymNames, Kind, Thin, Deterministic, NewMembers);
555 StringTable, SymNames, Kind, Thin, ArcName, Deterministic, NewMembers);
509556 if (Error E = DataOrErr.takeError())
510557 return E;
511558 std::vector &Data = *DataOrErr;
+0
-15
test/tools/llvm-ar/flatten-thin-archive-directories.test less more
None # This test creates a thin archive in a directory and adds it to a thin archive
1 # in the parent directory. The relative path should be included when flattening
2 # the archive.
3
4 RUN: mkdir -p %t/foo
5 RUN: touch %t/foo/a.txt
6 RUN: rm -f %t/archive.a %t/foo/archive.a
7
8 # These tests must be run in the same directory as %t/archive.a. cd %t is
9 # included on each line to make debugging this test case easier.
10 RUN: cd %t && llvm-ar rcST foo/archive.a foo/a.txt
11 RUN: cd %t && llvm-ar rcST archive.a foo/archive.a
12 RUN: cd %t && llvm-ar t archive.a | FileCheck %s --match-full-lines
13
14 CHECK: foo/a.txt
55 # flattened members appearing together.
66
77 RUN: touch %t-a.txt %t-b.txt %t-c.txt %t-d.txt %t-e.txt
8 RUN: rm -f %t-a-plus-b.a %t-d-plus-e.a %t.a
8 RUN: rm -f %t-a-plus-b.a %t.a
99 RUN: llvm-ar rcsT %t-a-plus-b.a %t-a.txt %t-b.txt
1010 RUN: llvm-ar rcs %t-d-plus-e.a %t-d.txt %t-e.txt
1111 RUN: llvm-ar rcsT %t.a %t-a-plus-b.a %t-c.txt %t-d-plus-e.a
191191 // This variable holds the list of member files to proecess, as given
192192 // on the command line.
193193 static std::vector Members;
194
195 // Static buffer to hold StringRefs.
196 static BumpPtrAllocator Alloc;
197194
198195 // Extract the member filename from the command line for the [relpos] argument
199196 // associated with a, b, and i modifiers
539536 exit(1);
540537 }
541538
542 // Compute the relative path from From to To.
543 static std::string computeRelativePath(StringRef From, StringRef To) {
544 if (sys::path::is_absolute(From) || sys::path::is_absolute(To))
545 return To;
546
547 StringRef DirFrom = sys::path::parent_path(From);
548 auto FromI = sys::path::begin(DirFrom);
549 auto ToI = sys::path::begin(To);
550 while (*FromI == *ToI) {
551 ++FromI;
552 ++ToI;
553 }
554
555 SmallString<128> Relative;
556 for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
557 sys::path::append(Relative, "..");
558
559 for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI)
560 sys::path::append(Relative, *ToI);
561
562 #ifdef _WIN32
563 // Replace backslashes with slashes so that the path is portable between *nix
564 // and Windows.
565 std::replace(Relative.begin(), Relative.end(), '\\', '/');
566 #endif
567
568 return Relative.str();
569 }
570
571539 static void addChildMember(std::vector &Members,
572540 const object::Archive::Child &M,
573541 bool FlattenArchive = false) {
576544 Expected NMOrErr =
577545 NewArchiveMember::getOldMember(M, Deterministic);
578546 failIfError(NMOrErr.takeError());
579 // If the child member we're trying to add is thin, use the path relative to
580 // the archive it's in, so the file resolves correctly.
581 if (Thin && FlattenArchive) {
582 StringSaver Saver(Alloc);
583 Expected FileNameOrErr = M.getFullName();
584 failIfError(FileNameOrErr.takeError());
585 NMOrErr->MemberName =
586 Saver.save(computeRelativePath(ArchiveName, *FileNameOrErr));
587 }
588547 if (FlattenArchive &&
589548 identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
590549 Expected FileNameOrErr = M.getFullName();
608567 Expected NMOrErr =
609568 NewArchiveMember::getFile(FileName, Deterministic);
610569 failIfError(NMOrErr.takeError(), FileName);
611 StringSaver Saver(Alloc);
612 // For regular archives, use the basename of the object path for the member
613 // name. For thin archives, use the full relative paths so the file resolves
614 // correctly.
615 NMOrErr->MemberName =
616 Thin ? Saver.save(computeRelativePath(ArchiveName, FileName))
617 : sys::path::filename(NMOrErr->MemberName);
618570 if (FlattenArchive &&
619571 identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
620572 object::Archive &Lib = readLibrary(FileName);
628580 return;
629581 }
630582 }
583 // Use the basename of the object path for the member name.
584 NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
631585 Members.push_back(std::move(*NMOrErr));
632586 }
633587
717671 computeInsertAction(Operation, Child, Name, MemberI);
718672 switch (Action) {
719673 case IA_AddOldMember:
720 addChildMember(Ret, Child, /*FlattenArchive=*/Thin);
674 addChildMember(Ret, Child);
721675 break;
722676 case IA_AddNewMember:
723677 addMember(Ret, *MemberI);
725679 case IA_Delete:
726680 break;
727681 case IA_MoveOldMember:
728 addChildMember(Moved, Child, /*FlattenArchive=*/Thin);
682 addChildMember(Moved, Child);
729683 break;
730684 case IA_MoveNewMember:
731685 addMember(Moved, *MemberI);
944898 {
945899 Error Err = Error::success();
946900 for (auto &Member : Lib.children(Err))
947 addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin);
901 addChildMember(NewMembers, Member);
948902 failIfError(std::move(Err));
949903 }
950904 break;
996950
997951 static int ar_main(int argc, char **argv) {
998952 SmallVector Argv(argv, argv + argc);
953 BumpPtrAllocator Alloc;
999954 StringSaver Saver(Alloc);
1000955 cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
1001956 for (size_t i = 1; i < Argv.size(); ++i) {