LLVM: lib/MC/ELFObjectWriter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

50#include

51#include

52#include

53#include

54#include

55#include

56#include

57

58using namespace llvm;

59

60#define DEBUG_TYPE "elf-object-writer"

61

62namespace {

64

65STATISTIC(ELFHeaderBytes, "Total size of ELF headers");

66STATISTIC(SectionHeaderBytes, "Total size of section headers table");

67STATISTIC(AllocTextBytes, "Total size of SHF_ALLOC text sections");

68STATISTIC(AllocROBytes, "Total size of SHF_ALLOC readonly sections");

69STATISTIC(AllocRWBytes, "Total size of SHF_ALLOC read-write sections");

70STATISTIC(StrtabBytes, "Total size of SHT_STRTAB sections");

71STATISTIC(SymtabBytes, "Total size of SHT_SYMTAB sections");

72STATISTIC(RelocationBytes, "Total size of relocation sections");

73STATISTIC(DynsymBytes, "Total size of SHT_DYNSYM sections");

74STATISTIC(DebugBytes, "Total size of debug info sections");

75STATISTIC(UnwindBytes, "Total size of unwind sections");

76STATISTIC(OtherBytes, "Total size of uncategorized sections");

77

78}

79

80struct ELFWriter;

81

84}

85

86class SymbolTableWriter {

87 ELFWriter &EWriter;

88 bool Is64Bit;

89

90

91 std::vector<uint32_t> ShndxIndexes;

92

93

94 unsigned NumWritten;

95

96 void createSymtabShndx();

97

98 template void write(T Value);

99

100public:

101 SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit);

102

105

107};

108

109struct ELFWriter {

112

113 enum DwoMode {

114 AllSections,

115 NonDwoOnly,

116 DwoOnly,

118

121 bool Used, bool Renamed);

122

123

124 struct ELFSymbolData {

129 };

130

131

132

133

134

136

137

138

139

140 unsigned LastLocalSymbolIndex = ~0u;

141

142 unsigned StringTableIndex = ~0u;

143

144 unsigned SymbolTableIndex = ~0u;

145

146

147 std::vector<MCSectionELF *> SectionTable;

148 unsigned addToSectionTable(MCSectionELF *Sec);

149

150

152

154

157 Align Alignment);

158

159public:

161 bool IsLittleEndian, DwoMode Mode)

165

166 void writeWord(uint64_t Word) {

169 else

171 }

172

173 template void write(T Val) {

174 W.write(Val);

175 }

176

177 void writeHeader(const MCAssembler &Asm);

178

179 void writeSymbol(const MCAssembler &Asm, SymbolTableWriter &Writer,

180 uint32_t StringIndex, ELFSymbolData &MSD);

181

182

184

185

186

187

188

189 void computeSymbolTable(MCAssembler &Asm, const RevGroupMapTy &RevGroupMap);

190

191 void writeAddrsigSection();

192

195

196 void writeSectionHeaders(const MCAssembler &Asm);

197

199

204

206

210};

211}

212

216 W.OS.write_zeros(NewOffset - Offset);

217 return NewOffset;

218}

219

220unsigned ELFWriter::addToSectionTable(MCSectionELF *Sec) {

221 SectionTable.push_back(Sec);

222 StrTabBuilder.add(Sec->getName());

223 return SectionTable.size();

224}

225

226void SymbolTableWriter::createSymtabShndx() {

227 if (!ShndxIndexes.empty())

228 return;

229

230 ShndxIndexes.resize(NumWritten);

231}

232

233template void SymbolTableWriter::write(T Value) {

234 EWriter.write(Value);

235}

236

237SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit)

238 : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}

239

244

245 if (LargeIndex)

246 createSymtabShndx();

247

248 if (!ShndxIndexes.empty()) {

249 if (LargeIndex)

250 ShndxIndexes.push_back(shndx);

251 else

252 ShndxIndexes.push_back(0);

253 }

254

256

257 if (Is64Bit) {

260 write(other);

261 write(Index);

263 write(size);

264 } else {

269 write(other);

270 write(Index);

271 }

272

273 ++NumWritten;

274}

275

276bool ELFWriter::is64Bit() const {

278}

279

