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
27namespace llvm {
28namespace object {
29
30constexpr std::string_view ImportDescriptorPrefix = "__IMPORT_DESCRIPTOR_";
31constexpr std::string_view NullImportDescriptorSymbolName =
32 "__NULL_IMPORT_DESCRIPTOR";
33constexpr std::string_view NullThunkDataPrefix = "\x7f";
34constexpr std::string_view NullThunkDataSuffix = "_NULL_THUNK_DATA";
35
36class COFFImportFile : public SymbolicFile {
37private:
38 enum SymbolIndex { ImpSymbol, ThunkSymbol, ECAuxSymbol, ECThunkSymbol };
39
40public:
41 COFFImportFile(MemoryBufferRef Source)
42 : SymbolicFile(ID_COFFImportFile, Source) {}
43
44 static bool classof(Binary const *V) { return V->isCOFFImportFile(); }
45
46 void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; }
47
48 Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override;
49
50 Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override {
51 return SymbolRef::SF_Global;
52 }
53
54 basic_symbol_iterator symbol_begin() const override {
55 return BasicSymbolRef(DataRefImpl(), this);
56 }
57
58 basic_symbol_iterator symbol_end() const override {
59 DataRefImpl Symb;
60 if (isData())
61 Symb.p = ImpSymbol + 1;
62 else if (COFF::isArm64EC(Machine: getMachine()))
63 Symb.p = ECThunkSymbol + 1;
64 else
65 Symb.p = ThunkSymbol + 1;
66 return BasicSymbolRef(Symb, this);
67 }
68
69 bool is64Bit() const override { return false; }
70
71 const coff_import_header *getCOFFImportHeader() const {
72 return reinterpret_cast<const object::coff_import_header *>(
73 Data.getBufferStart());
74 }
75
76 uint16_t getMachine() const { return getCOFFImportHeader()->Machine; }
77
78 StringRef getFileFormatName() const;
79 StringRef getExportName() const;
80
81private:
82 bool isData() const {
83 return getCOFFImportHeader()->getType() == COFF::IMPORT_DATA;
84 }
85};
86
87struct 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.
138Error 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

source code of llvm/include/llvm/Object/COFFImportFile.h