llvm.org GIT mirror llvm / d9613da
Object: Replace NewArchiveIterator with a simpler NewArchiveMember class. NFCI. The NewArchiveIterator class has a problem: it requires too much context. Any memory buffers added to the archive must be stored within an Archive::Member, which must have an associated Archive. This makes it harder than necessary to create new archive members (or new archives entirely) from scratch using memory buffers. This patch replaces NewArchiveIterator with a NewArchiveMember class that stores just the memory buffer and the information that goes into the archive member header. Differential Revision: http://reviews.llvm.org/D21721 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274183 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 3 years ago
4 changed file(s) with 147 addition(s) and 210 deletion(s). Raw diff Collapse all Expand all
1919
2020 namespace llvm {
2121
22 class NewArchiveIterator {
23 bool IsNewMember;
24 StringRef Name;
22 struct NewArchiveMember {
23 std::unique_ptr Buf;
24 sys::TimeValue ModTime = sys::TimeValue::PosixZeroTime();
25 unsigned UID = 0, GID = 0, Perms = 0644;
2526
26 object::Archive::Child OldMember;
27 NewArchiveMember() = default;
28 NewArchiveMember(MemoryBufferRef BufRef);
2729
28 public:
29 NewArchiveIterator(const object::Archive::Child &OldMember, StringRef Name);
30 NewArchiveIterator(StringRef FileName);
31 bool isNewMember() const;
32 StringRef getName() const;
30 static Expected
31 getOldMember(const object::Archive::Child &OldMember, bool Deterministic);
3332
34 const object::Archive::Child &getOld() const;
35
36 StringRef getNew() const;
37 llvm::ErrorOr getFD(sys::fs::file_status &NewStatus) const;
38 const sys::fs::file_status &getStatus() const;
33 static Expected getFile(StringRef FileName,
34 bool Deterministic);
3935 };
4036
4137 std::pair
42 writeArchive(StringRef ArcName, std::vectorIterator> &NewMembers,
38 writeArchive(StringRef ArcName, std::vectorMember> &NewMembers,
4339 bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic,
4440 bool Thin, std::unique_ptr OldArchiveBuf = nullptr);
4541 }
5656 }
5757
5858 static std::string getOutputPath(llvm::opt::InputArgList *Args,
59 const llvm::NewArchiveIterator &FirstMember) {
59 const llvm::NewArchiveMember &FirstMember) {
6060 if (auto *Arg = Args->getLastArg(OPT_out))
6161 return Arg->getValue();
62 SmallString<128> Val = FirstMember.getNew();
62 SmallString<128> Val = StringRef(FirstMember.Buf->getBufferIdentifier());
6363 llvm::sys::path::replace_extension(Val, ".lib");
6464 return Val.str();
6565 }
127127
128128 std::vector SearchPaths = getSearchPaths(&Args, Saver);
129129
130 std::vectorIterator> Members;
130 std::vectorMember> Members;
131131 for (auto *Arg : Args.filtered(OPT_INPUT)) {
132132 Optional Path = findInputFile(Arg->getValue(), SearchPaths);
133133 if (!Path.hasValue()) {
134134 llvm::errs() << Arg->getValue() << ": no such file or directory\n";
135135 return 1;
136136 }
137 Members.emplace_back(Saver.save(*Path));
137 Expected MOrErr =
138 NewArchiveMember::getFile(Saver.save(*Path), /*Deterministic=*/true);
139 if (!MOrErr) {
140 handleAllErrors(MOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) {
141 llvm::errs() << Arg->getValue() << ": " << EIB.message() << "\n";
142 });
143 return 1;
144 }
145 Members.emplace_back(std::move(*MOrErr));
138146 }
139147
140148 std::pair Result =
3333
3434 using namespace llvm;
3535
36 NewArchiveIterator::NewArchiveIterator(const object::Archive::Child &OldMember,
37 StringRef Name)
38 : IsNewMember(false), Name(Name), OldMember(OldMember) {}
39
40 NewArchiveIterator::NewArchiveIterator(StringRef FileName)
41 : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr, nullptr) {}
42
43 StringRef NewArchiveIterator::getName() const { return Name; }
44
45 bool NewArchiveIterator::isNewMember() const { return IsNewMember; }
46
47 const object::Archive::Child &NewArchiveIterator::getOld() const {
48 assert(!IsNewMember);
49 return OldMember;
50 }
51
52 StringRef NewArchiveIterator::getNew() const {
53 assert(IsNewMember);
54 return Name;
55 }
56
57 llvm::ErrorOr
58 NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
59 assert(IsNewMember);
60 int NewFD;
61 if (auto EC = sys::fs::openFileForRead(Name, NewFD))
62 return EC;
63 assert(NewFD != -1);
64
65 if (auto EC = sys::fs::status(NewFD, NewStatus))
66 return EC;
36 NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
37 : Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {}
38
39 Expected
40 NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
41 bool Deterministic) {
42 ErrorOr BufOrErr = OldMember.getMemoryBufferRef();
43 if (!BufOrErr)
44 return errorCodeToError(BufOrErr.getError());
45
46 NewArchiveMember M;
47 M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
48 if (!Deterministic) {
49 M.ModTime = OldMember.getLastModified();
50 M.UID = OldMember.getUID();
51 M.GID = OldMember.getGID();
52 M.Perms = OldMember.getAccessMode();
53 }
54 return std::move(M);
55 }
56
57 Expected NewArchiveMember::getFile(StringRef FileName,
58 bool Deterministic) {
59 sys::fs::file_status Status;
60 int FD;
61 if (auto EC = sys::fs::openFileForRead(FileName, FD))
62 return errorCodeToError(EC);
63 assert(FD != -1);
64
65 if (auto EC = sys::fs::status(FD, Status))
66 return errorCodeToError(EC);
6767
6868 // Opening a directory doesn't make sense. Let it fail.
6969 // Linux cannot open directories with open(2), although
7070 // cygwin and *bsd can.
71 if (NewStatus.type() == sys::fs::file_type::directory_file)
72 return make_error_code(errc::is_a_directory);
73
74 return NewFD;
71 if (Status.type() == sys::fs::file_type::directory_file)
72 return errorCodeToError(make_error_code(errc::is_a_directory));
73
74 ErrorOr> MemberBufferOrErr =
75 MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false);
76 if (!MemberBufferOrErr)
77 return errorCodeToError(MemberBufferOrErr.getError());
78
79 if (close(FD) != 0)
80 return errorCodeToError(std::error_code(errno, std::generic_category()));
81
82 NewArchiveMember M;
83 M.Buf = std::move(*MemberBufferOrErr);
84 if (!Deterministic) {
85 M.ModTime = Status.getLastModificationTime();
86 M.UID = Status.getUser();
87 M.GID = Status.getGroup();
88 M.Perms = Status.permissions();
89 }
90 return std::move(M);
7591 }
7692
7793 template
177193 }
178194
179195 static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
180 ArrayRefIterator> Members,
196 ArrayRefMember> Members,
181197 std::vector &StringMapIndexes,
182198 bool Thin) {
183199 unsigned StartOffset = 0;
184 for (const NewArchiveIterator &I : Members) {
185 StringRef Name = sys::path::filename(I.getName());
200 for (const NewArchiveMember &M : Members) {
201 StringRef Path = M.Buf->getBufferIdentifier();
202 StringRef Name = sys::path::filename(Path);
186203 if (!useStringTable(Thin, Name))
187204 continue;
188205 if (StartOffset == 0) {
193210 StringMapIndexes.push_back(Out.tell() - StartOffset);
194211
195212 if (Thin)
196 Out << computeRelativePath(ArcName, I.getName());
213 Out << computeRelativePath(ArcName, Path);
197214 else
198215 Out << Name;
199216
220237 // Returns the offset of the first reference to a member offset.
221238 static ErrorOr
222239 writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
223 ArrayRef Members,
224 ArrayRef<MemoryBufferRef> Buffers,
240 ArrayRef<NewArchiveMember> Members,
225241 std::vector &MemberOffsetRefs, bool Deterministic) {
226242 unsigned HeaderStartOffset = 0;
227243 unsigned BodyStartOffset = 0;
229245 raw_svector_ostream NameOS(NameBuf);
230246 LLVMContext Context;
231247 for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) {
232 MemoryBufferRef MemberBuffer = Buffers[MemberNum];
248 MemoryBufferRef MemberBuffer = Members[MemberNum].Buf->getMemBufferRef();
233249 Expected> ObjOrErr =
234250 object::SymbolicFile::createSymbolicFile(
235251 MemberBuffer, sys::fs::file_magic::unknown, &Context);
304320
305321 std::pair
306322 llvm::writeArchive(StringRef ArcName,
307 std::vectorIterator> &NewMembers,
323 std::vectorMember> &NewMembers,
308324 bool WriteSymtab, object::Archive::Kind Kind,
309325 bool Deterministic, bool Thin,
310326 std::unique_ptr OldArchiveBuf) {
329345 std::vector Members;
330346 std::vector NewMemberStatus;
331347
332 for (NewArchiveIterator &Member : NewMembers) {
333 MemoryBufferRef MemberRef;
334
335 if (Member.isNewMember()) {
336 StringRef Filename = Member.getNew();
337 NewMemberStatus.resize(NewMemberStatus.size() + 1);
338 sys::fs::file_status &Status = NewMemberStatus.back();
339 ErrorOr FD = Member.getFD(Status);
340 if (auto EC = FD.getError())
341 return std::make_pair(Filename, EC);
342 ErrorOr> MemberBufferOrErr =
343 MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(),
344 false);
345 if (auto EC = MemberBufferOrErr.getError())
346 return std::make_pair(Filename, EC);
347 if (close(FD.get()) != 0)
348 return std::make_pair(Filename,
349 std::error_code(errno, std::generic_category()));
350 Buffers.push_back(std::move(MemberBufferOrErr.get()));
351 MemberRef = Buffers.back()->getMemBufferRef();
352 } else {
353 const object::Archive::Child &OldMember = Member.getOld();
354 assert((!Thin || OldMember.getParent()->isThin()) &&
355 "Thin archives cannot refers to member of other archives");
356 ErrorOr MemberBufferOrErr =
357 OldMember.getMemoryBufferRef();
358 if (auto EC = MemberBufferOrErr.getError())
359 return std::make_pair("", EC);
360 MemberRef = MemberBufferOrErr.get();
361 }
362 Members.push_back(MemberRef);
363 }
364
365348 unsigned MemberReferenceOffset = 0;
366349 if (WriteSymtab) {
367350 ErrorOr MemberReferenceOffsetOrErr = writeSymbolTable(
368 Out, Kind, NewMembers, Members, MemberOffsetRefs, Deterministic);
351 Out, Kind, NewMembers, MemberOffsetRefs, Deterministic);
369352 if (auto EC = MemberReferenceOffsetOrErr.getError())
370353 return std::make_pair(ArcName, EC);
371354 MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
375358 if (Kind != object::Archive::K_BSD)
376359 writeStringTable(Out, ArcName, NewMembers, StringMapIndexes, Thin);
377360
378 unsigned MemberNum = 0;
379 unsigned NewMemberNum = 0;
380361 std::vector::iterator StringMapIndexIter = StringMapIndexes.begin();
381362 std::vector MemberOffset;
382 for (const NewArchiveIterator &I : NewMembers) {
383 MemoryBufferRef File = Members[MemberNum++];
363 for (const NewArchiveMember &M : NewMembers) {
364 MemoryBufferRef File = M.Buf->getMemBufferRef();
384365
385366 unsigned Pos = Out.tell();
386367 MemberOffset.push_back(Pos);
387368
388 sys::TimeValue ModTime;
389 unsigned UID;
390 unsigned GID;
391 unsigned Perms;
392 if (Deterministic) {
393 ModTime.fromEpochTime(0);
394 UID = 0;
395 GID = 0;
396 Perms = 0644;
397 } else if (I.isNewMember()) {
398 const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum];
399 ModTime = Status.getLastModificationTime();
400 UID = Status.getUser();
401 GID = Status.getGroup();
402 Perms = Status.permissions();
403 } else {
404 const object::Archive::Child &OldMember = I.getOld();
405 ModTime = OldMember.getLastModified();
406 UID = OldMember.getUID();
407 GID = OldMember.getGID();
408 Perms = OldMember.getAccessMode();
409 }
410
411 if (I.isNewMember()) {
412 StringRef FileName = I.getNew();
413 const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
414 printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
415 StringMapIndexIter, ModTime, UID, GID, Perms,
416 Status.getSize());
417 } else {
418 const object::Archive::Child &OldMember = I.getOld();
419 ErrorOr Size = OldMember.getSize();
420 if (std::error_code EC = Size.getError())
421 return std::make_pair("", EC);
422 StringRef FileName = I.getName();
423 printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
424 StringMapIndexIter, ModTime, UID, GID, Perms,
425 Size.get());
426 }
369 printMemberHeader(Out, Kind, Thin,
370 sys::path::filename(M.Buf->getBufferIdentifier()),
371 StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms,
372 M.Buf->getBufferSize());
427373
428374 if (!Thin)
429375 Out << File.getBuffer();
6464 fail(Context + ": " + EC.message());
6565 }
6666
67 static void failIfError(Error E, Twine Context = "") {
68 if (!E)
69 return;
70
71 handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
72 std::string ContextStr = Context.str();
73 if (ContextStr == "")
74 fail(EIB.message());
75 fail(Context + ": " + EIB.message());
76 });
77 }
78
6779 // llvm-ar/llvm-ranlib remaining positional arguments.
6880 static cl::list
6981 RestOfArgs(cl::Positional, cl::ZeroOrMore,
428440 std::exit(1);
429441 }
430442
431 static void addMember(std::vectorIterator> &Members,
443 static void addMember(std::vectorMember> &Members,
432444 StringRef FileName, int Pos = -1) {
433 NewArchiveIterator NI(FileName);
445 Expected NMOrErr =
446 NewArchiveMember::getFile(FileName, Deterministic);
447 failIfError(NMOrErr.takeError(), FileName);
434448 if (Pos == -1)
435 Members.push_back(NI);
449 Members.push_back(std::move(*NMOrErr));
436450 else
437 Members[Pos] = NI;
438 }
439
440 static void addMember(std::vector &Members,
441 const object::Archive::Child &M, StringRef Name,
442 int Pos = -1) {
451 Members[Pos] = std::move(*NMOrErr);
452 }
453
454 static void addMember(std::vector &Members,
455 const object::Archive::Child &M, int Pos = -1) {
443456 if (Thin && !M.getParent()->isThin())
444457 fail("Cannot convert a regular archive to a thin one");
445 NewArchiveIterator NI(M, Name);
458 Expected NMOrErr =
459 NewArchiveMember::getOldMember(M, Deterministic);
460 failIfError(NMOrErr.takeError());
446461 if (Pos == -1)
447 Members.push_back(NI);
462 Members.push_back(std::move(*NMOrErr));
448463 else
449 Members[Pos] = NI;
464 Members[Pos] = std::move(*NMOrErr);
450465 }
451466
452467 enum InsertAction {
507522
508523 // We have to walk this twice and computing it is not trivial, so creating an
509524 // explicit std::vector is actually fairly efficient.
510 static std::vectorIterator>
525 static std::vectorMember>
511526 computeNewArchiveMembers(ArchiveOperation Operation,
512527 object::Archive *OldArchive) {
513 std::vector Ret;
514 std::vectorIterator> Moved;
528 std::vectorMember> Ret;
529 std::vector Moved;
515530 int InsertPos = -1;
516531 StringRef PosName = sys::path::filename(RelPos);
517532 if (OldArchive) {
535550 computeInsertAction(Operation, Child, Name, MemberI);
536551 switch (Action) {
537552 case IA_AddOldMember:
538 addMember(Ret, Child, Name);
553 addMember(Ret, Child);
539554 break;
540555 case IA_AddNewMeber:
541556 addMember(Ret, *MemberI);
543558 case IA_Delete:
544559 break;
545560 case IA_MoveOldMember:
546 addMember(Moved, Child, Name);
561 addMember(Moved, Child);
547562 break;
548563 case IA_MoveNewMember:
549564 addMember(Moved, *MemberI);
564579 InsertPos = Ret.size();
565580
566581 assert(unsigned(InsertPos) <= Ret.size());
567 Ret.insert(Ret.begin() + InsertPos, Moved.begin(), Moved.end());
568
569 Ret.insert(Ret.begin() + InsertPos, Members.size(), NewArchiveIterator(""));
570582 int Pos = InsertPos;
583 for (auto &M : Moved) {
584 Ret.insert(Ret.begin() + Pos, std::move(M));
585 ++Pos;
586 }
587
588 for (unsigned I = 0; I != Members.size(); ++I)
589 Ret.insert(Ret.begin() + InsertPos, NewArchiveMember());
590 Pos = InsertPos;
571591 for (auto &Member : Members) {
572592 addMember(Ret, Member, Pos);
573593 ++Pos;
581601 : object::Archive::K_GNU;
582602 }
583603
584 static object::Archive::Kind
585 getKindFromMember(const NewArchiveIterator &Member) {
586 auto getKindFromMemberInner =
587 [](MemoryBufferRef Buffer) -> object::Archive::Kind {
588 Expected> OptionalObject =
589 object::ObjectFile::createObjectFile(Buffer);
590
591 if (OptionalObject)
592 return isa(**OptionalObject)
593 ? object::Archive::K_BSD
594 : object::Archive::K_GNU;
595
596 // squelch the error in case we had a non-object file
597 consumeError(OptionalObject.takeError());
598 return getDefaultForHost();
599 };
600
601 if (Member.isNewMember()) {
602 object::Archive::Kind Kind = getDefaultForHost();
603
604 sys::fs::file_status Status;
605 if (auto OptionalFD = Member.getFD(Status)) {
606 if (auto MB = MemoryBuffer::getOpenFile(*OptionalFD, Member.getName(),
607 Status.getSize(), false))
608 Kind = getKindFromMemberInner((*MB)->getMemBufferRef());
609
610 if (close(*OptionalFD) != 0)
611 failIfError(std::error_code(errno, std::generic_category()),
612 "failed to close file");
613 }
614
615 return Kind;
616 } else {
617 const object::Archive::Child &OldMember = Member.getOld();
618 if (OldMember.getParent()->isThin())
619 return object::Archive::Kind::K_GNU;
620
621 auto OptionalMB = OldMember.getMemoryBufferRef();
622 failIfError(OptionalMB.getError());
623
624 return getKindFromMemberInner(*OptionalMB);
625 }
604 static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) {
605 Expected> OptionalObject =
606 object::ObjectFile::createObjectFile(Member.Buf->getMemBufferRef());
607
608 if (OptionalObject)
609 return isa(**OptionalObject)
610 ? object::Archive::K_BSD
611 : object::Archive::K_GNU;
612
613 // squelch the error in case we had a non-object file
614 consumeError(OptionalObject.takeError());
615 return getDefaultForHost();
626616 }
627617
628618 static void
629619 performWriteOperation(ArchiveOperation Operation,
630620 object::Archive *OldArchive,
631621 std::unique_ptr OldArchiveBuf,
632 std::vector *NewMembersP) {
633 std::vector NewMembers;
622 std::vector *NewMembersP) {
623 std::vector NewMembers;
634624 if (!NewMembersP)
635625 NewMembers = computeNewArchiveMembers(Operation, OldArchive);
636626
680670 static void performOperation(ArchiveOperation Operation,
681671 object::Archive *OldArchive,
682672 std::unique_ptr OldArchiveBuf,
683 std::vectorIterator> *NewMembers) {
673 std::vectorMember> *NewMembers) {
684674 switch (Operation) {
685675 case Print:
686676 case DisplayTable:
703693 }
704694
705695 static int performOperation(ArchiveOperation Operation,
706 std::vectorIterator> *NewMembers) {
696 std::vectorMember> *NewMembers) {
707697 // Create or open the archive object.
708698 ErrorOr> Buf =
709699 MemoryBuffer::getFile(ArchiveName, -1, false);
743733 failIfError(Buf.getError());
744734 const MemoryBuffer &Ref = *Buf.get();
745735 bool Saved = false;
746 std::vectorIterator> NewMembers;
736 std::vectorMember> NewMembers;
747737 std::vector> ArchiveBuffers;
748738 std::vector> Archives;
749739
775765 object::Archive &Lib = *Archives.back();
776766 for (auto &MemberOrErr : Lib.children()) {
777767 failIfError(MemberOrErr.getError());
778 auto &Member = MemberOrErr.get();
779 ErrorOr NameOrErr = Member.getName();
780 failIfError(NameOrErr.getError());
781 addMember(NewMembers, Member, *NameOrErr);
768 addMember(NewMembers, *MemberOrErr);
782769 }
783770 break;
784771 }