LibDriver.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. //===- LibDriver.cpp - lib.exe-compatible driver --------------------------===//
  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. // Defines an interface to a lib.exe-compatible driver that also understands
  10. // bitcode files. Used by llvm-lib and lld-link /lib.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
  14. #include "llvm/ADT/STLExtras.h"
  15. #include "llvm/ADT/StringSet.h"
  16. #include "llvm/BinaryFormat/COFF.h"
  17. #include "llvm/BinaryFormat/Magic.h"
  18. #include "llvm/Bitcode/BitcodeReader.h"
  19. #include "llvm/Object/ArchiveWriter.h"
  20. #include "llvm/Object/COFF.h"
  21. #include "llvm/Object/WindowsMachineFlag.h"
  22. #include "llvm/Option/Arg.h"
  23. #include "llvm/Option/ArgList.h"
  24. #include "llvm/Option/Option.h"
  25. #include "llvm/Support/CommandLine.h"
  26. #include "llvm/Support/Path.h"
  27. #include "llvm/Support/Process.h"
  28. #include "llvm/Support/StringSaver.h"
  29. #include "llvm/Support/raw_ostream.h"
  30. #include <optional>
  31. using namespace llvm;
  32. namespace {
  33. enum {
  34. OPT_INVALID = 0,
  35. #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
  36. #include "Options.inc"
  37. #undef OPTION
  38. };
  39. #define PREFIX(NAME, VALUE) \
  40. static constexpr StringLiteral NAME##_init[] = VALUE; \
  41. static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
  42. std::size(NAME##_init) - 1);
  43. #include "Options.inc"
  44. #undef PREFIX
  45. static constexpr opt::OptTable::Info InfoTable[] = {
  46. #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
  47. {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
  48. X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
  49. #include "Options.inc"
  50. #undef OPTION
  51. };
  52. class LibOptTable : public opt::GenericOptTable {
  53. public:
  54. LibOptTable() : opt::GenericOptTable(InfoTable, true) {}
  55. };
  56. }
  57. static std::string getDefaultOutputPath(const NewArchiveMember &FirstMember) {
  58. SmallString<128> Val = StringRef(FirstMember.Buf->getBufferIdentifier());
  59. sys::path::replace_extension(Val, ".lib");
  60. return std::string(Val.str());
  61. }
  62. static std::vector<StringRef> getSearchPaths(opt::InputArgList *Args,
  63. StringSaver &Saver) {
  64. std::vector<StringRef> Ret;
  65. // Add current directory as first item of the search path.
  66. Ret.push_back("");
  67. // Add /libpath flags.
  68. for (auto *Arg : Args->filtered(OPT_libpath))
  69. Ret.push_back(Arg->getValue());
  70. // Add $LIB.
  71. std::optional<std::string> EnvOpt = sys::Process::GetEnv("LIB");
  72. if (!EnvOpt)
  73. return Ret;
  74. StringRef Env = Saver.save(*EnvOpt);
  75. while (!Env.empty()) {
  76. StringRef Path;
  77. std::tie(Path, Env) = Env.split(';');
  78. Ret.push_back(Path);
  79. }
  80. return Ret;
  81. }
  82. static std::string findInputFile(StringRef File, ArrayRef<StringRef> Paths) {
  83. for (StringRef Dir : Paths) {
  84. SmallString<128> Path = Dir;
  85. sys::path::append(Path, File);
  86. if (sys::fs::exists(Path))
  87. return std::string(Path);
  88. }
  89. return "";
  90. }
  91. static void fatalOpenError(llvm::Error E, Twine File) {
  92. if (!E)
  93. return;
  94. handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
  95. llvm::errs() << "error opening '" << File << "': " << EIB.message() << '\n';
  96. exit(1);
  97. });
  98. }
  99. static void doList(opt::InputArgList& Args) {
  100. // lib.exe prints the contents of the first archive file.
  101. std::unique_ptr<MemoryBuffer> B;
  102. for (auto *Arg : Args.filtered(OPT_INPUT)) {
  103. // Create or open the archive object.
  104. ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeBuf = MemoryBuffer::getFile(
  105. Arg->getValue(), /*IsText=*/false, /*RequiresNullTerminator=*/false);
  106. fatalOpenError(errorCodeToError(MaybeBuf.getError()), Arg->getValue());
  107. if (identify_magic(MaybeBuf.get()->getBuffer()) == file_magic::archive) {
  108. B = std::move(MaybeBuf.get());
  109. break;
  110. }
  111. }
  112. // lib.exe doesn't print an error if no .lib files are passed.
  113. if (!B)
  114. return;
  115. Error Err = Error::success();
  116. object::Archive Archive(B.get()->getMemBufferRef(), Err);
  117. fatalOpenError(std::move(Err), B->getBufferIdentifier());
  118. for (auto &C : Archive.children(Err)) {
  119. Expected<StringRef> NameOrErr = C.getName();
  120. fatalOpenError(NameOrErr.takeError(), B->getBufferIdentifier());
  121. StringRef Name = NameOrErr.get();
  122. llvm::outs() << Name << '\n';
  123. }
  124. fatalOpenError(std::move(Err), B->getBufferIdentifier());
  125. }
  126. static Expected<COFF::MachineTypes> getCOFFFileMachine(MemoryBufferRef MB) {
  127. std::error_code EC;
  128. auto Obj = object::COFFObjectFile::create(MB);
  129. if (!Obj)
  130. return Obj.takeError();
  131. uint16_t Machine = (*Obj)->getMachine();
  132. if (Machine != COFF::IMAGE_FILE_MACHINE_I386 &&
  133. Machine != COFF::IMAGE_FILE_MACHINE_AMD64 &&
  134. Machine != COFF::IMAGE_FILE_MACHINE_ARMNT &&
  135. Machine != COFF::IMAGE_FILE_MACHINE_ARM64) {
  136. return createStringError(inconvertibleErrorCode(),
  137. "unknown machine: " + std::to_string(Machine));
  138. }
  139. return static_cast<COFF::MachineTypes>(Machine);
  140. }
  141. static Expected<COFF::MachineTypes> getBitcodeFileMachine(MemoryBufferRef MB) {
  142. Expected<std::string> TripleStr = getBitcodeTargetTriple(MB);
  143. if (!TripleStr)
  144. return TripleStr.takeError();
  145. switch (Triple(*TripleStr).getArch()) {
  146. case Triple::x86:
  147. return COFF::IMAGE_FILE_MACHINE_I386;
  148. case Triple::x86_64:
  149. return COFF::IMAGE_FILE_MACHINE_AMD64;
  150. case Triple::arm:
  151. return COFF::IMAGE_FILE_MACHINE_ARMNT;
  152. case Triple::aarch64:
  153. return COFF::IMAGE_FILE_MACHINE_ARM64;
  154. default:
  155. return createStringError(inconvertibleErrorCode(),
  156. "unknown arch in target triple: " + *TripleStr);
  157. }
  158. }
  159. static void appendFile(std::vector<NewArchiveMember> &Members,
  160. COFF::MachineTypes &LibMachine,
  161. std::string &LibMachineSource, MemoryBufferRef MB) {
  162. file_magic Magic = identify_magic(MB.getBuffer());
  163. if (Magic != file_magic::coff_object && Magic != file_magic::bitcode &&
  164. Magic != file_magic::archive && Magic != file_magic::windows_resource &&
  165. Magic != file_magic::coff_import_library) {
  166. llvm::errs() << MB.getBufferIdentifier()
  167. << ": not a COFF object, bitcode, archive, import library or "
  168. "resource file\n";
  169. exit(1);
  170. }
  171. // If a user attempts to add an archive to another archive, llvm-lib doesn't
  172. // handle the first archive file as a single file. Instead, it extracts all
  173. // members from the archive and add them to the second archive. This behavior
  174. // is for compatibility with Microsoft's lib command.
  175. if (Magic == file_magic::archive) {
  176. Error Err = Error::success();
  177. object::Archive Archive(MB, Err);
  178. fatalOpenError(std::move(Err), MB.getBufferIdentifier());
  179. for (auto &C : Archive.children(Err)) {
  180. Expected<MemoryBufferRef> ChildMB = C.getMemoryBufferRef();
  181. if (!ChildMB) {
  182. handleAllErrors(ChildMB.takeError(), [&](const ErrorInfoBase &EIB) {
  183. llvm::errs() << MB.getBufferIdentifier() << ": " << EIB.message()
  184. << "\n";
  185. });
  186. exit(1);
  187. }
  188. appendFile(Members, LibMachine, LibMachineSource, *ChildMB);
  189. }
  190. fatalOpenError(std::move(Err), MB.getBufferIdentifier());
  191. return;
  192. }
  193. // Check that all input files have the same machine type.
  194. // Mixing normal objects and LTO bitcode files is fine as long as they
  195. // have the same machine type.
  196. // Doing this here duplicates the header parsing work that writeArchive()
  197. // below does, but it's not a lot of work and it's a bit awkward to do
  198. // in writeArchive() which needs to support many tools, can't assume the
  199. // input is COFF, and doesn't have a good way to report errors.
  200. if (Magic == file_magic::coff_object || Magic == file_magic::bitcode) {
  201. Expected<COFF::MachineTypes> MaybeFileMachine =
  202. (Magic == file_magic::coff_object) ? getCOFFFileMachine(MB)
  203. : getBitcodeFileMachine(MB);
  204. if (!MaybeFileMachine) {
  205. handleAllErrors(MaybeFileMachine.takeError(),
  206. [&](const ErrorInfoBase &EIB) {
  207. llvm::errs() << MB.getBufferIdentifier() << ": "
  208. << EIB.message() << "\n";
  209. });
  210. exit(1);
  211. }
  212. COFF::MachineTypes FileMachine = *MaybeFileMachine;
  213. // FIXME: Once lld-link rejects multiple resource .obj files:
  214. // Call convertResToCOFF() on .res files and add the resulting
  215. // COFF file to the .lib output instead of adding the .res file, and remove
  216. // this check. See PR42180.
  217. if (FileMachine != COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
  218. if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
  219. LibMachine = FileMachine;
  220. LibMachineSource =
  221. (" (inferred from earlier file '" + MB.getBufferIdentifier() + "')")
  222. .str();
  223. } else if (LibMachine != FileMachine) {
  224. llvm::errs() << MB.getBufferIdentifier() << ": file machine type "
  225. << machineToStr(FileMachine)
  226. << " conflicts with library machine type "
  227. << machineToStr(LibMachine) << LibMachineSource << '\n';
  228. exit(1);
  229. }
  230. }
  231. }
  232. Members.emplace_back(MB);
  233. }
  234. int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
  235. BumpPtrAllocator Alloc;
  236. StringSaver Saver(Alloc);
  237. // Parse command line arguments.
  238. SmallVector<const char *, 20> NewArgs(ArgsArr.begin(), ArgsArr.end());
  239. cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgs);
  240. ArgsArr = NewArgs;
  241. LibOptTable Table;
  242. unsigned MissingIndex;
  243. unsigned MissingCount;
  244. opt::InputArgList Args =
  245. Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount);
  246. if (MissingCount) {
  247. llvm::errs() << "missing arg value for \""
  248. << Args.getArgString(MissingIndex) << "\", expected "
  249. << MissingCount
  250. << (MissingCount == 1 ? " argument.\n" : " arguments.\n");
  251. return 1;
  252. }
  253. for (auto *Arg : Args.filtered(OPT_UNKNOWN))
  254. llvm::errs() << "ignoring unknown argument: " << Arg->getAsString(Args)
  255. << "\n";
  256. // Handle /help
  257. if (Args.hasArg(OPT_help)) {
  258. Table.printHelp(outs(), "llvm-lib [options] file...", "LLVM Lib");
  259. return 0;
  260. }
  261. // Parse /ignore:
  262. llvm::StringSet<> IgnoredWarnings;
  263. for (auto *Arg : Args.filtered(OPT_ignore))
  264. IgnoredWarnings.insert(Arg->getValue());
  265. // If no input files and not told otherwise, silently do nothing to match
  266. // lib.exe
  267. if (!Args.hasArgNoClaim(OPT_INPUT) && !Args.hasArg(OPT_llvmlibempty)) {
  268. if (!IgnoredWarnings.contains("emptyoutput")) {
  269. llvm::errs() << "warning: no input files, not writing output file\n";
  270. llvm::errs() << " pass /llvmlibempty to write empty .lib file,\n";
  271. llvm::errs() << " pass /ignore:emptyoutput to suppress warning\n";
  272. if (Args.hasFlag(OPT_WX, OPT_WX_no, false)) {
  273. llvm::errs() << "treating warning as error due to /WX\n";
  274. return 1;
  275. }
  276. }
  277. return 0;
  278. }
  279. if (Args.hasArg(OPT_lst)) {
  280. doList(Args);
  281. return 0;
  282. }
  283. std::vector<StringRef> SearchPaths = getSearchPaths(&Args, Saver);
  284. COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
  285. std::string LibMachineSource;
  286. if (auto *Arg = Args.getLastArg(OPT_machine)) {
  287. LibMachine = getMachineType(Arg->getValue());
  288. if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
  289. llvm::errs() << "unknown /machine: arg " << Arg->getValue() << '\n';
  290. return 1;
  291. }
  292. LibMachineSource =
  293. std::string(" (from '/machine:") + Arg->getValue() + "' flag)";
  294. }
  295. std::vector<std::unique_ptr<MemoryBuffer>> MBs;
  296. StringSet<> Seen;
  297. std::vector<NewArchiveMember> Members;
  298. // Create a NewArchiveMember for each input file.
  299. for (auto *Arg : Args.filtered(OPT_INPUT)) {
  300. // Find a file
  301. std::string Path = findInputFile(Arg->getValue(), SearchPaths);
  302. if (Path.empty()) {
  303. llvm::errs() << Arg->getValue() << ": no such file or directory\n";
  304. return 1;
  305. }
  306. // Input files are uniquified by pathname. If you specify the exact same
  307. // path more than once, all but the first one are ignored.
  308. //
  309. // Note that there's a loophole in the rule; you can prepend `.\` or
  310. // something like that to a path to make it look different, and they are
  311. // handled as if they were different files. This behavior is compatible with
  312. // Microsoft lib.exe.
  313. if (!Seen.insert(Path).second)
  314. continue;
  315. // Open a file.
  316. ErrorOr<std::unique_ptr<MemoryBuffer>> MOrErr = MemoryBuffer::getFile(
  317. Path, /*IsText=*/false, /*RequiresNullTerminator=*/false);
  318. fatalOpenError(errorCodeToError(MOrErr.getError()), Path);
  319. MemoryBufferRef MBRef = (*MOrErr)->getMemBufferRef();
  320. // Append a file.
  321. appendFile(Members, LibMachine, LibMachineSource, MBRef);
  322. // Take the ownership of the file buffer to keep the file open.
  323. MBs.push_back(std::move(*MOrErr));
  324. }
  325. // Create an archive file.
  326. std::string OutputPath;
  327. if (auto *Arg = Args.getLastArg(OPT_out)) {
  328. OutputPath = Arg->getValue();
  329. } else if (!Members.empty()) {
  330. OutputPath = getDefaultOutputPath(Members[0]);
  331. } else {
  332. llvm::errs() << "no output path given, and cannot infer with no inputs\n";
  333. return 1;
  334. }
  335. // llvm-lib uses relative paths for both regular and thin archives, unlike
  336. // standard GNU ar, which only uses relative paths for thin archives and
  337. // basenames for regular archives.
  338. for (NewArchiveMember &Member : Members) {
  339. if (sys::path::is_relative(Member.MemberName)) {
  340. Expected<std::string> PathOrErr =
  341. computeArchiveRelativePath(OutputPath, Member.MemberName);
  342. if (PathOrErr)
  343. Member.MemberName = Saver.save(*PathOrErr);
  344. }
  345. }
  346. if (Error E =
  347. writeArchive(OutputPath, Members,
  348. /*WriteSymtab=*/true, object::Archive::K_GNU,
  349. /*Deterministic*/ true, Args.hasArg(OPT_llvmlibthin))) {
  350. handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
  351. llvm::errs() << OutputPath << ": " << EI.message() << "\n";
  352. });
  353. return 1;
  354. }
  355. return 0;
  356. }