280

281void ELFWriter::writeHeader(const MCAssembler &Asm) {

282

283

284

285

286

287

288

289

290 W.OS << ELF::ElfMagic;

291

293

294

297

299

303 : OSABI);

304

308

310

312

314

316 writeWord(0);

317 writeWord(0);

318 writeWord(0);

319

320

322

323

326

327 W.write<uint16_t>(0);

328 W.write<uint16_t>(0);

329

330

333

334

336

337

339 W.write<uint16_t>(StringTableIndex);

340}

341

343 if (Sym.isCommon())

344 return Sym.getCommonAlignment()->value();

345

347 if (Asm.getSymbolOffset(Sym, Res))

348 return 0;

349

350 if (Asm.isThumbFunc(&Sym))

351 Res |= 1;

352

353 return Res;

354}

355

358

359

360

361

362

363

364 switch (origType) {

365 default:

366 break;

371 break;

376 break;

380 break;

385 break;

386 }

387

389}

390

394 if (!Symbol->isVariable() ||

395 !(Value = dyn_cast(Symbol->getVariableValue())) ||

398 return false;

399 Symbol = &cast(Value->getSymbol());

400 }

401 return true;

402}

403

404void ELFWriter::writeSymbol(const MCAssembler &Asm, SymbolTableWriter &Writer,

405 uint32_t StringIndex, ELFSymbolData &MSD) {

406 const auto &Symbol = cast(*MSD.Symbol);

408 cast_or_null(Asm.getBaseSymbol(Symbol));

409

410

411

412 bool IsReserved = Base || Symbol.isCommon();

413

414

421 }

423

424

425

428

431

432 const MCExpr *ESize = MSD.Symbol->getSize();

433 if (!ESize && Base) {

434

435 ESize = Base->getSize();

436

437

438

439

440

442 while (Sym->isVariable()) {

443 if (auto *Expr =

444 dyn_cast(Sym->getVariableValue(false))) {

445 Sym = cast(&Expr->getSymbol());

446 if (Sym->getSize())

447 continue;

448 ESize = Sym->getSize();

449 }

450 break;

451 }

452 }

453

454 if (ESize) {

455 int64_t Res;

459 }

460

461

462 Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex,

463 IsReserved);

464}

465

467 bool Used, bool Renamed) {

468 if (Symbol.isVariable()) {

469 const MCExpr *Expr = Symbol.getVariableValue();

470

471 if (const auto *T = dyn_cast(Expr))

472 if (T->inlineAssignedExpr())

473 return false;

476 return false;

477 }

478 }

479

480 if (Used)

481 return true;

482

483 if (Renamed)

484 return false;

485

486 if (Symbol.isVariable() && Symbol.isUndefined()) {

487

488 Asm.getBaseSymbol(Symbol);

489 return false;

490 }

491

492 if (Symbol.isTemporary())

493 return false;

494

496 return false;

497

498 return true;

499}

500

501void ELFWriter::computeSymbolTable(MCAssembler &Asm,

502 const RevGroupMapTy &RevGroupMap) {

504 SymbolTableWriter Writer(*this, is64Bit());

505

506

511 SymbolTableIndex = addToSectionTable(SymtabSection);

512

514

515

516 Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);

517

518 std::vector LocalSymbolData;

519 std::vector ExternalSymbolData;

522 for (const std::pair<std::string, size_t> &F : FileNames)

523 StrTabBuilder.add(F.first);

524

525

526 bool HasLargeSectionIndex = false;

528 const auto &Symbol = cast(It.value());

530 bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();

531 bool isSignature = Symbol.isSignature();

532

533 if (isInSymtab(Asm, Symbol, Used || WeakrefUsed || isSignature,

534 OWriter.Renames.count(&Symbol)))

535 continue;

536

537 if (Symbol.isTemporary() && Symbol.isUndefined()) {

539 continue;

540 }

541

542 ELFSymbolData MSD;

543 MSD.Symbol = cast(&Symbol);

544 MSD.Order = It.index();

545

548

