From e539932aad0e5b0cb2c506c6a790a176749d29cf Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 21 Oct 2014 21:56:47 +0000 Subject: [PATCH] Overwrite instead of adding to archives when creating them in mri scripts. This matches the behavior of GNU ar and also makes it easier to implemnt support for the addlib command. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220336 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Object/mri-addmod.test | 18 +++++ tools/llvm-ar/llvm-ar.cpp | 142 +++++++++++++++++++----------------- 2 files changed, 93 insertions(+), 67 deletions(-) diff --git a/test/Object/mri-addmod.test b/test/Object/mri-addmod.test index b8a41debc1d..3a59a3bbd96 100644 --- a/test/Object/mri-addmod.test +++ b/test/Object/mri-addmod.test @@ -14,5 +14,23 @@ ; CHECK-NEXT: 0000000000000000 T main ; CHECK-NEXT: U puts +; Now test that CREATE overwrites an existing file. +; RUN: echo create %t.a > %t2.mri +; RUN: echo addmod %p/Inputs/trivial-object-test2.elf-x86-64 >> %t2.mri +; RUN: echo save >> %t2.mri +; RUN: echo end >> %t2.mri + +; RUN: llvm-ar -M < %t2.mri +; RUN: llvm-nm -M %t.a | FileCheck --check-prefix=NEW %s + +; NEW: Archive map +; NEW-NEXT: foo in trivial-object-test2.elf-x86-64 +; NEW-NEXT: main in trivial-object-test2.elf-x86-64 + +; NEW: trivial-object-test2.elf-x86-64: +; NEW-NEXT: 0000000000000000 t bar +; NEW-NEXT: 0000000000000006 T foo +; NEW-NEXT: 0000000000000016 T main + ; line_iterator is incompatible to CRLF. ; REQUIRES: shell diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 22fa291fbab..a6517e8510d 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -176,59 +176,7 @@ static void getMembers() { Members.push_back(Arg); } -namespace { -enum class MRICommand { AddMod, Create, Save, End, Invalid }; -} - -static std::vector MRIMembers; -static ArchiveOperation parseMRIScript() { - ErrorOr> Buf = MemoryBuffer::getSTDIN(); - failIfError(Buf.getError()); - const MemoryBuffer &Ref = *Buf.get(); - bool Saved = false; - - for (line_iterator I(Ref, /*SkipBlanks*/ true, ';'), E; I != E; ++I) { - StringRef Line = *I; - StringRef CommandStr, Rest; - std::tie(CommandStr, Rest) = Line.split(' '); - auto Command = StringSwitch(CommandStr.lower()) - .Case("addmod", MRICommand::AddMod) - .Case("create", MRICommand::Create) - .Case("save", MRICommand::Save) - .Case("end", MRICommand::End) - .Default(MRICommand::Invalid); - - switch (Command) { - case MRICommand::AddMod: - MRIMembers.push_back(Rest); - break; - case MRICommand::Create: - Create = true; - if (!ArchiveName.empty()) - fail("Editing multiple archives not supported"); - if (Saved) - fail("File already saved"); - ArchiveName = Rest; - break; - case MRICommand::Save: - Saved = true; - break; - case MRICommand::End: - break; - case MRICommand::Invalid: - fail("Unknown command: " + CommandStr); - } - } - - // Nothing to do if not saved. - if (!Saved) - exit(0); - - for (auto &M : MRIMembers) - Members.push_back(M); - - return ReplaceOrInsert; -} +static void runMRIScript(); // Parse the command line options as presented and return the operation // specified. Process all modifiers and check to make sure that constraints on @@ -237,7 +185,7 @@ static ArchiveOperation parseCommandLine() { if (MRI) { if (!RestOfArgs.empty()) fail("Cannot mix -M and other options"); - return parseMRIScript(); + runMRIScript(); } getOptions(); @@ -805,8 +753,9 @@ writeSymbolTable(raw_fd_ostream &Out, ArrayRef Members, Out.seek(Pos); } -static void performWriteOperation(ArchiveOperation Operation, - object::Archive *OldArchive) { +static void +performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, + std::vector &NewMembers) { SmallString<128> TmpArchive; failIfError(sys::fs::createUniqueFile(ArchiveName + ".temp-archive-%%%%%%%.a", TmpArchiveFD, TmpArchive)); @@ -816,9 +765,6 @@ static void performWriteOperation(ArchiveOperation Operation, raw_fd_ostream &Out = Output.os(); Out << "!\n"; - std::vector NewMembers = - computeNewArchiveMembers(Operation, OldArchive); - std::vector > MemberOffsetRefs; std::vector> Buffers; @@ -914,6 +860,18 @@ static void performWriteOperation(ArchiveOperation Operation, TemporaryOutput = nullptr; } +static void +performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, + std::vector *NewMembersP) { + if (NewMembersP) { + performWriteOperation(Operation, OldArchive, *NewMembersP); + return; + } + std::vector NewMembers = + computeNewArchiveMembers(Operation, OldArchive); + performWriteOperation(Operation, OldArchive, NewMembers); +} + static void createSymbolTable(object::Archive *OldArchive) { // When an archive is created or modified, if the s option is given, the // resulting archive will have a current symbol table. If the S option @@ -924,11 +882,12 @@ static void createSymbolTable(object::Archive *OldArchive) { if (OldArchive->hasSymbolTable()) return; - performWriteOperation(CreateSymTab, OldArchive); + performWriteOperation(CreateSymTab, OldArchive, nullptr); } static void performOperation(ArchiveOperation Operation, - object::Archive *OldArchive) { + object::Archive *OldArchive, + std::vector *NewMembers) { switch (Operation) { case Print: case DisplayTable: @@ -940,7 +899,7 @@ static void performOperation(ArchiveOperation Operation, case Move: case QuickAppend: case ReplaceOrInsert: - performWriteOperation(Operation, OldArchive); + performWriteOperation(Operation, OldArchive, NewMembers); return; case CreateSymTab: createSymbolTable(OldArchive); @@ -949,7 +908,8 @@ static void performOperation(ArchiveOperation Operation, llvm_unreachable("Unknown operation."); } -static int performOperation(ArchiveOperation Operation) { +static int performOperation(ArchiveOperation Operation, + std::vector *NewMembers) { // Create or open the archive object. ErrorOr> Buf = MemoryBuffer::getFile(ArchiveName, -1, false); @@ -968,7 +928,7 @@ static int performOperation(ArchiveOperation Operation) { << "': " << EC.message() << "!\n"; return 1; } - performOperation(Operation, &Archive); + performOperation(Operation, &Archive, NewMembers); return 0; } @@ -983,22 +943,70 @@ static int performOperation(ArchiveOperation Operation) { } } - performOperation(Operation, nullptr); + performOperation(Operation, nullptr, NewMembers); return 0; } +static void runMRIScript() { + enum class MRICommand { AddMod, Create, Save, End, Invalid }; + + ErrorOr> Buf = MemoryBuffer::getSTDIN(); + failIfError(Buf.getError()); + const MemoryBuffer &Ref = *Buf.get(); + bool Saved = false; + std::vector NewMembers; + + for (line_iterator I(Ref, /*SkipBlanks*/ true, ';'), E; I != E; ++I) { + StringRef Line = *I; + StringRef CommandStr, Rest; + std::tie(CommandStr, Rest) = Line.split(' '); + auto Command = StringSwitch(CommandStr.lower()) + .Case("addmod", MRICommand::AddMod) + .Case("create", MRICommand::Create) + .Case("save", MRICommand::Save) + .Case("end", MRICommand::End) + .Default(MRICommand::Invalid); + + switch (Command) { + case MRICommand::AddMod: + addMember(NewMembers, Rest, sys::path::filename(Rest)); + break; + case MRICommand::Create: + Create = true; + if (!ArchiveName.empty()) + fail("Editing multiple archives not supported"); + if (Saved) + fail("File already saved"); + ArchiveName = Rest; + break; + case MRICommand::Save: + Saved = true; + break; + case MRICommand::End: + break; + case MRICommand::Invalid: + fail("Unknown command: " + CommandStr); + } + } + + // Nothing to do if not saved. + if (Saved) + performOperation(ReplaceOrInsert, &NewMembers); + exit(0); +} + int ar_main(char **argv) { // Do our own parsing of the command line because the CommandLine utility // can't handle the grouped positional parameters without a dash. ArchiveOperation Operation = parseCommandLine(); - return performOperation(Operation); + return performOperation(Operation, nullptr); } int ranlib_main() { if (RestOfArgs.size() != 1) fail(ToolName + "takes just one archive as argument"); ArchiveName = RestOfArgs[0]; - return performOperation(CreateSymTab); + return performOperation(CreateSymTab, nullptr); } int main(int argc, char **argv) { -- 2.34.1