llvm-ar.cpp revision 327952
1//===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Builds up (relatively) standard unix archive files (.a) containing LLVM 11// bitcode or other files. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/ADT/StringSwitch.h" 16#include "llvm/ADT/Triple.h" 17#include "llvm/IR/LLVMContext.h" 18#include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h" 19#include "llvm/ToolDrivers/llvm-lib/LibDriver.h" 20#include "llvm/Object/Archive.h" 21#include "llvm/Object/ArchiveWriter.h" 22#include "llvm/Object/MachO.h" 23#include "llvm/Object/ObjectFile.h" 24#include "llvm/Support/Chrono.h" 25#include "llvm/Support/CommandLine.h" 26#include "llvm/Support/Errc.h" 27#include "llvm/Support/FileSystem.h" 28#include "llvm/Support/Format.h" 29#include "llvm/Support/LineIterator.h" 30#include "llvm/Support/ManagedStatic.h" 31#include "llvm/Support/MemoryBuffer.h" 32#include "llvm/Support/Path.h" 33#include "llvm/Support/PrettyStackTrace.h" 34#include "llvm/Support/Signals.h" 35#include "llvm/Support/TargetSelect.h" 36#include "llvm/Support/ToolOutputFile.h" 37#include "llvm/Support/raw_ostream.h" 38 39#if !defined(_MSC_VER) && !defined(__MINGW32__) 40#include <unistd.h> 41#else 42#include <io.h> 43#endif 44 45using namespace llvm; 46 47// The name this program was invoked as. 48static StringRef ToolName; 49 50// Show the error message and exit. 51LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) { 52 errs() << ToolName << ": " << Error << ".\n"; 53 cl::PrintHelpMessage(); 54 exit(1); 55} 56 57static void failIfError(std::error_code EC, Twine Context = "") { 58 if (!EC) 59 return; 60 61 std::string ContextStr = Context.str(); 62 if (ContextStr == "") 63 fail(EC.message()); 64 fail(Context + ": " + EC.message()); 65} 66 67static void failIfError(Error E, Twine Context = "") { 68 if (!E) 69 return; 70 71 handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) { 72 std::string ContextStr = Context.str(); 73 if (ContextStr == "") 74 fail(EIB.message()); 75 fail(Context + ": " + EIB.message()); 76 }); 77} 78 79// llvm-ar/llvm-ranlib remaining positional arguments. 80static cl::list<std::string> 81 RestOfArgs(cl::Positional, cl::ZeroOrMore, 82 cl::desc("[relpos] [count] <archive-file> [members]...")); 83 84static cl::opt<bool> MRI("M", cl::desc("")); 85static cl::opt<std::string> Plugin("plugin", cl::desc("plugin (ignored for compatibility")); 86 87namespace { 88enum Format { Default, GNU, BSD, DARWIN }; 89} 90 91static cl::opt<Format> 92 FormatOpt("format", cl::desc("Archive format to create"), 93 cl::values(clEnumValN(Default, "default", "default"), 94 clEnumValN(GNU, "gnu", "gnu"), 95 clEnumValN(DARWIN, "darwin", "darwin"), 96 clEnumValN(BSD, "bsd", "bsd"))); 97 98static std::string Options; 99 100// Provide additional help output explaining the operations and modifiers of 101// llvm-ar. This object instructs the CommandLine library to print the text of 102// the constructor when the --help option is given. 103static cl::extrahelp MoreHelp( 104 "\nOPERATIONS:\n" 105 " d[NsS] - delete file(s) from the archive\n" 106 " m[abiSs] - move file(s) in the archive\n" 107 " p[kN] - print file(s) found in the archive\n" 108 " q[ufsS] - quick append file(s) to the archive\n" 109 " r[abfiuRsS] - replace or insert file(s) into the archive\n" 110 " t - display contents of archive\n" 111 " x[No] - extract file(s) from the archive\n" 112 "\nMODIFIERS (operation specific):\n" 113 " [a] - put file(s) after [relpos]\n" 114 " [b] - put file(s) before [relpos] (same as [i])\n" 115 " [i] - put file(s) before [relpos] (same as [b])\n" 116 " [o] - preserve original dates\n" 117 " [s] - create an archive index (cf. ranlib)\n" 118 " [S] - do not build a symbol table\n" 119 " [T] - create a thin archive\n" 120 " [u] - update only files newer than archive contents\n" 121 "\nMODIFIERS (generic):\n" 122 " [c] - do not warn if the library had to be created\n" 123 " [v] - be verbose about actions taken\n" 124); 125 126static const char OptionChars[] = "dmpqrtxabiosSTucv"; 127 128// This enumeration delineates the kinds of operations on an archive 129// that are permitted. 130enum ArchiveOperation { 131 Print, ///< Print the contents of the archive 132 Delete, ///< Delete the specified members 133 Move, ///< Move members to end or as given by {a,b,i} modifiers 134 QuickAppend, ///< Quickly append to end of archive 135 ReplaceOrInsert, ///< Replace or Insert members 136 DisplayTable, ///< Display the table of contents 137 Extract, ///< Extract files back to file system 138 CreateSymTab ///< Create a symbol table in an existing archive 139}; 140 141// Modifiers to follow operation to vary behavior 142static bool AddAfter = false; ///< 'a' modifier 143static bool AddBefore = false; ///< 'b' modifier 144static bool Create = false; ///< 'c' modifier 145static bool OriginalDates = false; ///< 'o' modifier 146static bool OnlyUpdate = false; ///< 'u' modifier 147static bool Verbose = false; ///< 'v' modifier 148static bool Symtab = true; ///< 's' modifier 149static bool Deterministic = true; ///< 'D' and 'U' modifiers 150static bool Thin = false; ///< 'T' modifier 151 152// Relative Positional Argument (for insert/move). This variable holds 153// the name of the archive member to which the 'a', 'b' or 'i' modifier 154// refers. Only one of 'a', 'b' or 'i' can be specified so we only need 155// one variable. 156static std::string RelPos; 157 158// This variable holds the name of the archive file as given on the 159// command line. 160static std::string ArchiveName; 161 162// This variable holds the list of member files to proecess, as given 163// on the command line. 164static std::vector<StringRef> Members; 165 166// Extract the member filename from the command line for the [relpos] argument 167// associated with a, b, and i modifiers 168static void getRelPos() { 169 if(RestOfArgs.size() == 0) 170 fail("Expected [relpos] for a, b, or i modifier"); 171 RelPos = RestOfArgs[0]; 172 RestOfArgs.erase(RestOfArgs.begin()); 173} 174 175static void getOptions() { 176 if(RestOfArgs.size() == 0) 177 fail("Expected options"); 178 Options = RestOfArgs[0]; 179 RestOfArgs.erase(RestOfArgs.begin()); 180} 181 182// Get the archive file name from the command line 183static void getArchive() { 184 if(RestOfArgs.size() == 0) 185 fail("An archive name must be specified"); 186 ArchiveName = RestOfArgs[0]; 187 RestOfArgs.erase(RestOfArgs.begin()); 188} 189 190// Copy over remaining items in RestOfArgs to our Members vector 191static void getMembers() { 192 for (auto &Arg : RestOfArgs) 193 Members.push_back(Arg); 194} 195 196static void runMRIScript(); 197 198// Parse the command line options as presented and return the operation 199// specified. Process all modifiers and check to make sure that constraints on 200// modifier/operation pairs have not been violated. 201static ArchiveOperation parseCommandLine() { 202 if (MRI) { 203 if (!RestOfArgs.empty()) 204 fail("Cannot mix -M and other options"); 205 runMRIScript(); 206 } 207 208 getOptions(); 209 210 // Keep track of number of operations. We can only specify one 211 // per execution. 212 unsigned NumOperations = 0; 213 214 // Keep track of the number of positional modifiers (a,b,i). Only 215 // one can be specified. 216 unsigned NumPositional = 0; 217 218 // Keep track of which operation was requested 219 ArchiveOperation Operation; 220 221 bool MaybeJustCreateSymTab = false; 222 223 for(unsigned i=0; i<Options.size(); ++i) { 224 switch(Options[i]) { 225 case 'd': ++NumOperations; Operation = Delete; break; 226 case 'm': ++NumOperations; Operation = Move ; break; 227 case 'p': ++NumOperations; Operation = Print; break; 228 case 'q': ++NumOperations; Operation = QuickAppend; break; 229 case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 230 case 't': ++NumOperations; Operation = DisplayTable; break; 231 case 'x': ++NumOperations; Operation = Extract; break; 232 case 'c': Create = true; break; 233 case 'l': /* accepted but unused */ break; 234 case 'o': OriginalDates = true; break; 235 case 's': 236 Symtab = true; 237 MaybeJustCreateSymTab = true; 238 break; 239 case 'S': 240 Symtab = false; 241 break; 242 case 'u': OnlyUpdate = true; break; 243 case 'v': Verbose = true; break; 244 case 'a': 245 getRelPos(); 246 AddAfter = true; 247 NumPositional++; 248 break; 249 case 'b': 250 getRelPos(); 251 AddBefore = true; 252 NumPositional++; 253 break; 254 case 'i': 255 getRelPos(); 256 AddBefore = true; 257 NumPositional++; 258 break; 259 case 'D': 260 Deterministic = true; 261 break; 262 case 'U': 263 Deterministic = false; 264 break; 265 case 'T': 266 Thin = true; 267 break; 268 default: 269 fail(std::string("unknown option ") + Options[i]); 270 } 271 } 272 273 // At this point, the next thing on the command line must be 274 // the archive name. 275 getArchive(); 276 277 // Everything on the command line at this point is a member. 278 getMembers(); 279 280 if (NumOperations == 0 && MaybeJustCreateSymTab) { 281 NumOperations = 1; 282 Operation = CreateSymTab; 283 if (!Members.empty()) 284 fail("The s operation takes only an archive as argument"); 285 } 286 287 // Perform various checks on the operation/modifier specification 288 // to make sure we are dealing with a legal request. 289 if (NumOperations == 0) 290 fail("You must specify at least one of the operations"); 291 if (NumOperations > 1) 292 fail("Only one operation may be specified"); 293 if (NumPositional > 1) 294 fail("You may only specify one of a, b, and i modifiers"); 295 if (AddAfter || AddBefore) { 296 if (Operation != Move && Operation != ReplaceOrInsert) 297 fail("The 'a', 'b' and 'i' modifiers can only be specified with " 298 "the 'm' or 'r' operations"); 299 } 300 if (OriginalDates && Operation != Extract) 301 fail("The 'o' modifier is only applicable to the 'x' operation"); 302 if (OnlyUpdate && Operation != ReplaceOrInsert) 303 fail("The 'u' modifier is only applicable to the 'r' operation"); 304 305 // Return the parsed operation to the caller 306 return Operation; 307} 308 309// Implements the 'p' operation. This function traverses the archive 310// looking for members that match the path list. 311static void doPrint(StringRef Name, const object::Archive::Child &C) { 312 if (Verbose) 313 outs() << "Printing " << Name << "\n"; 314 315 Expected<StringRef> DataOrErr = C.getBuffer(); 316 failIfError(DataOrErr.takeError()); 317 StringRef Data = *DataOrErr; 318 outs().write(Data.data(), Data.size()); 319} 320 321// Utility function for printing out the file mode when the 't' operation is in 322// verbose mode. 323static void printMode(unsigned mode) { 324 outs() << ((mode & 004) ? "r" : "-"); 325 outs() << ((mode & 002) ? "w" : "-"); 326 outs() << ((mode & 001) ? "x" : "-"); 327} 328 329// Implement the 't' operation. This function prints out just 330// the file names of each of the members. However, if verbose mode is requested 331// ('v' modifier) then the file type, permission mode, user, group, size, and 332// modification time are also printed. 333static void doDisplayTable(StringRef Name, const object::Archive::Child &C) { 334 if (Verbose) { 335 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); 336 failIfError(ModeOrErr.takeError()); 337 sys::fs::perms Mode = ModeOrErr.get(); 338 printMode((Mode >> 6) & 007); 339 printMode((Mode >> 3) & 007); 340 printMode(Mode & 007); 341 Expected<unsigned> UIDOrErr = C.getUID(); 342 failIfError(UIDOrErr.takeError()); 343 outs() << ' ' << UIDOrErr.get(); 344 Expected<unsigned> GIDOrErr = C.getGID(); 345 failIfError(GIDOrErr.takeError()); 346 outs() << '/' << GIDOrErr.get(); 347 Expected<uint64_t> Size = C.getSize(); 348 failIfError(Size.takeError()); 349 outs() << ' ' << format("%6llu", Size.get()); 350 auto ModTimeOrErr = C.getLastModified(); 351 failIfError(ModTimeOrErr.takeError()); 352 outs() << ' ' << ModTimeOrErr.get(); 353 outs() << ' '; 354 } 355 356 if (C.getParent()->isThin()) { 357 outs() << sys::path::parent_path(ArchiveName); 358 outs() << '/'; 359 } 360 outs() << Name << "\n"; 361} 362 363// Implement the 'x' operation. This function extracts files back to the file 364// system. 365static void doExtract(StringRef Name, const object::Archive::Child &C) { 366 // Retain the original mode. 367 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); 368 failIfError(ModeOrErr.takeError()); 369 sys::fs::perms Mode = ModeOrErr.get(); 370 371 int FD; 372 failIfError(sys::fs::openFileForWrite(sys::path::filename(Name), FD, 373 sys::fs::F_None, Mode), 374 Name); 375 376 { 377 raw_fd_ostream file(FD, false); 378 379 // Get the data and its length 380 Expected<StringRef> BufOrErr = C.getBuffer(); 381 failIfError(BufOrErr.takeError()); 382 StringRef Data = BufOrErr.get(); 383 384 // Write the data. 385 file.write(Data.data(), Data.size()); 386 } 387 388 // If we're supposed to retain the original modification times, etc. do so 389 // now. 390 if (OriginalDates) { 391 auto ModTimeOrErr = C.getLastModified(); 392 failIfError(ModTimeOrErr.takeError()); 393 failIfError( 394 sys::fs::setLastModificationAndAccessTime(FD, ModTimeOrErr.get())); 395 } 396 397 if (close(FD)) 398 fail("Could not close the file"); 399} 400 401static bool shouldCreateArchive(ArchiveOperation Op) { 402 switch (Op) { 403 case Print: 404 case Delete: 405 case Move: 406 case DisplayTable: 407 case Extract: 408 case CreateSymTab: 409 return false; 410 411 case QuickAppend: 412 case ReplaceOrInsert: 413 return true; 414 } 415 416 llvm_unreachable("Missing entry in covered switch."); 417} 418 419static void performReadOperation(ArchiveOperation Operation, 420 object::Archive *OldArchive) { 421 if (Operation == Extract && OldArchive->isThin()) 422 fail("extracting from a thin archive is not supported"); 423 424 bool Filter = !Members.empty(); 425 { 426 Error Err = Error::success(); 427 for (auto &C : OldArchive->children(Err)) { 428 Expected<StringRef> NameOrErr = C.getName(); 429 failIfError(NameOrErr.takeError()); 430 StringRef Name = NameOrErr.get(); 431 432 if (Filter) { 433 auto I = find(Members, Name); 434 if (I == Members.end()) 435 continue; 436 Members.erase(I); 437 } 438 439 switch (Operation) { 440 default: 441 llvm_unreachable("Not a read operation"); 442 case Print: 443 doPrint(Name, C); 444 break; 445 case DisplayTable: 446 doDisplayTable(Name, C); 447 break; 448 case Extract: 449 doExtract(Name, C); 450 break; 451 } 452 } 453 failIfError(std::move(Err)); 454 } 455 456 if (Members.empty()) 457 return; 458 for (StringRef Name : Members) 459 errs() << Name << " was not found\n"; 460 exit(1); 461} 462 463static void addMember(std::vector<NewArchiveMember> &Members, 464 StringRef FileName, int Pos = -1) { 465 Expected<NewArchiveMember> NMOrErr = 466 NewArchiveMember::getFile(FileName, Deterministic); 467 failIfError(NMOrErr.takeError(), FileName); 468 469 // Use the basename of the object path for the member name. 470 NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName); 471 472 if (Pos == -1) 473 Members.push_back(std::move(*NMOrErr)); 474 else 475 Members[Pos] = std::move(*NMOrErr); 476} 477 478static void addMember(std::vector<NewArchiveMember> &Members, 479 const object::Archive::Child &M, int Pos = -1) { 480 if (Thin && !M.getParent()->isThin()) 481 fail("Cannot convert a regular archive to a thin one"); 482 Expected<NewArchiveMember> NMOrErr = 483 NewArchiveMember::getOldMember(M, Deterministic); 484 failIfError(NMOrErr.takeError()); 485 if (Pos == -1) 486 Members.push_back(std::move(*NMOrErr)); 487 else 488 Members[Pos] = std::move(*NMOrErr); 489} 490 491enum InsertAction { 492 IA_AddOldMember, 493 IA_AddNewMember, 494 IA_Delete, 495 IA_MoveOldMember, 496 IA_MoveNewMember 497}; 498 499static InsertAction computeInsertAction(ArchiveOperation Operation, 500 const object::Archive::Child &Member, 501 StringRef Name, 502 std::vector<StringRef>::iterator &Pos) { 503 if (Operation == QuickAppend || Members.empty()) 504 return IA_AddOldMember; 505 506 auto MI = find_if(Members, [Name](StringRef Path) { 507 return Name == sys::path::filename(Path); 508 }); 509 510 if (MI == Members.end()) 511 return IA_AddOldMember; 512 513 Pos = MI; 514 515 if (Operation == Delete) 516 return IA_Delete; 517 518 if (Operation == Move) 519 return IA_MoveOldMember; 520 521 if (Operation == ReplaceOrInsert) { 522 StringRef PosName = sys::path::filename(RelPos); 523 if (!OnlyUpdate) { 524 if (PosName.empty()) 525 return IA_AddNewMember; 526 return IA_MoveNewMember; 527 } 528 529 // We could try to optimize this to a fstat, but it is not a common 530 // operation. 531 sys::fs::file_status Status; 532 failIfError(sys::fs::status(*MI, Status), *MI); 533 auto ModTimeOrErr = Member.getLastModified(); 534 failIfError(ModTimeOrErr.takeError()); 535 if (Status.getLastModificationTime() < ModTimeOrErr.get()) { 536 if (PosName.empty()) 537 return IA_AddOldMember; 538 return IA_MoveOldMember; 539 } 540 541 if (PosName.empty()) 542 return IA_AddNewMember; 543 return IA_MoveNewMember; 544 } 545 llvm_unreachable("No such operation"); 546} 547 548// We have to walk this twice and computing it is not trivial, so creating an 549// explicit std::vector is actually fairly efficient. 550static std::vector<NewArchiveMember> 551computeNewArchiveMembers(ArchiveOperation Operation, 552 object::Archive *OldArchive) { 553 std::vector<NewArchiveMember> Ret; 554 std::vector<NewArchiveMember> Moved; 555 int InsertPos = -1; 556 StringRef PosName = sys::path::filename(RelPos); 557 if (OldArchive) { 558 Error Err = Error::success(); 559 for (auto &Child : OldArchive->children(Err)) { 560 int Pos = Ret.size(); 561 Expected<StringRef> NameOrErr = Child.getName(); 562 failIfError(NameOrErr.takeError()); 563 StringRef Name = NameOrErr.get(); 564 if (Name == PosName) { 565 assert(AddAfter || AddBefore); 566 if (AddBefore) 567 InsertPos = Pos; 568 else 569 InsertPos = Pos + 1; 570 } 571 572 std::vector<StringRef>::iterator MemberI = Members.end(); 573 InsertAction Action = 574 computeInsertAction(Operation, Child, Name, MemberI); 575 switch (Action) { 576 case IA_AddOldMember: 577 addMember(Ret, Child); 578 break; 579 case IA_AddNewMember: 580 addMember(Ret, *MemberI); 581 break; 582 case IA_Delete: 583 break; 584 case IA_MoveOldMember: 585 addMember(Moved, Child); 586 break; 587 case IA_MoveNewMember: 588 addMember(Moved, *MemberI); 589 break; 590 } 591 if (MemberI != Members.end()) 592 Members.erase(MemberI); 593 } 594 failIfError(std::move(Err)); 595 } 596 597 if (Operation == Delete) 598 return Ret; 599 600 if (!RelPos.empty() && InsertPos == -1) 601 fail("Insertion point not found"); 602 603 if (RelPos.empty()) 604 InsertPos = Ret.size(); 605 606 assert(unsigned(InsertPos) <= Ret.size()); 607 int Pos = InsertPos; 608 for (auto &M : Moved) { 609 Ret.insert(Ret.begin() + Pos, std::move(M)); 610 ++Pos; 611 } 612 613 for (unsigned I = 0; I != Members.size(); ++I) 614 Ret.insert(Ret.begin() + InsertPos, NewArchiveMember()); 615 Pos = InsertPos; 616 for (auto &Member : Members) { 617 addMember(Ret, Member, Pos); 618 ++Pos; 619 } 620 621 return Ret; 622} 623 624static object::Archive::Kind getDefaultForHost() { 625 return Triple(sys::getProcessTriple()).isOSDarwin() 626 ? object::Archive::K_DARWIN 627 : object::Archive::K_GNU; 628} 629 630static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) { 631 Expected<std::unique_ptr<object::ObjectFile>> OptionalObject = 632 object::ObjectFile::createObjectFile(Member.Buf->getMemBufferRef()); 633 634 if (OptionalObject) 635 return isa<object::MachOObjectFile>(**OptionalObject) 636 ? object::Archive::K_DARWIN 637 : object::Archive::K_GNU; 638 639 // squelch the error in case we had a non-object file 640 consumeError(OptionalObject.takeError()); 641 return getDefaultForHost(); 642} 643 644static void 645performWriteOperation(ArchiveOperation Operation, 646 object::Archive *OldArchive, 647 std::unique_ptr<MemoryBuffer> OldArchiveBuf, 648 std::vector<NewArchiveMember> *NewMembersP) { 649 std::vector<NewArchiveMember> NewMembers; 650 if (!NewMembersP) 651 NewMembers = computeNewArchiveMembers(Operation, OldArchive); 652 653 object::Archive::Kind Kind; 654 switch (FormatOpt) { 655 case Default: 656 if (Thin) 657 Kind = object::Archive::K_GNU; 658 else if (OldArchive) 659 Kind = OldArchive->kind(); 660 else if (NewMembersP) 661 Kind = NewMembersP->size() ? getKindFromMember(NewMembersP->front()) 662 : getDefaultForHost(); 663 else 664 Kind = NewMembers.size() ? getKindFromMember(NewMembers.front()) 665 : getDefaultForHost(); 666 break; 667 case GNU: 668 Kind = object::Archive::K_GNU; 669 break; 670 case BSD: 671 if (Thin) 672 fail("Only the gnu format has a thin mode"); 673 Kind = object::Archive::K_BSD; 674 break; 675 case DARWIN: 676 if (Thin) 677 fail("Only the gnu format has a thin mode"); 678 Kind = object::Archive::K_DARWIN; 679 break; 680 } 681 682 Error E = 683 writeArchive(ArchiveName, NewMembersP ? *NewMembersP : NewMembers, Symtab, 684 Kind, Deterministic, Thin, std::move(OldArchiveBuf)); 685 failIfError(std::move(E), ArchiveName); 686} 687 688static void createSymbolTable(object::Archive *OldArchive) { 689 // When an archive is created or modified, if the s option is given, the 690 // resulting archive will have a current symbol table. If the S option 691 // is given, it will have no symbol table. 692 // In summary, we only need to update the symbol table if we have none. 693 // This is actually very common because of broken build systems that think 694 // they have to run ranlib. 695 if (OldArchive->hasSymbolTable()) 696 return; 697 698 performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr); 699} 700 701static void performOperation(ArchiveOperation Operation, 702 object::Archive *OldArchive, 703 std::unique_ptr<MemoryBuffer> OldArchiveBuf, 704 std::vector<NewArchiveMember> *NewMembers) { 705 switch (Operation) { 706 case Print: 707 case DisplayTable: 708 case Extract: 709 performReadOperation(Operation, OldArchive); 710 return; 711 712 case Delete: 713 case Move: 714 case QuickAppend: 715 case ReplaceOrInsert: 716 performWriteOperation(Operation, OldArchive, std::move(OldArchiveBuf), 717 NewMembers); 718 return; 719 case CreateSymTab: 720 createSymbolTable(OldArchive); 721 return; 722 } 723 llvm_unreachable("Unknown operation."); 724} 725 726static int performOperation(ArchiveOperation Operation, 727 std::vector<NewArchiveMember> *NewMembers) { 728 // Create or open the archive object. 729 ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = 730 MemoryBuffer::getFile(ArchiveName, -1, false); 731 std::error_code EC = Buf.getError(); 732 if (EC && EC != errc::no_such_file_or_directory) 733 fail("error opening '" + ArchiveName + "': " + EC.message() + "!"); 734 735 if (!EC) { 736 Error Err = Error::success(); 737 object::Archive Archive(Buf.get()->getMemBufferRef(), Err); 738 EC = errorToErrorCode(std::move(Err)); 739 failIfError(EC, 740 "error loading '" + ArchiveName + "': " + EC.message() + "!"); 741 performOperation(Operation, &Archive, std::move(Buf.get()), NewMembers); 742 return 0; 743 } 744 745 assert(EC == errc::no_such_file_or_directory); 746 747 if (!shouldCreateArchive(Operation)) { 748 failIfError(EC, Twine("error loading '") + ArchiveName + "'"); 749 } else { 750 if (!Create) { 751 // Produce a warning if we should and we're creating the archive 752 errs() << ToolName << ": creating " << ArchiveName << "\n"; 753 } 754 } 755 756 performOperation(Operation, nullptr, nullptr, NewMembers); 757 return 0; 758} 759 760static void runMRIScript() { 761 enum class MRICommand { AddLib, AddMod, Create, Save, End, Invalid }; 762 763 ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getSTDIN(); 764 failIfError(Buf.getError()); 765 const MemoryBuffer &Ref = *Buf.get(); 766 bool Saved = false; 767 std::vector<NewArchiveMember> NewMembers; 768 std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers; 769 std::vector<std::unique_ptr<object::Archive>> Archives; 770 771 for (line_iterator I(Ref, /*SkipBlanks*/ true, ';'), E; I != E; ++I) { 772 StringRef Line = *I; 773 StringRef CommandStr, Rest; 774 std::tie(CommandStr, Rest) = Line.split(' '); 775 Rest = Rest.trim(); 776 if (!Rest.empty() && Rest.front() == '"' && Rest.back() == '"') 777 Rest = Rest.drop_front().drop_back(); 778 auto Command = StringSwitch<MRICommand>(CommandStr.lower()) 779 .Case("addlib", MRICommand::AddLib) 780 .Case("addmod", MRICommand::AddMod) 781 .Case("create", MRICommand::Create) 782 .Case("save", MRICommand::Save) 783 .Case("end", MRICommand::End) 784 .Default(MRICommand::Invalid); 785 786 switch (Command) { 787 case MRICommand::AddLib: { 788 auto BufOrErr = MemoryBuffer::getFile(Rest, -1, false); 789 failIfError(BufOrErr.getError(), "Could not open library"); 790 ArchiveBuffers.push_back(std::move(*BufOrErr)); 791 auto LibOrErr = 792 object::Archive::create(ArchiveBuffers.back()->getMemBufferRef()); 793 failIfError(errorToErrorCode(LibOrErr.takeError()), 794 "Could not parse library"); 795 Archives.push_back(std::move(*LibOrErr)); 796 object::Archive &Lib = *Archives.back(); 797 { 798 Error Err = Error::success(); 799 for (auto &Member : Lib.children(Err)) 800 addMember(NewMembers, Member); 801 failIfError(std::move(Err)); 802 } 803 break; 804 } 805 case MRICommand::AddMod: 806 addMember(NewMembers, Rest); 807 break; 808 case MRICommand::Create: 809 Create = true; 810 if (!ArchiveName.empty()) 811 fail("Editing multiple archives not supported"); 812 if (Saved) 813 fail("File already saved"); 814 ArchiveName = Rest; 815 break; 816 case MRICommand::Save: 817 Saved = true; 818 break; 819 case MRICommand::End: 820 break; 821 case MRICommand::Invalid: 822 fail("Unknown command: " + CommandStr); 823 } 824 } 825 826 // Nothing to do if not saved. 827 if (Saved) 828 performOperation(ReplaceOrInsert, &NewMembers); 829 exit(0); 830} 831 832static int ar_main() { 833 // Do our own parsing of the command line because the CommandLine utility 834 // can't handle the grouped positional parameters without a dash. 835 ArchiveOperation Operation = parseCommandLine(); 836 return performOperation(Operation, nullptr); 837} 838 839static int ranlib_main() { 840 if (RestOfArgs.size() != 1) 841 fail(ToolName + " takes just one archive as an argument"); 842 ArchiveName = RestOfArgs[0]; 843 return performOperation(CreateSymTab, nullptr); 844} 845 846int main(int argc, char **argv) { 847 ToolName = argv[0]; 848 // Print a stack trace if we signal out. 849 sys::PrintStackTraceOnErrorSignal(argv[0]); 850 PrettyStackTraceProgram X(argc, argv); 851 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 852 853 llvm::InitializeAllTargetInfos(); 854 llvm::InitializeAllTargetMCs(); 855 llvm::InitializeAllAsmParsers(); 856 857 StringRef Stem = sys::path::stem(ToolName); 858 if (Stem.find("dlltool") != StringRef::npos) 859 return dlltoolDriverMain(makeArrayRef(argv, argc)); 860 861 if (Stem.find("ranlib") == StringRef::npos && 862 Stem.find("lib") != StringRef::npos) 863 return libDriverMain(makeArrayRef(argv, argc)); 864 865 for (int i = 1; i < argc; i++) { 866 // If an argument starts with a dash and only contains chars 867 // that belong to the options chars set, remove the dash. 868 // We can't handle it after the command line options parsing 869 // is done, since it will error out on an unrecognized string 870 // starting with a dash. 871 // Make sure this doesn't match the actual llvm-ar specific options 872 // that start with a dash. 873 StringRef S = argv[i]; 874 if (S.startswith("-") && 875 S.find_first_not_of(OptionChars, 1) == StringRef::npos) { 876 argv[i]++; 877 break; 878 } 879 if (S == "--") 880 break; 881 } 882 883 // Have the command line options parsed and handle things 884 // like --help and --version. 885 cl::ParseCommandLineOptions(argc, argv, 886 "LLVM Archiver (llvm-ar)\n\n" 887 " This program archives bitcode files into single libraries\n" 888 ); 889 890 if (Stem.find("ranlib") != StringRef::npos) 891 return ranlib_main(); 892 if (Stem.find("ar") != StringRef::npos) 893 return ar_main(); 894 fail("Not ranlib, ar, lib or dlltool!"); 895} 896