549 if (Symbol.isAbsolute()) {

551 } else if (Symbol.isCommon()) {

552 if (Symbol.isTargetCommon()) {

553 MSD.SectionIndex = Symbol.getIndex();

554 } else {

557 }

558 } else if (Symbol.isUndefined()) {

559 if (isSignature && !Used) {

560 MSD.SectionIndex = RevGroupMap.lookup(&Symbol);

562 HasLargeSectionIndex = true;

563 } else {

565 }

566 } else {

569

570

571

572

573

574

575 if (Section.isRegistered()) {

579 "Undefined section reference: " + Symbol.getName());

580 continue;

581 }

582

583 if (Mode == NonDwoOnly && isDwoSection(Section))

584 continue;

585 MSD.SectionIndex = Section.getOrdinal();

586 assert(MSD.SectionIndex && "Invalid section index!");

588 HasLargeSectionIndex = true;

589 }

590

591

592

593

594

596 if (Name.empty())

597 Name = ".L0 ";

598

599

601 MSD.Name = Name;

602 StrTabBuilder.add(Name);

603 }

604

606 LocalSymbolData.push_back(MSD);

607 else

608 ExternalSymbolData.push_back(MSD);

609 }

610

611

612 unsigned SymtabShndxSectionIndex = 0;

613

614 if (HasLargeSectionIndex) {

617 SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);

619 }

620

621 StrTabBuilder.finalize();

622

623

624 unsigned Index = 1;

625 auto FileNameIt = FileNames.begin();

626 if (!FileNames.empty())

627 FileNames[0].second = 0;

628

629 for (ELFSymbolData &MSD : LocalSymbolData) {

630

631 for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;

632 ++FileNameIt) {

633 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),

637 }

638

639 unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION

640 ? 0

641 : StrTabBuilder.getOffset(MSD.Name);

642 MSD.Symbol->setIndex(Index++);

643 writeSymbol(Asm, Writer, StringIndex, MSD);

644 }

645 for (; FileNameIt != FileNames.end(); ++FileNameIt) {

646 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),

650 }

651

652

653 LastLocalSymbolIndex = Index;

654

655 for (ELFSymbolData &MSD : ExternalSymbolData) {

656 unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);

657 MSD.Symbol->setIndex(Index++);

658 writeSymbol(Asm, Writer, StringIndex, MSD);

660 }

661

663 SymtabSection->setOffsets(SecStart, SecEnd);

664

666 if (ShndxIndexes.empty()) {

667 assert(SymtabShndxSectionIndex == 0);

668 return;

669 }

670 assert(SymtabShndxSectionIndex != 0);

671

672 SecStart = W.OS.tell();

673 MCSectionELF *SymtabShndxSection = SectionTable[SymtabShndxSectionIndex - 1];

674 for (uint32_t Index : ShndxIndexes)

676 SecEnd = W.OS.tell();

677 SymtabShndxSection->setOffsets(SecStart, SecEnd);

678}

679

680void ELFWriter::writeAddrsigSection() {

682 if (Sym->getIndex() != 0)

684}

685

689 return nullptr;

690

694

697 if (TO && TO->Crel) {

700 1, Sec.getGroup(), &Sec);

701 return RelaSection;

702 }

703

704 const bool Rela = OWriter.usesRela(TO, Sec);

705 unsigned EntrySize;

706 if (Rela)

708 else

710

714 EntrySize, Sec.getGroup(), &Sec);

716 return RelaSection;

717}

718

719

720bool ELFWriter::maybeWriteCompression(

725 if (Size <= HdrSize + CompressedContents.size())

726 return false;

727

729

734 } else {

735

739 }

740 return true;

741}

742

746 auto &Ctx = Asm.getContext();

749 : DebugCompressionType::None;

750 if (CompressionType == DebugCompressionType::None ||

752 Asm.writeSectionData(W.OS, &Section);

753 return;

754 }

755

758 Asm.writeSectionData(VecOS, &Section);

761 UncompressedData.size());

762

765 switch (CompressionType) {

766 case DebugCompressionType::None:

768 case DebugCompressionType::Zlib:

770 break;

771 case DebugCompressionType::Zstd:

773 break;

774 }

776 Compressed);

777 if (!maybeWriteCompression(ChType, UncompressedData.size(), Compressed,

779 W.OS << UncompressedData;

780 return;

781 }

782

784

785

788}

