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