1 //===- COFFImportFile.h - COFF short import file implementation -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // COFF short import file is a special kind of file which contains 10 // only symbol names for DLL-exported symbols. This class implements 11 // exporting of Symbols to create libraries and a SymbolicFile 12 // interface for the file type. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_OBJECT_COFFIMPORTFILE_H 17 #define LLVM_OBJECT_COFFIMPORTFILE_H 18 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/IR/Mangler.h" 21 #include "llvm/Object/COFF.h" 22 #include "llvm/Object/ObjectFile.h" 23 #include "llvm/Object/SymbolicFile.h" 24 #include "llvm/Support/Compiler.h" 25 #include "llvm/Support/MemoryBufferRef.h" 26 #include "llvm/Support/raw_ostream.h" 27 28 namespace llvm { 29 namespace object { 30 31 constexpr std::string_view ImportDescriptorPrefix = "__IMPORT_DESCRIPTOR_"; 32 constexpr std::string_view NullImportDescriptorSymbolName = 33 "__NULL_IMPORT_DESCRIPTOR"; 34 constexpr std::string_view NullThunkDataPrefix = "\x7f"; 35 constexpr std::string_view NullThunkDataSuffix = "_NULL_THUNK_DATA"; 36 37 class LLVM_ABI COFFImportFile : public SymbolicFile { 38 private: 39 enum SymbolIndex { ImpSymbol, ThunkSymbol, ECAuxSymbol, ECThunkSymbol }; 40 41 public: COFFImportFile(MemoryBufferRef Source)42 COFFImportFile(MemoryBufferRef Source) 43 : SymbolicFile(ID_COFFImportFile, Source) {} 44 classof(Binary const * V)45 static bool classof(Binary const *V) { return V->isCOFFImportFile(); } 46 moveSymbolNext(DataRefImpl & Symb)47 void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; } 48 49 Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; 50 getSymbolFlags(DataRefImpl Symb)51 Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override { 52 return SymbolRef::SF_Global; 53 } 54 symbol_begin()55 basic_symbol_iterator symbol_begin() const override { 56 return BasicSymbolRef(DataRefImpl(), this); 57 } 58 symbol_end()59 basic_symbol_iterator symbol_end() const override { 60 DataRefImpl Symb; 61 if (isData()) 62 Symb.p = ImpSymbol + 1; 63 else if (COFF::isArm64EC(getMachine())) 64 Symb.p = ECThunkSymbol + 1; 65 else 66 Symb.p = ThunkSymbol + 1; 67 return BasicSymbolRef(Symb, this); 68 } 69 is64Bit()70 bool is64Bit() const override { return false; } 71 getCOFFImportHeader()72 const coff_import_header *getCOFFImportHeader() const { 73 return reinterpret_cast<const object::coff_import_header *>( 74 Data.getBufferStart()); 75 } 76 getMachine()77 uint16_t getMachine() const { return getCOFFImportHeader()->Machine; } 78 79 StringRef getFileFormatName() const; 80 StringRef getExportName() const; 81 82 private: isData()83 bool isData() const { 84 return getCOFFImportHeader()->getType() == COFF::IMPORT_DATA; 85 } 86 }; 87 88 struct COFFShortExport { 89 /// The name of the export as specified in the .def file or on the command 90 /// line, i.e. "foo" in "/EXPORT:foo", and "bar" in "/EXPORT:foo=bar". This 91 /// may lack mangling, such as underscore prefixing and stdcall suffixing. 92 std::string Name; 93 94 /// The external, exported name. Only non-empty when export renaming is in 95 /// effect, i.e. "foo" in "/EXPORT:foo=bar". 96 std::string ExtName; 97 98 /// The real, mangled symbol name from the object file. Given 99 /// "/export:foo=bar", this could be "_bar@8" if bar is stdcall. 100 std::string SymbolName; 101 102 /// Creates an import library entry that imports from a DLL export with a 103 /// different name. This is the name of the DLL export that should be 104 /// referenced when linking against this import library entry. In a .def 105 /// file, this is "baz" in "EXPORTS\nfoo = bar == baz". 106 std::string ImportName; 107 108 /// Specifies EXPORTAS name. In a .def file, this is "bar" in 109 /// "EXPORTS\nfoo EXPORTAS bar". 110 std::string ExportAs; 111 112 uint16_t Ordinal = 0; 113 bool Noname = false; 114 bool Data = false; 115 bool Private = false; 116 bool Constant = false; 117 118 friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) { 119 return L.Name == R.Name && L.ExtName == R.ExtName && 120 L.Ordinal == R.Ordinal && L.Noname == R.Noname && 121 L.Data == R.Data && L.Private == R.Private; 122 } 123 124 friend bool operator!=(const COFFShortExport &L, const COFFShortExport &R) { 125 return !(L == R); 126 } 127 }; 128 129 /// Writes a COFF import library containing entries described by the Exports 130 /// array. 131 /// 132 /// For hybrid targets such as ARM64EC, additional native entry points can be 133 /// exposed using the NativeExports parameter. When NativeExports is used, the 134 /// output import library will expose these native ARM64 imports alongside the 135 /// entries described in the Exports array. Such a library can be used for 136 /// linking both ARM64EC and pure ARM64 objects, and the linker will pick only 137 /// the exports relevant to the target platform. For non-hybrid targets, 138 /// the NativeExports parameter should not be used. 139 LLVM_ABI Error writeImportLibrary(StringRef ImportName, StringRef Path, 140 ArrayRef<COFFShortExport> Exports, 141 COFF::MachineTypes Machine, bool MinGW, 142 ArrayRef<COFFShortExport> NativeExports = {}); 143 144 } // namespace object 145 } // namespace llvm 146 147 #endif 148