From 71571d65a9a2943e05643c205279a8850b313598 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 15 Jul 2015 05:47:46 +0000 Subject: [PATCH] Initial support for writing thin archives. llvm-svn: 242269 --- include/llvm/Object/ArchiveWriter.h | 3 ++- lib/LibDriver/LibDriver.cpp | 2 +- lib/Object/ArchiveWriter.cpp | 37 +++++++++++++++++++---------- test/Object/archive-format.test | 11 +++++++++ tools/llvm-ar/llvm-ar.cpp | 10 +++++--- 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index 3648d0c77fb..9d1dd61bf66 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -43,7 +43,8 @@ public: std::pair writeArchive(StringRef ArcName, std::vector &NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic); + bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, + bool Thin); } #endif diff --git a/lib/LibDriver/LibDriver.cpp b/lib/LibDriver/LibDriver.cpp index b33a22ff0cf..98148750204 100644 --- a/lib/LibDriver/LibDriver.cpp +++ b/lib/LibDriver/LibDriver.cpp @@ -142,7 +142,7 @@ int llvm::libDriverMain(llvm::ArrayRef ArgsArr) { std::pair Result = llvm::writeArchive(getOutputPath(&Args, Members[0]), Members, /*WriteSymtab=*/true, object::Archive::K_GNU, - /*Deterministic*/ true); + /*Deterministic*/ true, /*Thin*/ false); if (Result.second) { if (Result.first.empty()) diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp index dd7af472565..bcd5382d91e 100644 --- a/lib/Object/ArchiveWriter.cpp +++ b/lib/Object/ArchiveWriter.cpp @@ -135,15 +135,19 @@ 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::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); @@ -152,11 +156,12 @@ printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind, static void writeStringTable(raw_fd_ostream &Out, ArrayRef Members, - std::vector &StringMapIndexes) { + std::vector &StringMapIndexes, + bool Thin) { unsigned StartOffset = 0; for (const NewArchiveIterator &I : Members) { StringRef Name = I.getName(); - if (Name.size() < 16) + if (!useStringTable(Thin, Name)) continue; if (StartOffset == 0) { printWithSpacePadding(Out, "//", 58); @@ -266,9 +271,11 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, return BodyStartOffset + 4; } -std::pair llvm::writeArchive( - StringRef ArcName, std::vector &NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic) { +std::pair +llvm::writeArchive(StringRef ArcName, + std::vector &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", @@ -277,7 +284,10 @@ std::pair llvm::writeArchive( tool_output_file Output(TmpArchive, TmpArchiveFD); raw_fd_ostream &Out = Output.os(); - Out << "!\n"; + if (Thin) + Out << "!\n"; + else + Out << "!\n"; std::vector MemberOffsetRefs; @@ -328,7 +338,7 @@ std::pair llvm::writeArchive( std::vector StringMapIndexes; if (Kind != object::Archive::K_BSD) - writeStringTable(Out, NewMembers, StringMapIndexes); + writeStringTable(Out, NewMembers, StringMapIndexes, Thin); unsigned MemberNum = 0; unsigned NewMemberNum = 0; @@ -366,16 +376,17 @@ std::pair llvm::writeArchive( 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()); + printMemberHeader(Out, Kind, Thin, I.getName(), StringMapIndexIter, + ModTime, UID, GID, Perms, OldMember->getSize()); } - Out << File.getBuffer(); + if (!Thin) + Out << File.getBuffer(); if (Out.tell() % 2) Out << '\n'; diff --git a/test/Object/archive-format.test b/test/Object/archive-format.test index 40af9a33d8d..376eb053c6d 100644 --- a/test/Object/archive-format.test +++ b/test/Object/archive-format.test @@ -27,3 +27,14 @@ BSD-NEXT: #1/20 0 0 0 644 24 ` BSD-NEXT: 0123456789abcde{{.....}}bar. BSD-SAME: #1/16 0 0 0 644 20 ` BSD-NEXT: 0123456789abcdefzed. + +RUN: rm -f %t.a +RUN: llvm-ar --format=gnu rcT %t.a 0123456789abcde 0123456789abcdef +RUN: cat %t.a | FileCheck -strict-whitespace --check-prefix=THIN %s +THIN: ! +THIN-NEXT: // 36 ` +THIN-NEXT: 0123456789abcde/ +THIN-NEXT: 0123456789abcdef/{{$}} +THIN: {{^$}} +THIN: /0 0 0 0 644 4 ` +THIN-NEXT: /17 0 0 0 644 4 ` diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 2c9668c63b8..0e3c4fdc2ce 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -130,6 +130,7 @@ static bool OnlyUpdate = false; ///< 'u' modifier static bool Verbose = false; ///< 'v' modifier static bool Symtab = true; ///< 's' modifier static bool Deterministic = true; ///< 'D' and 'U' modifiers +static bool Thin = false; ///< 'T' modifier // Relative Positional Argument (for insert/move). This variable holds // the name of the archive member to which the 'a', 'b' or 'i' modifier @@ -252,6 +253,9 @@ static ArchiveOperation parseCommandLine() { case 'U': Deterministic = false; break; + case 'T': + Thin = true; + break; default: cl::PrintHelpMessage(); } @@ -590,15 +594,15 @@ performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, break; } if (NewMembersP) { - std::pair Result = - writeArchive(ArchiveName, *NewMembersP, Symtab, Kind, Deterministic); + std::pair Result = writeArchive( + ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin); failIfError(Result.second, Result.first); return; } std::vector NewMembers = computeNewArchiveMembers(Operation, OldArchive); auto Result = - writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic); + writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin); failIfError(Result.second, Result.first); }