COFFImportFile.cpp 20 KB

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