64 #define DEBUG_TYPE "reloc-info"
70 class ELFObjectWriter;
77 class SymbolTableWriter {
82 std::vector<uint32_t> ShndxIndexes;
87 void createSymtabShndx();
92 SymbolTableWriter(ELFWriter &EWriter,
bool Is64Bit);
95 uint8_t other,
uint32_t shndx,
bool Reserved);
101 ELFObjectWriter &OWriter;
112 bool Used,
bool Renamed);
115 struct ELFSymbolData {
131 unsigned LastLocalSymbolIndex;
133 unsigned StringTableIndex;
135 unsigned SymbolTableIndex;
138 std::vector<const MCSectionELF *> SectionTable;
147 bool maybeWriteCompression(
uint64_t Size,
149 bool ZLibStyle,
unsigned Alignment);
153 bool IsLittleEndian, DwoMode
Mode)
164 template <
typename T>
void write(
T Val) {
170 void writeSymbol(SymbolTableWriter &Writer,
uint32_t StringIndex,
174 using SectionOffsetsTy =
175 std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>;
186 const SectionIndexMapTy &SectionIndexMap,
187 const RevGroupMapTy &RevGroupMap,
188 SectionOffsetsTy &SectionOffsets);
190 void writeAddrsigSection();
196 const SectionIndexMapTy &SectionIndexMap,
197 const SectionOffsetsTy &SectionOffsets);
210 void writeSection(
const SectionIndexMapTy &SectionIndexMap,
217 std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
223 bool SeenGnuAbi =
false;
225 bool hasRelocationAddend()
const;
230 unsigned Type)
const;
233 ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW)
236 void reset()
override {
243 bool isSymbolRefDifferenceFullyResolvedImpl(
const MCAssembler &
Asm,
246 bool IsPCRel)
const override;
261 void markGnuAbi()
override { SeenGnuAbi =
true; }
262 bool seenGnuAbi()
const {
return SeenGnuAbi; }
264 friend struct ELFWriter;
267 class ELFSingleObjectWriter :
public ELFObjectWriter {
272 ELFSingleObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
274 : ELFObjectWriter(
std::move(MOTW)), OS(OS),
275 IsLittleEndian(IsLittleEndian) {}
278 return ELFWriter(*
this, OS, IsLittleEndian, ELFWriter::AllSections)
279 .writeObject(
Asm, Layout);
282 friend struct ELFWriter;
285 class ELFDwoObjectWriter :
public ELFObjectWriter {
290 ELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
293 : ELFObjectWriter(
std::move(MOTW)), OS(OS), DwoOS(DwoOS),
294 IsLittleEndian(IsLittleEndian) {}
299 if (isDwoSection(*
From)) {
300 Ctx.
reportError(Loc,
"A dwo section may not contain relocations");
303 if (To && isDwoSection(*To)) {
304 Ctx.
reportError(Loc,
"A relocation may not refer to a dwo section");
311 uint64_t Size = ELFWriter(*
this, OS, IsLittleEndian, ELFWriter::NonDwoOnly)
312 .writeObject(
Asm, Layout);
313 Size += ELFWriter(*
this, DwoOS, IsLittleEndian, ELFWriter::DwoOnly)
314 .writeObject(
Asm, Layout);
323 W.OS.write_zeros(NewOffset - Offset);
327 unsigned ELFWriter::addToSectionTable(
const MCSectionELF *Sec) {
328 SectionTable.push_back(Sec);
329 StrTabBuilder.add(Sec->
getName());
330 return SectionTable.size();
333 void SymbolTableWriter::createSymtabShndx() {
334 if (!ShndxIndexes.empty())
337 ShndxIndexes.resize(NumWritten);
341 EWriter.write(
Value);
344 SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter,
bool Is64Bit)
345 : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
355 if (!ShndxIndexes.empty()) {
357 ShndxIndexes.push_back(shndx);
359 ShndxIndexes.push_back(0);
384 return OWriter.TargetObjectWriter->is64Bit();
387 bool ELFWriter::usesRela(
const MCSectionELF &Sec)
const {
388 return OWriter.hasRelocationAddend() &&
412 uint8_t OSABI = OWriter.TargetObjectWriter->getOSABI();
417 W.OS << char(OWriter.TargetObjectWriter->getABIVersion());
423 W.write<
uint16_t>(OWriter.TargetObjectWriter->getEMachine());
468 uint8_t
Type = newType;
505 if (!
Symbol->isVariable() ||
506 !(
Value = dyn_cast<MCSymbolRefExpr>(
Symbol->getVariableValue())) ||
507 Value->getKind() != MCSymbolRefExpr::VK_None ||
515 void ELFWriter::writeSymbol(SymbolTableWriter &Writer,
uint32_t StringIndex,
517 const auto &
Symbol = cast<MCSymbolELF>(*MSD.Symbol);
537 uint8_t Visibility =
Symbol.getVisibility();
543 const MCExpr *ESize = MSD.Symbol->getSize();
544 if (!ESize &&
Base) {
546 ESize =
Base->getSize();
556 Sym = cast<MCSymbolELF>(&Expr->getSymbol());
578 bool Used,
bool Renamed) {
579 if (
Symbol.isVariable()) {
582 if (
const auto *
T = dyn_cast<MCTargetExpr>(Expr))
583 if (
T->inlineAssignedExpr())
586 if (
Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF)
612 void ELFWriter::computeSymbolTable(
614 const SectionIndexMapTy &SectionIndexMap,
const RevGroupMapTy &RevGroupMap,
615 SectionOffsetsTy &SectionOffsets) {
617 SymbolTableWriter Writer(*
this,
is64Bit());
624 SymbolTableIndex = addToSectionTable(SymtabSection);
629 Writer.writeSymbol(0, 0, 0, 0, 0, 0,
false);
631 std::vector<ELFSymbolData> LocalSymbolData;
632 std::vector<ELFSymbolData> ExternalSymbolData;
635 for (
const std::pair<std::string, size_t> &
F : FileNames)
636 StrTabBuilder.add(
F.first);
639 bool HasLargeSectionIndex =
false;
641 const auto &
Symbol = cast<MCSymbolELF>(It.value());
643 bool WeakrefUsed =
Symbol.isWeakrefUsedInReloc();
644 bool isSignature =
Symbol.isSignature();
647 OWriter.Renames.count(&
Symbol)))
656 MSD.Symbol = cast<MCSymbolELF>(&
Symbol);
657 MSD.Order = It.index();
662 if (
Symbol.isAbsolute()) {
664 }
else if (
Symbol.isCommon()) {
665 if (
Symbol.isTargetCommon()) {
666 MSD.SectionIndex =
Symbol.getIndex();
671 }
else if (
Symbol.isUndefined()) {
672 if (isSignature && !Used) {
673 MSD.SectionIndex = RevGroupMap.lookup(&
Symbol);
675 HasLargeSectionIndex =
true;
692 "Undefined section reference: " +
Symbol.getName());
698 MSD.SectionIndex = SectionIndexMap.lookup(&
Section);
699 assert(MSD.SectionIndex &&
"Invalid section index!");
701 HasLargeSectionIndex =
true;
709 StrTabBuilder.add(
Name);
713 LocalSymbolData.push_back(MSD);
715 ExternalSymbolData.push_back(MSD);
719 unsigned SymtabShndxSectionIndex = 0;
721 if (HasLargeSectionIndex) {
724 SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
728 StrTabBuilder.finalize();
732 auto FileNameIt = FileNames.begin();
733 if (!FileNames.empty())
734 FileNames[0].second = 0;
736 for (ELFSymbolData &MSD : LocalSymbolData) {
738 for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;
740 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
748 : StrTabBuilder.getOffset(MSD.Name);
749 MSD.Symbol->setIndex(
Index++);
750 writeSymbol(Writer, StringIndex, MSD, Layout);
752 for (; FileNameIt != FileNames.end(); ++FileNameIt) {
753 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
760 LastLocalSymbolIndex =
Index;
762 for (ELFSymbolData &MSD : ExternalSymbolData) {
763 unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
764 MSD.Symbol->setIndex(
Index++);
765 writeSymbol(Writer, StringIndex, MSD, Layout);
770 SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
773 if (ShndxIndexes.
empty()) {
774 assert(SymtabShndxSectionIndex == 0);
777 assert(SymtabShndxSectionIndex != 0);
779 SecStart =
W.OS.tell();
781 SectionTable[SymtabShndxSectionIndex - 1];
784 SecEnd =
W.OS.tell();
785 SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
788 void ELFWriter::writeAddrsigSection() {
789 for (
const MCSymbol *Sym : OWriter.AddrsigSyms)
795 if (OWriter.Relocations[&Sec].empty())
799 bool Rela = usesRela(Sec);
800 std::string RelaSectionName = Rela ?
".rela" :
".rel";
821 bool ELFWriter::maybeWriteCompression(
823 unsigned Alignment) {
827 if (
Size <= HdrSize + CompressedContents.size())
848 if (
Size <=
Magic.size() +
sizeof(
Size) + CompressedContents.size())
860 auto &MC =
Asm.getContext();
861 const auto &MAI = MC.getAsmInfo();
863 bool CompressionEnabled =
865 if (!CompressionEnabled || !
SectionName.startswith(
".debug_")) {
871 MAI->compressDebugSections() == DebugCompressionType::GNU) &&
872 "expected zlib or zlib-gnu style compression");
876 Asm.writeSectionData(VecOS, &
Section, Layout);
883 if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
885 W.OS << UncompressedData;
899 W.OS << CompressedContents;
914 WriteWord(Alignment);
915 WriteWord(EntrySize);
920 std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec];
929 OWriter.TargetObjectWriter->sortRelocs(
Asm, Relocs);
931 const bool Rela = usesRela(Sec);
932 for (
unsigned i = 0,
e = Relocs.size();
i !=
e; ++
i) {
934 unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
938 if (OWriter.TargetObjectWriter->getEMachine() ==
ELF::EM_MIPS) {
941 write(OWriter.TargetObjectWriter->getRSsym(Entry.Type));
942 write(OWriter.TargetObjectWriter->getRType3(Entry.Type));
943 write(OWriter.TargetObjectWriter->getRType2(Entry.Type));
944 write(OWriter.TargetObjectWriter->getRType(Entry.Type));
962 if (OWriter.TargetObjectWriter->getEMachine() ==
ELF::EM_MIPS) {
964 OWriter.TargetObjectWriter->getRType2(Entry.Type)) {
967 ERE32.setSymbolAndType(0, RType);
972 OWriter.TargetObjectWriter->getRType3(Entry.Type)) {
975 ERE32.setSymbolAndType(0, RType);
984 void ELFWriter::writeSection(
const SectionIndexMapTy &SectionIndexMap,
1000 sh_link = SymbolTableIndex;
1001 assert(sh_link &&
".symtab not found");
1003 sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection));
1008 sh_link = StringTableIndex;
1009 sh_info = LastLocalSymbolIndex;
1015 sh_link = SymbolTableIndex;
1019 sh_link = SymbolTableIndex;
1020 sh_info = GroupSymbolIndex;
1030 sh_link = SectionIndexMap.lookup(Sec);
1034 WriteSecHdrEntry(StrTabBuilder.getOffset(
Section.getName()),
1036 sh_link, sh_info,
Section.getAlignment(),
1040 void ELFWriter::writeSectionHeader(
1041 const MCAsmLayout &Layout,
const SectionIndexMapTy &SectionIndexMap,
1042 const SectionOffsetsTy &SectionOffsets) {
1043 const unsigned NumSections = SectionTable.size();
1048 WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0);
1054 GroupSymbolIndex = 0;
1056 GroupSymbolIndex =
Section->getGroup()->getIndex();
1058 const std::pair<uint64_t, uint64_t> &
Offsets =
1059 SectionOffsets.find(
Section)->second;
1066 writeSection(SectionIndexMap, GroupSymbolIndex,
Offsets.first,
Size,
1077 StringTableIndex = addToSectionTable(StrtabSection);
1079 RevGroupMapTy RevGroupMap;
1080 SectionIndexMapTy SectionIndexMap;
1082 std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers;
1088 SectionOffsetsTy SectionOffsets;
1089 std::vector<MCSectionELF *>
Groups;
1090 std::vector<MCSectionELF *> Relocations;
1105 SectionOffsets[&
Section] = std::make_pair(SecStart, SecEnd);
1109 if (SignatureSymbol) {
1110 unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
1114 GroupIdx = addToSectionTable(Group);
1118 std::vector<const MCSectionELF *> &Members =
1119 GroupMembers[SignatureSymbol];
1122 Members.push_back(RelSection);
1127 SectionIndexMap[RelSection] = addToSectionTable(RelSection);
1128 Relocations.push_back(RelSection);
1131 OWriter.TargetObjectWriter->addTargetSectionFlags(Ctx,
Section);
1141 for (
const MCSectionELF *Member : GroupMembers[SignatureSymbol]) {
1142 uint32_t SecIndex = SectionIndexMap.lookup(Member);
1147 SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
1150 if (
Mode == DwoOnly) {
1153 StrTabBuilder.finalize();
1156 if (OWriter.EmitAddrsigSection) {
1159 addToSectionTable(AddrsigSection);
1163 computeSymbolTable(
Asm, Layout, SectionIndexMap, RevGroupMap,
1170 writeRelocations(
Asm,
1174 SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
1177 if (OWriter.EmitAddrsigSection) {
1179 writeAddrsigSection();
1181 SectionOffsets[AddrsigSection] = std::make_pair(SecStart, SecEnd);
1187 StrTabBuilder.write(
W.OS);
1188 SectionOffsets[StrtabSection] = std::make_pair(SecStart,
W.OS.tell());
1194 writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
1196 uint16_t NumSections = support::endian::byte_swap<uint16_t>(
1198 : SectionTable.size() + 1,
1200 unsigned NumSectionsOffset;
1205 support::endian::byte_swap<uint64_t>(SectionHeaderOffset,
W.Endian);
1206 Stream.pwrite(
reinterpret_cast<char *
>(&Val),
sizeof(Val),
1211 support::endian::byte_swap<uint32_t>(SectionHeaderOffset,
W.Endian);
1212 Stream.pwrite(
reinterpret_cast<char *
>(&Val),
sizeof(Val),
1216 Stream.pwrite(
reinterpret_cast<char *
>(&NumSections),
sizeof(NumSections),
1219 return W.OS.tell() - StartOffset;
1222 bool ELFObjectWriter::hasRelocationAddend()
const {
1223 return TargetObjectWriter->hasRelocationAddend();
1232 const auto &
Symbol = cast<MCSymbolELF>(*
S.Sym);
1233 size_t Pos = AliasName.
find(
'@');
1234 assert(Pos != StringRef::npos);
1243 cast<MCSymbolELF>(
Asm.getContext().getOrCreateSymbol(
Prefix +
Tail));
1244 Asm.registerSymbol(*Alias);
1246 Alias->setVariableValue(
Value);
1250 Alias->setBinding(
Symbol.getBinding());
1251 Alias->setVisibility(
Symbol.getVisibility());
1252 Alias->setOther(
Symbol.getOther());
1254 if (!
Symbol.isUndefined() &&
S.KeepOriginalSym)
1259 Asm.getContext().reportError(
S.Loc,
"default version symbol " +
1260 AliasName +
" must be defined");
1264 if (Renames.count(&
Symbol) && Renames[&
Symbol] != Alias) {
1265 Asm.getContext().reportError(
S.Loc,
Twine(
"multiple versions for ") +
1270 Renames.insert(std::make_pair(&
Symbol, Alias));
1273 for (
const MCSymbol *&Sym : AddrsigSyms) {
1274 if (
const MCSymbol *
R = Renames.lookup(cast<MCSymbolELF>(Sym)))
1285 bool ELFObjectWriter::shouldRelocateWithSymbol(
const MCAssembler &
Asm,
1289 unsigned Type)
const {
1305 case MCSymbolRefExpr::VK_PPC_TOCBASE:
1312 case MCSymbolRefExpr::VK_GOT:
1313 case MCSymbolRefExpr::VK_PLT:
1314 case MCSymbolRefExpr::VK_GOTPCREL:
1315 case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:
1316 case MCSymbolRefExpr::VK_PPC_GOT_LO:
1317 case MCSymbolRefExpr::VK_PPC_GOT_HI:
1318 case MCSymbolRefExpr::VK_PPC_GOT_HA:
1324 assert(Sym &&
"Expected a symbol");
1360 auto &Sec = cast<MCSectionELF>(Sym->
getSection());
1368 if (TargetObjectWriter->getEMachine() ==
ELF::EM_386 &&
1369 Type == ELF::R_386_GOTOFF)
1379 if (TargetObjectWriter->getEMachine() ==
ELF::EM_MIPS &&
1380 !hasRelocationAddend())
1396 if (
Asm.isThumbFunc(Sym))
1399 if (TargetObjectWriter->needsRelocateWithSymbol(*Sym,
Type))
1411 MCFixupKindInfo::FKF_IsPCRel;
1418 const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
1419 if (SymB.isUndefined()) {
1421 Twine(
"symbol '") + SymB.getName() +
1422 "' can not be undefined in a subtraction expression");
1426 assert(!SymB.isAbsolute() &&
"Should have been folded");
1427 const MCSection &SecB = SymB.getSection();
1428 if (&SecB != &FixupSection) {
1430 "Cannot represent a difference across sections");
1434 assert(!IsPCRel &&
"should have been folded");
1441 const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->
getSymbol()) : nullptr;
1443 bool ViaWeakRef =
false;
1444 if (SymA && SymA->isVariable()) {
1445 const MCExpr *Expr = SymA->getVariableValue();
1446 if (
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
1447 if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
1448 SymA = cast<MCSymbolELF>(&Inner->getSymbol());
1454 const MCSectionELF *SecA = (SymA && SymA->isInSection())
1455 ? cast<MCSectionELF>(&SymA->getSection())
1457 if (!checkRelocation(Ctx,
Fixup.getLoc(), &FixupSection, SecA))
1460 unsigned Type = TargetObjectWriter->getRelocType(Ctx,
Target,
Fixup, IsPCRel);
1461 const auto *Parent = cast<MCSectionELF>(
Fragment->getParent());
1463 bool RelocateWithSymbol =
1464 shouldRelocateWithSymbol(
Asm, RefA, SymA,
C,
Type) ||
1468 FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined()
1471 if (hasRelocationAddend()) {
1472 Addend = FixedValue;
1476 if (!RelocateWithSymbol) {
1477 const auto *SectionSymbol =
1480 SectionSymbol->setUsedInReloc();
1482 Relocations[&FixupSection].push_back(Rec);
1497 Relocations[&FixupSection].push_back(Rec);
1500 bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
1502 bool InSet,
bool IsPCRel)
const {
1503 const auto &SymA = cast<MCSymbolELF>(SA);
1510 return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
Asm, SymA, FB,
1514 std::unique_ptr<MCObjectWriter>
1517 return std::make_unique<ELFSingleObjectWriter>(
std::move(MOTW), OS,
1521 std::unique_ptr<MCObjectWriter>
1524 bool IsLittleEndian) {
1525 return std::make_unique<ELFDwoObjectWriter>(
std::move(MOTW), OS, DwoOS,