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 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 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 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 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 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 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: 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 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 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 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 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 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 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