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