LCOV - code coverage report
Current view: top level - lib/Object - COFFImportFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 177 184 96.2 %
Date: 2018-10-20 13:21:21 Functions: 18 18 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      33             : static bool is32bit(MachineTypes Machine) {
      34         592 :   switch (Machine) {
      35           0 :   default:
      36           0 :     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             : 
      46             : static uint16_t getImgRelRelocation(MachineTypes Machine) {
      47         184 :   switch (Machine) {
      48           0 :   default:
      49           0 :     llvm_unreachable("unsupported machine");
      50             :   case IMAGE_FILE_MACHINE_AMD64:
      51             :     return IMAGE_REL_AMD64_ADDR32NB;
      52           9 :   case IMAGE_FILE_MACHINE_ARMNT:
      53             :     return IMAGE_REL_ARM_ADDR32NB;
      54          12 :   case IMAGE_FILE_MACHINE_ARM64:
      55             :     return IMAGE_REL_ARM64_ADDR32NB;
      56          87 :   case IMAGE_FILE_MACHINE_I386:
      57             :     return IMAGE_REL_I386_DIR32NB;
      58             :   }
      59             : }
      60             : 
      61        1794 : template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
      62        2322 :   size_t S = B.size();
      63        2322 :   B.resize(S + sizeof(T));
      64        4116 :   memcpy(&B[S], &Data, sizeof(T));
      65        1794 : }
      66           6 : 
      67           6 : static void writeStringTable(std::vector<uint8_t> &B,
      68           6 :                              ArrayRef<const std::string> Strings) {
      69          12 :   // The COFF string table consists of a 4-byte value which is the size of the
      70           6 :   // table, including the length field itself.  This value is followed by the
      71         296 :   // string content itself, which is an array of null-terminated C-style
      72         296 :   // strings.  The termination is important as they are referenced to by offset
      73         296 :   // by the symbol entity in the file format.
      74         592 : 
      75         296 :   size_t Pos = B.size();
      76         154 :   size_t Offset = B.size();
      77         154 : 
      78         154 :   // Skip over the length field, we will fill it in later as we will have
      79         308 :   // computed the length while emitting the string content itself.
      80         154 :   Pos += sizeof(uint32_t);
      81         148 : 
      82         148 :   for (const auto &S : Strings) {
      83         148 :     B.resize(Pos + S.length() + 1);
      84         296 :     strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
      85         148 :     Pos += S.length() + 1;
      86         148 :   }
      87         148 : 
      88         148 :   // Backfill the length of the table now that it has been computed.
      89         296 :   support::ulittle32_t Length(B.size() - Offset);
      90         148 :   support::endian::write32le(&B[Offset], Length);
      91         296 : }
      92         296 : 
      93         296 : static ImportNameType getNameType(StringRef Sym, StringRef ExtName,
      94         592 :                                   MachineTypes Machine, bool MinGW) {
      95         296 :   // A decorated stdcall function in MSVC is exported with the
      96         296 :   // type IMPORT_NAME, and the exported function name includes the
      97         296 :   // the leading underscore. In MinGW on the other hand, a decorated
      98         296 :   // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX).
      99         592 :   // See the comment in isDecorated in COFFModuleDefinition.cpp for more
     100         296 :   // details.
     101         450 :   if (ExtName.startswith("_") && ExtName.contains('@') && !MinGW)
     102         450 :     return IMPORT_NAME;
     103         450 :   if (Sym != ExtName)
     104         900 :     return IMPORT_NAME_UNDECORATE;
     105         450 :   if (Machine == IMAGE_FILE_MACHINE_I386 && Sym.startswith("_"))
     106             :     return IMPORT_NAME_NOPREFIX;
     107         450 :   return IMPORT_NAME;
     108             : }
     109             : 
     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         450 :   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         450 : 
     121             :   if (Pos == StringRef::npos) {
     122        1202 :     return make_error<StringError>(
     123         752 :       StringRef(Twine(S + ": replacing '" + From +
     124         752 :         "' with '" + To + "' failed").str()), object_error::parse_failed);
     125         752 :   }
     126             : 
     127             :   return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
     128             : }
     129         900 : 
     130             : static const std::string NullImportDescriptorSymbolName =
     131         450 :     "__NULL_IMPORT_DESCRIPTOR";
     132             : 
     133         212 : 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          55 :   MachineTypes Machine;
     142             :   BumpPtrAllocator Alloc;
     143             :   StringRef ImportName;
     144             :   StringRef Library;
     145         193 :   std::string ImportDescriptorSymbolName;
     146          38 :   std::string NullThunkSymbolName;
     147             : 
     148             : public:
     149             :   ObjectFactory(StringRef S, MachineTypes M)
     150          11 :       : Machine(M), ImportName(S), Library(S.drop_back(4)),
     151             :         ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
     152          11 :         NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
     153             : 
     154             :   // Creates an Import Descriptor.  This is a small object file which contains a
     155          11 :   // reference to the terminators and contains the library name (entry) for the
     156           1 :   // import name table.  It will force the linker to construct the necessary
     157           1 :   // structure to import symbols from the DLL.
     158           1 :   NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
     159             : 
     160             :   // Creates a NULL import descriptor.  This is a small object file whcih
     161          11 :   // contains a NULL import descriptor.  It is used to terminate the imports
     162             :   // from a specific DLL.
     163           0 :   NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
     164           0 : 
     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          44 :   // 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
     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         148 :       u16(NumberOfSections),
     190         296 :       u32(0),
     191         148 :       u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
     192         444 :           // .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         148 :        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         148 :        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         296 :       {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
     241         148 :        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         444 :        u32(0),
     271         148 :        u16(2),
     272             :        u16(0),
     273             :        IMAGE_SYM_CLASS_STATIC,
     274             :        0},
     275             :       {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
     276             :        u32(0),
     277         148 :        u16(0),
     278             :        u16(0),
     279             :        IMAGE_SYM_CLASS_SECTION,
     280             :        0},
     281         148 :       {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
     282             :        u32(0),
     283             :        u16(0),
     284             :        u16(0),
     285             :        IMAGE_SYM_CLASS_SECTION,
     286             :        0},
     287         148 :       {{{0, 0, 0, 0, 0, 0, 0, 0}},
     288             :        u32(0),
     289             :        u16(0),
     290         148 :        u16(0),
     291         148 :        IMAGE_SYM_CLASS_EXTERNAL,
     292         296 :        0},
     293         148 :       {{{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
     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        1184 :   // Section Header Table
     340             :   const coff_section SectionTable[NumberOfSections] = {
     341             :       {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
     342             :        u32(0),
     343             :        u32(0),
     344         148 :        u32(sizeof(coff_import_directory_table_entry)),
     345         148 :        u32(sizeof(coff_file_header) +
     346         148 :            (NumberOfSections * sizeof(coff_section))),
     347         148 :        u32(0),
     348         148 :        u32(0),
     349         148 :        u16(0),
     350             :        u16(0),
     351             :        u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
     352         592 :            IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
     353             :   };
     354             :   append(Buffer, SectionTable);
     355             : 
     356         148 :   // .idata$3
     357         148 :   const coff_import_directory_table_entry ImportDescriptor{
     358             :       u32(0), u32(0), u32(0), u32(0), u32(0),
     359             :   };
     360             :   append(Buffer, ImportDescriptor);
     361         148 : 
     362             :   // Symbol Table
     363             :   coff_symbol16 SymbolTable[NumberOfSymbols] = {
     364             :       {{{0, 0, 0, 0, 0, 0, 0, 0}},
     365             :        u32(0),
     366             :        u16(1),
     367         148 :        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         148 : 
     377         148 :   StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
     378             :   return {MemoryBufferRef(F, ImportName)};
     379             : }
     380             : 
     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         148 :           VASize +
     394         148 :           // .idata$4
     395             :           VASize),
     396             :       u32(NumberOfSymbols),
     397             :       u16(0),
     398             :       u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : C_Invalid),
     399             :   };
     400         148 :   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         296 :        u32(0),
     411             :        u16(0),
     412         148 :        u16(0),
     413             :        u32((is32bit(Machine) ? IMAGE_SCN_ALIGN_4BYTES
     414             :                              : IMAGE_SCN_ALIGN_8BYTES) |
     415         296 :            IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
     416             :            IMAGE_SCN_MEM_WRITE)},
     417         148 :       {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
     418         148 :        u32(0),
     419             :        u32(0),
     420             :        u32(VASize),
     421         148 :        u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
     422             :            VASize),
     423             :        u32(0),
     424         148 :        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         296 :   // .idata$4, IAT
     440         148 :   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         148 :   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             : 
     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         380 :   char *P = Buf;
     472         148 : 
     473             :   // Write short import library.
     474             :   auto *Imp = reinterpret_cast<coff_import_header *>(P);
     475         148 :   P += sizeof(*Imp);
     476         148 :   Imp->Sig2 = 0xFFFF;
     477         116 :   Imp->Machine = Machine;
     478             :   Imp->SizeOfData = ImpSize;
     479             :   if (Ordinal > 0)
     480         148 :     Imp->OrdinalHint = Ordinal;
     481         148 :   Imp->TypeInfo = (NameType << 2) | ImportType;
     482         116 : 
     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             : 
     491             : NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
     492         296 :                                                    StringRef Weak, bool Imp) {
     493             :   std::vector<uint8_t> Buffer;
     494         148 :   const uint32_t NumberOfSections = 1;
     495             :   const uint32_t NumberOfSymbols = 5;
     496             : 
     497         296 :   // COFF Header
     498             :   coff_file_header Header{
     499         148 :       u16(0),
     500         148 :       u16(NumberOfSections),
     501             :       u32(0),
     502             :       u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
     503         209 :       u32(NumberOfSymbols),
     504             :       u16(0),
     505             :       u16(0),
     506             :   };
     507         209 :   append(Buffer, Header);
     508         209 : 
     509         209 :   // Section Header Table
     510         209 :   const coff_section SectionTable[NumberOfSections] = {
     511             :       {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
     512             :        u32(0),
     513             :        u32(0),
     514             :        u32(0),
     515         209 :        u32(0),
     516             :        u32(0),
     517         209 :        u32(0),
     518         209 :        u16(0),
     519         209 :        u16(0),
     520             :        u32(IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE)}};
     521         209 :   append(Buffer, SectionTable);
     522             : 
     523             :   // Symbol Table
     524         209 :   coff_symbol16 SymbolTable[NumberOfSymbols] = {
     525         209 :       {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
     526         209 :        u32(0),
     527             :        u16(0xFFFF),
     528         209 :        u16(0),
     529             :        IMAGE_SYM_CLASS_STATIC,
     530             :        0},
     531           6 :       {{{'@', '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           6 :        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           6 :   SymbolTable[3].Name.Offset.Offset =
     561           6 :       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             : 
     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          36 :     if (E.Constant)
     596             :       ImportType = IMPORT_CONST;
     597             : 
     598             :     StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
     599           6 :     ImportNameType NameType = getNameType(SymbolName, E.Name, Machine, MinGW);
     600           6 :     Expected<std::string> Name = E.ExtName.empty()
     601           6 :                                      ? SymbolName
     602           6 :                                      : replace(SymbolName, E.Name, E.ExtName);
     603          24 : 
     604           6 :     if (!Name)
     605             :       return Name.takeError();
     606             : 
     607           6 :     if (!E.AliasTarget.empty() && *Name != E.AliasTarget) {
     608          12 :       Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, false));
     609           6 :       Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, true));
     610             :       continue;
     611             :     }
     612         148 : 
     613             :     Members.push_back(
     614             :         OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
     615             :   }
     616         148 : 
     617         296 :   return writeArchive(Path, Members, /*WriteSymtab*/ true,
     618             :                       object::Archive::K_GNU,
     619             :                       /*Deterministic*/ true, /*Thin*/ false);
     620         296 : }
     621             : 
     622             : } // namespace object
     623         296 : } // namespace llvm

Generated by: LCOV version 1.13