LCOV - code coverage report
Current view: top level - lib/Object - COFFImportFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 139 146 95.2 %
Date: 2018-06-17 00:07:59 Functions: 20 20 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        1032 :   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         387 :   switch (Machine) {
      48           0 :   default:
      49           0 :     llvm_unreachable("unsupported machine");
      50             :   case IMAGE_FILE_MACHINE_AMD64:
      51             :     return IMAGE_REL_AMD64_ADDR32NB;
      52           3 :   case IMAGE_FILE_MACHINE_ARMNT:
      53             :     return IMAGE_REL_ARM_ADDR32NB;
      54           6 :   case IMAGE_FILE_MACHINE_ARM64:
      55             :     return IMAGE_REL_ARM64_ADDR32NB;
      56          81 :   case IMAGE_FILE_MACHINE_I386:
      57             :     return IMAGE_REL_I386_DIR32NB;
      58             :   }
      59             : }
      60             : 
      61        1566 : template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
      62        2026 :   size_t S = B.size();
      63        2026 :   B.resize(S + sizeof(T));
      64        4052 :   memcpy(&B[S], &Data, sizeof(T));
      65        1566 : }
      66             : 
      67         393 : 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         393 :   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         393 :   Pos += sizeof(uint32_t);
      81             : 
      82        1707 :   for (const auto &S : Strings) {
      83         657 :     B.resize(Pos + S.length() + 1);
      84        1314 :     strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
      85         657 :     Pos += S.length() + 1;
      86             :   }
      87             : 
      88             :   // Backfill the length of the table now that it has been computed.
      89         786 :   support::ulittle32_t Length(B.size() - Offset);
      90             :   support::endian::write32le(&B[Offset], Length);
      91         393 : }
      92             : 
      93         195 : 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          55 :   if (ExtName.startswith("_") && ExtName.contains('@') && !MinGW)
     102             :     return IMPORT_NAME;
     103             :   if (Sym != ExtName)
     104             :     return IMPORT_NAME_UNDECORATE;
     105         176 :   if (Machine == IMAGE_FILE_MACHINE_I386 && Sym.startswith("_"))
     106             :     return IMPORT_NAME_NOPREFIX;
     107             :   return IMPORT_NAME;
     108             : }
     109             : 
     110          11 : static Expected<std::string> replace(StringRef S, StringRef From,
     111             :                                      StringRef To) {
     112          11 :   size_t Pos = S.find(From);
     113             : 
     114             :   // From and To may be mangled, but substrings in S may not.
     115          11 :   if (Pos == StringRef::npos && From.startswith("_") && To.startswith("_")) {
     116           1 :     From = From.substr(1);
     117           1 :     To = To.substr(1);
     118           1 :     Pos = S.find(From);
     119             :   }
     120             : 
     121          11 :   if (Pos == StringRef::npos) {
     122             :     return make_error<StringError>(
     123           0 :       StringRef(Twine(S + ": replacing '" + From +
     124           0 :         "' with '" + To + "' failed").str()), object_error::parse_failed);
     125             :   }
     126             : 
     127          55 :   return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
     128             : }
     129             : 
     130      101169 : 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         258 : 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:
     149         129 :   ObjectFactory(StringRef S, MachineTypes M)
     150         129 :       : Machine(M), ImportName(S), Library(S.drop_back(4)),
     151         258 :         ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
     152         645 :         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
     181         129 : 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         129 :       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         258 :   };
     201         129 :   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         387 :   };
     231         129 :   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         129 :   append(Buffer, ImportDescriptor);
     238             : 
     239             :   const coff_relocation RelocationTable[NumberOfRelocations] = {
     240             :       {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
     241         129 :        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         129 :   append(Buffer, RelocationTable);
     248             : 
     249             :   // .idata$6
     250         129 :   auto S = Buffer.size();
     251         129 :   Buffer.resize(S + ImportName.size() + 1);
     252         258 :   memcpy(&Buffer[S], ImportName.data(), ImportName.size());
     253         258 :   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        1032 :   };
     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         129 :   SymbolTable[5].Name.Offset.Offset =
     305         129 :       sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
     306         129 :   SymbolTable[6].Name.Offset.Offset =
     307         129 :       sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
     308         129 :       NullImportDescriptorSymbolName.length() + 1;
     309         129 :   append(Buffer, SymbolTable);
     310             : 
     311             :   // String Table
     312         258 :   writeStringTable(Buffer,
     313             :                    {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
     314             :                     NullThunkSymbolName});
     315             : 
     316         129 :   StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
     317         129 :   return {MemoryBufferRef(F, ImportName)};
     318             : }
     319             : 
     320             : NewArchiveMember
     321         129 : 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         129 :       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         129 :   };
     337         129 :   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         129 :   };
     354         129 :   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         129 :   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         258 :   };
     371             :   SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
     372         129 :   append(Buffer, SymbolTable);
     373             : 
     374             :   // String Table
     375         258 :   writeStringTable(Buffer, {NullImportDescriptorSymbolName});
     376             : 
     377         129 :   StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
     378         129 :   return {MemoryBufferRef(F, ImportName)};
     379             : }
     380             : 
     381         129 : NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
     382             :   const uint32_t NumberOfSections = 2;
     383             :   const uint32_t NumberOfSymbols = 1;
     384         129 :   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         258 :   };
     400         129 :   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         129 :        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         387 :   };
     432         129 :   append(Buffer, SectionTable);
     433             : 
     434             :   // .idata$5, ILT
     435         129 :   append(Buffer, u32(0));
     436         129 :   if (!is32bit(Machine))
     437         101 :     append(Buffer, u32(0));
     438             : 
     439             :   // .idata$4, IAT
     440         129 :   append(Buffer, u32(0));
     441         129 :   if (!is32bit(Machine))
     442         101 :     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         258 :   };
     453             :   SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
     454         129 :   append(Buffer, SymbolTable);
     455             : 
     456             :   // String Table
     457         258 :   writeStringTable(Buffer, {NullThunkSymbolName});
     458             : 
     459         129 :   StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
     460         129 :   return {MemoryBufferRef{F, ImportName}};
     461             : }
     462             : 
     463         192 : NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
     464             :                                                   uint16_t Ordinal,
     465             :                                                   ImportType ImportType,
     466             :                                                   ImportNameType NameType) {
     467         192 :   size_t ImpSize = ImportName.size() + Sym.size() + 2; // +2 for NULs
     468         192 :   size_t Size = sizeof(coff_import_header) + ImpSize;
     469         192 :   char *Buf = Alloc.Allocate<char>(Size);
     470         192 :   memset(Buf, 0, Size);
     471             :   char *P = Buf;
     472             : 
     473             :   // Write short import library.
     474             :   auto *Imp = reinterpret_cast<coff_import_header *>(P);
     475         192 :   P += sizeof(*Imp);
     476             :   Imp->Sig2 = 0xFFFF;
     477         192 :   Imp->Machine = Machine;
     478         192 :   Imp->SizeOfData = ImpSize;
     479         192 :   if (Ordinal > 0)
     480             :     Imp->OrdinalHint = Ordinal;
     481         192 :   Imp->TypeInfo = (NameType << 2) | ImportType;
     482             : 
     483             :   // Write symbol name and DLL name.
     484         192 :   memcpy(P, Sym.data(), Sym.size());
     485         192 :   P += Sym.size() + 1;
     486         192 :   memcpy(P, ImportName.data(), ImportName.size());
     487             : 
     488         192 :   return {MemoryBufferRef(StringRef(Buf, Size), ImportName)};
     489             : }
     490             : 
     491           6 : 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           6 :   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           6 :        u32(IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE)}};
     521           6 :   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, 3, 0, 0, 0}}, u32(0), u16(0), u16(0), uint8_t(0), 0},
     550          36 :   };
     551             :   SymbolTable[2].Name.Offset.Offset = sizeof(uint32_t);
     552             : 
     553             :   //__imp_ String Table
     554           6 :   StringRef Prefix = Imp ? "__imp_" : "";
     555           6 :   SymbolTable[3].Name.Offset.Offset =
     556           6 :       sizeof(uint32_t) + Sym.size() + Prefix.size() + 1;
     557           6 :   append(Buffer, SymbolTable);
     558          30 :   writeStringTable(Buffer, {(Prefix + Sym).str(),
     559           6 :                             (Prefix + Weak).str()});
     560             : 
     561             :   // Copied here so we can still use writeStringTable
     562           6 :   char *Buf = Alloc.Allocate<char>(Buffer.size());
     563          12 :   memcpy(Buf, Buffer.data(), Buffer.size());
     564          12 :   return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};
     565             : }
     566             : 
     567         129 : Error writeImportLibrary(StringRef ImportName, StringRef Path,
     568             :                          ArrayRef<COFFShortExport> Exports,
     569             :                          MachineTypes Machine, bool MinGW) {
     570             : 
     571         129 :   std::vector<NewArchiveMember> Members;
     572         258 :   ObjectFactory OF(llvm::sys::path::filename(ImportName), Machine);
     573             : 
     574             :   std::vector<uint8_t> ImportDescriptor;
     575         258 :   Members.push_back(OF.createImportDescriptor(ImportDescriptor));
     576             : 
     577             :   std::vector<uint8_t> NullImportDescriptor;
     578         258 :   Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
     579             : 
     580             :   std::vector<uint8_t> NullThunk;
     581         258 :   Members.push_back(OF.createNullThunk(NullThunk));
     582             : 
     583         711 :   for (COFFShortExport E : Exports) {
     584         195 :     if (E.Private)
     585           3 :       continue;
     586             : 
     587             :     ImportType ImportType = IMPORT_CODE;
     588         195 :     if (E.Data)
     589             :       ImportType = IMPORT_DATA;
     590         195 :     if (E.Constant)
     591             :       ImportType = IMPORT_CONST;
     592             : 
     593         195 :     StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
     594         390 :     ImportNameType NameType = getNameType(SymbolName, E.Name, Machine, MinGW);
     595             :     Expected<std::string> Name = E.ExtName.empty()
     596             :                                      ? SymbolName
     597         398 :                                      : replace(SymbolName, E.Name, E.ExtName);
     598             : 
     599         195 :     if (!Name)
     600           0 :       return Name.takeError();
     601             : 
     602         201 :     if (!E.AliasTarget.empty() && *Name != E.AliasTarget) {
     603           6 :       Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, false));
     604           6 :       Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, true));
     605           3 :       continue;
     606             :     }
     607             : 
     608             :     Members.push_back(
     609         576 :         OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
     610             :   }
     611             : 
     612             :   return writeArchive(Path, Members, /*WriteSymtab*/ true,
     613             :                       object::Archive::K_GNU,
     614         258 :                       /*Deterministic*/ true, /*Thin*/ false);
     615             : }
     616             : 
     617             : } // namespace object
     618      202338 : } // namespace llvm

Generated by: LCOV version 1.13