1406 lines · cpp
1//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements ELF object file writer information.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ADT/ArrayRef.h"14#include "llvm/ADT/DenseMap.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/ADT/StringExtras.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/ADT/Twine.h"21#include "llvm/BinaryFormat/ELF.h"22#include "llvm/MC/MCAsmBackend.h"23#include "llvm/MC/MCAsmInfo.h"24#include "llvm/MC/MCAssembler.h"25#include "llvm/MC/MCContext.h"26#include "llvm/MC/MCELFExtras.h"27#include "llvm/MC/MCELFObjectWriter.h"28#include "llvm/MC/MCExpr.h"29#include "llvm/MC/MCFixup.h"30#include "llvm/MC/MCObjectWriter.h"31#include "llvm/MC/MCSection.h"32#include "llvm/MC/MCSectionELF.h"33#include "llvm/MC/MCSymbol.h"34#include "llvm/MC/MCSymbolELF.h"35#include "llvm/MC/MCTargetOptions.h"36#include "llvm/MC/MCValue.h"37#include "llvm/MC/StringTableBuilder.h"38#include "llvm/Support/Alignment.h"39#include "llvm/Support/Casting.h"40#include "llvm/Support/Compression.h"41#include "llvm/Support/Endian.h"42#include "llvm/Support/EndianStream.h"43#include "llvm/Support/ErrorHandling.h"44#include "llvm/Support/LEB128.h"45#include "llvm/Support/SMLoc.h"46#include "llvm/Support/raw_ostream.h"47#include "llvm/TargetParser/Host.h"48#include <cassert>49#include <cstddef>50#include <cstdint>51#include <memory>52#include <string>53#include <utility>54#include <vector>55 56using namespace llvm;57 58#define DEBUG_TYPE "elf-object-writer"59 60namespace {61namespace stats {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");72STATISTIC(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} // namespace stats80 81struct ELFWriter;82 83bool isDwoSection(const MCSectionELF &Sec) {84 return Sec.getName().ends_with(".dwo");85}86 87class SymbolTableWriter {88 ELFWriter &EWriter;89 bool Is64Bit;90 91 // indexes we are going to write to .symtab_shndx.92 std::vector<uint32_t> ShndxIndexes;93 94 // The numbel of symbols written so far.95 unsigned NumWritten;96 97 void createSymtabShndx();98 99 template <typename T> 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 /// Helper struct for containing some precomputed information on symbols.125 struct ELFSymbolData {126 const MCSymbolELF *Symbol;127 StringRef Name;128 uint32_t SectionIndex;129 uint32_t Order;130 };131 132 /// @}133 /// @name Symbol Table Data134 /// @{135 136 StringTableBuilder StrTabBuilder{StringTableBuilder::ELF};137 138 /// @}139 140 // This holds the symbol table index of the last local symbol.141 unsigned LastLocalSymbolIndex = ~0u;142 // This holds the .strtab section index.143 unsigned StringTableIndex = ~0u;144 // This holds the .symtab section index.145 unsigned SymbolTableIndex = ~0u;146 147 // Sections in the order they are to be output in the section table.148 std::vector<MCSectionELF *> SectionTable;149 unsigned addToSectionTable(MCSectionELF *Sec);150 151 // TargetObjectWriter wrappers.152 bool is64Bit() const;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,165 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big),166 Mode(Mode) {}167 168 MCContext &getContext() const { return Asm.getContext(); }169 170 void writeWord(uint64_t Word) {171 if (is64Bit())172 W.write<uint64_t>(Word);173 else174 W.write<uint32_t>(Word);175 }176 177 template <typename T> 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 // Map from a signature symbol to the group section index187 using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>;188 189 /// Compute the symbol table data190 ///191 /// \param Asm - The assembler.192 /// \param RevGroupMap - Maps a signature symbol to the group section.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,205 uint64_t Address, uint64_t Offset, uint64_t Size,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} // end anonymous namespace216 217uint64_t ELFWriter::align(Align Alignment) {218 uint64_t Offset = W.OS.tell();219 uint64_t NewOffset = alignTo(Offset, Alignment);220 W.OS.write_zeros(NewOffset - Offset);221 return NewOffset;222}223 224unsigned ELFWriter::addToSectionTable(MCSectionELF *Sec) {225 SectionTable.push_back(Sec);226 StrTabBuilder.add(Sec->getName());227 return SectionTable.size();228}229 230void SymbolTableWriter::createSymtabShndx() {231 if (!ShndxIndexes.empty())232 return;233 234 ShndxIndexes.resize(NumWritten);235}236 237template <typename T> 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 244void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,245 uint64_t size, uint8_t other,246 uint32_t shndx, bool Reserved) {247 bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved;248 249 if (LargeIndex)250 createSymtabShndx();251 252 if (!ShndxIndexes.empty()) {253 if (LargeIndex)254 ShndxIndexes.push_back(shndx);255 else256 ShndxIndexes.push_back(0);257 }258 259 uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;260 261 if (Is64Bit) {262 write(name); // st_name263 write(info); // st_info264 write(other); // st_other265 write(Index); // st_shndx266 write(value); // st_value267 write(size); // st_size268 } else {269 write(name); // st_name270 write(uint32_t(value)); // st_value271 write(uint32_t(size)); // st_size272 write(info); // st_info273 write(other); // st_other274 write(Index); // st_shndx275 }276 277 ++NumWritten;278}279 280bool ELFWriter::is64Bit() const {281 return OWriter.TargetObjectWriter->is64Bit();282}283 284// Emit the ELF header.285void ELFWriter::writeHeader() {286 // ELF Header287 // ----------288 //289 // Note290 // ----291 // emitWord method behaves differently for ELF32 and ELF64, writing292 // 4 bytes in the former and 8 in the latter.293 294 W.OS << ELF::ElfMagic; // e_ident[EI_MAG0] to e_ident[EI_MAG3]295 296 W.OS << char(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]297 298 // e_ident[EI_DATA]299 W.OS << char(W.Endian == llvm::endianness::little ? ELF::ELFDATA2LSB300 : ELF::ELFDATA2MSB);301 302 W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION]303 // e_ident[EI_OSABI]304 uint8_t OSABI = OWriter.TargetObjectWriter->getOSABI();305 W.OS << char(OSABI == ELF::ELFOSABI_NONE && OWriter.seenGnuAbi()306 ? int(ELF::ELFOSABI_GNU)307 : OSABI);308 // e_ident[EI_ABIVERSION]309 W.OS << char(OWriter.OverrideABIVersion310 ? *OWriter.OverrideABIVersion311 : OWriter.TargetObjectWriter->getABIVersion());312 313 W.OS.write_zeros(ELF::EI_NIDENT - ELF::EI_PAD);314 315 W.write<uint16_t>(ELF::ET_REL); // e_type316 317 W.write<uint16_t>(OWriter.TargetObjectWriter->getEMachine()); // e_machine = target318 319 W.write<uint32_t>(ELF::EV_CURRENT); // e_version320 writeWord(0); // e_entry, no entry point in .o file321 writeWord(0); // e_phoff, no program header for .o322 writeWord(0); // e_shoff = sec hdr table off in bytes323 324 // e_flags = whatever the target wants325 W.write<uint32_t>(OWriter.getELFHeaderEFlags());326 327 // e_ehsize = ELF header size328 W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr)329 : sizeof(ELF::Elf32_Ehdr));330 331 W.write<uint16_t>(0); // e_phentsize = prog header entry size332 W.write<uint16_t>(0); // e_phnum = # prog header entries = 0333 334 // e_shentsize = Section header entry size335 W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr)336 : sizeof(ELF::Elf32_Shdr));337 338 // e_shnum = # of section header ents339 W.write<uint16_t>(0);340 341 // e_shstrndx = Section # of '.strtab'342 assert(StringTableIndex < ELF::SHN_LORESERVE);343 W.write<uint16_t>(StringTableIndex);344}345 346uint64_t ELFWriter::symbolValue(const MCSymbol &Sym) {347 if (Sym.isCommon())348 return Sym.getCommonAlignment()->value();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 360static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {361 uint8_t Type = newType;362 363 // Propagation rules:364 // IFUNC > FUNC > OBJECT > NOTYPE365 // TLS_OBJECT > OBJECT > NOTYPE366 //367 // dont let the new type degrade the old type368 switch (origType) {369 default:370 break;371 case ELF::STT_GNU_IFUNC:372 if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||373 Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS)374 Type = ELF::STT_GNU_IFUNC;375 break;376 case ELF::STT_FUNC:377 if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||378 Type == ELF::STT_TLS)379 Type = ELF::STT_FUNC;380 break;381 case ELF::STT_OBJECT:382 if (Type == ELF::STT_NOTYPE)383 Type = ELF::STT_OBJECT;384 break;385 case ELF::STT_TLS:386 if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||387 Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC)388 Type = ELF::STT_TLS;389 break;390 }391 392 return Type;393}394 395static bool isIFunc(const MCSymbolELF *Symbol) {396 while (Symbol->getType() != ELF::STT_GNU_IFUNC) {397 const MCSymbolRefExpr *Value;398 if (!Symbol->isVariable() ||399 !(Value = dyn_cast<MCSymbolRefExpr>(Symbol->getVariableValue())) ||400 Value->getSpecifier() ||401 mergeTypeForSet(Symbol->getType(), ELF::STT_GNU_IFUNC) !=402 ELF::STT_GNU_IFUNC)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 // This has to be in sync with when computeSymbolTable uses SHN_ABS or415 // SHN_COMMON.416 bool IsReserved = !Base || Symbol.isCommon();417 418 // Binding and Type share the same byte as upper and lower nibbles419 uint8_t Binding = Symbol.getBinding();420 uint8_t Type = Symbol.getType();421 if (isIFunc(&Symbol))422 Type = ELF::STT_GNU_IFUNC;423 if (Base) {424 Type = mergeTypeForSet(Type, Base->getType());425 }426 uint8_t Info = (Binding << 4) | Type;427 428 // Other and Visibility share the same byte with Visibility using the lower429 // 2 bits430 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 // For expressions like .set y, x+1, if y's size is unset, inherit from x.439 ESize = Base->getSize();440 441 // For `.size x, 2; y = x; .size y, 1; z = y; z1 = z; .symver y, y@v1`, z,442 // z1, and y@v1's st_size equals y's. However, `Base` is `x` which will give443 // us 2. Follow the MCSymbolRefExpr assignment chain, which covers most444 // needs. MCBinaryExpr is not handled.445 const MCSymbolELF *Sym = &Symbol;446 while (Sym->isVariable()) {447 if (auto *Expr = dyn_cast<MCSymbolRefExpr>(Sym->getVariableValue())) {448 Sym = static_cast<const MCSymbolELF *>(&Expr->getSymbol());449 if (!Sym->getSize())450 continue;451 ESize = Sym->getSize();452 }453 break;454 }455 }456 457 if (ESize) {458 int64_t Res;459 if (!ESize->evaluateKnownAbsolute(Res, Asm))460 report_fatal_error("Size expression must be absolute.");461 Size = Res;462 }463 464 // Write out the symbol table entry465 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 // Target Expressions that are always inlined do not appear in the symtab479 if (const auto *T = dyn_cast<MCTargetExpr>(Expr))480 if (T->inlineAssignedExpr())481 return false;482 // The .weakref alias does not appear in the symtab.483 if (Symbol.isWeakref())484 return false;485 486 if (Symbol.isUndefined()) {487 // FIXME: this is here just to diagnose the case of a var = commmon_sym.488 Asm.getBaseSymbol(Symbol);489 return false;490 }491 }492 493 if (Symbol.isTemporary())494 return false;495 496 return Symbol.getType() != ELF::STT_SECTION;497}498 499void ELFWriter::computeSymbolTable(const RevGroupMapTy &RevGroupMap) {500 MCContext &Ctx = Asm.getContext();501 SymbolTableWriter Writer(*this, is64Bit());502 503 // Symbol table504 unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;505 MCSectionELF *SymtabSection =506 Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize);507 SymtabSection->setAlignment(is64Bit() ? Align(8) : Align(4));508 SymbolTableIndex = addToSectionTable(SymtabSection);509 510 uint64_t SecStart = align(SymtabSection->getAlign());511 512 // The first entry is the undefined symbol entry.513 Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);514 515 std::vector<ELFSymbolData> LocalSymbolData;516 std::vector<ELFSymbolData> ExternalSymbolData;517 MutableArrayRef<std::pair<std::string, size_t>> FileNames =518 OWriter.getFileNames();519 for (const std::pair<std::string, size_t> &F : FileNames)520 StrTabBuilder.add(F.first);521 522 // Add the data for the symbols.523 bool HasLargeSectionIndex = false;524 for (auto It : llvm::enumerate(Asm.symbols())) {525 auto &Symbol = static_cast<const MCSymbolELF &>(It.value());526 if (!isInSymtab(Symbol))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 538 bool Local = Symbol.getBinding() == ELF::STB_LOCAL;539 assert(Local || !Symbol.isTemporary());540 541 if (Symbol.isAbsolute()) {542 MSD.SectionIndex = ELF::SHN_ABS;543 } else if (Symbol.isCommon()) {544 auto Shndx = Symbol.getIndex();545 if (!Shndx) {546 assert(!Local);547 Shndx = ELF::SHN_COMMON;548 }549 MSD.SectionIndex = Shndx;550 } else if (Symbol.isUndefined()) {551 if (Symbol.isSignature() && !Symbol.isUsedInReloc()) {552 MSD.SectionIndex = RevGroupMap.lookup(&Symbol);553 if (MSD.SectionIndex >= ELF::SHN_LORESERVE)554 HasLargeSectionIndex = true;555 } else {556 MSD.SectionIndex = ELF::SHN_UNDEF;557 }558 } else {559 const MCSectionELF &Section =560 static_cast<const MCSectionELF &>(Symbol.getSection());561 assert(Section.isRegistered());562 if (Mode == NonDwoOnly && isDwoSection(Section))563 continue;564 MSD.SectionIndex = Section.getOrdinal();565 assert(MSD.SectionIndex && "Invalid section index!");566 if (MSD.SectionIndex >= ELF::SHN_LORESERVE)567 HasLargeSectionIndex = true;568 }569 570 // Temporary symbols generated for certain assembler features (.eh_frame,571 // .debug_line) of an empty name may be referenced by relocations due to572 // linker relaxation. Rename them to ".L0 " to match the gas fake label name573 // and allow ld/objcopy --discard-locals to discard such symbols.574 StringRef Name = Symbol.getName();575 if (Name.empty())576 Name = ".L0 ";577 578 // Sections have their own string table579 if (Symbol.getType() != ELF::STT_SECTION) {580 MSD.Name = Name;581 StrTabBuilder.add(Name);582 }583 584 if (Local)585 LocalSymbolData.push_back(MSD);586 else587 ExternalSymbolData.push_back(MSD);588 }589 590 // This holds the .symtab_shndx section index.591 unsigned SymtabShndxSectionIndex = 0;592 593 if (HasLargeSectionIndex) {594 MCSectionELF *SymtabShndxSection =595 Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4);596 SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);597 SymtabShndxSection->setAlignment(Align(4));598 }599 600 StrTabBuilder.finalize();601 602 // Make the first STT_FILE precede previous local symbols.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 // Emit STT_FILE symbols before their associated local symbols.610 for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;611 ++FileNameIt) {612 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),613 ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,614 ELF::SHN_ABS, true);615 ++Index;616 }617 618 unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION619 ? 0620 : 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),626 ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,627 ELF::SHN_ABS, true);628 ++Index;629 }630 631 // Write the symbol table entries.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);638 assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);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)654 write(Index);655 SecEnd = W.OS.tell();656 SymtabShndxSection->setOffsets(SecStart, SecEnd);657}658 659void ELFWriter::writeAddrsigSection() {660 for (const MCSymbol *Sym : OWriter.getAddrsigSyms())661 if (Sym->getIndex() != 0)662 encodeULEB128(Sym->getIndex(), W.OS);663}664 665MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,666 const MCSectionELF &Sec) {667 if (OWriter.Relocations[&Sec].empty())668 return nullptr;669 670 unsigned Flags = ELF::SHF_INFO_LINK;671 if (Sec.getFlags() & ELF::SHF_GROUP)672 Flags = ELF::SHF_GROUP;673 674 const StringRef SectionName = Sec.getName();675 const MCTargetOptions *TO = Ctx.getTargetOptions();676 if (TO && TO->Crel) {677 MCSectionELF *RelaSection =678 Ctx.createELFRelSection(".crel" + SectionName, ELF::SHT_CREL, Flags,679 /*EntrySize=*/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 else688 EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);689 690 MCSectionELF *RelaSection =691 Ctx.createELFRelSection(((Rela ? ".rela" : ".rel") + SectionName),692 Rela ? ELF::SHT_RELA : ELF::SHT_REL, Flags,693 EntrySize, Sec.getGroup(), &Sec);694 RelaSection->setAlignment(is64Bit() ? Align(8) : Align(4));695 return RelaSection;696}697 698// Include the debug info compression header.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 // Platform specific header is followed by compressed data.707 if (is64Bit()) {708 // Write Elf64_Chdr header.709 write(static_cast<ELF::Elf64_Word>(ChType));710 write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field.711 write(static_cast<ELF::Elf64_Xword>(Size));712 write(static_cast<ELF::Elf64_Xword>(Alignment.value()));713 } else {714 // Write Elf32_Chdr header otherwise.715 write(static_cast<ELF::Elf32_Word>(ChType));716 write(static_cast<ELF::Elf32_Word>(Size));717 write(static_cast<ELF::Elf32_Word>(Alignment.value()));718 }719 return true;720}721 722void ELFWriter::writeSectionData(MCSection &Sec) {723 MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);724 StringRef SectionName = Section.getName();725 auto &Ctx = Asm.getContext();726 const DebugCompressionType CompressionType =727 Ctx.getTargetOptions() ? Ctx.getTargetOptions()->CompressDebugSections728 : DebugCompressionType::None;729 if (CompressionType == DebugCompressionType::None ||730 !SectionName.starts_with(".debug_")) {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:746 llvm_unreachable("has been handled");747 case DebugCompressionType::Zlib:748 ChType = ELF::ELFCOMPRESS_ZLIB;749 break;750 case DebugCompressionType::Zstd:751 ChType = ELF::ELFCOMPRESS_ZSTD;752 break;753 }754 compression::compress(compression::Params(CompressionType), Uncompressed,755 Compressed);756 if (!maybeWriteCompression(ChType, UncompressedData.size(), Compressed,757 Sec.getAlign())) {758 W.OS << UncompressedData;759 return;760 }761 762 Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);763 // Alignment field should reflect the requirements of764 // the compressed section header.765 Section.setAlignment(is64Bit() ? Align(8) : Align(4));766 W.OS << toStringRef(Compressed);767}768 769void ELFWriter::writeSectionHeaderEntry(uint32_t Name, uint32_t Type,770 uint64_t Flags, uint64_t Address,771 uint64_t Offset, uint64_t Size,772 uint32_t Link, uint32_t Info,773 MaybeAlign Alignment,774 uint64_t EntrySize) {775 W.write<uint32_t>(Name); // sh_name: index into string table776 W.write<uint32_t>(Type); // sh_type777 writeWord(Flags); // sh_flags778 writeWord(Address); // sh_addr779 writeWord(Offset); // sh_offset780 writeWord(Size); // sh_size781 W.write<uint32_t>(Link); // sh_link782 W.write<uint32_t>(Info); // sh_info783 writeWord(Alignment ? Alignment->value() : 0); // sh_addralign784 writeWord(EntrySize); // sh_entsize785}786 787template <bool Is64>788static void encodeCrel(ArrayRef<ELFRelocationEntry> Relocs, raw_ostream &OS) {789 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;790 ELF::encodeCrel<Is64>(OS, Relocs, [&](const ELFRelocationEntry &R) {791 uint32_t SymIdx = R.Symbol ? R.Symbol->getIndex() : 0;792 return ELF::Elf_Crel<Is64>{static_cast<uint>(R.Offset), SymIdx, R.Type,793 std::make_signed_t<uint>(R.Addend)};794 });795}796 797void ELFWriter::writeRelocations(const MCSectionELF &Sec) {798 std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec];799 const MCTargetOptions *TO = getContext().getTargetOptions();800 const bool Rela = OWriter.usesRela(TO, Sec);801 802 // Sort the relocation entries. MIPS needs this.803 OWriter.TargetObjectWriter->sortRelocs(Relocs);804 805 if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {806 for (const ELFRelocationEntry &Entry : Relocs) {807 uint32_t SymIdx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;808 if (is64Bit()) {809 write(Entry.Offset);810 write(uint32_t(SymIdx));811 write(OWriter.TargetObjectWriter->getRSsym(Entry.Type));812 write(OWriter.TargetObjectWriter->getRType3(Entry.Type));813 write(OWriter.TargetObjectWriter->getRType2(Entry.Type));814 write(OWriter.TargetObjectWriter->getRType(Entry.Type));815 if (Rela)816 write(Entry.Addend);817 } else {818 write(uint32_t(Entry.Offset));819 ELF::Elf32_Rela ERE32;820 ERE32.setSymbolAndType(SymIdx, Entry.Type);821 write(ERE32.r_info);822 if (Rela)823 write(uint32_t(Entry.Addend));824 if (uint32_t RType =825 OWriter.TargetObjectWriter->getRType2(Entry.Type)) {826 write(uint32_t(Entry.Offset));827 ERE32.setSymbolAndType(0, RType);828 write(ERE32.r_info);829 write(uint32_t(0));830 }831 if (uint32_t RType =832 OWriter.TargetObjectWriter->getRType3(Entry.Type)) {833 write(uint32_t(Entry.Offset));834 ERE32.setSymbolAndType(0, RType);835 write(ERE32.r_info);836 write(uint32_t(0));837 }838 }839 }840 } else if (TO && TO->Crel) {841 if (is64Bit())842 encodeCrel<true>(Relocs, W.OS);843 else844 encodeCrel<false>(Relocs, W.OS);845 } else {846 for (const ELFRelocationEntry &Entry : Relocs) {847 uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;848 if (is64Bit()) {849 write(Entry.Offset);850 ELF::Elf64_Rela ERE;851 ERE.setSymbolAndType(Symidx, Entry.Type);852 write(ERE.r_info);853 if (Rela)854 write(Entry.Addend);855 } else {856 write(uint32_t(Entry.Offset));857 ELF::Elf32_Rela ERE;858 ERE.setSymbolAndType(Symidx, Entry.Type);859 write(ERE.r_info);860 if (Rela)861 write(uint32_t(Entry.Addend));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 // Nothing to do.875 break;876 877 case ELF::SHT_DYNAMIC:878 llvm_unreachable("SHT_DYNAMIC in a relocatable object");879 880 case ELF::SHT_REL:881 case ELF::SHT_RELA:882 case ELF::SHT_CREL: {883 sh_link = SymbolTableIndex;884 assert(sh_link && ".symtab not found");885 const MCSection *InfoSection = Section.getLinkedToSection();886 sh_info = InfoSection->getOrdinal();887 break;888 }889 890 case ELF::SHT_SYMTAB:891 sh_link = StringTableIndex;892 sh_info = LastLocalSymbolIndex;893 break;894 895 case ELF::SHT_SYMTAB_SHNDX:896 case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:897 case ELF::SHT_LLVM_ADDRSIG:898 sh_link = SymbolTableIndex;899 break;900 901 case ELF::SHT_GROUP:902 sh_link = SymbolTableIndex;903 sh_info = GroupSymbolIndex;904 break;905 }906 907 if (Section.getFlags() & ELF::SHF_LINK_ORDER) {908 // If the value in the associated metadata is not a definition, Sym will be909 // undefined. Represent this with sh_link=0.910 const MCSymbol *Sym = Section.getLinkedToSymbol();911 if (Sym && Sym->isInSection())912 sh_link = Sym->getSection().getOrdinal();913 }914 915 writeSectionHeaderEntry(StrTabBuilder.getOffset(Section.getName()),916 Section.getType(), Section.getFlags(), 0, Offset,917 Size, sh_link, sh_info, Section.getAlign(),918 Section.getEntrySize());919}920 921void ELFWriter::writeSectionHeaders() {922 uint64_t Start = W.OS.tell();923 const unsigned NumSections = SectionTable.size();924 925 // Null section first.926 uint64_t FirstSectionSize =927 (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;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;933 unsigned Type = Section->getType();934 if (Type != ELF::SHT_GROUP)935 GroupSymbolIndex = 0;936 else937 GroupSymbolIndex = Section->getGroup()->getIndex();938 939 std::pair<uint64_t, uint64_t> Offsets = Section->getOffsets();940 uint64_t Size;941 if (Type == ELF::SHT_NOBITS)942 Size = Asm.getSectionAddressSize(*Section);943 else944 Size = Offsets.second - Offsets.first;945 946 auto SectionHasFlag = [&](uint64_t Flag) -> bool {947 return Section->getFlags() & Flag;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;956 } else if (SectionHasFlag(ELF::SHF_ALLOC)) {957 if (SectionHasFlag(ELF::SHF_EXECINSTR)) {958 stats::AllocTextBytes += Size;959 } else if (SectionHasFlag(ELF::SHF_WRITE)) {960 stats::AllocRWBytes += Size;961 } else {962 stats::AllocROBytes += Size;963 }964 } else {965 switch (Section->getType()) {966 case ELF::SHT_STRTAB:967 stats::StrtabBytes += Size;968 break;969 case ELF::SHT_SYMTAB:970 stats::SymtabBytes += Size;971 break;972 case ELF::SHT_DYNSYM:973 stats::DynsymBytes += Size;974 break;975 case ELF::SHT_REL:976 case ELF::SHT_RELA:977 case ELF::SHT_CREL: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 995 MCContext &Ctx = getContext();996 MCSectionELF *StrtabSection =997 Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);998 StringTableIndex = addToSectionTable(StrtabSection);999 1000 RevGroupMapTy RevGroupMap;1001 1002 // Write out the ELF header ...1003 writeHeader();1004 1005 stats::ELFHeaderBytes += W.OS.tell() - StartOffset;1006 1007 // ... then the sections ...1008 SmallVector<std::pair<MCSectionELF *, SmallVector<unsigned>>, 0> Groups;1009 // Map from group section index to group1010 SmallVector<unsigned, 0> GroupMap;1011 SmallVector<MCSectionELF *> Relocations;1012 for (MCSection &Sec : Asm) {1013 MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);1014 if (Mode == NonDwoOnly && isDwoSection(Section))1015 continue;1016 if (Mode == DwoOnly && !isDwoSection(Section))1017 continue;1018 1019 // Remember the offset into the file for this section.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 =1035 Ctx.createELFGroupSection(SignatureSymbol, Section.isComdat());1036 *GroupIdxEntry = addToSectionTable(Group);1037 Group->setAlignment(Align(4));1038 1039 GroupMap.resize(*GroupIdxEntry + 1);1040 GroupMap[*GroupIdxEntry] = Groups.size();1041 Groups.emplace_back(Group, SmallVector<unsigned>{});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 // Remember the offset into the file for this section.1061 const uint64_t SecStart = align(Group->getAlign());1062 1063 write(uint32_t(Group->isComdat() ? unsigned(ELF::GRP_COMDAT) : 0));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 // dwo files don't have symbol tables or relocations, but they do have1072 // string tables.1073 StrTabBuilder.finalize();1074 } else {1075 MCSectionELF *AddrsigSection;1076 if (OWriter.getEmitAddrsigSection()) {1077 AddrsigSection = Ctx.getELFSection(".llvm_addrsig", ELF::SHT_LLVM_ADDRSIG,1078 ELF::SHF_EXCLUDE);1079 addToSectionTable(AddrsigSection);1080 }1081 1082 // Compute symbol table information.1083 computeSymbolTable(RevGroupMap);1084 1085 for (MCSectionELF *RelSection : Relocations) {1086 // Remember the offset into the file for this section.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 1096 if (OWriter.getEmitAddrsigSection()) {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 // ... then the section header table ...1113 writeSectionHeaders();1114 1115 uint16_t NumSections = support::endian::byte_swap<uint16_t>(1116 (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF1117 : SectionTable.size() + 1,1118 W.Endian);1119 unsigned NumSectionsOffset;1120 1121 auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);1122 if (is64Bit()) {1123 uint64_t Val =1124 support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian);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 =1130 support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian);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 1141ELFObjectWriter::ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,1142 raw_pwrite_stream &OS, bool IsLittleEndian)1143 : TargetObjectWriter(std::move(MOTW)), OS(OS),1144 IsLittleEndian(IsLittleEndian) {}1145ELFObjectWriter::ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,1146 raw_pwrite_stream &OS,1147 raw_pwrite_stream &DwoOS, bool IsLittleEndian)1148 : TargetObjectWriter(std::move(MOTW)), OS(OS), DwoOS(&DwoOS),1149 IsLittleEndian(IsLittleEndian) {}1150 1151void ELFObjectWriter::reset() {1152 ELFHeaderEFlags = 0;1153 SeenGnuAbi = false;1154 OverrideABIVersion.reset();1155 Relocations.clear();1156 Renames.clear();1157 Weakrefs.clear();1158 Symvers.clear();1159 SeenGnuAbi = false;1160 MCObjectWriter::reset();1161}1162 1163void ELFObjectWriter::setAssembler(MCAssembler *Asm) {1164 MCObjectWriter::setAssembler(Asm);1165 TargetObjectWriter->setAssembler(Asm);1166}1167 1168bool ELFObjectWriter::hasRelocationAddend() const {1169 return TargetObjectWriter->hasRelocationAddend();1170}1171 1172void ELFObjectWriter::executePostLayoutBinding() {1173 // The presence of symbol versions causes undefined symbols and1174 // versions declared with @@@ to be renamed.1175 for (const Symver &S : Symvers) {1176 StringRef AliasName = S.Name;1177 auto &Symbol = static_cast<const MCSymbolELF &>(*S.Sym);1178 size_t Pos = AliasName.find('@');1179 assert(Pos != StringRef::npos);1180 1181 StringRef Prefix = AliasName.substr(0, Pos);1182 StringRef Rest = AliasName.substr(Pos);1183 StringRef Tail = Rest;1184 if (Rest.starts_with("@@@"))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);1190 const MCExpr *Value = MCSymbolRefExpr::create(&Symbol, Asm->getContext());1191 Alias->setVariableValue(Value);1192 1193 // Aliases defined with .symvar copy the binding from the symbol they alias.1194 // This is the first place we are able to copy this information.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("@@") &&1203 !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 1219 for (const MCSymbol *&Sym : AddrsigSyms) {1220 if (const MCSymbol *R =1221 Renames.lookup(static_cast<const MCSymbolELF *>(Sym)))1222 Sym = R;1223 if (Sym->isInSection() && Sym->getName().starts_with(".L"))1224 Sym = Sym->getSection().getBeginSymbol();1225 Sym->setUsedInReloc();1226 }1227 1228 // For each `.weakref alias, target`, if the variable `alias` is registered1229 // (typically through MCObjectStreamer::visitUsedSymbol), register `target`.1230 // If `target` was unregistered before (not directly referenced or defined),1231 // make it weak.1232 for (const MCSymbol *Alias : Weakrefs) {1233 if (!Alias->isRegistered())1234 continue;1235 auto *Expr = Alias->getVariableValue();1236 if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {1237 auto &Sym = static_cast<const MCSymbolELF &>(Inner->getSymbol());1238 if (Asm->registerSymbol(Sym))1239 Sym.setBinding(ELF::STB_WEAK);1240 }1241 }1242}1243 1244// It is always valid to create a relocation with a symbol. It is preferable1245// to use a relocation with a section if that is possible. Using the section1246// allows us to omit some local symbols from the symbol table.1247bool ELFObjectWriter::useSectionSymbol(const MCValue &Val,1248 const MCSymbolELF *Sym, uint64_t C,1249 unsigned Type) const {1250 // Keep symbol type for a local ifunc because it may result in an IRELATIVE1251 // reloc that the dynamic loader will use to resolve the address at startup1252 // time.1253 if (Sym->getType() == ELF::STT_GNU_IFUNC)1254 return false;1255 1256 // If a relocation points to a mergeable section, we have to be careful.1257 // If the offset is zero, a relocation with the section will encode the1258 // same information. With a non-zero offset, the situation is different.1259 // For example, a relocation can point 42 bytes past the end of a string.1260 // If we change such a relocation to use the section, the linker would think1261 // that it pointed to another string and subtracting 42 at runtime will1262 // produce the wrong value.1263 if (Sym->isInSection()) {1264 auto &Sec = static_cast<const MCSectionELF &>(Sym->getSection());1265 unsigned Flags = Sec.getFlags();1266 if (Flags & ELF::SHF_MERGE) {1267 if (C != 0)1268 return false;1269 1270 // gold<2.34 incorrectly ignored the addend for R_386_GOTOFF (9)1271 // (http://sourceware.org/PR16794).1272 if (TargetObjectWriter->getEMachine() == ELF::EM_386 &&1273 Type == ELF::R_386_GOTOFF)1274 return false;1275 1276 // ld.lld handles R_MIPS_HI16/R_MIPS_LO16 separately, not as a whole, so1277 // it doesn't know that an R_MIPS_HI16 with implicit addend 1 and an1278 // R_MIPS_LO16 with implicit addend -32768 represents 32768, which is in1279 // range of a MergeInputSection. We could introduce a new RelExpr member1280 // (like R_RISCV_PC_INDIRECT for R_RISCV_PCREL_HI20 / R_RISCV_PCREL_LO12)1281 // but the complexity is unnecessary given that GNU as keeps the original1282 // symbol for this case as well.1283 if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS &&1284 !hasRelocationAddend())1285 return false;1286 }1287 1288 // Most TLS relocations use a got, so they need the symbol. Even those that1289 // are just an offset (@tpoff), require a symbol in gold versions before1290 // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed1291 // http://sourceware.org/PR16773.1292 if (Flags & ELF::SHF_TLS)1293 return false;1294 }1295 1296 return !TargetObjectWriter->needsRelocateWithSymbol(Val, Type);1297}1298 1299bool ELFObjectWriter::checkRelocation(SMLoc Loc, const MCSectionELF *From,1300 const MCSectionELF *To) {1301 if (isDwoSection(*From)) {1302 getContext().reportError(Loc, "A dwo section may not contain relocations");1303 return false;1304 }1305 if (To && isDwoSection(*To)) {1306 getContext().reportError(Loc,1307 "A relocation may not refer to a dwo section");1308 return false;1309 }1310 return true;1311}1312 1313void ELFObjectWriter::recordRelocation(const MCFragment &F,1314 const MCFixup &Fixup, MCValue Target,1315 uint64_t &FixedValue) {1316 auto &Section = static_cast<const MCSectionELF &>(*F.getParent());1317 MCContext &Ctx = getContext();1318 1319 auto *SymA = static_cast<const MCSymbolELF *>(Target.getAddSym());1320 const MCSectionELF *SecA =1321 (SymA && SymA->isInSection())1322 ? static_cast<const MCSectionELF *>(&SymA->getSection())1323 : nullptr;1324 if (DwoOS && !checkRelocation(Fixup.getLoc(), &Section, SecA))1325 return;1326 1327 bool IsPCRel = Fixup.isPCRel();1328 uint64_t FixupOffset = Asm->getFragmentOffset(F) + Fixup.getOffset();1329 uint64_t Addend = Target.getConstant();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;1353 if (mc::isRelocRelocation(Fixup.getKind()))1354 Type = Fixup.getKind() - FirstLiteralRelocationKind;1355 else1356 Type = TargetObjectWriter->getRelocType(Fixup, Target, IsPCRel);1357 1358 // Convert SymA to an STT_SECTION symbol if it's defined, local, and meets1359 // specific conditions, unless it's a .reloc directive, which disables1360 // STT_SECTION adjustment.1361 bool UseSectionSym = SymA && SymA->getBinding() == ELF::STB_LOCAL &&1362 !SymA->isUndefined() &&1363 !mc::isRelocRelocation(Fixup.getKind());1364 if (UseSectionSym && useSectionSymbol(Target, SymA, Addend, Type)) {1365 Addend += Asm->getSymbolOffset(*SymA);1366 SymA = static_cast<const MCSymbolELF *>(SecA->getBeginSymbol());1367 } else if (const MCSymbolELF *R = Renames.lookup(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 1377bool ELFObjectWriter::usesRela(const MCTargetOptions *TO,1378 const MCSectionELF &Sec) const {1379 return (hasRelocationAddend() &&1380 Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE) ||1381 (TO && TO->Crel);1382}1383 1384bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(1385 const MCSymbol &SA, const MCFragment &FB, bool InSet, bool IsPCRel) const {1386 auto &SymA = static_cast<const MCSymbolELF &>(SA);1387 if (IsPCRel) {1388 assert(!InSet);1389 if (SymA.getBinding() != ELF::STB_LOCAL ||1390 SymA.getType() == ELF::STT_GNU_IFUNC)1391 return false;1392 }1393 return &SymA.getSection() == FB.getParent();1394}1395 1396uint64_t ELFObjectWriter::writeObject() {1397 uint64_t Size =1398 ELFWriter(*Asm, *this, OS, IsLittleEndian,1399 DwoOS ? ELFWriter::NonDwoOnly : ELFWriter::AllSections)1400 .writeObject();1401 if (DwoOS)1402 Size += ELFWriter(*Asm, *this, *DwoOS, IsLittleEndian, ELFWriter::DwoOnly)1403 .writeObject();1404 return Size;1405}1406