789

796 W.write<uint32_t>(Name);

798 writeWord(Flags);

799 writeWord(Address);

800 writeWord(Offset);

801 writeWord(Size);

804 writeWord(Alignment ? Alignment->value() : 0);

805 writeWord(EntrySize);

806}

807

808template

810 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;

812 uint32_t SymIdx = R.Symbol ? R.Symbol->getIndex() : 0;

814 std::make_signed_t(R.Addend)};

815 });

816}

817

818void ELFWriter::writeRelocations(const MCAssembler &Asm,

820 std::vector &Relocs = OWriter.Relocations[&Sec];

822 const bool Rela = OWriter.usesRela(TO, Sec);

823

824

826

837 if (Rela)

839 } else {

844 if (Rela)

852 }

859 }

860 }

861 }

862 } else if (TO && TO->Crel) {

864 encodeCrel(Relocs, W.OS);

865 else

866 encodeCrel(Relocs, W.OS);

867 } else {

875 if (Rela)

877 } else {

882 if (Rela)

884 }

885 }

886 }

887}

888

893

894 switch(Section.getType()) {

895 default:

896

897 break;

898

901

905 sh_link = SymbolTableIndex;

906 assert(sh_link && ".symtab not found");

909 break;

910 }

911

913 sh_link = StringTableIndex;

914 sh_info = LastLocalSymbolIndex;

915 break;

916

920 sh_link = SymbolTableIndex;

921 break;

922

924 sh_link = SymbolTableIndex;

925 sh_info = GroupSymbolIndex;

926 break;

927 }

928

930

931

933 if (Sym && Sym->isInSection())

934 sh_link = Sym->getSection().getOrdinal();

935 }

936

937 writeSectionHeaderEntry(StrTabBuilder.getOffset(Section.getName()),

939 Size, sh_link, sh_info, Section.getAlign(),

941}

942

943void ELFWriter::writeSectionHeaders(const MCAssembler &Asm) {

945 const unsigned NumSections = SectionTable.size();

946

947

950 writeSectionHeaderEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, std::nullopt,

951 0);

952

953 for (const MCSectionELF *Section : SectionTable) {

957 GroupSymbolIndex = 0;

958 else

959 GroupSymbolIndex = Section->getGroup()->getIndex();

960

961 std::pair<uint64_t, uint64_t> Offsets = Section->getOffsets();

964 Size = Asm.getSectionAddressSize(*Section);

965 else

967

968 auto SectionHasFlag = [&](uint64_t Flag) -> bool {

970 };

971

972 if (Section->getName().starts_with(".debug")) {

973 stats::DebugBytes += Size;

974 } else if (Section->getName().starts_with(".eh_frame")) {

975 stats::UnwindBytes += Size;

978 stats::AllocTextBytes += Size;

980 stats::AllocRWBytes += Size;

981 } else {

982 stats::AllocROBytes += Size;

983 }

984 } else {

985 switch (Section->getType()) {

987 stats::StrtabBytes += Size;

988 break;

990 stats::SymtabBytes += Size;

991 break;

993 stats::DynsymBytes += Size;

994 break;

998 stats::RelocationBytes += Size;

999 break;

1000 default:

1001 stats::OtherBytes += Size;

1002 break;

1003 }

1004 }

1005

1006 writeSectionHeader(GroupSymbolIndex, Offsets.first, Size, *Section);

1007 }

1008

1009 stats::SectionHeaderBytes += W.OS.tell() - Start;

1010}

1011

1013 uint64_t StartOffset = W.OS.tell();

1014

1018 StringTableIndex = addToSectionTable(StrtabSection);

1019

1020 RevGroupMapTy RevGroupMap;

1021

1022

1023 writeHeader(Asm);

1024

1025 stats::ELFHeaderBytes += W.OS.tell() - StartOffset;

1026

1027

1029

1034 if (Mode == NonDwoOnly && isDwoSection(Section))

1035 continue;

1036 if (Mode == DwoOnly && isDwoSection(Section))

1037 continue;

1038

1039

1041

1043 writeSectionData(Asm, Section);

1044

1046 Section.setOffsets(SecStart, SecEnd);

1047

