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

Generated by: LCOV version 1.13