COFFImportFile.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. //===- COFFImportFile.cpp - COFF short import file implementation ---------===//
  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. // This file defines the writeImportLibrary function.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Object/COFFImportFile.h"
  14. #include "llvm/ADT/ArrayRef.h"
  15. #include "llvm/Object/Archive.h"
  16. #include "llvm/Object/ArchiveWriter.h"
  17. #include "llvm/Object/COFF.h"
  18. #include "llvm/Support/Error.h"
  19. #include "llvm/Support/Path.h"
  20. #include <cstdint>
  21. #include <map>
  22. #include <set>
  23. #include <string>
  24. #include <vector>
  25. using namespace llvm::COFF;
  26. using namespace llvm::object;
  27. using namespace llvm;
  28. namespace llvm {
  29. namespace object {
  30. static bool is32bit(MachineTypes Machine) {
  31. switch (Machine) {
  32. default:
  33. llvm_unreachable("unsupported machine");
  34. case IMAGE_FILE_MACHINE_ARM64:
  35. case IMAGE_FILE_MACHINE_AMD64:
  36. return false;
  37. case IMAGE_FILE_MACHINE_ARMNT:
  38. case IMAGE_FILE_MACHINE_I386:
  39. return true;
  40. }
  41. }
  42. static uint16_t getImgRelRelocation(MachineTypes Machine) {
  43. switch (Machine) {
  44. default:
  45. llvm_unreachable("unsupported machine");
  46. case IMAGE_FILE_MACHINE_AMD64:
  47. return IMAGE_REL_AMD64_ADDR32NB;
  48. case IMAGE_FILE_MACHINE_ARMNT:
  49. return IMAGE_REL_ARM_ADDR32NB;
  50. case IMAGE_FILE_MACHINE_ARM64:
  51. return IMAGE_REL_ARM64_ADDR32NB;
  52. case IMAGE_FILE_MACHINE_I386:
  53. return IMAGE_REL_I386_DIR32NB;
  54. }
  55. }
  56. template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
  57. size_t S = B.size();
  58. B.resize(S + sizeof(T));
  59. memcpy(&B[S], &Data, sizeof(T));
  60. }
  61. static void writeStringTable(std::vector<uint8_t> &B,
  62. ArrayRef<const std::string> Strings) {
  63. // The COFF string table consists of a 4-byte value which is the size of the
  64. // table, including the length field itself. This value is followed by the
  65. // string content itself, which is an array of null-terminated C-style
  66. // strings. The termination is important as they are referenced to by offset
  67. // by the symbol entity in the file format.
  68. size_t Pos = B.size();
  69. size_t Offset = B.size();
  70. // Skip over the length field, we will fill it in later as we will have
  71. // computed the length while emitting the string content itself.
  72. Pos += sizeof(uint32_t);
  73. for (const auto &S : Strings) {
  74. B.resize(Pos + S.length() + 1);
  75. strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
  76. Pos += S.length() + 1;
  77. }
  78. // Backfill the length of the table now that it has been computed.
  79. support::ulittle32_t Length(B.size() - Offset);
  80. support::endian::write32le(&B[Offset], Length);
  81. }
  82. static ImportNameType getNameType(StringRef Sym, StringRef ExtName,
  83. MachineTypes Machine) {
  84. if (Sym != ExtName)
  85. return IMPORT_NAME_UNDECORATE;
  86. if (Machine == IMAGE_FILE_MACHINE_I386 && Sym.startswith("_"))
  87. return IMPORT_NAME_NOPREFIX;
  88. return IMPORT_NAME;
  89. }
  90. static Expected<std::string> replace(StringRef S, StringRef From,
  91. StringRef To) {
  92. size_t Pos = S.find(From);
  93. // From and To may be mangled, but substrings in S may not.
  94. if (Pos == StringRef::npos && From.startswith("_") && To.startswith("_")) {
  95. From = From.substr(1);
  96. To = To.substr(1);
  97. Pos = S.find(From);
  98. }
  99. if (Pos == StringRef::npos) {
  100. return make_error<StringError>(
  101. StringRef(Twine(S + ": replacing '" + From +
  102. "' with '" + To + "' failed").str()), object_error::parse_failed);
  103. }
  104. return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
  105. }
  106. static const std::string NullImportDescriptorSymbolName =
  107. "__NULL_IMPORT_DESCRIPTOR";
  108. namespace {
  109. // This class constructs various small object files necessary to support linking
  110. // symbols imported from a DLL. The contents are pretty strictly defined and
  111. // nearly entirely static. The details of the structures files are defined in
  112. // WINNT.h and the PE/COFF specification.
  113. class ObjectFactory {
  114. using u16 = support::ulittle16_t;
  115. using u32 = support::ulittle32_t;
  116. MachineTypes Machine;
  117. BumpPtrAllocator Alloc;
  118. StringRef ImportName;
  119. StringRef Library;
  120. std::string ImportDescriptorSymbolName;
  121. std::string NullThunkSymbolName;
  122. public:
  123. ObjectFactory(StringRef S, MachineTypes M)
  124. : Machine(M), ImportName(S), Library(S.drop_back(4)),
  125. ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
  126. NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
  127. // Creates an Import Descriptor. This is a small object file which contains a
  128. // reference to the terminators and contains the library name (entry) for the
  129. // import name table. It will force the linker to construct the necessary
  130. // structure to import symbols from the DLL.
  131. NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
  132. // Creates a NULL import descriptor. This is a small object file whcih
  133. // contains a NULL import descriptor. It is used to terminate the imports
  134. // from a specific DLL.
  135. NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
  136. // Create a NULL Thunk Entry. This is a small object file which contains a
  137. // NULL Import Address Table entry and a NULL Import Lookup Table Entry. It
  138. // is used to terminate the IAT and ILT.
  139. NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
  140. // Create a short import file which is described in PE/COFF spec 7. Import
  141. // Library Format.
  142. NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
  143. ImportType Type, ImportNameType NameType);
  144. // Create a weak external file which is described in PE/COFF Aux Format 3.
  145. NewArchiveMember createWeakExternal(StringRef Sym, StringRef Weak, bool Imp);
  146. };
  147. } // namespace
  148. NewArchiveMember
  149. ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
  150. const uint32_t NumberOfSections = 2;
  151. const uint32_t NumberOfSymbols = 7;
  152. const uint32_t NumberOfRelocations = 3;
  153. // COFF Header
  154. coff_file_header Header{
  155. u16(Machine),
  156. u16(NumberOfSections),
  157. u32(0),
  158. u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
  159. // .idata$2
  160. sizeof(coff_import_directory_table_entry) +
  161. NumberOfRelocations * sizeof(coff_relocation) +
  162. // .idata$4
  163. (ImportName.size() + 1)),
  164. u32(NumberOfSymbols),
  165. u16(0),
  166. u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
  167. };
  168. append(Buffer, Header);
  169. // Section Header Table
  170. const coff_section SectionTable[NumberOfSections] = {
  171. {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
  172. u32(0),
  173. u32(0),
  174. u32(sizeof(coff_import_directory_table_entry)),
  175. u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
  176. u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
  177. sizeof(coff_import_directory_table_entry)),
  178. u32(0),
  179. u16(NumberOfRelocations),
  180. u16(0),
  181. u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
  182. IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
  183. {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
  184. u32(0),
  185. u32(0),
  186. u32(ImportName.size() + 1),
  187. u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
  188. sizeof(coff_import_directory_table_entry) +
  189. NumberOfRelocations * sizeof(coff_relocation)),
  190. u32(0),
  191. u32(0),
  192. u16(0),
  193. u16(0),
  194. u32(IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
  195. IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
  196. };
  197. append(Buffer, SectionTable);
  198. // .idata$2
  199. const coff_import_directory_table_entry ImportDescriptor{
  200. u32(0), u32(0), u32(0), u32(0), u32(0),
  201. };
  202. append(Buffer, ImportDescriptor);
  203. const coff_relocation RelocationTable[NumberOfRelocations] = {
  204. {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
  205. u16(getImgRelRelocation(Machine))},
  206. {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
  207. u32(3), u16(getImgRelRelocation(Machine))},
  208. {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
  209. u32(4), u16(getImgRelRelocation(Machine))},
  210. };
  211. append(Buffer, RelocationTable);
  212. // .idata$6
  213. auto S = Buffer.size();
  214. Buffer.resize(S + ImportName.size() + 1);
  215. memcpy(&Buffer[S], ImportName.data(), ImportName.size());
  216. Buffer[S + ImportName.size()] = '\0';
  217. // Symbol Table
  218. coff_symbol16 SymbolTable[NumberOfSymbols] = {
  219. {{{0, 0, 0, 0, 0, 0, 0, 0}},
  220. u32(0),
  221. u16(1),
  222. u16(0),
  223. IMAGE_SYM_CLASS_EXTERNAL,
  224. 0},
  225. {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
  226. u32(0),
  227. u16(1),
  228. u16(0),
  229. IMAGE_SYM_CLASS_SECTION,
  230. 0},
  231. {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
  232. u32(0),
  233. u16(2),
  234. u16(0),
  235. IMAGE_SYM_CLASS_STATIC,
  236. 0},
  237. {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
  238. u32(0),
  239. u16(0),
  240. u16(0),
  241. IMAGE_SYM_CLASS_SECTION,
  242. 0},
  243. {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
  244. u32(0),
  245. u16(0),
  246. u16(0),
  247. IMAGE_SYM_CLASS_SECTION,
  248. 0},
  249. {{{0, 0, 0, 0, 0, 0, 0, 0}},
  250. u32(0),
  251. u16(0),
  252. u16(0),
  253. IMAGE_SYM_CLASS_EXTERNAL,
  254. 0},
  255. {{{0, 0, 0, 0, 0, 0, 0, 0}},
  256. u32(0),
  257. u16(0),
  258. u16(0),
  259. IMAGE_SYM_CLASS_EXTERNAL,
  260. 0},
  261. };
  262. // TODO: Name.Offset.Offset here and in the all similar places below
  263. // suggests a names refactoring. Maybe StringTableOffset.Value?
  264. SymbolTable[0].Name.Offset.Offset =
  265. sizeof(uint32_t);
  266. SymbolTable[5].Name.Offset.Offset =
  267. sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
  268. SymbolTable[6].Name.Offset.Offset =
  269. sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
  270. NullImportDescriptorSymbolName.length() + 1;
  271. append(Buffer, SymbolTable);
  272. // String Table
  273. writeStringTable(Buffer,
  274. {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
  275. NullThunkSymbolName});
  276. StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
  277. return {MemoryBufferRef(F, ImportName)};
  278. }
  279. NewArchiveMember
  280. ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
  281. const uint32_t NumberOfSections = 1;
  282. const uint32_t NumberOfSymbols = 1;
  283. // COFF Header
  284. coff_file_header Header{
  285. u16(Machine),
  286. u16(NumberOfSections),
  287. u32(0),
  288. u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
  289. // .idata$3
  290. sizeof(coff_import_directory_table_entry)),
  291. u32(NumberOfSymbols),
  292. u16(0),
  293. u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
  294. };
  295. append(Buffer, Header);
  296. // Section Header Table
  297. const coff_section SectionTable[NumberOfSections] = {
  298. {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
  299. u32(0),
  300. u32(0),
  301. u32(sizeof(coff_import_directory_table_entry)),
  302. u32(sizeof(coff_file_header) +
  303. (NumberOfSections * sizeof(coff_section))),
  304. u32(0),
  305. u32(0),
  306. u16(0),
  307. u16(0),
  308. u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
  309. IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
  310. };
  311. append(Buffer, SectionTable);
  312. // .idata$3
  313. const coff_import_directory_table_entry ImportDescriptor{
  314. u32(0), u32(0), u32(0), u32(0), u32(0),
  315. };
  316. append(Buffer, ImportDescriptor);
  317. // Symbol Table
  318. coff_symbol16 SymbolTable[NumberOfSymbols] = {
  319. {{{0, 0, 0, 0, 0, 0, 0, 0}},
  320. u32(0),
  321. u16(1),
  322. u16(0),
  323. IMAGE_SYM_CLASS_EXTERNAL,
  324. 0},
  325. };
  326. SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
  327. append(Buffer, SymbolTable);
  328. // String Table
  329. writeStringTable(Buffer, {NullImportDescriptorSymbolName});
  330. StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
  331. return {MemoryBufferRef(F, ImportName)};
  332. }
  333. NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
  334. const uint32_t NumberOfSections = 2;
  335. const uint32_t NumberOfSymbols = 1;
  336. uint32_t VASize = is32bit(Machine) ? 4 : 8;
  337. // COFF Header
  338. coff_file_header Header{
  339. u16(Machine),
  340. u16(NumberOfSections),
  341. u32(0),
  342. u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
  343. // .idata$5
  344. VASize +
  345. // .idata$4
  346. VASize),
  347. u32(NumberOfSymbols),
  348. u16(0),
  349. u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
  350. };
  351. append(Buffer, Header);
  352. // Section Header Table
  353. const coff_section SectionTable[NumberOfSections] = {
  354. {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
  355. u32(0),
  356. u32(0),
  357. u32(VASize),
  358. u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
  359. u32(0),
  360. u32(0),
  361. u16(0),
  362. u16(0),
  363. u32((is32bit(Machine) ? IMAGE_SCN_ALIGN_4BYTES
  364. : IMAGE_SCN_ALIGN_8BYTES) |
  365. IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
  366. IMAGE_SCN_MEM_WRITE)},
  367. {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
  368. u32(0),
  369. u32(0),
  370. u32(VASize),
  371. u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
  372. VASize),
  373. u32(0),
  374. u32(0),
  375. u16(0),
  376. u16(0),
  377. u32((is32bit(Machine) ? IMAGE_SCN_ALIGN_4BYTES
  378. : IMAGE_SCN_ALIGN_8BYTES) |
  379. IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
  380. IMAGE_SCN_MEM_WRITE)},
  381. };
  382. append(Buffer, SectionTable);
  383. // .idata$5, ILT
  384. append(Buffer, u32(0));
  385. if (!is32bit(Machine))
  386. append(Buffer, u32(0));
  387. // .idata$4, IAT
  388. append(Buffer, u32(0));
  389. if (!is32bit(Machine))
  390. append(Buffer, u32(0));
  391. // Symbol Table
  392. coff_symbol16 SymbolTable[NumberOfSymbols] = {
  393. {{{0, 0, 0, 0, 0, 0, 0, 0}},
  394. u32(0),
  395. u16(1),
  396. u16(0),
  397. IMAGE_SYM_CLASS_EXTERNAL,
  398. 0},
  399. };
  400. SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
  401. append(Buffer, SymbolTable);
  402. // String Table
  403. writeStringTable(Buffer, {NullThunkSymbolName});
  404. StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
  405. return {MemoryBufferRef{F, ImportName}};
  406. }
  407. NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
  408. uint16_t Ordinal,
  409. ImportType ImportType,
  410. ImportNameType NameType) {
  411. size_t ImpSize = ImportName.size() + Sym.size() + 2; // +2 for NULs
  412. size_t Size = sizeof(coff_import_header) + ImpSize;
  413. char *Buf = Alloc.Allocate<char>(Size);
  414. memset(Buf, 0, Size);
  415. char *P = Buf;
  416. // Write short import library.
  417. auto *Imp = reinterpret_cast<coff_import_header *>(P);
  418. P += sizeof(*Imp);
  419. Imp->Sig2 = 0xFFFF;
  420. Imp->Machine = Machine;
  421. Imp->SizeOfData = ImpSize;
  422. if (Ordinal > 0)
  423. Imp->OrdinalHint = Ordinal;
  424. Imp->TypeInfo = (NameType << 2) | ImportType;
  425. // Write symbol name and DLL name.
  426. memcpy(P, Sym.data(), Sym.size());
  427. P += Sym.size() + 1;
  428. memcpy(P, ImportName.data(), ImportName.size());
  429. return {MemoryBufferRef(StringRef(Buf, Size), ImportName)};
  430. }
  431. NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
  432. StringRef Weak, bool Imp) {
  433. std::vector<uint8_t> Buffer;
  434. const uint32_t NumberOfSections = 1;
  435. const uint32_t NumberOfSymbols = 5;
  436. // COFF Header
  437. coff_file_header Header{
  438. u16(0),
  439. u16(NumberOfSections),
  440. u32(0),
  441. u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
  442. u32(NumberOfSymbols),
  443. u16(0),
  444. u16(0),
  445. };
  446. append(Buffer, Header);
  447. // Section Header Table
  448. const coff_section SectionTable[NumberOfSections] = {
  449. {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
  450. u32(0),
  451. u32(0),
  452. u32(0),
  453. u32(0),
  454. u32(0),
  455. u32(0),
  456. u16(0),
  457. u16(0),
  458. u32(IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE)}};
  459. append(Buffer, SectionTable);
  460. // Symbol Table
  461. coff_symbol16 SymbolTable[NumberOfSymbols] = {
  462. {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
  463. u32(0),
  464. u16(0xFFFF),
  465. u16(0),
  466. IMAGE_SYM_CLASS_STATIC,
  467. 0},
  468. {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},
  469. u32(0),
  470. u16(0xFFFF),
  471. u16(0),
  472. IMAGE_SYM_CLASS_STATIC,
  473. 0},
  474. {{{0, 0, 0, 0, 0, 0, 0, 0}},
  475. u32(0),
  476. u16(0),
  477. u16(0),
  478. IMAGE_SYM_CLASS_EXTERNAL,
  479. 0},
  480. {{{0, 0, 0, 0, 0, 0, 0, 0}},
  481. u32(0),
  482. u16(0),
  483. u16(0),
  484. IMAGE_SYM_CLASS_WEAK_EXTERNAL,
  485. 1},
  486. {{{2, 0, 0, 0, 3, 0, 0, 0}}, u32(0), u16(0), u16(0), uint8_t(0), 0},
  487. };
  488. SymbolTable[2].Name.Offset.Offset = sizeof(uint32_t);
  489. //__imp_ String Table
  490. StringRef Prefix = Imp ? "__imp_" : "";
  491. SymbolTable[3].Name.Offset.Offset =
  492. sizeof(uint32_t) + Sym.size() + Prefix.size() + 1;
  493. append(Buffer, SymbolTable);
  494. writeStringTable(Buffer, {(Prefix + Sym).str(),
  495. (Prefix + Weak).str()});
  496. // Copied here so we can still use writeStringTable
  497. char *Buf = Alloc.Allocate<char>(Buffer.size());
  498. memcpy(Buf, Buffer.data(), Buffer.size());
  499. return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};
  500. }
  501. std::error_code writeImportLibrary(StringRef ImportName, StringRef Path,
  502. ArrayRef<COFFShortExport> Exports,
  503. MachineTypes Machine, bool MakeWeakAliases) {
  504. std::vector<NewArchiveMember> Members;
  505. ObjectFactory OF(llvm::sys::path::filename(ImportName), Machine);
  506. std::vector<uint8_t> ImportDescriptor;
  507. Members.push_back(OF.createImportDescriptor(ImportDescriptor));
  508. std::vector<uint8_t> NullImportDescriptor;
  509. Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
  510. std::vector<uint8_t> NullThunk;
  511. Members.push_back(OF.createNullThunk(NullThunk));
  512. for (COFFShortExport E : Exports) {
  513. if (E.Private)
  514. continue;
  515. if (E.isWeak() && MakeWeakAliases) {
  516. Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, false));
  517. Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, true));
  518. continue;
  519. }
  520. ImportType ImportType = IMPORT_CODE;
  521. if (E.Data)
  522. ImportType = IMPORT_DATA;
  523. if (E.Constant)
  524. ImportType = IMPORT_CONST;
  525. StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
  526. ImportNameType NameType = getNameType(SymbolName, E.Name, Machine);
  527. Expected<std::string> Name = E.ExtName.empty()
  528. ? SymbolName
  529. : replace(SymbolName, E.Name, E.ExtName);
  530. if (!Name) {
  531. return errorToErrorCode(Name.takeError());
  532. }
  533. Members.push_back(
  534. OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
  535. }
  536. return writeArchive(Path, Members, /*WriteSymtab*/ true,
  537. object::Archive::K_GNU,
  538. /*Deterministic*/ true, /*Thin*/ false);
  539. }
  540. } // namespace object
  541. } // namespace llvm