LLVM: lib/MC/ELFObjectWriter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
48#include
49#include
50#include
51#include
52#include
53#include
54#include
55
56using namespace llvm;
57
58#define DEBUG_TYPE "elf-object-writer"
59
60namespace {
62
63STATISTIC(ELFHeaderBytes, "Total size of ELF headers");
64STATISTIC(SectionHeaderBytes, "Total size of section headers table");
65STATISTIC(AllocTextBytes, "Total size of SHF_ALLOC text sections");
66STATISTIC(AllocROBytes, "Total size of SHF_ALLOC readonly sections");
67STATISTIC(AllocRWBytes, "Total size of SHF_ALLOC read-write sections");
68STATISTIC(StrtabBytes, "Total size of SHT_STRTAB sections");
69STATISTIC(SymtabBytes, "Total size of SHT_SYMTAB sections");
70STATISTIC(RelocationBytes, "Total size of relocation sections");
71STATISTIC(DynsymBytes, "Total size of SHT_DYNSYM sections");
73 DebugBytes,
74 "Total size of debug info sections (not including those written to .dwo)");
75STATISTIC(UnwindBytes, "Total size of unwind sections");
76STATISTIC(OtherBytes, "Total size of uncategorized sections");
77STATISTIC(DwoBytes, "Total size of sections written to .dwo file");
78
79}
80
81struct ELFWriter;
82
85}
86
87class SymbolTableWriter {
88 ELFWriter &EWriter;
89 bool Is64Bit;
90
91
92 std::vector<uint32_t> ShndxIndexes;
93
94
95 unsigned NumWritten;
96
97 void createSymtabShndx();
98
99 template void write(T Value);
100
101public:
102 SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit);
103
104 void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
105 uint8_t other, uint32_t shndx, bool Reserved);
106
107 ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; }
108};
109
110struct ELFWriter {
111 MCAssembler &Asm;
112 ELFObjectWriter &OWriter;
113 support::endian::Writer W;
114
115 enum DwoMode {
116 AllSections,
117 NonDwoOnly,
118 DwoOnly,
119 } Mode;
120
121 uint64_t symbolValue(const MCSymbol &Sym);
122 bool isInSymtab(const MCSymbolELF &Symbol);
123
124
125 struct ELFSymbolData {
126 const MCSymbolELF *Symbol;
127 StringRef Name;
128 uint32_t SectionIndex;
129 uint32_t Order;
130 };
131
132
133
134
135
137
138
139
140
141 unsigned LastLocalSymbolIndex = ~0u;
142
143 unsigned StringTableIndex = ~0u;
144
145 unsigned SymbolTableIndex = ~0u;
146
147
148 std::vector<MCSectionELF *> SectionTable;
149 unsigned addToSectionTable(MCSectionELF *Sec);
150
151
153
154 uint64_t align(Align Alignment);
155
156 bool maybeWriteCompression(uint32_t ChType, uint64_t Size,
157 SmallVectorImpl<uint8_t> &CompressedContents,
158 Align Alignment);
159
160public:
161 ELFWriter(MCAssembler &Asm, ELFObjectWriter &OWriter, raw_pwrite_stream &OS,
162 bool IsLittleEndian, DwoMode Mode)
163 : Asm(Asm), OWriter(OWriter),
164 W(OS,
166 Mode(Mode) {}
167
168 MCContext &getContext() const { return Asm.getContext(); }
169
170 void writeWord(uint64_t Word) {
172 W.write<uint64_t>(Word);
173 else
174 W.write<uint32_t>(Word);
175 }
176
177 template void write(T Val) {
178 W.write(Val);
179 }
180
181 void writeHeader();
182
183 void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
184 ELFSymbolData &MSD);
185
186
187 using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>;
188
189
190
191
192
193 void computeSymbolTable(const RevGroupMapTy &RevGroupMap);
194
195 void writeAddrsigSection();
196
197 MCSectionELF *createRelocationSection(MCContext &Ctx,
198 const MCSectionELF &Sec);
199
200 void writeSectionHeaders();
201
202 void writeSectionData(MCSection &Sec);
203
204 void writeSectionHeaderEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
206 uint32_t Link, uint32_t Info,
207 MaybeAlign Alignment, uint64_t EntrySize);
208
209 void writeRelocations(const MCSectionELF &Sec);
210
211 uint64_t writeObject();
212 void writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset,
213 uint64_t Size, const MCSectionELF &Section);
214};
215}
216
218 uint64_t Offset = W.OS.tell();
220 W.OS.write_zeros(NewOffset - Offset);
221 return NewOffset;
222}
223
224unsigned ELFWriter::addToSectionTable(MCSectionELF *Sec) {
225 SectionTable.push_back(Sec);
227 return SectionTable.size();
228}
229
230void SymbolTableWriter::createSymtabShndx() {
231 if (!ShndxIndexes.empty())
232 return;
233
234 ShndxIndexes.resize(NumWritten);
235}
236
237template void SymbolTableWriter::write(T Value) {
238 EWriter.write(Value);
239}
240
241SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit)
242 : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
243
248
249 if (LargeIndex)
250 createSymtabShndx();
251
252 if (!ShndxIndexes.empty()) {
253 if (LargeIndex)
254 ShndxIndexes.push_back(shndx);
255 else
256 ShndxIndexes.push_back(0);
257 }
258
260
261 if (Is64Bit) {
264 write(other);
265 write(Index);
266 write(value);
268 } else {
270 write(uint32_t(value));
273 write(other);
274 write(Index);
275 }
276
277 ++NumWritten;
278}
279
280bool ELFWriter::is64Bit() const {
282}
283
284
285void ELFWriter::writeHeader() {
286
287
288
289
290
291
292
293
294 W.OS << ELF::ElfMagic;
295
297
298
301
303
307 : OSABI);
308
312
314
316
317 W.write<uint16_t>(OWriter.TargetObjectWriter->getEMachine());
318
320 writeWord(0);
321 writeWord(0);
322 writeWord(0);
323
324
326
327
328 W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr)
329 : sizeof(ELF::Elf32_Ehdr));
330
331 W.write<uint16_t>(0);
332 W.write<uint16_t>(0);
333
334
335 W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr)
336 : sizeof(ELF::Elf32_Shdr));
337
338
339 W.write<uint16_t>(0);
340
341
343 W.write<uint16_t>(StringTableIndex);
344}
345
346uint64_t ELFWriter::symbolValue(const MCSymbol &Sym) {
349
350 uint64_t Res;
351 if (.getSymbolOffset(Sym, Res))
352 return 0;
353
354 if (Asm.isThumbFunc(&Sym))
355 Res |= 1;
356
357 return Res;
358}
359
362
363
364
365
366
367
368 switch (origType) {
369 default:
370 break;
375 break;
380 break;
384 break;
389 break;
390 }
391
393}
394
398 if (!Symbol->isVariable() ||
400 Value->getSpecifier() ||
403 return false;
404 Symbol = &static_cast<const MCSymbolELF &>(Value->getSymbol());
405 }
406 return true;
407}
408
409void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
410 ELFSymbolData &MSD) {
411 auto &Symbol = static_cast<const MCSymbolELF &>(*MSD.Symbol);
412 auto *Base = static_cast<const MCSymbolELF *>(Asm.getBaseSymbol(Symbol));
413
414
415
416 bool IsReserved = || Symbol.isCommon();
417
418
425 }
427
428
429
430 uint8_t Visibility = Symbol.getVisibility();
431 uint8_t Other = Symbol.getOther() | Visibility;
432
433 uint64_t Value = symbolValue(*MSD.Symbol);
434 uint64_t Size = 0;
435
436 const MCExpr *ESize = MSD.Symbol->getSize();
437 if (!ESize && Base) {
438
439 ESize = Base->getSize();
440
441
442
443
444
445 const MCSymbolELF *Sym = &Symbol;
448 Sym = static_cast<const MCSymbolELF *>(&Expr->getSymbol());
450 continue;
452 }
453 break;
454 }
455 }
456
457 if (ESize) {
458 int64_t Res;
462 }
463
464
465 Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex,
466 IsReserved);
467}
468
469bool ELFWriter::isInSymtab(const MCSymbolELF &Symbol) {
470 if (Symbol.isUsedInReloc() || Symbol.isSignature())
471 return true;
472
473 if (OWriter.Renames.count(&Symbol))
474 return false;
475
476 if (Symbol.isVariable()) {
477 const MCExpr *Expr = Symbol.getVariableValue();
478
480 if (T->inlineAssignedExpr())
481 return false;
482
483 if (Symbol.isWeakref())
484 return false;
485
486 if (Symbol.isUndefined()) {
487
488 Asm.getBaseSymbol(Symbol);
489 return false;
490 }
491 }
492
493 if (Symbol.isTemporary())
494 return false;
495
497}
498
499void ELFWriter::computeSymbolTable(const RevGroupMapTy &RevGroupMap) {
500 MCContext &Ctx = Asm.getContext();
501 SymbolTableWriter Writer(*this, is64Bit());
502
503
505 MCSectionELF *SymtabSection =
508 SymbolTableIndex = addToSectionTable(SymtabSection);
509
510 uint64_t SecStart = align(SymtabSection->getAlign());
511
512
513 Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
514
515 std::vector LocalSymbolData;
516 std::vector ExternalSymbolData;
519 for (const std::pair<std::string, size_t> &F : FileNames)
520 StrTabBuilder.add(F.first);
521
522
523 bool HasLargeSectionIndex = false;
525 auto &Symbol = static_cast<const MCSymbolELF &>(It.value());
527 continue;
528
529 if (Symbol.isTemporary() && Symbol.isUndefined()) {
530 Ctx.reportError(SMLoc(), "Undefined temporary symbol " + Symbol.getName());
531 continue;
532 }
533
534 ELFSymbolData MSD;
535 MSD.Symbol = static_cast<const MCSymbolELF *>(&Symbol);
536 MSD.Order = It.index();
537
540
541 if (Symbol.isAbsolute()) {
543 } else if (Symbol.isCommon()) {
544 auto Shndx = Symbol.getIndex();
545 if (!Shndx) {
548 }
549 MSD.SectionIndex = Shndx;
550 } else if (Symbol.isUndefined()) {
551 if (Symbol.isSignature() && .isUsedInReloc()) {
552 MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
554 HasLargeSectionIndex = true;
555 } else {
557 }
558 } else {
559 const MCSectionELF &Section =
560 static_cast<const MCSectionELF &>(Symbol.getSection());
563 continue;
564 MSD.SectionIndex = Section.getOrdinal();
565 assert(MSD.SectionIndex && "Invalid section index!");
567 HasLargeSectionIndex = true;
568 }
569
570
571
572
573
575 if (Name.empty())
576 Name = ".L0 ";
577
578
580 MSD.Name = Name;
581 StrTabBuilder.add(Name);
582 }
583
585 LocalSymbolData.push_back(MSD);
586 else
587 ExternalSymbolData.push_back(MSD);
588 }
589
590
591 unsigned SymtabShndxSectionIndex = 0;
592
593 if (HasLargeSectionIndex) {
594 MCSectionELF *SymtabShndxSection =
596 SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
598 }
599
601
602
603 unsigned Index = 1;
604 auto FileNameIt = FileNames.begin();
605 if (!FileNames.empty())
606 FileNames[0].second = 0;
607
608 for (ELFSymbolData &MSD : LocalSymbolData) {
609
610 for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;
611 ++FileNameIt) {
612 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
616 }
617
618 unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
619 ? 0
620 : StrTabBuilder.getOffset(MSD.Name);
621 MSD.Symbol->setIndex(Index++);
622 writeSymbol(Writer, StringIndex, MSD);
623 }
624 for (; FileNameIt != FileNames.end(); ++FileNameIt) {
625 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
629 }
630
631
632 LastLocalSymbolIndex = Index;
633
634 for (ELFSymbolData &MSD : ExternalSymbolData) {
635 unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
636 MSD.Symbol->setIndex(Index++);
637 writeSymbol(Writer, StringIndex, MSD);
639 }
640
641 uint64_t SecEnd = W.OS.tell();
642 SymtabSection->setOffsets(SecStart, SecEnd);
643
644 ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
645 if (ShndxIndexes.empty()) {
646 assert(SymtabShndxSectionIndex == 0);
647 return;
648 }
649 assert(SymtabShndxSectionIndex != 0);
650
651 SecStart = W.OS.tell();
652 MCSectionELF *SymtabShndxSection = SectionTable[SymtabShndxSectionIndex - 1];
653 for (uint32_t Index : ShndxIndexes)
655 SecEnd = W.OS.tell();
656 SymtabShndxSection->setOffsets(SecStart, SecEnd);
657}
658
659void ELFWriter::writeAddrsigSection() {
663}
664
665MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
666 const MCSectionELF &Sec) {
668 return nullptr;
669
673
676 if (TO && TO->Crel) {
677 MCSectionELF *RelaSection =
679 1, Sec.getGroup(), &Sec);
680 return RelaSection;
681 }
682
683 const bool Rela = OWriter.usesRela(TO, Sec);
684 unsigned EntrySize;
685 if (Rela)
686 EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
687 else
688 EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);
689
690 MCSectionELF *RelaSection =
693 EntrySize, Sec.getGroup(), &Sec);
695 return RelaSection;
696}
697
698
699bool ELFWriter::maybeWriteCompression(
700 uint32_t ChType, uint64_t Size,
701 SmallVectorImpl<uint8_t> &CompressedContents, Align Alignment) {
702 uint64_t HdrSize =
703 is64Bit() ? sizeof(ELF::Elf64_Chdr) : sizeof(ELF::Elf32_Chdr);
704 if (Size <= HdrSize + CompressedContents.size())
705 return false;
706
708
713 } else {
714
718 }
719 return true;
720}
721
722void ELFWriter::writeSectionData(MCSection &Sec) {
723 MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
725 auto &Ctx = Asm.getContext();
728 : DebugCompressionType::None;
729 if (CompressionType == DebugCompressionType::None ||
731 Asm.writeSectionData(W.OS, &Section);
732 return;
733 }
734
735 SmallVector<char, 128> UncompressedData;
736 raw_svector_ostream VecOS(UncompressedData);
737 Asm.writeSectionData(VecOS, &Section);
738 ArrayRef<uint8_t> Uncompressed =
739 ArrayRef(reinterpret_cast<uint8_t *>(UncompressedData.data()),
740 UncompressedData.size());
741
742 SmallVector<uint8_t, 128> Compressed;
743 uint32_t ChType;
744 switch (CompressionType) {
745 case DebugCompressionType::None:
747 case DebugCompressionType::Zlib:
749 break;
750 case DebugCompressionType::Zstd:
752 break;
753 }
755 Compressed);
756 if (!maybeWriteCompression(ChType, UncompressedData.size(), Compressed,
758 W.OS << UncompressedData;
759 return;
760 }
761
763
764
767}
768
769void ELFWriter::writeSectionHeaderEntry(uint32_t Name, uint32_t Type,
770 uint64_t Flags, uint64_t Address,
772 uint32_t Link, uint32_t Info,
773 MaybeAlign Alignment,
774 uint64_t EntrySize) {
777 writeWord(Flags);
778 writeWord(Address);
779 writeWord(Offset);
780 writeWord(Size);
781 W.write<uint32_t>(Link);
783 writeWord(Alignment ? Alignment->value() : 0);
784 writeWord(EntrySize);
785}
786
787template
789 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
791 uint32_t SymIdx = R.Symbol ? R.Symbol->getIndex() : 0;
793 std::make_signed_t(R.Addend)};
794 });
795}
796
797void ELFWriter::writeRelocations(const MCSectionELF &Sec) {
798 std::vector &Relocs = OWriter.Relocations[&Sec];
799 const MCTargetOptions *TO = getContext().getTargetOptions();
800 const bool Rela = OWriter.usesRela(TO, Sec);
801
802
804
806 for (const ELFRelocationEntry &Entry : Relocs) {
807 uint32_t SymIdx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
810 write(uint32_t(SymIdx));
815 if (Rela)
817 } else {
819 ELF::Elf32_Rela ERE32;
822 if (Rela)
824 if (uint32_t RType =
829 write(uint32_t(0));
830 }
831 if (uint32_t RType =
836 write(uint32_t(0));
837 }
838 }
839 }
840 } else if (TO && TO->Crel) {
843 else
845 } else {
846 for (const ELFRelocationEntry &Entry : Relocs) {
847 uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
850 ELF::Elf64_Rela ERE;
853 if (Rela)
855 } else {
857 ELF::Elf32_Rela ERE;
860 if (Rela)
862 }
863 }
864 }
865}
866
867void ELFWriter::writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset,
868 uint64_t Size, const MCSectionELF &Section) {
869 uint64_t sh_link = 0;
870 uint64_t sh_info = 0;
871
872 switch(Section.getType()) {
873 default:
874
875 break;
876
879
883 sh_link = SymbolTableIndex;
884 assert(sh_link && ".symtab not found");
885 const MCSection *InfoSection = Section.getLinkedToSection();
887 break;
888 }
889
891 sh_link = StringTableIndex;
892 sh_info = LastLocalSymbolIndex;
893 break;
894
898 sh_link = SymbolTableIndex;
899 break;
900
902 sh_link = SymbolTableIndex;
903 sh_info = GroupSymbolIndex;
904 break;
905 }
906
908
909
913 }
914
915 writeSectionHeaderEntry(StrTabBuilder.getOffset(Section.getName()),
917 Size, sh_link, sh_info, Section.getAlign(),
919}
920
921void ELFWriter::writeSectionHeaders() {
922 uint64_t Start = W.OS.tell();
923 const unsigned NumSections = SectionTable.size();
924
925
926 uint64_t FirstSectionSize =
928 writeSectionHeaderEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, std::nullopt,
929 0);
930
931 for (const MCSectionELF *Section : SectionTable) {
932 uint32_t GroupSymbolIndex;
935 GroupSymbolIndex = 0;
936 else
937 GroupSymbolIndex = Section->getGroup()->getIndex();
938
939 std::pair<uint64_t, uint64_t> Offsets = Section->getOffsets();
940 uint64_t Size;
942 Size = Asm.getSectionAddressSize(*Section);
943 else
945
946 auto SectionHasFlag = [&](uint64_t Flag) -> bool {
948 };
949
950 if (Mode == DwoOnly) {
951 stats::DwoBytes += Size;
952 } else if (Section->getName().starts_with(".debug")) {
953 stats::DebugBytes += Size;
954 } else if (Section->getName().starts_with(".eh_frame")) {
955 stats::UnwindBytes += Size;
958 stats::AllocTextBytes += Size;
960 stats::AllocRWBytes += Size;
961 } else {
962 stats::AllocROBytes += Size;
963 }
964 } else {
965 switch (Section->getType()) {
967 stats::StrtabBytes += Size;
968 break;
970 stats::SymtabBytes += Size;
971 break;
973 stats::DynsymBytes += Size;
974 break;
978 stats::RelocationBytes += Size;
979 break;
980 default:
981 stats::OtherBytes += Size;
982 break;
983 }
984 }
985
986 writeSectionHeader(GroupSymbolIndex, Offsets.first, Size, *Section);
987 }
988
989 stats::SectionHeaderBytes += W.OS.tell() - Start;
990}
991
992uint64_t ELFWriter::writeObject() {
993 uint64_t StartOffset = W.OS.tell();
994
996 MCSectionELF *StrtabSection =
998 StringTableIndex = addToSectionTable(StrtabSection);
999
1000 RevGroupMapTy RevGroupMap;
1001
1002
1003 writeHeader();
1004
1005 stats::ELFHeaderBytes += W.OS.tell() - StartOffset;
1006
1007
1009
1010 SmallVector<unsigned, 0> GroupMap;
1012 for (MCSection &Sec : Asm) {
1013 MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
1015 continue;
1017 continue;
1018
1019
1020 const uint64_t SecStart = align(Section.getAlign());
1021
1022 const MCSymbolELF *SignatureSymbol = Section.getGroup();
1023 writeSectionData(Section);
1024
1025 uint64_t SecEnd = W.OS.tell();
1026 Section.setOffsets(SecStart, SecEnd);
1027
1028 MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
1029
1030 unsigned *GroupIdxEntry = nullptr;
1031 if (SignatureSymbol) {
1032 GroupIdxEntry = &RevGroupMap[SignatureSymbol];
1033 if (!*GroupIdxEntry) {
1034 MCSectionELF *Group =
1036 *GroupIdxEntry = addToSectionTable(Group);
1038
1039 GroupMap.resize(*GroupIdxEntry + 1);
1040 GroupMap[*GroupIdxEntry] = Groups.size();
1041 Groups.emplace_back(Group, SmallVector{});
1042 }
1043 }
1044
1045 Section.setOrdinal(addToSectionTable(&Section));
1046 if (RelSection) {
1047 RelSection->setOrdinal(addToSectionTable(RelSection));
1048 Relocations.push_back(RelSection);
1049 }
1050
1051 if (GroupIdxEntry) {
1052 auto &Members = Groups[GroupMap[*GroupIdxEntry]];
1053 Members.second.push_back(Section.getOrdinal());
1054 if (RelSection)
1055 Members.second.push_back(RelSection->getOrdinal());
1056 }
1057 }
1058
1059 for (auto &[Group, Members] : Groups) {
1060
1061 const uint64_t SecStart = align(Group->getAlign());
1062
1064 W.write<unsigned>(Members);
1065
1066 uint64_t SecEnd = W.OS.tell();
1067 Group->setOffsets(SecStart, SecEnd);
1068 }
1069
1070 if (Mode == DwoOnly) {
1071
1072
1074 } else {
1075 MCSectionELF *AddrsigSection;
1079 addToSectionTable(AddrsigSection);
1080 }
1081
1082
1083 computeSymbolTable(RevGroupMap);
1084
1085 for (MCSectionELF *RelSection : Relocations) {
1086
1087 const uint64_t SecStart = align(RelSection->getAlign());
1088
1089 writeRelocations(
1090 static_cast<const MCSectionELF &>(*RelSection->getLinkedToSection()));
1091
1092 uint64_t SecEnd = W.OS.tell();
1093 RelSection->setOffsets(SecStart, SecEnd);
1094 }
1095
1097 uint64_t SecStart = W.OS.tell();
1098 writeAddrsigSection();
1099 uint64_t SecEnd = W.OS.tell();
1100 AddrsigSection->setOffsets(SecStart, SecEnd);
1101 }
1102 }
1103
1104 {
1105 uint64_t SecStart = W.OS.tell();
1106 StrTabBuilder.write(W.OS);
1107 StrtabSection->setOffsets(SecStart, W.OS.tell());
1108 }
1109
1110 const uint64_t SectionHeaderOffset = align(is64Bit() ? Align(8) : Align(4));
1111
1112
1113 writeSectionHeaders();
1114
1117 : SectionTable.size() + 1,
1118 W.Endian);
1119 unsigned NumSectionsOffset;
1120
1121 auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
1123 uint64_t Val =
1125 Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1126 offsetof(ELF::Elf64_Ehdr, e_shoff));
1127 NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
1128 } else {
1129 uint32_t Val =
1131 Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1132 offsetof(ELF::Elf32_Ehdr, e_shoff));
1133 NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
1134 }
1135 Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
1136 NumSectionsOffset);
1137
1138 return W.OS.tell() - StartOffset;
1139}
1140
1150
1152 ELFHeaderEFlags = 0;
1161}
1162
1167
1171
1173
1174
1177 auto &Symbol = static_cast<const MCSymbolELF &>(*S.Sym);
1178 size_t Pos = AliasName.find('@');
1180
1185 Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1);
1186
1187 auto *Alias = static_cast<MCSymbolELF *>(
1188 Asm->getContext().getOrCreateSymbol(Prefix + Tail));
1189 Asm->registerSymbol(*Alias);
1191 Alias->setVariableValue(Value);
1192
1193
1194
1195 Alias->setBinding(Symbol.getBinding());
1196 Alias->setVisibility(Symbol.getVisibility());
1197 Alias->setOther(Symbol.getOther());
1198
1199 if (!Symbol.isUndefined() && S.KeepOriginalSym)
1200 continue;
1201
1202 if (Symbol.isUndefined() && Rest.starts_with("@@") &&
1204 Asm->getContext().reportError(S.Loc, "default version symbol " +
1205 AliasName + " must be defined");
1206 continue;
1207 }
1208
1209 if (auto It = Renames.find(&Symbol);
1210 It != Renames.end() && It->second != Alias) {
1211 Asm->getContext().reportError(S.Loc, Twine("multiple versions for ") +
1212 Symbol.getName());
1213 continue;
1214 }
1215
1216 Renames.insert(std::make_pair(&Symbol, Alias));
1217 }
1218
1222 Sym = R;
1226 }
1227
1228
1229
1230
1231
1233 if (!Alias->isRegistered())
1234 continue;
1235 auto *Expr = Alias->getVariableValue();
1237 auto &Sym = static_cast<const MCSymbolELF &>(Inner->getSymbol());
1238 if (Asm->registerSymbol(Sym))
1240 }
1241 }
1242}
1243
1244
1245
1246
1249 unsigned Type) const {
1250
1251
1252
1254 return false;
1255
1256
1257
1258
1259
1260
1261
1262
1265 unsigned Flags = Sec.getFlags();
1267 if (C != 0)
1268 return false;
1269
1270
1271
1273 Type == ELF::R_386_GOTOFF)
1274 return false;
1275
1276
1277
1278
1279
1280
1281
1282
1285 return false;
1286 }
1287
1288
1289
1290
1291
1293 return false;
1294 }
1295
1297}
1298
1303 return false;
1304 }
1307 "A relocation may not refer to a dwo section");
1308 return false;
1309 }
1310 return true;
1311}
1312
1316 auto &Section = static_cast<const MCSectionELF &>(*F.getParent());
1318
1319 auto *SymA = static_cast<const MCSymbolELF *>(Target.getAddSym());
1321 (SymA && SymA->isInSection())
1322 ? static_cast<const MCSectionELF *>(&SymA->getSection())
1323 : nullptr;
1325 return;
1326
1327 bool IsPCRel = Fixup.isPCRel();
1328 uint64_t FixupOffset = Asm->getFragmentOffset(F) + Fixup.getOffset();
1330 if (auto *RefB = Target.getSubSym()) {
1331 auto &SymB = static_cast<const MCSymbolELF &>(*RefB);
1332 if (SymB.isUndefined()) {
1333 Ctx.reportError(Fixup.getLoc(),
1334 Twine("symbol '") + SymB.getName() +
1335 "' can not be undefined in a subtraction expression");
1336 return;
1337 }
1338
1339 assert(!SymB.isAbsolute() && "Should have been folded");
1340 const MCSection &SecB = SymB.getSection();
1341 if (&SecB != &Section) {
1342 Ctx.reportError(Fixup.getLoc(),
1343 "Cannot represent a difference across sections");
1344 return;
1345 }
1346
1347 assert(!IsPCRel && "should have been folded");
1348 IsPCRel = true;
1349 Addend += FixupOffset - Asm->getSymbolOffset(SymB);
1350 }
1351
1352 unsigned Type;
1355 else
1357
1358
1359
1360
1361 bool UseSectionSym = SymA && SymA->getBinding() == ELF::STB_LOCAL &&
1362 !SymA->isUndefined() &&
1365 Addend += Asm->getSymbolOffset(*SymA);
1368 SymA = R;
1369 }
1370 if (SymA)
1371 SymA->setUsedInReloc();
1372
1373 FixedValue = usesRela(Ctx.getTargetOptions(), Section) ? 0 : Addend;
1374 Relocations[&Section].emplace_back(FixupOffset, SymA, Type, Addend);
1375}
1376
1381 (TO && TO->Crel);
1382}
1383
1385 const MCSymbol &SA, const MCFragment &FB, bool InSet, bool IsPCRel) const {
1386 auto &SymA = static_cast<const MCSymbolELF &>(SA);
1387 if (IsPCRel) {
1391 return false;
1392 }
1394}
1395
1399 DwoOS ? ELFWriter::NonDwoOnly : ELFWriter::AllSections)
1400 .writeObject();
1403 .writeObject();
1404 return Size;
1405}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
DXIL Resource Implicit Binding
This file defines the DenseMap class.
static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType)
Definition ELFObjectWriter.cpp:360
static void encodeCrel(ArrayRef< ELFRelocationEntry > Relocs, raw_ostream &OS)
Definition ELFObjectWriter.cpp:788
static bool isIFunc(const MCSymbolELF *Symbol)
Definition ELFObjectWriter.cpp:395
#define offsetof(TYPE, MEMBER)
PowerPC TLS Dynamic Call Fixup
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool isInSymtab(const MCSymbolWasm &Sym)
static bool isDwoSection(const MCSection &Sec)
static bool is64Bit(const char *name)
static const X86InstrFMA3Group Groups[]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
std::unique_ptr< MCELFObjectTargetWriter > TargetObjectWriter
ELFObjectWriter(std::unique_ptr< MCELFObjectTargetWriter > MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
Definition ELFObjectWriter.cpp:1141
void setAssembler(MCAssembler *Asm) override
Definition ELFObjectWriter.cpp:1163
SmallVector< const MCSymbolELF *, 0 > Weakrefs
bool checkRelocation(SMLoc Loc, const MCSectionELF *From, const MCSectionELF *To)
Definition ELFObjectWriter.cpp:1299
unsigned getELFHeaderEFlags() const
void reset() override
lifetime management
Definition ELFObjectWriter.cpp:1151
std::optional< uint8_t > OverrideABIVersion
uint64_t writeObject() override
Write the object file and returns the number of bytes written.
Definition ELFObjectWriter.cpp:1396
DenseMap< const MCSectionELF *, std::vector< ELFRelocationEntry > > Relocations
void executePostLayoutBinding() override
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
Definition ELFObjectWriter.cpp:1172
bool isSymbolRefDifferenceFullyResolvedImpl(const MCSymbol &SymA, const MCFragment &FB, bool InSet, bool IsPCRel) const override
Definition ELFObjectWriter.cpp:1384
SmallVector< Symver, 0 > Symvers
bool hasRelocationAddend() const
Definition ELFObjectWriter.cpp:1168
void recordRelocation(const MCFragment &F, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) override
Record a relocation entry.
Definition ELFObjectWriter.cpp:1313
raw_pwrite_stream * DwoOS
bool usesRela(const MCTargetOptions *TO, const MCSectionELF &Sec) const
Definition ELFObjectWriter.cpp:1377
bool useSectionSymbol(const MCValue &Val, const MCSymbolELF *Sym, uint64_t C, unsigned Type) const
Definition ELFObjectWriter.cpp:1247
DenseMap< const MCSymbolELF *, const MCSymbolELF * > Renames
Context object for machine code objects.
LLVM_ABI MCSectionELF * createELFRelSection(const Twine &Name, unsigned Type, unsigned Flags, unsigned EntrySize, const MCSymbolELF *Group, const MCSectionELF *RelInfoSection)
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
const MCTargetOptions * getTargetOptions() const
LLVM_ABI MCSectionELF * createELFGroupSection(const MCSymbolELF *Group, bool IsComdat)
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const
Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
MCSection * getParent() const
MutableArrayRef< std::pair< std::string, size_t > > getFileNames()
virtual void setAssembler(MCAssembler *A)
bool getEmitAddrsigSection()
std::vector< const MCSymbol * > & getAddrsigSyms()
virtual void reset()
lifetime management
std::vector< const MCSymbol * > AddrsigSyms
MCContext & getContext() const
This represents a section on linux, lots of unix variants and some bare metal systems.
const MCSection * getLinkedToSection() const
unsigned getFlags() const
void setOffsets(uint64_t Start, uint64_t End)
const MCSymbolELF * getGroup() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
void setAlignment(Align Value)
unsigned getOrdinal() const
void setOrdinal(unsigned Value)
StringRef getName() const
MCSymbol * getBeginSymbol()
const MCExpr * getSize() const
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).
bool isCommon() const
Is this a 'common' symbol.
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
MaybeAlign getCommonAlignment() const
Return the alignment of a 'common' symbol.
void setUsedInReloc() const
uint32_t getIndex() const
Get the (implementation defined) index.
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
DebugCompressionType CompressDebugSections
Represents a location in source code.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
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.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
LLVM_ABI size_t getOffset(CachedHashStringRef S) const
Get the offest of a string in the string table.
LLVM_ABI size_t add(CachedHashStringRef S, uint8_t Priority=0)
Add a string to the builder.
LLVM_ABI void write(raw_ostream &OS) const
LLVM_ABI void finalize()
Analyze the strings and build the final table.
Target - Wrapper for Target specific information.
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.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
An abstract base class for streams implementations that also support a pwrite operation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ C
The default llvm calling convention, compatible with C.
void encodeCrel(raw_ostream &OS, RelocsTy Relocs, F ToCrel)
static const char ElfMagic[]
@ SHT_LLVM_CALL_GRAPH_PROFILE
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Offsets
Offsets in bytes from the start of the input buffer.
LLVM_ABI void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)
support::ulittle32_t Word
bool isRelocRelocation(MCFixupKind FixupKind)
Context & getContext() const
value_type byte_swap(value_type value, endianness endian)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
@ FirstLiteralRelocationKind
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
Definition ELFObjectWriter.cpp:61
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
void setSymbolAndType(Elf32_Word s, unsigned char t)
void setSymbolAndType(Elf64_Word s, Elf64_Word t)