LibDriver.cpp 13 KB

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