1048 MCSectionELF *RelSection = createRelocationSection(Ctx, Section);

1049

1050 unsigned *GroupIdxEntry = nullptr;

1051 if (SignatureSymbol) {

1052 GroupIdxEntry = &RevGroupMap[SignatureSymbol];

1053 if (!*GroupIdxEntry) {

1056 *GroupIdxEntry = addToSectionTable(Group);

1058

1059 GroupMap.resize(*GroupIdxEntry + 1);

1060 GroupMap[*GroupIdxEntry] = Groups.size();

1062 }

1063 }

1064

1065 Section.setOrdinal(addToSectionTable(&Section));

1066 if (RelSection) {

1067 RelSection->setOrdinal(addToSectionTable(RelSection));

1068 Relocations.push_back(RelSection);

1069 }

1070

1071 if (GroupIdxEntry) {

1072 auto &Members = Groups[GroupMap[*GroupIdxEntry]];

1073 Members.second.push_back(Section.getOrdinal());

1074 if (RelSection)

1075 Members.second.push_back(RelSection->getOrdinal());

1076 }

1077 }

1078

1079 for (auto &[Group, Members] : Groups) {

1080

1082

1084 W.write<unsigned>(Members);

1085

1087 Group->setOffsets(SecStart, SecEnd);

1088 }

1089

1090 if (Mode == DwoOnly) {

1091

1092

1093 StrTabBuilder.finalize();

1094 } else {

1099 addToSectionTable(AddrsigSection);

1100 }

1101

1102

1103 computeSymbolTable(Asm, RevGroupMap);

1104

1105 for (MCSectionELF *RelSection : Relocations) {

1106

1108

1109 writeRelocations(Asm,

1111

1113 RelSection->setOffsets(SecStart, SecEnd);

1114 }

1115

1117 uint64_t SecStart = W.OS.tell();

1118 writeAddrsigSection();

1120 AddrsigSection->setOffsets(SecStart, SecEnd);

1121 }

1122 }

1123

1124 {

1125 uint64_t SecStart = W.OS.tell();

1126 StrTabBuilder.write(W.OS);

1127 StrtabSection->setOffsets(SecStart, W.OS.tell());

1128 }

1129

1131

1132

1133 writeSectionHeaders(Asm);

1134

1135 uint16_t NumSections = support::endian::byte_swap<uint16_t>(

1137 : SectionTable.size() + 1,

1138 W.Endian);

1139 unsigned NumSectionsOffset;

1140

1144 support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian);

1145 Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),

1148 } else {

1150 support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian);

1151 Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),

1154 }

1155 Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),

1156 NumSectionsOffset);

1157

1158 return W.OS.tell() - StartOffset;

1159}

1160

1163 : TargetObjectWriter(std::move(MOTW)), OS(OS),

1164 IsLittleEndian(IsLittleEndian) {}

1168 : TargetObjectWriter(std::move(MOTW)), OS(OS), DwoOS(&DwoOS),

1169 IsLittleEndian(IsLittleEndian) {}

1170

1172 ELFHeaderEFlags = 0;

1179}

1180

1183}

1184

1186

1187

1190 const auto &Symbol = cast(*S.Sym);

1191 size_t Pos = AliasName.find('@');

1193

1198 Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1);

1199

1200 auto *Alias =

1201 cast(Asm.getContext().getOrCreateSymbol(Prefix + Tail));

1202 Asm.registerSymbol(*Alias);

1204 Alias->setVariableValue(Value);

1205

1206

1207

1208 Alias->setBinding(Symbol.getBinding());

1209 Alias->setVisibility(Symbol.getVisibility());

1210 Alias->setOther(Symbol.getOther());

1211

1212 if (!Symbol.isUndefined() && S.KeepOriginalSym)

1213 continue;

1214

1215 if (Symbol.isUndefined() && Rest.starts_with("@@") &&

1217 Asm.getContext().reportError(S.Loc, "default version symbol " +

1218 AliasName + " must be defined");

1219 continue;

1220 }

1221

1222 if (auto It = Renames.find(&Symbol);

1223 It != Renames.end() && It->second != Alias) {

1224 Asm.getContext().reportError(S.Loc, Twine("multiple versions for ") +

1225 Symbol.getName());

1226 continue;

1227 }

