From: Rafael Espindola Date: Mon, 13 Jul 2015 20:38:09 +0000 (+0000) Subject: Add support deterministic output in llvm-ar and make it the default. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=168b1bebf041862929ce42548a54ade29ae44e50;p=oota-llvm.git Add support deterministic output in llvm-ar and make it the default. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242061 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index a467b25f0bc..3648d0c77fb 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -43,7 +43,7 @@ public: std::pair writeArchive(StringRef ArcName, std::vector &NewMembers, - bool WriteSymtab, object::Archive::Kind Kind); + bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic); } #endif diff --git a/lib/LibDriver/LibDriver.cpp b/lib/LibDriver/LibDriver.cpp index 4a9fa28c84a..b33a22ff0cf 100644 --- a/lib/LibDriver/LibDriver.cpp +++ b/lib/LibDriver/LibDriver.cpp @@ -141,7 +141,8 @@ int llvm::libDriverMain(llvm::ArrayRef ArgsArr) { std::pair Result = llvm::writeArchive(getOutputPath(&Args, Members[0]), Members, - /*WriteSymtab=*/true, object::Archive::K_GNU); + /*WriteSymtab=*/true, object::Archive::K_GNU, + /*Deterministic*/ true); if (Result.second) { if (Result.first.empty()) diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp index 1148c847549..a40901c924e 100644 --- a/lib/Object/ArchiveWriter.cpp +++ b/lib/Object/ArchiveWriter.cpp @@ -178,12 +178,20 @@ static void writeStringTable(raw_fd_ostream &Out, Out.seek(Pos); } +static sys::TimeValue now(bool Deterministic) { + if (!Deterministic) + return sys::TimeValue::now(); + sys::TimeValue TV; + TV.fromEpochTime(0); + return TV; +} + // Returns the offset of the first reference to a member offset. static ErrorOr writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, ArrayRef Members, ArrayRef Buffers, - std::vector &MemberOffsetRefs) { + std::vector &MemberOffsetRefs, bool Deterministic) { unsigned HeaderStartOffset = 0; unsigned BodyStartOffset = 0; SmallString<128> NameBuf; @@ -201,10 +209,9 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, if (!HeaderStartOffset) { HeaderStartOffset = Out.tell(); if (Kind == object::Archive::K_GNU) - printGNUSmallMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); + printGNUSmallMemberHeader(Out, "", now(Deterministic), 0, 0, 0, 0); else - printBSDMemberHeader(Out, "__.SYMDEF", sys::TimeValue::now(), 0, 0, 0, - 0); + printBSDMemberHeader(Out, "__.SYMDEF", now(Deterministic), 0, 0, 0, 0); BodyStartOffset = Out.tell(); print32(Out, Kind, 0); // number of entries or bytes } @@ -261,10 +268,9 @@ 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) { +std::pair llvm::writeArchive( + StringRef ArcName, std::vector &NewMembers, + bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic) { SmallString<128> TmpArchive; int TmpArchiveFD; if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a", @@ -315,8 +321,8 @@ llvm::writeArchive(StringRef ArcName, unsigned MemberReferenceOffset = 0; if (WriteSymtab) { - ErrorOr MemberReferenceOffsetOrErr = - writeSymbolTable(Out, Kind, NewMembers, Members, MemberOffsetRefs); + ErrorOr MemberReferenceOffsetOrErr = writeSymbolTable( + Out, Kind, NewMembers, Members, MemberOffsetRefs, Deterministic); if (auto EC = MemberReferenceOffsetOrErr.getError()) return std::make_pair(ArcName, EC); MemberReferenceOffset = MemberReferenceOffsetOrErr.get(); @@ -336,19 +342,39 @@ llvm::writeArchive(StringRef ArcName, 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 { + object::Archive::child_iterator 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), - StringMapIndexIter, Status.getLastModificationTime(), - Status.getUser(), Status.getGroup(), - Status.permissions(), Status.getSize()); + StringMapIndexIter, ModTime, UID, GID, Perms, + Status.getSize()); } else { object::Archive::child_iterator OldMember = I.getOld(); - printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter, - OldMember->getLastModified(), OldMember->getUID(), - OldMember->getGID(), OldMember->getAccessMode(), - OldMember->getSize()); + printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter, ModTime, + UID, GID, Perms, OldMember->getSize()); } Out << File.getBuffer(); diff --git a/test/Object/archive-format.test b/test/Object/archive-format.test index 51fa72a1f7b..40af9a33d8d 100644 --- a/test/Object/archive-format.test +++ b/test/Object/archive-format.test @@ -7,23 +7,23 @@ RUN: cd %t RUN: echo -n bar. > 0123456789abcde RUN: echo -n zed. > 0123456789abcdef -RUN: rm -f test.a -RUN: llvm-ar --format=gnu rc test.a 0123456789abcde 0123456789abcdef -RUN: cat test.a | FileCheck -strict-whitespace %s +RUN: rm -f %t.a +RUN: llvm-ar --format=gnu rc %t.a 0123456789abcde 0123456789abcdef +RUN: cat %t.a | FileCheck -strict-whitespace %s CHECK: ! CHECK-NEXT: // 18 ` CHECK-NEXT: 0123456789abcdef/ -CHECK-NEXT: 0123456789abcde/{{................................}}4 ` -CHECK-NEXT: bar./0 {{................................}}4 ` +CHECK-NEXT: 0123456789abcde/0 0 0 644 4 ` +CHECK-NEXT: bar./0 0 0 0 644 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 +RUN: rm -f %t.a +RUN: llvm-ar --format=bsd rc %t.a 0123456789abcde 0123456789abcdef +RUN: cat %t.a | FileCheck -strict-whitespace --check-prefix=BSD %s BSD: ! -BSD-NEXT: #1/20 {{..............................}} 24 ` +BSD-NEXT: #1/20 0 0 0 644 24 ` BSD-NEXT: 0123456789abcde{{.....}}bar. -BSD-SAME: #1/16 {{..............................}} 20 ` +BSD-SAME: #1/16 0 0 0 644 20 ` BSD-NEXT: 0123456789abcdefzed. diff --git a/test/Object/archive-symtab.test b/test/Object/archive-symtab.test index 5f648ebc109..6e4c76fb376 100644 --- a/test/Object/archive-symtab.test +++ b/test/Object/archive-symtab.test @@ -1,5 +1,5 @@ RUN: rm -f %t.a -RUN: llvm-ar rcs %t.a %p/Inputs/trivial-object-test.elf-x86-64 %p/Inputs/trivial-object-test2.elf-x86-64 +RUN: llvm-ar rcsU %t.a %p/Inputs/trivial-object-test.elf-x86-64 %p/Inputs/trivial-object-test2.elf-x86-64 RUN: llvm-nm -M %t.a | FileCheck %s CHECK: Archive map @@ -19,7 +19,7 @@ CHECK-NEXT: 0000000000000006 T foo CHECK-NEXT: 0000000000000016 T main RUN: rm -f %t.a -RUN: llvm-ar rcS %t.a %p/Inputs/trivial-object-test.elf-x86-64 %p/Inputs/trivial-object-test2.elf-x86-64 +RUN: llvm-ar rcSU %t.a %p/Inputs/trivial-object-test.elf-x86-64 %p/Inputs/trivial-object-test2.elf-x86-64 RUN: llvm-nm -M %t.a | FileCheck %s --check-prefix=NOMAP NOMAP-NOT: Archive map @@ -54,7 +54,7 @@ RUN: llvm-nm -M %t.a | FileCheck %s --check-prefix=CORRUPT repeate the test with llvm-ranlib RUN: rm -f %t.a -RUN: llvm-ar rcS %t.a %p/Inputs/trivial-object-test.elf-x86-64 %p/Inputs/trivial-object-test2.elf-x86-64 +RUN: llvm-ar rcSU %t.a %p/Inputs/trivial-object-test.elf-x86-64 %p/Inputs/trivial-object-test2.elf-x86-64 RUN: llvm-nm -M %t.a | FileCheck %s --check-prefix=NOMAP RUN: llvm-ranlib %t.a @@ -68,7 +68,7 @@ BSD-MachO: _bar in bar.o BSD-MachO: _foo in foo.o RUN: rm -f %t.a -RUN: llvm-ar --format=bsd rcs %t.a %p/Inputs/trivial-object-test.macho-x86-64 %p/Inputs/trivial-object-test2.macho-x86-64 +RUN: llvm-ar --format=bsd rcsU %t.a %p/Inputs/trivial-object-test.macho-x86-64 %p/Inputs/trivial-object-test2.macho-x86-64 RUN: llvm-nm -M %t.a | FileCheck --check-prefix=MACHO %s MACHO: Archive map @@ -91,7 +91,7 @@ MACHO-NEXT: 0000000000000002 T _main Test that we pad the symbol table so that it ends in a multiple of 4 bytes: 8 + 60 + 36 == 104 RUN: rm -f %t.a -RUN: llvm-ar --format=bsd rcs %t.a %p/Inputs/trivial-object-test.macho-x86-64 +RUN: llvm-ar --format=bsd rcsU %t.a %p/Inputs/trivial-object-test.macho-x86-64 RUN: FileCheck --check-prefix=MACHO-SYMTAB-ALIGN %s < %t.a MACHO-SYMTAB-ALIGN: ! MACHO-SYMTAB-ALIGN-NEXT: #1/12 {{..........}} 0 0 0 36 ` diff --git a/test/Object/archive-update.test b/test/Object/archive-update.test index 91ca8102c7e..450b5cd4ed8 100644 --- a/test/Object/archive-update.test +++ b/test/Object/archive-update.test @@ -16,19 +16,19 @@ RUN: echo newer > %t.newer/evenlen RUN: touch %t.newer/evenlen Create an achive with the newest file -RUN: llvm-ar r %t.a %t.newer/evenlen +RUN: llvm-ar rU %t.a %t.newer/evenlen RUN: llvm-ar p %t.a | FileCheck --check-prefix=NEWER %s Check that without the 'u' option the member is replaced with an older file. -RUN: llvm-ar r %t.a %t.older/evenlen +RUN: llvm-ar rU %t.a %t.older/evenlen RUN: llvm-ar p %t.a | FileCheck --check-prefix=OLDER %s Check that with the 'u' option the member is replaced with a newer file. -RUN: llvm-ar ru %t.a %t.newer/evenlen +RUN: llvm-ar ruU %t.a %t.newer/evenlen RUN: llvm-ar p %t.a | FileCheck --check-prefix=NEWER %s Check that with the 'u' option the member is not replaced with an older file. -RUN: llvm-ar ru %t.a %t.older/evenlen +RUN: llvm-ar ruU %t.a %t.older/evenlen RUN: llvm-ar p %t.a | FileCheck --check-prefix=NEWER %s NEWER: newer diff --git a/test/Object/extract.ll b/test/Object/extract.ll index 8d77f09fe88..69d5ff107b4 100644 --- a/test/Object/extract.ll +++ b/test/Object/extract.ll @@ -39,7 +39,7 @@ ; RUN: rm -f very_long_bytecode_file_name.bc ; RUN: llvm-ar xo %p/Inputs/GNU.a very_long_bytecode_file_name.bc ; RUN: rm -f %t.a -; RUN: llvm-ar rc %t.a very_long_bytecode_file_name.bc +; RUN: llvm-ar rcU %t.a very_long_bytecode_file_name.bc ; RUN: env TZ=GMT llvm-ar tv %t.a | FileCheck %s CHECK: 1465 2004-11-19 03:01:31.000000000 very_long_bytecode_file_name.bc diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 66daba30a4a..698c9bb38c9 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -129,6 +129,7 @@ static bool OriginalDates = false; ///< 'o' modifier 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 // Relative Positional Argument (for insert/move). This variable holds // the name of the archive member to which the 'a', 'b' or 'i' modifier @@ -245,6 +246,12 @@ static ArchiveOperation parseCommandLine() { AddBefore = true; NumPositional++; break; + case 'D': + Deterministic = true; + break; + case 'U': + Deterministic = false; + break; default: cl::PrintHelpMessage(); } @@ -570,13 +577,14 @@ performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, } if (NewMembersP) { std::pair Result = - writeArchive(ArchiveName, *NewMembersP, Symtab, Kind); + writeArchive(ArchiveName, *NewMembersP, Symtab, Kind, Deterministic); failIfError(Result.second, Result.first); return; } std::vector NewMembers = computeNewArchiveMembers(Operation, OldArchive); - auto Result = writeArchive(ArchiveName, NewMembers, Symtab, Kind); + auto Result = + writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic); failIfError(Result.second, Result.first); }