1b5630dbaSDimitry Andric //===- COFFImportFile.cpp - COFF short import file implementation ---------===//
2b5630dbaSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b5630dbaSDimitry Andric //
7b5630dbaSDimitry Andric //===----------------------------------------------------------------------===//
8b5630dbaSDimitry Andric //
9b5630dbaSDimitry Andric // This file defines the writeImportLibrary function.
10b5630dbaSDimitry Andric //
11b5630dbaSDimitry Andric //===----------------------------------------------------------------------===//
12b5630dbaSDimitry Andric
13b5630dbaSDimitry Andric #include "llvm/Object/COFFImportFile.h"
14b5630dbaSDimitry Andric #include "llvm/ADT/ArrayRef.h"
15ac9a064cSDimitry Andric #include "llvm/ADT/SmallVector.h"
16ac9a064cSDimitry Andric #include "llvm/ADT/StringMap.h"
17145449b1SDimitry Andric #include "llvm/ADT/Twine.h"
18b5630dbaSDimitry Andric #include "llvm/Object/Archive.h"
19b5630dbaSDimitry Andric #include "llvm/Object/ArchiveWriter.h"
20b5630dbaSDimitry Andric #include "llvm/Object/COFF.h"
21145449b1SDimitry Andric #include "llvm/Support/Allocator.h"
22145449b1SDimitry Andric #include "llvm/Support/Endian.h"
23b5630dbaSDimitry Andric #include "llvm/Support/Error.h"
24145449b1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
25b5630dbaSDimitry Andric #include "llvm/Support/Path.h"
26b5630dbaSDimitry Andric
27b5630dbaSDimitry Andric #include <cstdint>
28b5630dbaSDimitry Andric #include <string>
29b5630dbaSDimitry Andric #include <vector>
30b5630dbaSDimitry Andric
31b5630dbaSDimitry Andric using namespace llvm::COFF;
32b5630dbaSDimitry Andric using namespace llvm::object;
33b5630dbaSDimitry Andric using namespace llvm;
34b5630dbaSDimitry Andric
35b5630dbaSDimitry Andric namespace llvm {
36b5630dbaSDimitry Andric namespace object {
37b5630dbaSDimitry Andric
getFileFormatName() const384df029ccSDimitry Andric StringRef COFFImportFile::getFileFormatName() const {
394df029ccSDimitry Andric switch (getMachine()) {
404df029ccSDimitry Andric case COFF::IMAGE_FILE_MACHINE_I386:
414df029ccSDimitry Andric return "COFF-import-file-i386";
424df029ccSDimitry Andric case COFF::IMAGE_FILE_MACHINE_AMD64:
434df029ccSDimitry Andric return "COFF-import-file-x86-64";
444df029ccSDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARMNT:
454df029ccSDimitry Andric return "COFF-import-file-ARM";
464df029ccSDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64:
474df029ccSDimitry Andric return "COFF-import-file-ARM64";
484df029ccSDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64EC:
494df029ccSDimitry Andric return "COFF-import-file-ARM64EC";
504df029ccSDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64X:
514df029ccSDimitry Andric return "COFF-import-file-ARM64X";
524df029ccSDimitry Andric default:
534df029ccSDimitry Andric return "COFF-import-file-<unknown arch>";
544df029ccSDimitry Andric }
554df029ccSDimitry Andric }
564df029ccSDimitry Andric
applyNameType(ImportNameType Type,StringRef name)57ac9a064cSDimitry Andric static StringRef applyNameType(ImportNameType Type, StringRef name) {
58ac9a064cSDimitry Andric auto ltrim1 = [](StringRef s, StringRef chars) {
59ac9a064cSDimitry Andric return !s.empty() && chars.contains(s[0]) ? s.substr(1) : s;
60ac9a064cSDimitry Andric };
61ac9a064cSDimitry Andric
62ac9a064cSDimitry Andric switch (Type) {
63ac9a064cSDimitry Andric case IMPORT_NAME_NOPREFIX:
64ac9a064cSDimitry Andric name = ltrim1(name, "?@_");
65ac9a064cSDimitry Andric break;
66ac9a064cSDimitry Andric case IMPORT_NAME_UNDECORATE:
67ac9a064cSDimitry Andric name = ltrim1(name, "?@_");
68ac9a064cSDimitry Andric name = name.substr(0, name.find('@'));
69ac9a064cSDimitry Andric break;
70ac9a064cSDimitry Andric default:
71ac9a064cSDimitry Andric break;
72ac9a064cSDimitry Andric }
73ac9a064cSDimitry Andric return name;
74ac9a064cSDimitry Andric }
75ac9a064cSDimitry Andric
getExportName() const76ac9a064cSDimitry Andric StringRef COFFImportFile::getExportName() const {
77ac9a064cSDimitry Andric const coff_import_header *hdr = getCOFFImportHeader();
78ac9a064cSDimitry Andric StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first;
79ac9a064cSDimitry Andric
80ac9a064cSDimitry Andric switch (hdr->getNameType()) {
81ac9a064cSDimitry Andric case IMPORT_ORDINAL:
82ac9a064cSDimitry Andric name = "";
83ac9a064cSDimitry Andric break;
84ac9a064cSDimitry Andric case IMPORT_NAME_NOPREFIX:
85ac9a064cSDimitry Andric case IMPORT_NAME_UNDECORATE:
86ac9a064cSDimitry Andric name = applyNameType(static_cast<ImportNameType>(hdr->getNameType()), name);
87ac9a064cSDimitry Andric break;
88ac9a064cSDimitry Andric case IMPORT_NAME_EXPORTAS: {
89ac9a064cSDimitry Andric // Skip DLL name
90ac9a064cSDimitry Andric name = Data.getBuffer().substr(sizeof(*hdr) + name.size() + 1);
91ac9a064cSDimitry Andric name = name.split('\0').second.split('\0').first;
92ac9a064cSDimitry Andric break;
93ac9a064cSDimitry Andric }
94ac9a064cSDimitry Andric default:
95ac9a064cSDimitry Andric break;
96ac9a064cSDimitry Andric }
97ac9a064cSDimitry Andric
98ac9a064cSDimitry Andric return name;
99ac9a064cSDimitry Andric }
100ac9a064cSDimitry Andric
printSymbolName(raw_ostream & OS,DataRefImpl Symb) const101ac9a064cSDimitry Andric Error COFFImportFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
102ac9a064cSDimitry Andric switch (Symb.p) {
103ac9a064cSDimitry Andric case ImpSymbol:
104ac9a064cSDimitry Andric OS << "__imp_";
105ac9a064cSDimitry Andric break;
106ac9a064cSDimitry Andric case ECAuxSymbol:
107ac9a064cSDimitry Andric OS << "__imp_aux_";
108ac9a064cSDimitry Andric break;
109ac9a064cSDimitry Andric }
110ac9a064cSDimitry Andric const char *Name = Data.getBufferStart() + sizeof(coff_import_header);
111ac9a064cSDimitry Andric if (Symb.p != ECThunkSymbol && COFF::isArm64EC(getMachine())) {
112ac9a064cSDimitry Andric if (std::optional<std::string> DemangledName =
113ac9a064cSDimitry Andric getArm64ECDemangledFunctionName(Name)) {
114ac9a064cSDimitry Andric OS << StringRef(*DemangledName);
115ac9a064cSDimitry Andric return Error::success();
116ac9a064cSDimitry Andric }
117ac9a064cSDimitry Andric }
118ac9a064cSDimitry Andric OS << StringRef(Name);
119ac9a064cSDimitry Andric return Error::success();
120ac9a064cSDimitry Andric }
121ac9a064cSDimitry Andric
getImgRelRelocation(MachineTypes Machine)122b5630dbaSDimitry Andric static uint16_t getImgRelRelocation(MachineTypes Machine) {
123b5630dbaSDimitry Andric switch (Machine) {
124b5630dbaSDimitry Andric default:
125b5630dbaSDimitry Andric llvm_unreachable("unsupported machine");
126b5630dbaSDimitry Andric case IMAGE_FILE_MACHINE_AMD64:
127b5630dbaSDimitry Andric return IMAGE_REL_AMD64_ADDR32NB;
128b5630dbaSDimitry Andric case IMAGE_FILE_MACHINE_ARMNT:
129b5630dbaSDimitry Andric return IMAGE_REL_ARM_ADDR32NB;
130044eb2f6SDimitry Andric case IMAGE_FILE_MACHINE_ARM64:
131e3b55780SDimitry Andric case IMAGE_FILE_MACHINE_ARM64EC:
1327fa27ce4SDimitry Andric case IMAGE_FILE_MACHINE_ARM64X:
133044eb2f6SDimitry Andric return IMAGE_REL_ARM64_ADDR32NB;
134b5630dbaSDimitry Andric case IMAGE_FILE_MACHINE_I386:
135b5630dbaSDimitry Andric return IMAGE_REL_I386_DIR32NB;
136b5630dbaSDimitry Andric }
137b5630dbaSDimitry Andric }
138b5630dbaSDimitry Andric
append(std::vector<uint8_t> & B,const T & Data)139b5630dbaSDimitry Andric template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
140b5630dbaSDimitry Andric size_t S = B.size();
141b5630dbaSDimitry Andric B.resize(S + sizeof(T));
142b5630dbaSDimitry Andric memcpy(&B[S], &Data, sizeof(T));
143b5630dbaSDimitry Andric }
144b5630dbaSDimitry Andric
writeStringTable(std::vector<uint8_t> & B,ArrayRef<const std::string_view> Strings)145b5630dbaSDimitry Andric static void writeStringTable(std::vector<uint8_t> &B,
146ac9a064cSDimitry Andric ArrayRef<const std::string_view> Strings) {
147b5630dbaSDimitry Andric // The COFF string table consists of a 4-byte value which is the size of the
148b5630dbaSDimitry Andric // table, including the length field itself. This value is followed by the
149b5630dbaSDimitry Andric // string content itself, which is an array of null-terminated C-style
150b5630dbaSDimitry Andric // strings. The termination is important as they are referenced to by offset
151b5630dbaSDimitry Andric // by the symbol entity in the file format.
152b5630dbaSDimitry Andric
153b5630dbaSDimitry Andric size_t Pos = B.size();
154b5630dbaSDimitry Andric size_t Offset = B.size();
155b5630dbaSDimitry Andric
156b5630dbaSDimitry Andric // Skip over the length field, we will fill it in later as we will have
157b5630dbaSDimitry Andric // computed the length while emitting the string content itself.
158b5630dbaSDimitry Andric Pos += sizeof(uint32_t);
159b5630dbaSDimitry Andric
160b5630dbaSDimitry Andric for (const auto &S : Strings) {
161b5630dbaSDimitry Andric B.resize(Pos + S.length() + 1);
1627fa27ce4SDimitry Andric std::copy(S.begin(), S.end(), std::next(B.begin(), Pos));
1637fa27ce4SDimitry Andric B[Pos + S.length()] = 0;
164b5630dbaSDimitry Andric Pos += S.length() + 1;
165b5630dbaSDimitry Andric }
166b5630dbaSDimitry Andric
167b5630dbaSDimitry Andric // Backfill the length of the table now that it has been computed.
168b5630dbaSDimitry Andric support::ulittle32_t Length(B.size() - Offset);
169b5630dbaSDimitry Andric support::endian::write32le(&B[Offset], Length);
170b5630dbaSDimitry Andric }
171b5630dbaSDimitry Andric
getNameType(StringRef Sym,StringRef ExtName,MachineTypes Machine,bool MinGW)172b5630dbaSDimitry Andric static ImportNameType getNameType(StringRef Sym, StringRef ExtName,
173eb11fae6SDimitry Andric MachineTypes Machine, bool MinGW) {
174eb11fae6SDimitry Andric // A decorated stdcall function in MSVC is exported with the
175eb11fae6SDimitry Andric // type IMPORT_NAME, and the exported function name includes the
176eb11fae6SDimitry Andric // the leading underscore. In MinGW on the other hand, a decorated
177eb11fae6SDimitry Andric // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX).
178eb11fae6SDimitry Andric // See the comment in isDecorated in COFFModuleDefinition.cpp for more
179eb11fae6SDimitry Andric // details.
180312c0ed1SDimitry Andric if (ExtName.starts_with("_") && ExtName.contains('@') && !MinGW)
181eb11fae6SDimitry Andric return IMPORT_NAME;
182b5630dbaSDimitry Andric if (Sym != ExtName)
183b5630dbaSDimitry Andric return IMPORT_NAME_UNDECORATE;
184312c0ed1SDimitry Andric if (Machine == IMAGE_FILE_MACHINE_I386 && Sym.starts_with("_"))
185b5630dbaSDimitry Andric return IMPORT_NAME_NOPREFIX;
186b5630dbaSDimitry Andric return IMPORT_NAME;
187b5630dbaSDimitry Andric }
188b5630dbaSDimitry Andric
replace(StringRef S,StringRef From,StringRef To)189b5630dbaSDimitry Andric static Expected<std::string> replace(StringRef S, StringRef From,
190b5630dbaSDimitry Andric StringRef To) {
191b5630dbaSDimitry Andric size_t Pos = S.find(From);
192b5630dbaSDimitry Andric
193b5630dbaSDimitry Andric // From and To may be mangled, but substrings in S may not.
194312c0ed1SDimitry Andric if (Pos == StringRef::npos && From.starts_with("_") && To.starts_with("_")) {
195b5630dbaSDimitry Andric From = From.substr(1);
196b5630dbaSDimitry Andric To = To.substr(1);
197b5630dbaSDimitry Andric Pos = S.find(From);
198b5630dbaSDimitry Andric }
199b5630dbaSDimitry Andric
200b5630dbaSDimitry Andric if (Pos == StringRef::npos) {
201b5630dbaSDimitry Andric return make_error<StringError>(
202b5630dbaSDimitry Andric StringRef(Twine(S + ": replacing '" + From +
203b5630dbaSDimitry Andric "' with '" + To + "' failed").str()), object_error::parse_failed);
204b5630dbaSDimitry Andric }
205b5630dbaSDimitry Andric
206b5630dbaSDimitry Andric return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
207b5630dbaSDimitry Andric }
208b5630dbaSDimitry Andric
209b5630dbaSDimitry Andric namespace {
210b5630dbaSDimitry Andric // This class constructs various small object files necessary to support linking
211b5630dbaSDimitry Andric // symbols imported from a DLL. The contents are pretty strictly defined and
212b5630dbaSDimitry Andric // nearly entirely static. The details of the structures files are defined in
213b5630dbaSDimitry Andric // WINNT.h and the PE/COFF specification.
214b5630dbaSDimitry Andric class ObjectFactory {
215b5630dbaSDimitry Andric using u16 = support::ulittle16_t;
216b5630dbaSDimitry Andric using u32 = support::ulittle32_t;
2174df029ccSDimitry Andric MachineTypes NativeMachine;
218b5630dbaSDimitry Andric BumpPtrAllocator Alloc;
21993c91e39SDimitry Andric StringRef ImportName;
220b5630dbaSDimitry Andric StringRef Library;
221b5630dbaSDimitry Andric std::string ImportDescriptorSymbolName;
222b5630dbaSDimitry Andric std::string NullThunkSymbolName;
223b5630dbaSDimitry Andric
224b5630dbaSDimitry Andric public:
ObjectFactory(StringRef S,MachineTypes M)225b5630dbaSDimitry Andric ObjectFactory(StringRef S, MachineTypes M)
2264df029ccSDimitry Andric : NativeMachine(M), ImportName(S), Library(llvm::sys::path::stem(S)),
227ac9a064cSDimitry Andric ImportDescriptorSymbolName((ImportDescriptorPrefix + Library).str()),
228ac9a064cSDimitry Andric NullThunkSymbolName(
229ac9a064cSDimitry Andric (NullThunkDataPrefix + Library + NullThunkDataSuffix).str()) {}
230b5630dbaSDimitry Andric
231b5630dbaSDimitry Andric // Creates an Import Descriptor. This is a small object file which contains a
232b5630dbaSDimitry Andric // reference to the terminators and contains the library name (entry) for the
233b5630dbaSDimitry Andric // import name table. It will force the linker to construct the necessary
234b5630dbaSDimitry Andric // structure to import symbols from the DLL.
235b5630dbaSDimitry Andric NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
236b5630dbaSDimitry Andric
237b5630dbaSDimitry Andric // Creates a NULL import descriptor. This is a small object file whcih
238b5630dbaSDimitry Andric // contains a NULL import descriptor. It is used to terminate the imports
239b5630dbaSDimitry Andric // from a specific DLL.
240b5630dbaSDimitry Andric NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
241b5630dbaSDimitry Andric
242b5630dbaSDimitry Andric // Create a NULL Thunk Entry. This is a small object file which contains a
243b5630dbaSDimitry Andric // NULL Import Address Table entry and a NULL Import Lookup Table Entry. It
244b5630dbaSDimitry Andric // is used to terminate the IAT and ILT.
245b5630dbaSDimitry Andric NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
246b5630dbaSDimitry Andric
247b5630dbaSDimitry Andric // Create a short import file which is described in PE/COFF spec 7. Import
248b5630dbaSDimitry Andric // Library Format.
249b5630dbaSDimitry Andric NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
2504df029ccSDimitry Andric ImportType Type, ImportNameType NameType,
251ac9a064cSDimitry Andric StringRef ExportName,
2524df029ccSDimitry Andric MachineTypes Machine);
25393c91e39SDimitry Andric
25493c91e39SDimitry Andric // Create a weak external file which is described in PE/COFF Aux Format 3.
2554df029ccSDimitry Andric NewArchiveMember createWeakExternal(StringRef Sym, StringRef Weak, bool Imp,
2564df029ccSDimitry Andric MachineTypes Machine);
2574df029ccSDimitry Andric
is64Bit() const2584df029ccSDimitry Andric bool is64Bit() const { return COFF::is64Bit(NativeMachine); }
259b5630dbaSDimitry Andric };
260b5630dbaSDimitry Andric } // namespace
261b5630dbaSDimitry Andric
262b5630dbaSDimitry Andric NewArchiveMember
createImportDescriptor(std::vector<uint8_t> & Buffer)263b5630dbaSDimitry Andric ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
26493c91e39SDimitry Andric const uint32_t NumberOfSections = 2;
26593c91e39SDimitry Andric const uint32_t NumberOfSymbols = 7;
26693c91e39SDimitry Andric const uint32_t NumberOfRelocations = 3;
267b5630dbaSDimitry Andric
268b5630dbaSDimitry Andric // COFF Header
269b5630dbaSDimitry Andric coff_file_header Header{
2704df029ccSDimitry Andric u16(NativeMachine),
271b5630dbaSDimitry Andric u16(NumberOfSections),
272b5630dbaSDimitry Andric u32(0),
273b5630dbaSDimitry Andric u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
274b5630dbaSDimitry Andric // .idata$2
275b5630dbaSDimitry Andric sizeof(coff_import_directory_table_entry) +
276b5630dbaSDimitry Andric NumberOfRelocations * sizeof(coff_relocation) +
277b5630dbaSDimitry Andric // .idata$4
27893c91e39SDimitry Andric (ImportName.size() + 1)),
279b5630dbaSDimitry Andric u32(NumberOfSymbols),
280b5630dbaSDimitry Andric u16(0),
2814df029ccSDimitry Andric u16(is64Bit() ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
282b5630dbaSDimitry Andric };
283b5630dbaSDimitry Andric append(Buffer, Header);
284b5630dbaSDimitry Andric
285b5630dbaSDimitry Andric // Section Header Table
28693c91e39SDimitry Andric const coff_section SectionTable[NumberOfSections] = {
287b5630dbaSDimitry Andric {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
288b5630dbaSDimitry Andric u32(0),
289b5630dbaSDimitry Andric u32(0),
290b5630dbaSDimitry Andric u32(sizeof(coff_import_directory_table_entry)),
291b5630dbaSDimitry Andric u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
292b5630dbaSDimitry Andric u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
293b5630dbaSDimitry Andric sizeof(coff_import_directory_table_entry)),
294b5630dbaSDimitry Andric u32(0),
295b5630dbaSDimitry Andric u16(NumberOfRelocations),
296b5630dbaSDimitry Andric u16(0),
297b5630dbaSDimitry Andric u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
298b5630dbaSDimitry Andric IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
299b5630dbaSDimitry Andric {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
300b5630dbaSDimitry Andric u32(0),
301b5630dbaSDimitry Andric u32(0),
30293c91e39SDimitry Andric u32(ImportName.size() + 1),
303b5630dbaSDimitry Andric u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
304b5630dbaSDimitry Andric sizeof(coff_import_directory_table_entry) +
305b5630dbaSDimitry Andric NumberOfRelocations * sizeof(coff_relocation)),
306b5630dbaSDimitry Andric u32(0),
307b5630dbaSDimitry Andric u32(0),
308b5630dbaSDimitry Andric u16(0),
309b5630dbaSDimitry Andric u16(0),
310b5630dbaSDimitry Andric u32(IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
311b5630dbaSDimitry Andric IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
312b5630dbaSDimitry Andric };
313b5630dbaSDimitry Andric append(Buffer, SectionTable);
314b5630dbaSDimitry Andric
315b5630dbaSDimitry Andric // .idata$2
31693c91e39SDimitry Andric const coff_import_directory_table_entry ImportDescriptor{
317b5630dbaSDimitry Andric u32(0), u32(0), u32(0), u32(0), u32(0),
318b5630dbaSDimitry Andric };
319b5630dbaSDimitry Andric append(Buffer, ImportDescriptor);
320b5630dbaSDimitry Andric
32193c91e39SDimitry Andric const coff_relocation RelocationTable[NumberOfRelocations] = {
322b5630dbaSDimitry Andric {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
3234df029ccSDimitry Andric u16(getImgRelRelocation(NativeMachine))},
324b5630dbaSDimitry Andric {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
3254df029ccSDimitry Andric u32(3), u16(getImgRelRelocation(NativeMachine))},
326b5630dbaSDimitry Andric {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
3274df029ccSDimitry Andric u32(4), u16(getImgRelRelocation(NativeMachine))},
328b5630dbaSDimitry Andric };
329b5630dbaSDimitry Andric append(Buffer, RelocationTable);
330b5630dbaSDimitry Andric
331b5630dbaSDimitry Andric // .idata$6
332b5630dbaSDimitry Andric auto S = Buffer.size();
33393c91e39SDimitry Andric Buffer.resize(S + ImportName.size() + 1);
33493c91e39SDimitry Andric memcpy(&Buffer[S], ImportName.data(), ImportName.size());
33593c91e39SDimitry Andric Buffer[S + ImportName.size()] = '\0';
336b5630dbaSDimitry Andric
337b5630dbaSDimitry Andric // Symbol Table
338b5630dbaSDimitry Andric coff_symbol16 SymbolTable[NumberOfSymbols] = {
339b5630dbaSDimitry Andric {{{0, 0, 0, 0, 0, 0, 0, 0}},
340b5630dbaSDimitry Andric u32(0),
341b5630dbaSDimitry Andric u16(1),
342b5630dbaSDimitry Andric u16(0),
343b5630dbaSDimitry Andric IMAGE_SYM_CLASS_EXTERNAL,
344b5630dbaSDimitry Andric 0},
345b5630dbaSDimitry Andric {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
346b5630dbaSDimitry Andric u32(0),
347b5630dbaSDimitry Andric u16(1),
348b5630dbaSDimitry Andric u16(0),
349b5630dbaSDimitry Andric IMAGE_SYM_CLASS_SECTION,
350b5630dbaSDimitry Andric 0},
351b5630dbaSDimitry Andric {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
352b5630dbaSDimitry Andric u32(0),
353b5630dbaSDimitry Andric u16(2),
354b5630dbaSDimitry Andric u16(0),
355b5630dbaSDimitry Andric IMAGE_SYM_CLASS_STATIC,
356b5630dbaSDimitry Andric 0},
357b5630dbaSDimitry Andric {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
358b5630dbaSDimitry Andric u32(0),
359b5630dbaSDimitry Andric u16(0),
360b5630dbaSDimitry Andric u16(0),
361b5630dbaSDimitry Andric IMAGE_SYM_CLASS_SECTION,
362b5630dbaSDimitry Andric 0},
363b5630dbaSDimitry Andric {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
364b5630dbaSDimitry Andric u32(0),
365b5630dbaSDimitry Andric u16(0),
366b5630dbaSDimitry Andric u16(0),
367b5630dbaSDimitry Andric IMAGE_SYM_CLASS_SECTION,
368b5630dbaSDimitry Andric 0},
369b5630dbaSDimitry Andric {{{0, 0, 0, 0, 0, 0, 0, 0}},
370b5630dbaSDimitry Andric u32(0),
371b5630dbaSDimitry Andric u16(0),
372b5630dbaSDimitry Andric u16(0),
373b5630dbaSDimitry Andric IMAGE_SYM_CLASS_EXTERNAL,
374b5630dbaSDimitry Andric 0},
375b5630dbaSDimitry Andric {{{0, 0, 0, 0, 0, 0, 0, 0}},
376b5630dbaSDimitry Andric u32(0),
377b5630dbaSDimitry Andric u16(0),
378b5630dbaSDimitry Andric u16(0),
379b5630dbaSDimitry Andric IMAGE_SYM_CLASS_EXTERNAL,
380b5630dbaSDimitry Andric 0},
381b5630dbaSDimitry Andric };
3827ab83427SDimitry Andric // TODO: Name.Offset.Offset here and in the all similar places below
3837ab83427SDimitry Andric // suggests a names refactoring. Maybe StringTableOffset.Value?
3847ab83427SDimitry Andric SymbolTable[0].Name.Offset.Offset =
385b5630dbaSDimitry Andric sizeof(uint32_t);
3867ab83427SDimitry Andric SymbolTable[5].Name.Offset.Offset =
387b5630dbaSDimitry Andric sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
3887ab83427SDimitry Andric SymbolTable[6].Name.Offset.Offset =
389b5630dbaSDimitry Andric sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
390b5630dbaSDimitry Andric NullImportDescriptorSymbolName.length() + 1;
391b5630dbaSDimitry Andric append(Buffer, SymbolTable);
392b5630dbaSDimitry Andric
393b5630dbaSDimitry Andric // String Table
394b5630dbaSDimitry Andric writeStringTable(Buffer,
395b5630dbaSDimitry Andric {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
396b5630dbaSDimitry Andric NullThunkSymbolName});
397b5630dbaSDimitry Andric
398b5630dbaSDimitry Andric StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
39993c91e39SDimitry Andric return {MemoryBufferRef(F, ImportName)};
400b5630dbaSDimitry Andric }
401b5630dbaSDimitry Andric
402b5630dbaSDimitry Andric NewArchiveMember
createNullImportDescriptor(std::vector<uint8_t> & Buffer)403b5630dbaSDimitry Andric ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
40493c91e39SDimitry Andric const uint32_t NumberOfSections = 1;
40593c91e39SDimitry Andric const uint32_t NumberOfSymbols = 1;
406b5630dbaSDimitry Andric
407b5630dbaSDimitry Andric // COFF Header
408b5630dbaSDimitry Andric coff_file_header Header{
4094df029ccSDimitry Andric u16(NativeMachine),
410b5630dbaSDimitry Andric u16(NumberOfSections),
411b5630dbaSDimitry Andric u32(0),
412b5630dbaSDimitry Andric u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
413b5630dbaSDimitry Andric // .idata$3
414b5630dbaSDimitry Andric sizeof(coff_import_directory_table_entry)),
415b5630dbaSDimitry Andric u32(NumberOfSymbols),
416b5630dbaSDimitry Andric u16(0),
4174df029ccSDimitry Andric u16(is64Bit() ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
418b5630dbaSDimitry Andric };
419b5630dbaSDimitry Andric append(Buffer, Header);
420b5630dbaSDimitry Andric
421b5630dbaSDimitry Andric // Section Header Table
42293c91e39SDimitry Andric const coff_section SectionTable[NumberOfSections] = {
423b5630dbaSDimitry Andric {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
424b5630dbaSDimitry Andric u32(0),
425b5630dbaSDimitry Andric u32(0),
426b5630dbaSDimitry Andric u32(sizeof(coff_import_directory_table_entry)),
427b5630dbaSDimitry Andric u32(sizeof(coff_file_header) +
428b5630dbaSDimitry Andric (NumberOfSections * sizeof(coff_section))),
429b5630dbaSDimitry Andric u32(0),
430b5630dbaSDimitry Andric u32(0),
431b5630dbaSDimitry Andric u16(0),
432b5630dbaSDimitry Andric u16(0),
433b5630dbaSDimitry Andric u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
434b5630dbaSDimitry Andric IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
435b5630dbaSDimitry Andric };
436b5630dbaSDimitry Andric append(Buffer, SectionTable);
437b5630dbaSDimitry Andric
438b5630dbaSDimitry Andric // .idata$3
43993c91e39SDimitry Andric const coff_import_directory_table_entry ImportDescriptor{
440b5630dbaSDimitry Andric u32(0), u32(0), u32(0), u32(0), u32(0),
441b5630dbaSDimitry Andric };
442b5630dbaSDimitry Andric append(Buffer, ImportDescriptor);
443b5630dbaSDimitry Andric
444b5630dbaSDimitry Andric // Symbol Table
445b5630dbaSDimitry Andric coff_symbol16 SymbolTable[NumberOfSymbols] = {
446b5630dbaSDimitry Andric {{{0, 0, 0, 0, 0, 0, 0, 0}},
447b5630dbaSDimitry Andric u32(0),
448b5630dbaSDimitry Andric u16(1),
449b5630dbaSDimitry Andric u16(0),
450b5630dbaSDimitry Andric IMAGE_SYM_CLASS_EXTERNAL,
451b5630dbaSDimitry Andric 0},
452b5630dbaSDimitry Andric };
4537ab83427SDimitry Andric SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
454b5630dbaSDimitry Andric append(Buffer, SymbolTable);
455b5630dbaSDimitry Andric
456b5630dbaSDimitry Andric // String Table
457b5630dbaSDimitry Andric writeStringTable(Buffer, {NullImportDescriptorSymbolName});
458b5630dbaSDimitry Andric
459b5630dbaSDimitry Andric StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
46093c91e39SDimitry Andric return {MemoryBufferRef(F, ImportName)};
461b5630dbaSDimitry Andric }
462b5630dbaSDimitry Andric
createNullThunk(std::vector<uint8_t> & Buffer)463b5630dbaSDimitry Andric NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
46493c91e39SDimitry Andric const uint32_t NumberOfSections = 2;
46593c91e39SDimitry Andric const uint32_t NumberOfSymbols = 1;
4664df029ccSDimitry Andric uint32_t VASize = is64Bit() ? 8 : 4;
467b5630dbaSDimitry Andric
468b5630dbaSDimitry Andric // COFF Header
469b5630dbaSDimitry Andric coff_file_header Header{
4704df029ccSDimitry Andric u16(NativeMachine),
471b5630dbaSDimitry Andric u16(NumberOfSections),
472b5630dbaSDimitry Andric u32(0),
473b5630dbaSDimitry Andric u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
474b5630dbaSDimitry Andric // .idata$5
475b5630dbaSDimitry Andric VASize +
476b5630dbaSDimitry Andric // .idata$4
477b5630dbaSDimitry Andric VASize),
478b5630dbaSDimitry Andric u32(NumberOfSymbols),
479b5630dbaSDimitry Andric u16(0),
4804df029ccSDimitry Andric u16(is64Bit() ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
481b5630dbaSDimitry Andric };
482b5630dbaSDimitry Andric append(Buffer, Header);
483b5630dbaSDimitry Andric
484b5630dbaSDimitry Andric // Section Header Table
48593c91e39SDimitry Andric const coff_section SectionTable[NumberOfSections] = {
486b5630dbaSDimitry Andric {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
487b5630dbaSDimitry Andric u32(0),
488b5630dbaSDimitry Andric u32(0),
489b5630dbaSDimitry Andric u32(VASize),
490b5630dbaSDimitry Andric u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
491b5630dbaSDimitry Andric u32(0),
492b5630dbaSDimitry Andric u32(0),
493b5630dbaSDimitry Andric u16(0),
494b5630dbaSDimitry Andric u16(0),
4954df029ccSDimitry Andric u32((is64Bit() ? IMAGE_SCN_ALIGN_8BYTES : IMAGE_SCN_ALIGN_4BYTES) |
496b5630dbaSDimitry Andric IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
497b5630dbaSDimitry Andric IMAGE_SCN_MEM_WRITE)},
498b5630dbaSDimitry Andric {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
499b5630dbaSDimitry Andric u32(0),
500b5630dbaSDimitry Andric u32(0),
501b5630dbaSDimitry Andric u32(VASize),
502b5630dbaSDimitry Andric u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
503b5630dbaSDimitry Andric VASize),
504b5630dbaSDimitry Andric u32(0),
505b5630dbaSDimitry Andric u32(0),
506b5630dbaSDimitry Andric u16(0),
507b5630dbaSDimitry Andric u16(0),
5084df029ccSDimitry Andric u32((is64Bit() ? IMAGE_SCN_ALIGN_8BYTES : IMAGE_SCN_ALIGN_4BYTES) |
509b5630dbaSDimitry Andric IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
510b5630dbaSDimitry Andric IMAGE_SCN_MEM_WRITE)},
511b5630dbaSDimitry Andric };
512b5630dbaSDimitry Andric append(Buffer, SectionTable);
513b5630dbaSDimitry Andric
514b5630dbaSDimitry Andric // .idata$5, ILT
515b5630dbaSDimitry Andric append(Buffer, u32(0));
5164df029ccSDimitry Andric if (is64Bit())
517b5630dbaSDimitry Andric append(Buffer, u32(0));
518b5630dbaSDimitry Andric
519b5630dbaSDimitry Andric // .idata$4, IAT
520b5630dbaSDimitry Andric append(Buffer, u32(0));
5214df029ccSDimitry Andric if (is64Bit())
522b5630dbaSDimitry Andric append(Buffer, u32(0));
523b5630dbaSDimitry Andric
524b5630dbaSDimitry Andric // Symbol Table
525b5630dbaSDimitry Andric coff_symbol16 SymbolTable[NumberOfSymbols] = {
526b5630dbaSDimitry Andric {{{0, 0, 0, 0, 0, 0, 0, 0}},
527b5630dbaSDimitry Andric u32(0),
528b5630dbaSDimitry Andric u16(1),
529b5630dbaSDimitry Andric u16(0),
530b5630dbaSDimitry Andric IMAGE_SYM_CLASS_EXTERNAL,
531b5630dbaSDimitry Andric 0},
532b5630dbaSDimitry Andric };
5337ab83427SDimitry Andric SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t);
534b5630dbaSDimitry Andric append(Buffer, SymbolTable);
535b5630dbaSDimitry Andric
536b5630dbaSDimitry Andric // String Table
537b5630dbaSDimitry Andric writeStringTable(Buffer, {NullThunkSymbolName});
538b5630dbaSDimitry Andric
539b5630dbaSDimitry Andric StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
54093c91e39SDimitry Andric return {MemoryBufferRef{F, ImportName}};
541b5630dbaSDimitry Andric }
542b5630dbaSDimitry Andric
543ac9a064cSDimitry Andric NewArchiveMember
createShortImport(StringRef Sym,uint16_t Ordinal,ImportType ImportType,ImportNameType NameType,StringRef ExportName,MachineTypes Machine)544ac9a064cSDimitry Andric ObjectFactory::createShortImport(StringRef Sym, uint16_t Ordinal,
545ac9a064cSDimitry Andric ImportType ImportType, ImportNameType NameType,
546ac9a064cSDimitry Andric StringRef ExportName, MachineTypes Machine) {
54793c91e39SDimitry Andric size_t ImpSize = ImportName.size() + Sym.size() + 2; // +2 for NULs
548ac9a064cSDimitry Andric if (!ExportName.empty())
549ac9a064cSDimitry Andric ImpSize += ExportName.size() + 1;
550b5630dbaSDimitry Andric size_t Size = sizeof(coff_import_header) + ImpSize;
551b5630dbaSDimitry Andric char *Buf = Alloc.Allocate<char>(Size);
552b5630dbaSDimitry Andric memset(Buf, 0, Size);
553b5630dbaSDimitry Andric char *P = Buf;
554b5630dbaSDimitry Andric
555b5630dbaSDimitry Andric // Write short import library.
556b5630dbaSDimitry Andric auto *Imp = reinterpret_cast<coff_import_header *>(P);
557b5630dbaSDimitry Andric P += sizeof(*Imp);
558b5630dbaSDimitry Andric Imp->Sig2 = 0xFFFF;
559b5630dbaSDimitry Andric Imp->Machine = Machine;
560b5630dbaSDimitry Andric Imp->SizeOfData = ImpSize;
561b5630dbaSDimitry Andric if (Ordinal > 0)
562b5630dbaSDimitry Andric Imp->OrdinalHint = Ordinal;
563b5630dbaSDimitry Andric Imp->TypeInfo = (NameType << 2) | ImportType;
564b5630dbaSDimitry Andric
565b5630dbaSDimitry Andric // Write symbol name and DLL name.
566b5630dbaSDimitry Andric memcpy(P, Sym.data(), Sym.size());
567b5630dbaSDimitry Andric P += Sym.size() + 1;
56893c91e39SDimitry Andric memcpy(P, ImportName.data(), ImportName.size());
569ac9a064cSDimitry Andric if (!ExportName.empty()) {
570ac9a064cSDimitry Andric P += ImportName.size() + 1;
571ac9a064cSDimitry Andric memcpy(P, ExportName.data(), ExportName.size());
572ac9a064cSDimitry Andric }
573b5630dbaSDimitry Andric
57493c91e39SDimitry Andric return {MemoryBufferRef(StringRef(Buf, Size), ImportName)};
575b5630dbaSDimitry Andric }
576b5630dbaSDimitry Andric
createWeakExternal(StringRef Sym,StringRef Weak,bool Imp,MachineTypes Machine)57793c91e39SDimitry Andric NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
5784df029ccSDimitry Andric StringRef Weak, bool Imp,
5794df029ccSDimitry Andric MachineTypes Machine) {
58093c91e39SDimitry Andric std::vector<uint8_t> Buffer;
58193c91e39SDimitry Andric const uint32_t NumberOfSections = 1;
58293c91e39SDimitry Andric const uint32_t NumberOfSymbols = 5;
58393c91e39SDimitry Andric
58493c91e39SDimitry Andric // COFF Header
58593c91e39SDimitry Andric coff_file_header Header{
586e6d15924SDimitry Andric u16(Machine),
58793c91e39SDimitry Andric u16(NumberOfSections),
58893c91e39SDimitry Andric u32(0),
58993c91e39SDimitry Andric u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
59093c91e39SDimitry Andric u32(NumberOfSymbols),
59193c91e39SDimitry Andric u16(0),
59293c91e39SDimitry Andric u16(0),
59393c91e39SDimitry Andric };
59493c91e39SDimitry Andric append(Buffer, Header);
59593c91e39SDimitry Andric
59693c91e39SDimitry Andric // Section Header Table
59793c91e39SDimitry Andric const coff_section SectionTable[NumberOfSections] = {
59893c91e39SDimitry Andric {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
59993c91e39SDimitry Andric u32(0),
60093c91e39SDimitry Andric u32(0),
60193c91e39SDimitry Andric u32(0),
60293c91e39SDimitry Andric u32(0),
60393c91e39SDimitry Andric u32(0),
60493c91e39SDimitry Andric u32(0),
60593c91e39SDimitry Andric u16(0),
60693c91e39SDimitry Andric u16(0),
60793c91e39SDimitry Andric u32(IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE)}};
60893c91e39SDimitry Andric append(Buffer, SectionTable);
60993c91e39SDimitry Andric
61093c91e39SDimitry Andric // Symbol Table
61193c91e39SDimitry Andric coff_symbol16 SymbolTable[NumberOfSymbols] = {
61293c91e39SDimitry Andric {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
61393c91e39SDimitry Andric u32(0),
61493c91e39SDimitry Andric u16(0xFFFF),
61593c91e39SDimitry Andric u16(0),
61693c91e39SDimitry Andric IMAGE_SYM_CLASS_STATIC,
61793c91e39SDimitry Andric 0},
61893c91e39SDimitry Andric {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},
61993c91e39SDimitry Andric u32(0),
62093c91e39SDimitry Andric u16(0xFFFF),
62193c91e39SDimitry Andric u16(0),
62293c91e39SDimitry Andric IMAGE_SYM_CLASS_STATIC,
62393c91e39SDimitry Andric 0},
62493c91e39SDimitry Andric {{{0, 0, 0, 0, 0, 0, 0, 0}},
62593c91e39SDimitry Andric u32(0),
62693c91e39SDimitry Andric u16(0),
62793c91e39SDimitry Andric u16(0),
62893c91e39SDimitry Andric IMAGE_SYM_CLASS_EXTERNAL,
62993c91e39SDimitry Andric 0},
63093c91e39SDimitry Andric {{{0, 0, 0, 0, 0, 0, 0, 0}},
63193c91e39SDimitry Andric u32(0),
63293c91e39SDimitry Andric u16(0),
63393c91e39SDimitry Andric u16(0),
63493c91e39SDimitry Andric IMAGE_SYM_CLASS_WEAK_EXTERNAL,
63593c91e39SDimitry Andric 1},
636eb11fae6SDimitry Andric {{{2, 0, 0, 0, IMAGE_WEAK_EXTERN_SEARCH_ALIAS, 0, 0, 0}},
637eb11fae6SDimitry Andric u32(0),
638eb11fae6SDimitry Andric u16(0),
639eb11fae6SDimitry Andric u16(0),
640eb11fae6SDimitry Andric IMAGE_SYM_CLASS_NULL,
641eb11fae6SDimitry Andric 0},
64293c91e39SDimitry Andric };
64393c91e39SDimitry Andric SymbolTable[2].Name.Offset.Offset = sizeof(uint32_t);
64493c91e39SDimitry Andric
64593c91e39SDimitry Andric //__imp_ String Table
6464e20bb04SDimitry Andric StringRef Prefix = Imp ? "__imp_" : "";
6474e20bb04SDimitry Andric SymbolTable[3].Name.Offset.Offset =
6484e20bb04SDimitry Andric sizeof(uint32_t) + Sym.size() + Prefix.size() + 1;
64993c91e39SDimitry Andric append(Buffer, SymbolTable);
6504e20bb04SDimitry Andric writeStringTable(Buffer, {(Prefix + Sym).str(),
6514e20bb04SDimitry Andric (Prefix + Weak).str()});
65293c91e39SDimitry Andric
65393c91e39SDimitry Andric // Copied here so we can still use writeStringTable
65493c91e39SDimitry Andric char *Buf = Alloc.Allocate<char>(Buffer.size());
65593c91e39SDimitry Andric memcpy(Buf, Buffer.data(), Buffer.size());
65693c91e39SDimitry Andric return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};
65793c91e39SDimitry Andric }
65893c91e39SDimitry Andric
writeImportLibrary(StringRef ImportName,StringRef Path,ArrayRef<COFFShortExport> Exports,MachineTypes Machine,bool MinGW,ArrayRef<COFFShortExport> NativeExports)659044eb2f6SDimitry Andric Error writeImportLibrary(StringRef ImportName, StringRef Path,
660b5630dbaSDimitry Andric ArrayRef<COFFShortExport> Exports,
661ac9a064cSDimitry Andric MachineTypes Machine, bool MinGW,
662ac9a064cSDimitry Andric ArrayRef<COFFShortExport> NativeExports) {
663b5630dbaSDimitry Andric
664ac9a064cSDimitry Andric MachineTypes NativeMachine = Machine;
665ac9a064cSDimitry Andric if (isArm64EC(Machine)) {
666ac9a064cSDimitry Andric NativeMachine = IMAGE_FILE_MACHINE_ARM64;
667ac9a064cSDimitry Andric Machine = IMAGE_FILE_MACHINE_ARM64EC;
668ac9a064cSDimitry Andric }
6694df029ccSDimitry Andric
670b5630dbaSDimitry Andric std::vector<NewArchiveMember> Members;
6714df029ccSDimitry Andric ObjectFactory OF(llvm::sys::path::filename(ImportName), NativeMachine);
672b5630dbaSDimitry Andric
673b5630dbaSDimitry Andric std::vector<uint8_t> ImportDescriptor;
674b5630dbaSDimitry Andric Members.push_back(OF.createImportDescriptor(ImportDescriptor));
675b5630dbaSDimitry Andric
676b5630dbaSDimitry Andric std::vector<uint8_t> NullImportDescriptor;
677b5630dbaSDimitry Andric Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
678b5630dbaSDimitry Andric
679b5630dbaSDimitry Andric std::vector<uint8_t> NullThunk;
680b5630dbaSDimitry Andric Members.push_back(OF.createNullThunk(NullThunk));
681b5630dbaSDimitry Andric
682ac9a064cSDimitry Andric auto addExports = [&](ArrayRef<COFFShortExport> Exp,
683ac9a064cSDimitry Andric MachineTypes M) -> Error {
684ac9a064cSDimitry Andric StringMap<std::string> RegularImports;
685ac9a064cSDimitry Andric struct Deferred {
686ac9a064cSDimitry Andric std::string Name;
687ac9a064cSDimitry Andric ImportType ImpType;
688ac9a064cSDimitry Andric const COFFShortExport *Export;
689ac9a064cSDimitry Andric };
690ac9a064cSDimitry Andric SmallVector<Deferred, 0> Renames;
691ac9a064cSDimitry Andric for (const COFFShortExport &E : Exp) {
692b5630dbaSDimitry Andric if (E.Private)
693b5630dbaSDimitry Andric continue;
694b5630dbaSDimitry Andric
695b5630dbaSDimitry Andric ImportType ImportType = IMPORT_CODE;
696b5630dbaSDimitry Andric if (E.Data)
697b5630dbaSDimitry Andric ImportType = IMPORT_DATA;
698b5630dbaSDimitry Andric if (E.Constant)
699b5630dbaSDimitry Andric ImportType = IMPORT_CONST;
700b5630dbaSDimitry Andric
70115c5c77fSDimitry Andric StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
702ac9a064cSDimitry Andric std::string Name;
703b5630dbaSDimitry Andric
704ac9a064cSDimitry Andric if (E.ExtName.empty()) {
705ac9a064cSDimitry Andric Name = std::string(SymbolName);
706ac9a064cSDimitry Andric } else {
707ac9a064cSDimitry Andric Expected<std::string> ReplacedName =
708ac9a064cSDimitry Andric replace(SymbolName, E.Name, E.ExtName);
709ac9a064cSDimitry Andric if (!ReplacedName)
710ac9a064cSDimitry Andric return ReplacedName.takeError();
711ac9a064cSDimitry Andric Name.swap(*ReplacedName);
712ac9a064cSDimitry Andric }
713b5630dbaSDimitry Andric
714ac9a064cSDimitry Andric ImportNameType NameType;
715ac9a064cSDimitry Andric std::string ExportName;
716ac9a064cSDimitry Andric if (E.Noname) {
717ac9a064cSDimitry Andric NameType = IMPORT_ORDINAL;
718ac9a064cSDimitry Andric } else if (!E.ExportAs.empty()) {
719ac9a064cSDimitry Andric NameType = IMPORT_NAME_EXPORTAS;
720ac9a064cSDimitry Andric ExportName = E.ExportAs;
721ac9a064cSDimitry Andric } else if (!E.ImportName.empty()) {
722ac9a064cSDimitry Andric // If we need to import from a specific ImportName, we may need to use
723ac9a064cSDimitry Andric // a weak alias (which needs another import to point at). But if we can
724ac9a064cSDimitry Andric // express ImportName based on the symbol name and a specific NameType,
725ac9a064cSDimitry Andric // prefer that over an alias.
726ac9a064cSDimitry Andric if (Machine == IMAGE_FILE_MACHINE_I386 &&
727ac9a064cSDimitry Andric applyNameType(IMPORT_NAME_UNDECORATE, Name) == E.ImportName)
728ac9a064cSDimitry Andric NameType = IMPORT_NAME_UNDECORATE;
729ac9a064cSDimitry Andric else if (Machine == IMAGE_FILE_MACHINE_I386 &&
730ac9a064cSDimitry Andric applyNameType(IMPORT_NAME_NOPREFIX, Name) == E.ImportName)
731ac9a064cSDimitry Andric NameType = IMPORT_NAME_NOPREFIX;
732ac9a064cSDimitry Andric else if (isArm64EC(M)) {
733ac9a064cSDimitry Andric NameType = IMPORT_NAME_EXPORTAS;
734ac9a064cSDimitry Andric ExportName = E.ImportName;
735ac9a064cSDimitry Andric } else if (Name == E.ImportName)
736ac9a064cSDimitry Andric NameType = IMPORT_NAME;
737ac9a064cSDimitry Andric else {
738ac9a064cSDimitry Andric Deferred D;
739ac9a064cSDimitry Andric D.Name = Name;
740ac9a064cSDimitry Andric D.ImpType = ImportType;
741ac9a064cSDimitry Andric D.Export = &E;
742ac9a064cSDimitry Andric Renames.push_back(D);
743eb11fae6SDimitry Andric continue;
744eb11fae6SDimitry Andric }
745ac9a064cSDimitry Andric } else {
746ac9a064cSDimitry Andric NameType = getNameType(SymbolName, E.Name, M, MinGW);
747b5630dbaSDimitry Andric }
748b5630dbaSDimitry Andric
749ac9a064cSDimitry Andric // On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
750ac9a064cSDimitry Andric if (ImportType == IMPORT_CODE && isArm64EC(M)) {
751ac9a064cSDimitry Andric if (std::optional<std::string> MangledName =
752ac9a064cSDimitry Andric getArm64ECMangledFunctionName(Name)) {
753ac9a064cSDimitry Andric if (!E.Noname && ExportName.empty()) {
754ac9a064cSDimitry Andric NameType = IMPORT_NAME_EXPORTAS;
755ac9a064cSDimitry Andric ExportName.swap(Name);
756ac9a064cSDimitry Andric }
757ac9a064cSDimitry Andric Name = std::move(*MangledName);
758ac9a064cSDimitry Andric } else if (!E.Noname && ExportName.empty()) {
759ac9a064cSDimitry Andric NameType = IMPORT_NAME_EXPORTAS;
760ac9a064cSDimitry Andric ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
761ac9a064cSDimitry Andric }
762ac9a064cSDimitry Andric }
763ac9a064cSDimitry Andric
764ac9a064cSDimitry Andric RegularImports[applyNameType(NameType, Name)] = Name;
765ac9a064cSDimitry Andric Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
766ac9a064cSDimitry Andric NameType, ExportName, M));
767ac9a064cSDimitry Andric }
768ac9a064cSDimitry Andric for (const auto &D : Renames) {
769ac9a064cSDimitry Andric auto It = RegularImports.find(D.Export->ImportName);
770ac9a064cSDimitry Andric if (It != RegularImports.end()) {
771ac9a064cSDimitry Andric // We have a regular import entry for a symbol with the name we
772ac9a064cSDimitry Andric // want to reference; produce an alias pointing at that.
773ac9a064cSDimitry Andric StringRef Symbol = It->second;
774ac9a064cSDimitry Andric if (D.ImpType == IMPORT_CODE)
775ac9a064cSDimitry Andric Members.push_back(OF.createWeakExternal(Symbol, D.Name, false, M));
776ac9a064cSDimitry Andric Members.push_back(OF.createWeakExternal(Symbol, D.Name, true, M));
777ac9a064cSDimitry Andric } else {
778ac9a064cSDimitry Andric Members.push_back(OF.createShortImport(D.Name, D.Export->Ordinal,
779ac9a064cSDimitry Andric D.ImpType, IMPORT_NAME_EXPORTAS,
780ac9a064cSDimitry Andric D.Export->ImportName, M));
781ac9a064cSDimitry Andric }
782ac9a064cSDimitry Andric }
783ac9a064cSDimitry Andric return Error::success();
784ac9a064cSDimitry Andric };
785ac9a064cSDimitry Andric
786ac9a064cSDimitry Andric if (Error e = addExports(Exports, Machine))
787ac9a064cSDimitry Andric return e;
788ac9a064cSDimitry Andric if (Error e = addExports(NativeExports, NativeMachine))
789ac9a064cSDimitry Andric return e;
790ac9a064cSDimitry Andric
791b1c73532SDimitry Andric return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab,
792ac9a064cSDimitry Andric object::Archive::K_COFF,
793b1c73532SDimitry Andric /*Deterministic*/ true, /*Thin*/ false,
794b1c73532SDimitry Andric /*OldArchiveBuf*/ nullptr, isArm64EC(Machine));
795b5630dbaSDimitry Andric }
796b5630dbaSDimitry Andric
797b5630dbaSDimitry Andric } // namespace object
798b5630dbaSDimitry Andric } // namespace llvm
799