llvm-ar.cpp 41 KB

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