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