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