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
llvm-svn: 274183
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index 93e285c..5357326 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -34,45 +34,61 @@
using namespace llvm;
-NewArchiveIterator::NewArchiveIterator(const object::Archive::Child &OldMember,
- StringRef Name)
- : IsNewMember(false), Name(Name), OldMember(OldMember) {}
+NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
+ : Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {}
-NewArchiveIterator::NewArchiveIterator(StringRef FileName)
- : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr, nullptr) {}
+Expected<NewArchiveMember>
+NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
+ bool Deterministic) {
+ ErrorOr<llvm::MemoryBufferRef> BufOrErr = OldMember.getMemoryBufferRef();
+ if (!BufOrErr)
+ return errorCodeToError(BufOrErr.getError());
-StringRef NewArchiveIterator::getName() const { return Name; }
-
-bool NewArchiveIterator::isNewMember() const { return IsNewMember; }
-
-const object::Archive::Child &NewArchiveIterator::getOld() const {
- assert(!IsNewMember);
- return OldMember;
+ NewArchiveMember M;
+ M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
+ if (!Deterministic) {
+ M.ModTime = OldMember.getLastModified();
+ M.UID = OldMember.getUID();
+ M.GID = OldMember.getGID();
+ M.Perms = OldMember.getAccessMode();
+ }
+ return std::move(M);
}
-StringRef NewArchiveIterator::getNew() const {
- assert(IsNewMember);
- return Name;
-}
+Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,
+ bool Deterministic) {
+ sys::fs::file_status Status;
+ int FD;
+ if (auto EC = sys::fs::openFileForRead(FileName, FD))
+ return errorCodeToError(EC);
+ assert(FD != -1);
-llvm::ErrorOr<int>
-NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
- assert(IsNewMember);
- int NewFD;
- if (auto EC = sys::fs::openFileForRead(Name, NewFD))
- return EC;
- assert(NewFD != -1);
-
- if (auto EC = sys::fs::status(NewFD, NewStatus))
- return EC;
+ if (auto EC = sys::fs::status(FD, Status))
+ return errorCodeToError(EC);
// Opening a directory doesn't make sense. Let it fail.
// Linux cannot open directories with open(2), although
// cygwin and *bsd can.
- if (NewStatus.type() == sys::fs::file_type::directory_file)
- return make_error_code(errc::is_a_directory);
+ if (Status.type() == sys::fs::file_type::directory_file)
+ return errorCodeToError(make_error_code(errc::is_a_directory));
- return NewFD;
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
+ MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false);
+ if (!MemberBufferOrErr)
+ return errorCodeToError(MemberBufferOrErr.getError());
+
+ if (close(FD) != 0)
+ return errorCodeToError(std::error_code(errno, std::generic_category()));
+
+ NewArchiveMember M;
+ M.Buf = std::move(*MemberBufferOrErr);
+ if (!Deterministic) {
+ M.ModTime = Status.getLastModificationTime();
+ M.UID = Status.getUser();
+ M.GID = Status.getGroup();
+ M.Perms = Status.permissions();
+ }
+ return std::move(M);
}
template <typename T>
@@ -178,12 +194,13 @@
}
static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
- ArrayRef<NewArchiveIterator> Members,
+ ArrayRef<NewArchiveMember> Members,
std::vector<unsigned> &StringMapIndexes,
bool Thin) {
unsigned StartOffset = 0;
- for (const NewArchiveIterator &I : Members) {
- StringRef Name = sys::path::filename(I.getName());
+ for (const NewArchiveMember &M : Members) {
+ StringRef Path = M.Buf->getBufferIdentifier();
+ StringRef Name = sys::path::filename(Path);
if (!useStringTable(Thin, Name))
continue;
if (StartOffset == 0) {
@@ -194,7 +211,7 @@
StringMapIndexes.push_back(Out.tell() - StartOffset);
if (Thin)
- Out << computeRelativePath(ArcName, I.getName());
+ Out << computeRelativePath(ArcName, Path);
else
Out << Name;
@@ -221,8 +238,7 @@
// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
- ArrayRef<NewArchiveIterator> Members,
- ArrayRef<MemoryBufferRef> Buffers,
+ ArrayRef<NewArchiveMember> Members,
std::vector<unsigned> &MemberOffsetRefs, bool Deterministic) {
unsigned HeaderStartOffset = 0;
unsigned BodyStartOffset = 0;
@@ -230,7 +246,7 @@
raw_svector_ostream NameOS(NameBuf);
LLVMContext Context;
for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) {
- MemoryBufferRef MemberBuffer = Buffers[MemberNum];
+ MemoryBufferRef MemberBuffer = Members[MemberNum].Buf->getMemBufferRef();
Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
object::SymbolicFile::createSymbolicFile(
MemberBuffer, sys::fs::file_magic::unknown, &Context);
@@ -305,7 +321,7 @@
std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
- std::vector<NewArchiveIterator> &NewMembers,
+ std::vector<NewArchiveMember> &NewMembers,
bool WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin,
std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
@@ -330,43 +346,10 @@
std::vector<MemoryBufferRef> Members;
std::vector<sys::fs::file_status> NewMemberStatus;
- for (NewArchiveIterator &Member : NewMembers) {
- MemoryBufferRef MemberRef;
-
- if (Member.isNewMember()) {
- StringRef Filename = Member.getNew();
- NewMemberStatus.resize(NewMemberStatus.size() + 1);
- sys::fs::file_status &Status = NewMemberStatus.back();
- ErrorOr<int> FD = Member.getFD(Status);
- if (auto EC = FD.getError())
- return std::make_pair(Filename, EC);
- ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
- MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(),
- false);
- if (auto EC = MemberBufferOrErr.getError())
- return std::make_pair(Filename, EC);
- if (close(FD.get()) != 0)
- return std::make_pair(Filename,
- std::error_code(errno, std::generic_category()));
- Buffers.push_back(std::move(MemberBufferOrErr.get()));
- MemberRef = Buffers.back()->getMemBufferRef();
- } else {
- const object::Archive::Child &OldMember = Member.getOld();
- assert((!Thin || OldMember.getParent()->isThin()) &&
- "Thin archives cannot refers to member of other archives");
- ErrorOr<MemoryBufferRef> MemberBufferOrErr =
- OldMember.getMemoryBufferRef();
- if (auto EC = MemberBufferOrErr.getError())
- return std::make_pair("", EC);
- MemberRef = MemberBufferOrErr.get();
- }
- Members.push_back(MemberRef);
- }
-
unsigned MemberReferenceOffset = 0;
if (WriteSymtab) {
ErrorOr<unsigned> MemberReferenceOffsetOrErr = writeSymbolTable(
- Out, Kind, NewMembers, Members, MemberOffsetRefs, Deterministic);
+ Out, Kind, NewMembers, MemberOffsetRefs, Deterministic);
if (auto EC = MemberReferenceOffsetOrErr.getError())
return std::make_pair(ArcName, EC);
MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
@@ -376,55 +359,18 @@
if (Kind != object::Archive::K_BSD)
writeStringTable(Out, ArcName, NewMembers, StringMapIndexes, Thin);
- unsigned MemberNum = 0;
- unsigned NewMemberNum = 0;
std::vector<unsigned>::iterator StringMapIndexIter = StringMapIndexes.begin();
std::vector<unsigned> MemberOffset;
- for (const NewArchiveIterator &I : NewMembers) {
- MemoryBufferRef File = Members[MemberNum++];
+ for (const NewArchiveMember &M : NewMembers) {
+ MemoryBufferRef File = M.Buf->getMemBufferRef();
unsigned Pos = Out.tell();
MemberOffset.push_back(Pos);
- sys::TimeValue ModTime;
- unsigned UID;
- unsigned GID;
- unsigned Perms;
- if (Deterministic) {
- ModTime.fromEpochTime(0);
- UID = 0;
- GID = 0;
- Perms = 0644;
- } else if (I.isNewMember()) {
- const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum];
- ModTime = Status.getLastModificationTime();
- UID = Status.getUser();
- GID = Status.getGroup();
- Perms = Status.permissions();
- } else {
- const object::Archive::Child &OldMember = I.getOld();
- ModTime = OldMember.getLastModified();
- UID = OldMember.getUID();
- GID = OldMember.getGID();
- Perms = OldMember.getAccessMode();
- }
-
- if (I.isNewMember()) {
- StringRef FileName = I.getNew();
- const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
- printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
- StringMapIndexIter, ModTime, UID, GID, Perms,
- Status.getSize());
- } else {
- const object::Archive::Child &OldMember = I.getOld();
- ErrorOr<uint32_t> Size = OldMember.getSize();
- if (std::error_code EC = Size.getError())
- return std::make_pair("", EC);
- StringRef FileName = I.getName();
- printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
- StringMapIndexIter, ModTime, UID, GID, Perms,
- Size.get());
- }
+ printMemberHeader(Out, Kind, Thin,
+ sys::path::filename(M.Buf->getBufferIdentifier()),
+ StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms,
+ M.Buf->getBufferSize());
if (!Thin)
Out << File.getBuffer();