LLVM: lib/Object/COFFImportFile.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
26
27#include
28#include
29#include
30
33using namespace llvm;
34
35namespace llvm {
37
41 return "COFF-import-file-i386";
43 return "COFF-import-file-x86-64";
45 return "COFF-import-file-ARM";
47 return "COFF-import-file-ARM64";
49 return "COFF-import-file-ARM64EC";
51 return "COFF-import-file-ARM64X";
52 default:
53 return "COFF-import-file-";
54 }
55}
56
59 return !s.empty() && chars.contains(s[0]) ? s.substr(1) : s;
60 };
61
62 switch (Type) {
65 break;
69 break;
70 default:
71 break;
72 }
74}
75
78 StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first;
79
83 break;
87 break;
89
90 name = Data.getBuffer().substr(sizeof(*hdr) + name.size() + 1);
91 name = name.split('\0').second.split('\0').first;
92 break;
93 }
94 default:
95 break;
96 }
97
99}
100
102 switch (Symb.p) {
103 case ImpSymbol:
104 OS << "__imp_";
105 break;
106 case ECAuxSymbol:
107 OS << "__imp_aux_";
108 break;
109 }
112 if (std::optionalstd::string DemangledName =
116 }
117 }
120}
121
140
141template static void append(std::vector<uint8_t> &B, const T &Data) {
142 size_t S = B.size();
144 memcpy(&B[S], &Data, sizeof(T));
145}
146
149
150
151
152
153
154
155 size_t Pos = B.size();
157
158
159
161
162 for (const auto &S : Strings) {
163 B.resize(Pos + S.length() + 1);
164 llvm::copy(S, std::next(B.begin(), Pos));
165 B[Pos + S.length()] = 0;
166 Pos += S.length() + 1;
167 }
168
169
172}
173
176
177
178
179
180
181
184 if (Sym != ExtName)
189}
190
193 size_t Pos = S.find(From);
194
195
197 From = From.substr(1);
199 Pos = S.find(From);
200 }
201
206 }
207
209}
210
211namespace {
212
213
214
215
216class ObjectFactory {
223 std::string ImportDescriptorSymbolName;
224 std::string NullThunkSymbolName;
225
226public:
228 : NativeMachine(M), ImportName(S), Library(llvm::sys::path::stem(S)),
230 NullThunkSymbolName(
232
233
234
235
236
237 NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
238
239
240
241
242 NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
243
244
245
246
247 NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
248
249
250
255
256
259
261};
262}
263
264NewArchiveMember
265ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
266 const uint32_t NumberOfSections = 2;
267 const uint32_t NumberOfSymbols = 7;
268 const uint32_t NumberOfRelocations = 3;
269
270
271 coff_file_header Header{
272 u16(NativeMachine),
273 u16(NumberOfSections),
274 u32(0),
275 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
276
277 sizeof(coff_import_directory_table_entry) +
278 NumberOfRelocations * sizeof(coff_relocation) +
279
280 (ImportName.size() + 1)),
281 u32(NumberOfSymbols),
282 u16(0),
284 };
285 append(Buffer, Header);
286
287
288 const coff_section SectionTable[NumberOfSections] = {
289 {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
290 u32(0),
291 u32(0),
292 u32(sizeof(coff_import_directory_table_entry)),
293 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
294 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
295 sizeof(coff_import_directory_table_entry)),
296 u32(0),
297 u16(NumberOfRelocations),
298 u16(0),
301 {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
302 u32(0),
303 u32(0),
304 u32(ImportName.size() + 1),
305 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
306 sizeof(coff_import_directory_table_entry) +
307 NumberOfRelocations * sizeof(coff_relocation)),
308 u32(0),
309 u32(0),
310 u16(0),
311 u16(0),
314 };
315 append(Buffer, SectionTable);
316
317
318 const coff_import_directory_table_entry ImportDescriptor{
319 u32(0), u32(0), u32(0), u32(0), u32(0),
320 };
321 append(Buffer, ImportDescriptor);
322
323 const coff_relocation RelocationTable[NumberOfRelocations] = {
324 {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
326 {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
328 {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
330 };
331 append(Buffer, RelocationTable);
332
333
334 auto S = Buffer.size();
335 Buffer.resize(S + ImportName.size() + 1);
336 memcpy(&Buffer[S], ImportName.data(), ImportName.size());
337 Buffer[S + ImportName.size()] = '\0';
338
339
341 {{{0, 0, 0, 0, 0, 0, 0, 0}},
342 u32(0),
343 u16(1),
344 u16(0),
346 0},
347 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
348 u32(0),
349 u16(1),
350 u16(0),
352 0},
353 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
354 u32(0),
355 u16(2),
356 u16(0),
358 0},
359 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
360 u32(0),
361 u16(0),
362 u16(0),
364 0},
365 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
366 u32(0),
367 u16(0),
368 u16(0),
370 0},
371 {{{0, 0, 0, 0, 0, 0, 0, 0}},
372 u32(0),
373 u16(0),
374 u16(0),
376 0},
377 {{{0, 0, 0, 0, 0, 0, 0, 0}},
378 u32(0),
379 u16(0),
380 u16(0),
382 0},
383 };
384
385
387 sizeof(uint32_t);
389 sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
391 sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
393 append(Buffer, SymbolTable);
394
395
398 NullThunkSymbolName});
399
400 StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
401 return {MemoryBufferRef(F, ImportName)};
402}
403
404NewArchiveMember
405ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
406 const uint32_t NumberOfSections = 1;
407 const uint32_t NumberOfSymbols = 1;
408
409
410 coff_file_header Header{
411 u16(NativeMachine),
412 u16(NumberOfSections),
413 u32(0),
414 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
415
416 sizeof(coff_import_directory_table_entry)),
417 u32(NumberOfSymbols),
418 u16(0),
420 };
421 append(Buffer, Header);
422
423
424 const coff_section SectionTable[NumberOfSections] = {
425 {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
426 u32(0),
427 u32(0),
428 u32(sizeof(coff_import_directory_table_entry)),
429 u32(sizeof(coff_file_header) +
430 (NumberOfSections * sizeof(coff_section))),
431 u32(0),
432 u32(0),
433 u16(0),
434 u16(0),
437 };
438 append(Buffer, SectionTable);
439
440
441 const coff_import_directory_table_entry ImportDescriptor{
442 u32(0), u32(0), u32(0), u32(0), u32(0),
443 };
444 append(Buffer, ImportDescriptor);
445
446
448 {{{0, 0, 0, 0, 0, 0, 0, 0}},
449 u32(0),
450 u16(1),
451 u16(0),
453 0},
454 };
456 append(Buffer, SymbolTable);
457
458
460
461 StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
462 return {MemoryBufferRef(F, ImportName)};
463}
464
465NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
466 const uint32_t NumberOfSections = 2;
467 const uint32_t NumberOfSymbols = 1;
468 uint32_t VASize = is64Bit() ? 8 : 4;
469
470
471 coff_file_header Header{
472 u16(NativeMachine),
473 u16(NumberOfSections),
474 u32(0),
475 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
476
477 VASize +
478
479 VASize),
480 u32(NumberOfSymbols),
481 u16(0),
483 };
484 append(Buffer, Header);
485
486
487 const coff_section SectionTable[NumberOfSections] = {
488 {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
489 u32(0),
490 u32(0),
491 u32(VASize),
492 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
493 u32(0),
494 u32(0),
495 u16(0),
496 u16(0),
500 {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
501 u32(0),
502 u32(0),
503 u32(VASize),
504 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
505 VASize),
506 u32(0),
507 u32(0),
508 u16(0),
509 u16(0),
513 };
514 append(Buffer, SectionTable);
515
516
517 append(Buffer, u32(0));
519 append(Buffer, u32(0));
520
521
522 append(Buffer, u32(0));
524 append(Buffer, u32(0));
525
526
528 {{{0, 0, 0, 0, 0, 0, 0, 0}},
529 u32(0),
530 u16(1),
531 u16(0),
533 0},
534 };
536 append(Buffer, SymbolTable);
537
538
540
541 StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
542 return {MemoryBufferRef{F, ImportName}};
543}
544
545NewArchiveMember
546ObjectFactory::createShortImport(StringRef Sym, uint16_t Ordinal,
549 size_t ImpSize = ImportName.size() + Sym.size() + 2;
550 if (!ExportName.empty())
551 ImpSize += ExportName.size() + 1;
552 size_t Size = sizeof(coff_import_header) + ImpSize;
553 char *Buf = Alloc.Allocate<char>(Size);
554 memset(Buf, 0, Size);
555 char *P = Buf;
556
557
558 auto *Imp = reinterpret_cast<coff_import_header *>(P);
559 P += sizeof(*Imp);
560 Imp->Sig2 = 0xFFFF;
562 Imp->SizeOfData = ImpSize;
563 if (Ordinal > 0)
564 Imp->OrdinalHint = Ordinal;
566
567
568 memcpy(P, Sym.data(), Sym.size());
570 memcpy(P, ImportName.data(), ImportName.size());
571 if (!ExportName.empty()) {
572 P += ImportName.size() + 1;
573 memcpy(P, ExportName.data(), ExportName.size());
574 }
575
576 return {MemoryBufferRef(StringRef(Buf, Size), ImportName)};
577}
578
579NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
580 StringRef Weak, bool Imp,
582 std::vector<uint8_t> Buffer;
583 const uint32_t NumberOfSections = 1;
584 const uint32_t NumberOfSymbols = 5;
585
586
587 coff_file_header Header{
589 u16(NumberOfSections),
590 u32(0),
591 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
592 u32(NumberOfSymbols),
593 u16(0),
594 u16(0),
595 };
596 append(Buffer, Header);
597
598
599 const coff_section SectionTable[NumberOfSections] = {
600 {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
601 u32(0),
602 u32(0),
603 u32(0),
604 u32(0),
605 u32(0),
606 u32(0),
607 u16(0),
608 u16(0),
610 append(Buffer, SectionTable);
611
612
614 {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
615 u32(0),
616 u16(0xFFFF),
617 u16(0),
619 0},
620 {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},
621 u32(0),
622 u16(0xFFFF),
623 u16(0),
625 0},
626 {{{0, 0, 0, 0, 0, 0, 0, 0}},
627 u32(0),
628 u16(0),
629 u16(0),
631 0},
632 {{{0, 0, 0, 0, 0, 0, 0, 0}},
633 u32(0),
634 u16(0),
635 u16(0),
637 1},
639 u32(0),
640 u16(0),
641 u16(0),
643 0},
644 };
646
647
648 StringRef Prefix = Imp ? "__imp_" : "";
650 sizeof(uint32_t) + Sym.size() + Prefix.size() + 1;
651 append(Buffer, SymbolTable);
654
655
656 char *Buf = Alloc.Allocate<char>(Buffer.size());
657 memcpy(Buf, Buffer.data(), Buffer.size());
658 return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};
659}
660
665
670 }
671
672 std::vector Members;
674
675 std::vector<uint8_t> ImportDescriptor;
676 Members.push_back(OF.createImportDescriptor(ImportDescriptor));
677
678 std::vector<uint8_t> NullImportDescriptor;
679 Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
680
681 std::vector<uint8_t> NullThunk;
682 Members.push_back(OF.createNullThunk(NullThunk));
683
687 struct Deferred {
688 std::string Name;
691 };
694 if (E.Private)
695 continue;
696
698 if (E.Data)
700 if (E.Constant)
702
703 StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
704 std::string Name;
705
706 if (E.ExtName.empty()) {
707 Name = std::string(SymbolName);
708 } else {
711 if (!ReplacedName)
713 Name.swap(*ReplacedName);
714 }
715
717 std::string ExportName;
718 if (E.Noname) {
720 } else if (!E.ExportAs.empty()) {
722 ExportName = E.ExportAs;
723 } else if (!E.ImportName.empty()) {
724
725
726
727
736 ExportName = E.ImportName;
737 } else if (Name == E.ImportName)
739 else {
740 Deferred D;
741 D.Name = Name;
743 D.Export = &E;
745 continue;
746 }
747 } else {
749 }
750
751
753 if (std::optionalstd::string MangledName =
755 if (!E.Noname && ExportName.empty()) {
757 ExportName.swap(Name);
758 }
759 Name = std::move(*MangledName);
760 } else if (!E.Noname && ExportName.empty()) {
761 std::optionalstd::string DemangledName =
763 if (!DemangledName)
765 StringRef(Twine("Invalid ARM64EC function name '" + Name + "'")
766 .str()),
769 ExportName = std::move(*DemangledName);
770 }
771 }
772
774 Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
776 }
777 for (const auto &D : Renames) {
778 auto It = RegularImports.find(D.Export->ImportName);
779 if (It != RegularImports.end()) {
780
781
784 Members.push_back(OF.createWeakExternal(Symbol, D.Name, false, M));
785 Members.push_back(OF.createWeakExternal(Symbol, D.Name, true, M));
786 } else {
787 Members.push_back(OF.createShortImport(D.Name, D.Export->Ordinal,
789 D.Export->ImportName, M));
790 }
791 }
793 };
794
796 return e;
797 if (Error e = addExports(NativeExports, NativeMachine))
798 return e;
799
802 true, false,
804}
805
806}
807}
This file defines the StringMap class.
AMDGPU Prepare AGPR Alloc
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define offsetof(TYPE, MEMBER)
Function const char TargetMachine * Machine
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
StringRef - Represent a constant reference to a string, i.e.
static constexpr size_t npos
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
const coff_import_header * getCOFFImportHeader() const
StringRef getFileFormatName() const
Definition COFFImportFile.cpp:38
StringRef getExportName() const
Definition COFFImportFile.cpp:76
Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override
Definition COFFImportFile.cpp:101
uint16_t getMachine() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ IMAGE_REL_MIPS_REFWORDNB
@ IMAGE_FILE_MACHINE_ARM64
@ IMAGE_FILE_MACHINE_AMD64
@ IMAGE_FILE_MACHINE_ARM64EC
@ IMAGE_FILE_MACHINE_R4000
@ IMAGE_FILE_MACHINE_I386
@ IMAGE_FILE_MACHINE_ARM64X
@ IMAGE_FILE_MACHINE_ARMNT
@ IMAGE_SCN_CNT_INITIALIZED_DATA
@ IMAGE_REL_ARM64_ADDR32NB
@ IMAGE_REL_AMD64_ADDR32NB
@ IMAGE_SYM_CLASS_SECTION
Line number, reformatted as symbol.
@ IMAGE_SYM_CLASS_EXTERNAL
External symbol.
@ IMAGE_SYM_CLASS_NULL
No symbol.
@ IMAGE_SYM_CLASS_WEAK_EXTERNAL
Duplicate tag.
@ IMAGE_SYM_CLASS_STATIC
Static.
@ IMAGE_WEAK_EXTERN_SEARCH_ALIAS
bool isArm64EC(T Machine)
@ IMPORT_ORDINAL
Import is by ordinal.
@ IMPORT_NAME_EXPORTAS
The import name is specified as a separate string in the import library object file.
@ IMPORT_NAME
The import name is identical to the public symbol name.
@ IMPORT_NAME_UNDECORATE
The import name is the public symbol name, but skipping the leading ?
@ IMPORT_NAME_NOPREFIX
The import name is the public symbol name, but skipping the leading ?
@ IMAGE_FILE_32BIT_MACHINE
Machine is based on a 32bit word architecture.
static void append(std::vector< uint8_t > &B, const T &Data)
Definition COFFImportFile.cpp:141
constexpr std::string_view NullImportDescriptorSymbolName
static StringRef applyNameType(ImportNameType Type, StringRef name)
Definition COFFImportFile.cpp:57
static Expected< std::string > replace(StringRef S, StringRef From, StringRef To)
Definition COFFImportFile.cpp:191
static uint16_t getImgRelRelocation(MachineTypes Machine)
Definition COFFImportFile.cpp:122
constexpr std::string_view NullThunkDataPrefix
coff_symbol< support::ulittle16_t > coff_symbol16
constexpr std::string_view NullThunkDataSuffix
static ImportNameType getNameType(StringRef Sym, StringRef ExtName, MachineTypes Machine, bool MinGW)
Definition COFFImportFile.cpp:174
static void writeStringTable(std::vector< uint8_t > &B, ArrayRef< const std::string_view > Strings)
Definition COFFImportFile.cpp:147
constexpr std::string_view ImportDescriptorPrefix
LLVM_ABI Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef< COFFShortExport > Exports, COFF::MachineTypes Machine, bool MinGW, ArrayRef< COFFShortExport > NativeExports={})
Writes a COFF import library containing entries described by the Exports array.
Definition COFFImportFile.cpp:661
void write32le(void *P, uint32_t V)
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
detail::packed_endian_specific_integral< uint16_t, llvm::endianness::little, unaligned > ulittle16_t
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::optional< std::string > getArm64ECMangledFunctionName(StringRef Name)
Returns the ARM64EC mangled function name unless the input is already mangled.
LLVM_ABI Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr, std::optional< bool > IsEC=std::nullopt, function_ref< void(Error)> Warn=warnToStderr)
@ Export
Export information to summary.
LLVM_ABI std::optional< std::string > getArm64ECDemangledFunctionName(StringRef Name)
Returns the ARM64EC demangled function name, unless the input is not mangled.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
OutputIt copy(R &&Range, OutputIt Out)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
support::ulittle32_t Offset
union llvm::object::coff_symbol::@265345154330271214162033131142206023012313265335 Name