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));

271 write(uint32_t(size));

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 (Asm.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 = Base || 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() && Symbol.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) {

775 W.write<uint32_t>(Name);

776 W.write<uint32_t>(Type);

777 writeWord(Flags);

778 writeWord(Address);

779 writeWord(Offset);

780 writeWord(Size);

781 W.write<uint32_t>(Link);

782 W.write<uint32_t>(Info);

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)