summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Object/ArchiveWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Object/ArchiveWriter.cpp')
-rw-r--r--contrib/llvm/lib/Object/ArchiveWriter.cpp117
1 files changed, 81 insertions, 36 deletions
diff --git a/contrib/llvm/lib/Object/ArchiveWriter.cpp b/contrib/llvm/lib/Object/ArchiveWriter.cpp
index a40901c..c7343fd 100644
--- a/contrib/llvm/lib/Object/ArchiveWriter.cpp
+++ b/contrib/llvm/lib/Object/ArchiveWriter.cpp
@@ -34,32 +34,32 @@
using namespace llvm;
-NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I,
+NewArchiveIterator::NewArchiveIterator(const object::Archive::Child &OldMember,
StringRef Name)
- : IsNewMember(false), Name(Name), OldI(I) {}
+ : IsNewMember(false), Name(Name), OldMember(OldMember) {}
-NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name)
- : IsNewMember(true), Name(Name), NewFilename(NewFilename) {}
+NewArchiveIterator::NewArchiveIterator(StringRef FileName)
+ : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr, nullptr) {}
StringRef NewArchiveIterator::getName() const { return Name; }
bool NewArchiveIterator::isNewMember() const { return IsNewMember; }
-object::Archive::child_iterator NewArchiveIterator::getOld() const {
+const object::Archive::Child &NewArchiveIterator::getOld() const {
assert(!IsNewMember);
- return OldI;
+ return OldMember;
}
StringRef NewArchiveIterator::getNew() const {
assert(IsNewMember);
- return NewFilename;
+ return Name;
}
llvm::ErrorOr<int>
NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
assert(IsNewMember);
int NewFD;
- if (auto EC = sys::fs::openFileForRead(NewFilename, NewFD))
+ if (auto EC = sys::fs::openFileForRead(Name, NewFD))
return EC;
assert(NewFD != -1);
@@ -77,7 +77,7 @@ NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
template <typename T>
static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
- bool MayTruncate = false) {
+ bool MayTruncate = false) {
uint64_t OldPos = OS.tell();
OS << Data;
unsigned SizeSoFar = OS.tell() - OldPos;
@@ -135,30 +135,56 @@ static void printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
Out.write(uint8_t(0));
}
+static bool useStringTable(bool Thin, StringRef Name) {
+ return Thin || Name.size() >= 16;
+}
+
static void
-printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind,
+printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind, bool Thin,
StringRef Name,
std::vector<unsigned>::iterator &StringMapIndexIter,
const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
unsigned Perms, unsigned Size) {
if (Kind == object::Archive::K_BSD)
return printBSDMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
- if (Name.size() < 16)
+ if (!useStringTable(Thin, Name))
return printGNUSmallMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
Out << '/';
printWithSpacePadding(Out, *StringMapIndexIter++, 15);
printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}
-static void writeStringTable(raw_fd_ostream &Out,
+// Compute the relative path from From to To.
+static std::string computeRelativePath(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;
+ }
+
+ SmallString<128> Relative;
+ for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
+ sys::path::append(Relative, "..");
+
+ for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI)
+ sys::path::append(Relative, *ToI);
+
+ return Relative.str();
+}
+
+static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
ArrayRef<NewArchiveIterator> Members,
- std::vector<unsigned> &StringMapIndexes) {
+ std::vector<unsigned> &StringMapIndexes,
+ bool Thin) {
unsigned StartOffset = 0;
- for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
- E = Members.end();
- I != E; ++I) {
- StringRef Name = I->getName();
- if (Name.size() < 16)
+ for (const NewArchiveIterator &I : Members) {
+ StringRef Name = sys::path::filename(I.getName());
+ if (!useStringTable(Thin, Name))
continue;
if (StartOffset == 0) {
printWithSpacePadding(Out, "//", 58);
@@ -166,7 +192,13 @@ static void writeStringTable(raw_fd_ostream &Out,
StartOffset = Out.tell();
}
StringMapIndexes.push_back(Out.tell() - StartOffset);
- Out << Name << "/\n";
+
+ if (Thin)
+ Out << computeRelativePath(ArcName, I.getName());
+ else
+ Out << Name;
+
+ Out << "/\n";
}
if (StartOffset == 0)
return;
@@ -268,9 +300,11 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
return BodyStartOffset + 4;
}
-std::pair<StringRef, std::error_code> llvm::writeArchive(
- StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
- bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic) {
+std::pair<StringRef, std::error_code>
+llvm::writeArchive(StringRef ArcName,
+ std::vector<NewArchiveIterator> &NewMembers,
+ bool WriteSymtab, object::Archive::Kind Kind,
+ bool Deterministic, bool Thin) {
SmallString<128> TmpArchive;
int TmpArchiveFD;
if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
@@ -279,7 +313,10 @@ std::pair<StringRef, std::error_code> llvm::writeArchive(
tool_output_file Output(TmpArchive, TmpArchiveFD);
raw_fd_ostream &Out = Output.os();
- Out << "!<arch>\n";
+ if (Thin)
+ Out << "!<thin>\n";
+ else
+ Out << "!<arch>\n";
std::vector<unsigned> MemberOffsetRefs;
@@ -309,9 +346,11 @@ std::pair<StringRef, std::error_code> llvm::writeArchive(
Buffers.push_back(std::move(MemberBufferOrErr.get()));
MemberRef = Buffers.back()->getMemBufferRef();
} else {
- object::Archive::child_iterator OldMember = Member.getOld();
+ 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();
+ OldMember.getMemoryBufferRef();
if (auto EC = MemberBufferOrErr.getError())
return std::make_pair("", EC);
MemberRef = MemberBufferOrErr.get();
@@ -330,7 +369,7 @@ std::pair<StringRef, std::error_code> llvm::writeArchive(
std::vector<unsigned> StringMapIndexes;
if (Kind != object::Archive::K_BSD)
- writeStringTable(Out, NewMembers, StringMapIndexes);
+ writeStringTable(Out, ArcName, NewMembers, StringMapIndexes, Thin);
unsigned MemberNum = 0;
unsigned NewMemberNum = 0;
@@ -358,26 +397,32 @@ std::pair<StringRef, std::error_code> llvm::writeArchive(
GID = Status.getGroup();
Perms = Status.permissions();
} else {
- object::Archive::child_iterator OldMember = I.getOld();
- ModTime = OldMember->getLastModified();
- UID = OldMember->getUID();
- GID = OldMember->getGID();
- Perms = OldMember->getAccessMode();
+ 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, sys::path::filename(FileName),
+ printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
StringMapIndexIter, ModTime, UID, GID, Perms,
Status.getSize());
} else {
- object::Archive::child_iterator OldMember = I.getOld();
- printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter, ModTime,
- UID, GID, Perms, OldMember->getSize());
+ 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());
}
- Out << File.getBuffer();
+ if (!Thin)
+ Out << File.getBuffer();
if (Out.tell() % 2)
Out << '\n';
OpenPOWER on IntegriCloud