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