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