1228

1229 Renames.insert(std::make_pair(&Symbol, Alias));

1230 }

1231

1234 Sym = R;

1235 if (Sym->isInSection() && Sym->getName().starts_with(".L"))

1236 Sym = Sym->getSection().getBeginSymbol();

1237 Sym->setUsedInReloc();

1238 }

1239}

1240

1241

1242

1243

1248 unsigned Type) const {

1250

1251

1252 if (!RefA)

1253 return false;

1254

1256 switch (Kind) {

1257 default:

1258 break;

1259

1260

1261

1262

1263

1264

1266 return false;

1267

1268

1269

1270

1271

1279 return true;

1280 }

1281

1282

1283

1284 assert(Sym && "Expected a symbol");

1285 if (Sym->isUndefined())

1286 return true;

1287

1288

1289

1290

1291

1292

1293

1294 if (Sym->isMemtag())

1295 return true;

1296

1297 unsigned Binding = Sym->getBinding();

1298 switch(Binding) {

1299 default:

1302 break;

1304

1305

1306

1307 return true;

1310

1311

1312 return true;

1313 }

1314

1315

1316

1317

1319 return true;

1320

1321

1322

1323

1324

1325

1326

1327

1328 if (Sym->isInSection()) {

1329 auto &Sec = cast(Sym->getSection());

1330 unsigned Flags = Sec.getFlags();

1332 if (C != 0)

1333 return true;

1334

1335

1336

1338 Type == ELF::R_386_GOTOFF)

1339 return true;

1340

1341

1342

1343

1344

1345

1346

1347

1350 return true;

1351 }

1352

1353

1354

1355

1356

1358 return true;

1359 }

1360

1361

1362

1363

1364

1365 if (Asm.isThumbFunc(Sym))

1366 return true;

1367

1369 return true;

1370 return false;

1371}

1372

1378 Ctx.reportError(Loc, "A dwo section may not contain relocations");

1379 return false;

1380 }

1382 Ctx.reportError(Loc, "A relocation may not refer to a dwo section");

1383 return false;

1384 }

1385 }

1386 return true;

1387}

1388

1398 uint64_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();

1399 MCContext &Ctx = Asm.getContext();

1401

1403 const auto &SymB = cast(RefB->getSymbol());

1404 if (SymB.isUndefined()) {

1406 Twine("symbol '") + SymB.getName() +

1407 "' can not be undefined in a subtraction expression");

1408 return;

1409 }

1410

1411 assert(!SymB.isAbsolute() && "Should have been folded");

1412 const MCSection &SecB = SymB.getSection();

1413 if (&SecB != &FixupSection) {

1415 "Cannot represent a difference across sections");

1416 return;

1417 }

1418

1419 assert(!IsPCRel && "should have been folded");

1420 IsPCRel = true;

1421 C += FixupOffset - Asm.getSymbolOffset(SymB);

1422 }

1423

1424

1426 const auto *SymA = RefA ? cast(&RefA->getSymbol()) : nullptr;

1427

1428 bool ViaWeakRef = false;

1429 if (SymA && SymA->isVariable()) {

1430 const MCExpr *Expr = SymA->getVariableValue();

1431 if (const auto *Inner = dyn_cast(Expr)) {

1433 SymA = cast(&Inner->getSymbol());

1434 ViaWeakRef = true;

1435 }

1436 }

1437 }

1438

1439 const MCSectionELF *SecA = (SymA && SymA->isInSection())

1440 ? cast(&SymA->getSection())

1441 : nullptr;

1443 return;

1444

1446 const auto *Parent = cast(Fragment->getParent());

1447

1448 bool RelocateWithSymbol =

1451 uint64_t Addend = !RelocateWithSymbol && SymA && !SymA->isUndefined()

1452 ? C + Asm.getSymbolOffset(*SymA)

1453 : C;

1454 FixedValue = usesRela(TO, FixupSection) ? 0 : Addend;

1455

1456 if (!RelocateWithSymbol) {

1457 const auto *SectionSymbol =

1458 SecA ? cast(SecA->getBeginSymbol()) : nullptr;

1459 if (SectionSymbol)

1460 SectionSymbol->setUsedInReloc();

1462 Relocations[&FixupSection].push_back(Rec);

1463 return;

1464 }

