diff options
| -rw-r--r-- | llvm/test/Object/mri-addmod.test | 18 | ||||
| -rw-r--r-- | llvm/tools/llvm-ar/llvm-ar.cpp | 142 |
2 files changed, 93 insertions, 67 deletions
diff --git a/llvm/test/Object/mri-addmod.test b/llvm/test/Object/mri-addmod.test index b8a41debc1d..3a59a3bbd96 100644 --- a/llvm/test/Object/mri-addmod.test +++ b/llvm/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/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index 22fa291fbab..a6517e8510d 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/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<std::string> MRIMembers; -static ArchiveOperation parseMRIScript() { - ErrorOr<std::unique_ptr<MemoryBuffer>> 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<MRICommand>(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<NewArchiveIterator> Members, Out.seek(Pos); } -static void performWriteOperation(ArchiveOperation Operation, - object::Archive *OldArchive) { +static void +performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, + std::vector<NewArchiveIterator> &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 << "!<arch>\n"; - std::vector<NewArchiveIterator> NewMembers = - computeNewArchiveMembers(Operation, OldArchive); - std::vector<std::pair<unsigned, unsigned> > MemberOffsetRefs; std::vector<std::unique_ptr<MemoryBuffer>> Buffers; @@ -914,6 +860,18 @@ static void performWriteOperation(ArchiveOperation Operation, TemporaryOutput = nullptr; } +static void +performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, + std::vector<NewArchiveIterator> *NewMembersP) { + if (NewMembersP) { + performWriteOperation(Operation, OldArchive, *NewMembersP); + return; + } + std::vector<NewArchiveIterator> 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<NewArchiveIterator> *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<NewArchiveIterator> *NewMembers) { // Create or open the archive object. ErrorOr<std::unique_ptr<MemoryBuffer>> 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<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getSTDIN(); + failIfError(Buf.getError()); + const MemoryBuffer &Ref = *Buf.get(); + bool Saved = false; + std::vector<NewArchiveIterator> 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<MRICommand>(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) { |

