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