1465

1467 if (SymA) {

1469 RenamedSymA = R;

1470

1471 if (ViaWeakRef)

1473 else

1475 }

1477 Relocations[&FixupSection].push_back(Rec);

1478}

1479

1484 (TO && TO->Crel);

1485}

1486

1489 bool InSet, bool IsPCRel) const {

1490 const auto &SymA = cast(SA);

1491 if (IsPCRel) {

1495 return false;

1496 }

1497 return &SymA.getSection() == FB.getParent();

1498}

1499

1503 DwoOS ? ELFWriter::NonDwoOnly : ELFWriter::AllSections)

1504 .writeObject(Asm);

1507 .writeObject(Asm);

1508 return Size;

1509}

#define offsetof(TYPE, MEMBER)

BlockVerifier::State From

Analysis containing CSE Info

Given that RA is a live value

This file defines the DenseMap class.

static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType)

static void encodeCrel(ArrayRef< ELFRelocationEntry > Relocs, raw_ostream &OS)

static bool isIFunc(const MCSymbolELF *Symbol)

std::optional< std::vector< StOtherPiece > > Other

PowerPC TLS Dynamic Call Fixup

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

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 SymbolRef::Type getType(const Symbol *Sym)

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)

unsigned getELFHeaderEFlags() const

bool shouldRelocateWithSymbol(const MCAssembler &Asm, const MCValue &Val, const MCSymbolELF *Sym, uint64_t C, unsigned Type) const

uint64_t writeObject(MCAssembler &Asm) override

Write the object file and returns the number of bytes written.

void executePostLayoutBinding(MCAssembler &Asm) override

Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...

void reset() override

lifetime management

std::optional< uint8_t > OverrideABIVersion

void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) override

Record a relocation entry.

DenseMap< const MCSectionELF *, std::vector< ELFRelocationEntry > > Relocations

SmallVector< Symver, 0 > Symvers

bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, bool InSet, bool IsPCRel) const override

bool hasRelocationAddend() const

bool checkRelocation(MCContext &Ctx, SMLoc Loc, const MCSectionELF *From, const MCSectionELF *To)

raw_pwrite_stream * DwoOS

bool usesRela(const MCTargetOptions *TO, const MCSectionELF &Sec) const

DenseMap< const MCSymbolELF *, const MCSymbolELF * > Renames

Generic interface to target specific assembler backends.

virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const

Get information on a fixup kind.

Context object for machine code objects.

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)

void reportError(SMLoc L, const Twine &Msg)

const MCTargetOptions * getTargetOptions() const

MCSectionELF * createELFGroupSection(const MCSymbolELF *Group, bool IsComdat)

Base class for the full range of assembler expressions which are needed for parsing.

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

bool getEmitAddrsigSection()

std::vector< const MCSymbol * > & getAddrsigSyms()

virtual void reset()

lifetime management

std::vector< const MCSymbol * > AddrsigSyms

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

void setIsWeakrefUsedInReloc() const

Represent a reference to a symbol from inside an expression.

const MCSymbol & getSymbol() const

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)

VariantKind getKind() const

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

void setUsedInReloc() const

DebugCompressionType CompressDebugSections

This represents an "assembler immediate".

const MCSymbolRefExpr * getSymA() const

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

Represents a location in source code.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

pointer data()

Return a pointer to the vector's buffer, even if empty().

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

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.

static constexpr size_t npos

Utility for building string tables with deduplicated suffixes.

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.

A raw_ostream that writes to an SmallVector or SmallString.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ 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.

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.

void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)

StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})

Take an optional DWARFFormValue and try to extract a string value from it.

support::ulittle32_t Word

This is an optimization pass for GlobalISel generic memory operations.

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

@ Ref

The access may reference the value stored in memory.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a ULEB128 value to an output stream.

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.

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)

@ FKF_IsPCRel

Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...

unsigned Flags

Flags describing additional information on this fixup kind.

This struct is a compact representation of a valid (power of two) or undefined (0) alignment.

Adapter to write values to a stream in a particular byte order.