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