From b13e877e27d6b85f598a8a95b746acafcfb26710 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 8 Jul 2015 20:47:32 +0000 Subject: [PATCH] Start adding support for writing archives in BSD format. No support for the symbol table yet (but will hopefully add it today). We always use the long filename format so that we can align the member, which is an advantage of the BSD format. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241721 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ArchiveWriter.h | 3 +-- lib/LibDriver/LibDriver.cpp | 6 +++-- lib/Object/ArchiveWriter.cpp | 40 +++++++++++++++++++++-------- test/Object/archive-format.test | 10 ++++++++ tools/llvm-ar/llvm-ar.cpp | 26 +++++++++++++++++-- 5 files changed, 69 insertions(+), 16 deletions(-) diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index 1616e46d3e6..b6edf5882db 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -44,8 +44,7 @@ public: std::pair writeArchive(StringRef ArcName, std::vector &NewMembers, - bool WriteSymtab); - + bool WriteSymtab, object::Archive::Kind Kind); } #endif diff --git a/lib/LibDriver/LibDriver.cpp b/lib/LibDriver/LibDriver.cpp index bc3ed46040c..4a9fa28c84a 100644 --- a/lib/LibDriver/LibDriver.cpp +++ b/lib/LibDriver/LibDriver.cpp @@ -139,8 +139,10 @@ int llvm::libDriverMain(llvm::ArrayRef ArgsArr) { llvm::sys::path::filename(Arg->getValue())); } - std::pair Result = llvm::writeArchive( - getOutputPath(&Args, Members[0]), Members, /*WriteSymtab=*/true); + std::pair Result = + llvm::writeArchive(getOutputPath(&Args, Members[0]), Members, + /*WriteSymtab=*/true, object::Archive::K_GNU); + if (Result.second) { if (Result.first.empty()) Result.first = ArgsArr[0]; diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp index 41c82e7da74..99706a9bd5b 100644 --- a/lib/Object/ArchiveWriter.cpp +++ b/lib/Object/ArchiveWriter.cpp @@ -117,10 +117,25 @@ static void printMemberHeader(raw_fd_ostream &Out, StringRef Name, } static void -printMemberHeader(raw_fd_ostream &Out, StringRef Name, +printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind, + StringRef Name, std::vector::iterator &StringMapIndexIter, const sys::TimeValue &ModTime, unsigned UID, unsigned GID, unsigned Perms, unsigned Size) { + if (Kind == object::Archive::K_BSD) { + uint64_t PosAfterHeader = Out.tell() + 60 + Name.size(); + // Pad so that even 64 bit object files are aligned. + unsigned Pad = OffsetToAlignment(PosAfterHeader, 8); + unsigned NameWithPadding = Name.size() + Pad; + printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16); + printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, + NameWithPadding + Size); + Out << Name; + assert(PosAfterHeader == Out.tell()); + while (Pad--) + Out.write(uint8_t(0)); + return; + } if (Name.size() < 16) { printMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size); return; @@ -160,9 +175,13 @@ static void writeStringTable(raw_fd_ostream &Out, // Returns the offset of the first reference to a member offset. static ErrorOr -writeSymbolTable(raw_fd_ostream &Out, ArrayRef Members, +writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, + ArrayRef Members, ArrayRef Buffers, std::vector &MemberOffsetRefs) { + if (Kind != object::Archive::K_GNU) + return 0; + unsigned StartOffset = 0; unsigned MemberNum = 0; std::string NameBuf; @@ -222,7 +241,7 @@ writeSymbolTable(raw_fd_ostream &Out, ArrayRef Members, std::pair llvm::writeArchive(StringRef ArcName, std::vector &NewMembers, - bool WriteSymtab) { + bool WriteSymtab, object::Archive::Kind Kind) { SmallString<128> TmpArchive; int TmpArchiveFD; if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a", @@ -274,14 +293,15 @@ llvm::writeArchive(StringRef ArcName, unsigned MemberReferenceOffset = 0; if (WriteSymtab) { ErrorOr MemberReferenceOffsetOrErr = - writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs); + writeSymbolTable(Out, Kind, NewMembers, Members, MemberOffsetRefs); if (auto EC = MemberReferenceOffsetOrErr.getError()) return std::make_pair(ArcName, EC); MemberReferenceOffset = MemberReferenceOffsetOrErr.get(); } std::vector StringMapIndexes; - writeStringTable(Out, NewMembers, StringMapIndexes); + if (Kind != object::Archive::K_BSD) + writeStringTable(Out, NewMembers, StringMapIndexes); unsigned MemberNum = 0; unsigned NewMemberNum = 0; @@ -296,13 +316,13 @@ llvm::writeArchive(StringRef ArcName, if (I.isNewMember()) { StringRef FileName = I.getNew(); const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++]; - printMemberHeader(Out, sys::path::filename(FileName), StringMapIndexIter, - Status.getLastModificationTime(), Status.getUser(), - Status.getGroup(), Status.permissions(), - Status.getSize()); + printMemberHeader(Out, Kind, sys::path::filename(FileName), + StringMapIndexIter, Status.getLastModificationTime(), + Status.getUser(), Status.getGroup(), + Status.permissions(), Status.getSize()); } else { object::Archive::child_iterator OldMember = I.getOld(); - printMemberHeader(Out, I.getName(), StringMapIndexIter, + printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter, OldMember->getLastModified(), OldMember->getUID(), OldMember->getGID(), OldMember->getAccessMode(), OldMember->getSize()); diff --git a/test/Object/archive-format.test b/test/Object/archive-format.test index f076123d2ea..951177256b6 100644 --- a/test/Object/archive-format.test +++ b/test/Object/archive-format.test @@ -17,3 +17,13 @@ CHECK-NEXT: 0123456789abcdef/ CHECK-NEXT: 0123456789abcde/{{................................}}4 ` CHECK-NEXT: bar./0 {{................................}}4 ` CHECK-NEXT: zed. + +RUN: rm -f test-bsd.a +RUN: llvm-ar --format=bsd rc test-bsd.a 0123456789abcde 0123456789abcdef +RUN: cat test-bsd.a | FileCheck -strict-whitespace --check-prefix=BSD %s + +BSD: ! +BSD-NEXT: #1/20 {{..............................}} 24 ` +BSD-NEXT: 0123456789abcde{{.....}}bar. +BSD-SAME: #1/16 {{..............................}} 20 ` +BSD-NEXT: 0123456789abcdefzed. diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 0fd2df4f5aa..872c548454e 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -70,6 +70,16 @@ static cl::list static cl::opt MRI("M", cl::desc("")); +namespace { +enum Format { Default, GNU, BSD }; +} + +static cl::opt + FormatOpt("format", cl::desc("Archive format to create"), + cl::values(clEnumValN(Default, "defalut", "default"), + clEnumValN(GNU, "gnu", "gnu"), + clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd)); + std::string Options; // Provide additional help output explaining the operations and modifiers of @@ -539,15 +549,27 @@ computeNewArchiveMembers(ArchiveOperation Operation, static void performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, std::vector *NewMembersP) { + object::Archive::Kind Kind; + switch (FormatOpt) { + case Default: + // FIXME: change as the support for other formats improve. + Kind = object::Archive::K_GNU; + case GNU: + Kind = object::Archive::K_GNU; + break; + case BSD: + Kind = object::Archive::K_BSD; + break; + } if (NewMembersP) { std::pair Result = - writeArchive(ArchiveName, *NewMembersP, Symtab); + writeArchive(ArchiveName, *NewMembersP, Symtab, Kind); failIfError(Result.second, Result.first); return; } std::vector NewMembers = computeNewArchiveMembers(Operation, OldArchive); - auto Result = writeArchive(ArchiveName, NewMembers, Symtab); + auto Result = writeArchive(ArchiveName, NewMembers, Symtab, Kind); failIfError(Result.second, Result.first); } -- 2.34.1