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