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