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