xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/ELFObjectWriter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements ELF object file writer information.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
140b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
150b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
1706c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
2081ad6265SDimitry Andric #include "llvm/ADT/iterator.h"
210b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
26*0fca6ea1SDimitry Andric #include "llvm/MC/MCELFExtras.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCFragment.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCSection.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
3781ad6265SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
390b57cec5SDimitry Andric #include "llvm/MC/StringTableBuilder.h"
408bcb0991SDimitry Andric #include "llvm/Support/Alignment.h"
410b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
42*0fca6ea1SDimitry Andric #include "llvm/Support/CommandLine.h"
430b57cec5SDimitry Andric #include "llvm/Support/Compression.h"
4481ad6265SDimitry Andric #include "llvm/Support/Endian.h"
455ffd83dbSDimitry Andric #include "llvm/Support/EndianStream.h"
460b57cec5SDimitry Andric #include "llvm/Support/Error.h"
470b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
480b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
490b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
500b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
510b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
5206c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
530b57cec5SDimitry Andric #include <algorithm>
540b57cec5SDimitry Andric #include <cassert>
550b57cec5SDimitry Andric #include <cstddef>
560b57cec5SDimitry Andric #include <cstdint>
570b57cec5SDimitry Andric #include <map>
580b57cec5SDimitry Andric #include <memory>
590b57cec5SDimitry Andric #include <string>
600b57cec5SDimitry Andric #include <utility>
610b57cec5SDimitry Andric #include <vector>
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric using namespace llvm;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric #undef  DEBUG_TYPE
660b57cec5SDimitry Andric #define DEBUG_TYPE "reloc-info"
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric namespace {
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric struct ELFWriter;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric bool isDwoSection(const MCSectionELF &Sec) {
735f757f3fSDimitry Andric   return Sec.getName().ends_with(".dwo");
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric class SymbolTableWriter {
770b57cec5SDimitry Andric   ELFWriter &EWriter;
780b57cec5SDimitry Andric   bool Is64Bit;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   // indexes we are going to write to .symtab_shndx.
810b57cec5SDimitry Andric   std::vector<uint32_t> ShndxIndexes;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   // The numbel of symbols written so far.
840b57cec5SDimitry Andric   unsigned NumWritten;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   void createSymtabShndx();
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   template <typename T> void write(T Value);
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric public:
910b57cec5SDimitry Andric   SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit);
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
940b57cec5SDimitry Andric                    uint8_t other, uint32_t shndx, bool Reserved);
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; }
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric struct ELFWriter {
1000b57cec5SDimitry Andric   ELFObjectWriter &OWriter;
1010b57cec5SDimitry Andric   support::endian::Writer W;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   enum DwoMode {
1040b57cec5SDimitry Andric     AllSections,
1050b57cec5SDimitry Andric     NonDwoOnly,
1060b57cec5SDimitry Andric     DwoOnly,
1070b57cec5SDimitry Andric   } Mode;
1080b57cec5SDimitry Andric 
109*0fca6ea1SDimitry Andric   static uint64_t symbolValue(const MCAssembler &Asm, const MCSymbol &Sym);
110*0fca6ea1SDimitry Andric   static bool isInSymtab(const MCAssembler &Asm, const MCSymbolELF &Symbol,
1110b57cec5SDimitry Andric                          bool Used, bool Renamed);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   /// Helper struct for containing some precomputed information on symbols.
1140b57cec5SDimitry Andric   struct ELFSymbolData {
1150b57cec5SDimitry Andric     const MCSymbolELF *Symbol;
1160b57cec5SDimitry Andric     StringRef Name;
117fe6060f1SDimitry Andric     uint32_t SectionIndex;
118fe6060f1SDimitry Andric     uint32_t Order;
1190b57cec5SDimitry Andric   };
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   /// @}
1220b57cec5SDimitry Andric   /// @name Symbol Table Data
1230b57cec5SDimitry Andric   /// @{
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   StringTableBuilder StrTabBuilder{StringTableBuilder::ELF};
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   /// @}
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   // This holds the symbol table index of the last local symbol.
13006c3fb27SDimitry Andric   unsigned LastLocalSymbolIndex = ~0u;
1310b57cec5SDimitry Andric   // This holds the .strtab section index.
13206c3fb27SDimitry Andric   unsigned StringTableIndex = ~0u;
1330b57cec5SDimitry Andric   // This holds the .symtab section index.
13406c3fb27SDimitry Andric   unsigned SymbolTableIndex = ~0u;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   // Sections in the order they are to be output in the section table.
137*0fca6ea1SDimitry Andric   std::vector<MCSectionELF *> SectionTable;
138*0fca6ea1SDimitry Andric   unsigned addToSectionTable(MCSectionELF *Sec);
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   // TargetObjectWriter wrappers.
1410b57cec5SDimitry Andric   bool is64Bit() const;
1420b57cec5SDimitry Andric 
143bdd1243dSDimitry Andric   uint64_t align(Align Alignment);
1440b57cec5SDimitry Andric 
145fcaf7f86SDimitry Andric   bool maybeWriteCompression(uint32_t ChType, uint64_t Size,
146753f127fSDimitry Andric                              SmallVectorImpl<uint8_t> &CompressedContents,
147bdd1243dSDimitry Andric                              Align Alignment);
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric public:
1500b57cec5SDimitry Andric   ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS,
1510b57cec5SDimitry Andric             bool IsLittleEndian, DwoMode Mode)
1525f757f3fSDimitry Andric       : OWriter(OWriter), W(OS, IsLittleEndian ? llvm::endianness::little
1535f757f3fSDimitry Andric                                                : llvm::endianness::big),
1545f757f3fSDimitry Andric         Mode(Mode) {}
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   void WriteWord(uint64_t Word) {
1570b57cec5SDimitry Andric     if (is64Bit())
1580b57cec5SDimitry Andric       W.write<uint64_t>(Word);
1590b57cec5SDimitry Andric     else
1600b57cec5SDimitry Andric       W.write<uint32_t>(Word);
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   template <typename T> void write(T Val) {
1640b57cec5SDimitry Andric     W.write(Val);
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   void writeHeader(const MCAssembler &Asm);
1680b57cec5SDimitry Andric 
169*0fca6ea1SDimitry Andric   void writeSymbol(const MCAssembler &Asm, SymbolTableWriter &Writer,
170*0fca6ea1SDimitry Andric                    uint32_t StringIndex, ELFSymbolData &MSD);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   // Map from a signature symbol to the group section index
1730b57cec5SDimitry Andric   using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   /// Compute the symbol table data
1760b57cec5SDimitry Andric   ///
1770b57cec5SDimitry Andric   /// \param Asm - The assembler.
1780b57cec5SDimitry Andric   /// \param RevGroupMap - Maps a signature symbol to the group section.
179*0fca6ea1SDimitry Andric   void computeSymbolTable(MCAssembler &Asm, const RevGroupMapTy &RevGroupMap);
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   void writeAddrsigSection();
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   MCSectionELF *createRelocationSection(MCContext &Ctx,
1840b57cec5SDimitry Andric                                         const MCSectionELF &Sec);
1850b57cec5SDimitry Andric 
186*0fca6ea1SDimitry Andric   void writeSectionHeader(const MCAssembler &Asm);
187bdd1243dSDimitry Andric 
188*0fca6ea1SDimitry Andric   void writeSectionData(const MCAssembler &Asm, MCSection &Sec);
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
1910b57cec5SDimitry Andric                         uint64_t Address, uint64_t Offset, uint64_t Size,
192bdd1243dSDimitry Andric                         uint32_t Link, uint32_t Info, MaybeAlign Alignment,
1930b57cec5SDimitry Andric                         uint64_t EntrySize);
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
1960b57cec5SDimitry Andric 
197*0fca6ea1SDimitry Andric   uint64_t writeObject(MCAssembler &Asm);
198*0fca6ea1SDimitry Andric   void writeSection(uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
1990b57cec5SDimitry Andric                     const MCSectionELF &Section);
2000b57cec5SDimitry Andric };
2010b57cec5SDimitry Andric } // end anonymous namespace
2020b57cec5SDimitry Andric 
203bdd1243dSDimitry Andric uint64_t ELFWriter::align(Align Alignment) {
204bdd1243dSDimitry Andric   uint64_t Offset = W.OS.tell();
205bdd1243dSDimitry Andric   uint64_t NewOffset = alignTo(Offset, Alignment);
206fe6060f1SDimitry Andric   W.OS.write_zeros(NewOffset - Offset);
207fe6060f1SDimitry Andric   return NewOffset;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
210*0fca6ea1SDimitry Andric unsigned ELFWriter::addToSectionTable(MCSectionELF *Sec) {
2110b57cec5SDimitry Andric   SectionTable.push_back(Sec);
2125ffd83dbSDimitry Andric   StrTabBuilder.add(Sec->getName());
2130b57cec5SDimitry Andric   return SectionTable.size();
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric void SymbolTableWriter::createSymtabShndx() {
2170b57cec5SDimitry Andric   if (!ShndxIndexes.empty())
2180b57cec5SDimitry Andric     return;
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   ShndxIndexes.resize(NumWritten);
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric template <typename T> void SymbolTableWriter::write(T Value) {
2240b57cec5SDimitry Andric   EWriter.write(Value);
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit)
2280b57cec5SDimitry Andric     : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
2310b57cec5SDimitry Andric                                     uint64_t size, uint8_t other,
2320b57cec5SDimitry Andric                                     uint32_t shndx, bool Reserved) {
2330b57cec5SDimitry Andric   bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   if (LargeIndex)
2360b57cec5SDimitry Andric     createSymtabShndx();
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   if (!ShndxIndexes.empty()) {
2390b57cec5SDimitry Andric     if (LargeIndex)
2400b57cec5SDimitry Andric       ShndxIndexes.push_back(shndx);
2410b57cec5SDimitry Andric     else
2420b57cec5SDimitry Andric       ShndxIndexes.push_back(0);
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   if (Is64Bit) {
2480b57cec5SDimitry Andric     write(name);  // st_name
2490b57cec5SDimitry Andric     write(info);  // st_info
2500b57cec5SDimitry Andric     write(other); // st_other
2510b57cec5SDimitry Andric     write(Index); // st_shndx
2520b57cec5SDimitry Andric     write(value); // st_value
2530b57cec5SDimitry Andric     write(size);  // st_size
2540b57cec5SDimitry Andric   } else {
2550b57cec5SDimitry Andric     write(name);            // st_name
2560b57cec5SDimitry Andric     write(uint32_t(value)); // st_value
2570b57cec5SDimitry Andric     write(uint32_t(size));  // st_size
2580b57cec5SDimitry Andric     write(info);            // st_info
2590b57cec5SDimitry Andric     write(other);           // st_other
2600b57cec5SDimitry Andric     write(Index);           // st_shndx
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   ++NumWritten;
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric bool ELFWriter::is64Bit() const {
2670b57cec5SDimitry Andric   return OWriter.TargetObjectWriter->is64Bit();
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric // Emit the ELF header.
2710b57cec5SDimitry Andric void ELFWriter::writeHeader(const MCAssembler &Asm) {
2720b57cec5SDimitry Andric   // ELF Header
2730b57cec5SDimitry Andric   // ----------
2740b57cec5SDimitry Andric   //
2750b57cec5SDimitry Andric   // Note
2760b57cec5SDimitry Andric   // ----
2770b57cec5SDimitry Andric   // emitWord method behaves differently for ELF32 and ELF64, writing
2780b57cec5SDimitry Andric   // 4 bytes in the former and 8 in the latter.
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   W.OS << ELF::ElfMagic; // e_ident[EI_MAG0] to e_ident[EI_MAG3]
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   W.OS << char(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   // e_ident[EI_DATA]
2855f757f3fSDimitry Andric   W.OS << char(W.Endian == llvm::endianness::little ? ELF::ELFDATA2LSB
2860b57cec5SDimitry Andric                                                     : ELF::ELFDATA2MSB);
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   W.OS << char(ELF::EV_CURRENT);        // e_ident[EI_VERSION]
2890b57cec5SDimitry Andric   // e_ident[EI_OSABI]
290fe6060f1SDimitry Andric   uint8_t OSABI = OWriter.TargetObjectWriter->getOSABI();
291fe6060f1SDimitry Andric   W.OS << char(OSABI == ELF::ELFOSABI_NONE && OWriter.seenGnuAbi()
292fe6060f1SDimitry Andric                    ? int(ELF::ELFOSABI_GNU)
293fe6060f1SDimitry Andric                    : OSABI);
2940b57cec5SDimitry Andric   // e_ident[EI_ABIVERSION]
295*0fca6ea1SDimitry Andric   W.OS << char(OWriter.OverrideABIVersion
296*0fca6ea1SDimitry Andric                    ? *OWriter.OverrideABIVersion
2977a6dacacSDimitry Andric                    : OWriter.TargetObjectWriter->getABIVersion());
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   W.OS.write_zeros(ELF::EI_NIDENT - ELF::EI_PAD);
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   W.write<uint16_t>(ELF::ET_REL);             // e_type
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   W.write<uint16_t>(OWriter.TargetObjectWriter->getEMachine()); // e_machine = target
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   W.write<uint32_t>(ELF::EV_CURRENT);         // e_version
3060b57cec5SDimitry Andric   WriteWord(0);                    // e_entry, no entry point in .o file
3070b57cec5SDimitry Andric   WriteWord(0);                    // e_phoff, no program header for .o
3080b57cec5SDimitry Andric   WriteWord(0);                     // e_shoff = sec hdr table off in bytes
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   // e_flags = whatever the target wants
311*0fca6ea1SDimitry Andric   W.write<uint32_t>(OWriter.getELFHeaderEFlags());
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   // e_ehsize = ELF header size
3140b57cec5SDimitry Andric   W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr)
3150b57cec5SDimitry Andric                               : sizeof(ELF::Elf32_Ehdr));
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   W.write<uint16_t>(0);                  // e_phentsize = prog header entry size
3180b57cec5SDimitry Andric   W.write<uint16_t>(0);                  // e_phnum = # prog header entries = 0
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   // e_shentsize = Section header entry size
3210b57cec5SDimitry Andric   W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr)
3220b57cec5SDimitry Andric                               : sizeof(ELF::Elf32_Shdr));
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   // e_shnum     = # of section header ents
3250b57cec5SDimitry Andric   W.write<uint16_t>(0);
3260b57cec5SDimitry Andric 
327fe6060f1SDimitry Andric   // e_shstrndx  = Section # of '.strtab'
3280b57cec5SDimitry Andric   assert(StringTableIndex < ELF::SHN_LORESERVE);
3290b57cec5SDimitry Andric   W.write<uint16_t>(StringTableIndex);
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
332*0fca6ea1SDimitry Andric uint64_t ELFWriter::symbolValue(const MCAssembler &Asm, const MCSymbol &Sym) {
333e8d8bef9SDimitry Andric   if (Sym.isCommon())
334bdd1243dSDimitry Andric     return Sym.getCommonAlignment()->value();
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   uint64_t Res;
337*0fca6ea1SDimitry Andric   if (!Asm.getSymbolOffset(Sym, Res))
3380b57cec5SDimitry Andric     return 0;
3390b57cec5SDimitry Andric 
340*0fca6ea1SDimitry Andric   if (Asm.isThumbFunc(&Sym))
3410b57cec5SDimitry Andric     Res |= 1;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   return Res;
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
3470b57cec5SDimitry Andric   uint8_t Type = newType;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // Propagation rules:
3500b57cec5SDimitry Andric   // IFUNC > FUNC > OBJECT > NOTYPE
3510b57cec5SDimitry Andric   // TLS_OBJECT > OBJECT > NOTYPE
3520b57cec5SDimitry Andric   //
3530b57cec5SDimitry Andric   // dont let the new type degrade the old type
3540b57cec5SDimitry Andric   switch (origType) {
3550b57cec5SDimitry Andric   default:
3560b57cec5SDimitry Andric     break;
3570b57cec5SDimitry Andric   case ELF::STT_GNU_IFUNC:
3580b57cec5SDimitry Andric     if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||
3590b57cec5SDimitry Andric         Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS)
3600b57cec5SDimitry Andric       Type = ELF::STT_GNU_IFUNC;
3610b57cec5SDimitry Andric     break;
3620b57cec5SDimitry Andric   case ELF::STT_FUNC:
3630b57cec5SDimitry Andric     if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
3640b57cec5SDimitry Andric         Type == ELF::STT_TLS)
3650b57cec5SDimitry Andric       Type = ELF::STT_FUNC;
3660b57cec5SDimitry Andric     break;
3670b57cec5SDimitry Andric   case ELF::STT_OBJECT:
3680b57cec5SDimitry Andric     if (Type == ELF::STT_NOTYPE)
3690b57cec5SDimitry Andric       Type = ELF::STT_OBJECT;
3700b57cec5SDimitry Andric     break;
3710b57cec5SDimitry Andric   case ELF::STT_TLS:
3720b57cec5SDimitry Andric     if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
3730b57cec5SDimitry Andric         Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC)
3740b57cec5SDimitry Andric       Type = ELF::STT_TLS;
3750b57cec5SDimitry Andric     break;
3760b57cec5SDimitry Andric   }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   return Type;
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric 
3818bcb0991SDimitry Andric static bool isIFunc(const MCSymbolELF *Symbol) {
3828bcb0991SDimitry Andric   while (Symbol->getType() != ELF::STT_GNU_IFUNC) {
3838bcb0991SDimitry Andric     const MCSymbolRefExpr *Value;
3848bcb0991SDimitry Andric     if (!Symbol->isVariable() ||
3858bcb0991SDimitry Andric         !(Value = dyn_cast<MCSymbolRefExpr>(Symbol->getVariableValue())) ||
3868bcb0991SDimitry Andric         Value->getKind() != MCSymbolRefExpr::VK_None ||
3878bcb0991SDimitry Andric         mergeTypeForSet(Symbol->getType(), ELF::STT_GNU_IFUNC) != ELF::STT_GNU_IFUNC)
3888bcb0991SDimitry Andric       return false;
3898bcb0991SDimitry Andric     Symbol = &cast<MCSymbolELF>(Value->getSymbol());
3908bcb0991SDimitry Andric   }
3918bcb0991SDimitry Andric   return true;
3928bcb0991SDimitry Andric }
3938bcb0991SDimitry Andric 
394*0fca6ea1SDimitry Andric void ELFWriter::writeSymbol(const MCAssembler &Asm, SymbolTableWriter &Writer,
395*0fca6ea1SDimitry Andric                             uint32_t StringIndex, ELFSymbolData &MSD) {
3960b57cec5SDimitry Andric   const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
3970b57cec5SDimitry Andric   const MCSymbolELF *Base =
398*0fca6ea1SDimitry Andric       cast_or_null<MCSymbolELF>(Asm.getBaseSymbol(Symbol));
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   // This has to be in sync with when computeSymbolTable uses SHN_ABS or
4010b57cec5SDimitry Andric   // SHN_COMMON.
4020b57cec5SDimitry Andric   bool IsReserved = !Base || Symbol.isCommon();
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   // Binding and Type share the same byte as upper and lower nibbles
4050b57cec5SDimitry Andric   uint8_t Binding = Symbol.getBinding();
4060b57cec5SDimitry Andric   uint8_t Type = Symbol.getType();
4078bcb0991SDimitry Andric   if (isIFunc(&Symbol))
4088bcb0991SDimitry Andric     Type = ELF::STT_GNU_IFUNC;
4090b57cec5SDimitry Andric   if (Base) {
4100b57cec5SDimitry Andric     Type = mergeTypeForSet(Type, Base->getType());
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric   uint8_t Info = (Binding << 4) | Type;
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   // Other and Visibility share the same byte with Visibility using the lower
4150b57cec5SDimitry Andric   // 2 bits
4160b57cec5SDimitry Andric   uint8_t Visibility = Symbol.getVisibility();
4170b57cec5SDimitry Andric   uint8_t Other = Symbol.getOther() | Visibility;
4180b57cec5SDimitry Andric 
419*0fca6ea1SDimitry Andric   uint64_t Value = symbolValue(Asm, *MSD.Symbol);
4200b57cec5SDimitry Andric   uint64_t Size = 0;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   const MCExpr *ESize = MSD.Symbol->getSize();
4232a66634dSDimitry Andric   if (!ESize && Base) {
4242a66634dSDimitry Andric     // For expressions like .set y, x+1, if y's size is unset, inherit from x.
4250b57cec5SDimitry Andric     ESize = Base->getSize();
4260b57cec5SDimitry Andric 
4272a66634dSDimitry Andric     // For `.size x, 2; y = x; .size y, 1; z = y; z1 = z; .symver y, y@v1`, z,
4282a66634dSDimitry Andric     // z1, and y@v1's st_size equals y's. However, `Base` is `x` which will give
4292a66634dSDimitry Andric     // us 2. Follow the MCSymbolRefExpr assignment chain, which covers most
4302a66634dSDimitry Andric     // needs. MCBinaryExpr is not handled.
4312a66634dSDimitry Andric     const MCSymbolELF *Sym = &Symbol;
4322a66634dSDimitry Andric     while (Sym->isVariable()) {
4332a66634dSDimitry Andric       if (auto *Expr =
4342a66634dSDimitry Andric               dyn_cast<MCSymbolRefExpr>(Sym->getVariableValue(false))) {
4352a66634dSDimitry Andric         Sym = cast<MCSymbolELF>(&Expr->getSymbol());
4362a66634dSDimitry Andric         if (!Sym->getSize())
4372a66634dSDimitry Andric           continue;
4382a66634dSDimitry Andric         ESize = Sym->getSize();
4392a66634dSDimitry Andric       }
4402a66634dSDimitry Andric       break;
4412a66634dSDimitry Andric     }
4422a66634dSDimitry Andric   }
4432a66634dSDimitry Andric 
4440b57cec5SDimitry Andric   if (ESize) {
4450b57cec5SDimitry Andric     int64_t Res;
446*0fca6ea1SDimitry Andric     if (!ESize->evaluateKnownAbsolute(Res, Asm))
4470b57cec5SDimitry Andric       report_fatal_error("Size expression must be absolute.");
4480b57cec5SDimitry Andric     Size = Res;
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   // Write out the symbol table entry
4520b57cec5SDimitry Andric   Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex,
4530b57cec5SDimitry Andric                      IsReserved);
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
456*0fca6ea1SDimitry Andric bool ELFWriter::isInSymtab(const MCAssembler &Asm, const MCSymbolELF &Symbol,
4570b57cec5SDimitry Andric                            bool Used, bool Renamed) {
4580b57cec5SDimitry Andric   if (Symbol.isVariable()) {
4590b57cec5SDimitry Andric     const MCExpr *Expr = Symbol.getVariableValue();
4600b57cec5SDimitry Andric     // Target Expressions that are always inlined do not appear in the symtab
4610b57cec5SDimitry Andric     if (const auto *T = dyn_cast<MCTargetExpr>(Expr))
4620b57cec5SDimitry Andric       if (T->inlineAssignedExpr())
4630b57cec5SDimitry Andric         return false;
4640b57cec5SDimitry Andric     if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
4650b57cec5SDimitry Andric       if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF)
4660b57cec5SDimitry Andric         return false;
4670b57cec5SDimitry Andric     }
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   if (Used)
4710b57cec5SDimitry Andric     return true;
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric   if (Renamed)
4740b57cec5SDimitry Andric     return false;
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   if (Symbol.isVariable() && Symbol.isUndefined()) {
4770b57cec5SDimitry Andric     // FIXME: this is here just to diagnose the case of a var = commmon_sym.
478*0fca6ea1SDimitry Andric     Asm.getBaseSymbol(Symbol);
4790b57cec5SDimitry Andric     return false;
4800b57cec5SDimitry Andric   }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   if (Symbol.isTemporary())
4830b57cec5SDimitry Andric     return false;
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   if (Symbol.getType() == ELF::STT_SECTION)
4860b57cec5SDimitry Andric     return false;
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   return true;
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
491*0fca6ea1SDimitry Andric void ELFWriter::computeSymbolTable(MCAssembler &Asm,
492*0fca6ea1SDimitry Andric                                    const RevGroupMapTy &RevGroupMap) {
4930b57cec5SDimitry Andric   MCContext &Ctx = Asm.getContext();
4940b57cec5SDimitry Andric   SymbolTableWriter Writer(*this, is64Bit());
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   // Symbol table
4970b57cec5SDimitry Andric   unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
4980b57cec5SDimitry Andric   MCSectionELF *SymtabSection =
499fe6060f1SDimitry Andric       Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize);
5008bcb0991SDimitry Andric   SymtabSection->setAlignment(is64Bit() ? Align(8) : Align(4));
5010b57cec5SDimitry Andric   SymbolTableIndex = addToSectionTable(SymtabSection);
5020b57cec5SDimitry Andric 
503bdd1243dSDimitry Andric   uint64_t SecStart = align(SymtabSection->getAlign());
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   // The first entry is the undefined symbol entry.
5060b57cec5SDimitry Andric   Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   std::vector<ELFSymbolData> LocalSymbolData;
5090b57cec5SDimitry Andric   std::vector<ELFSymbolData> ExternalSymbolData;
510fe6060f1SDimitry Andric   MutableArrayRef<std::pair<std::string, size_t>> FileNames =
511*0fca6ea1SDimitry Andric       OWriter.getFileNames();
512fe6060f1SDimitry Andric   for (const std::pair<std::string, size_t> &F : FileNames)
513fe6060f1SDimitry Andric     StrTabBuilder.add(F.first);
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   // Add the data for the symbols.
5160b57cec5SDimitry Andric   bool HasLargeSectionIndex = false;
517fe6060f1SDimitry Andric   for (auto It : llvm::enumerate(Asm.symbols())) {
518fe6060f1SDimitry Andric     const auto &Symbol = cast<MCSymbolELF>(It.value());
5190b57cec5SDimitry Andric     bool Used = Symbol.isUsedInReloc();
5200b57cec5SDimitry Andric     bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
5210b57cec5SDimitry Andric     bool isSignature = Symbol.isSignature();
5220b57cec5SDimitry Andric 
523*0fca6ea1SDimitry Andric     if (!isInSymtab(Asm, Symbol, Used || WeakrefUsed || isSignature,
5240b57cec5SDimitry Andric                     OWriter.Renames.count(&Symbol)))
5250b57cec5SDimitry Andric       continue;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric     if (Symbol.isTemporary() && Symbol.isUndefined()) {
5285ffd83dbSDimitry Andric       Ctx.reportError(SMLoc(), "Undefined temporary symbol " + Symbol.getName());
5290b57cec5SDimitry Andric       continue;
5300b57cec5SDimitry Andric     }
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric     ELFSymbolData MSD;
5330b57cec5SDimitry Andric     MSD.Symbol = cast<MCSymbolELF>(&Symbol);
534fe6060f1SDimitry Andric     MSD.Order = It.index();
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric     bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
5370b57cec5SDimitry Andric     assert(Local || !Symbol.isTemporary());
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric     if (Symbol.isAbsolute()) {
5400b57cec5SDimitry Andric       MSD.SectionIndex = ELF::SHN_ABS;
5410b57cec5SDimitry Andric     } else if (Symbol.isCommon()) {
5420b57cec5SDimitry Andric       if (Symbol.isTargetCommon()) {
5430b57cec5SDimitry Andric         MSD.SectionIndex = Symbol.getIndex();
5440b57cec5SDimitry Andric       } else {
5450b57cec5SDimitry Andric         assert(!Local);
5460b57cec5SDimitry Andric         MSD.SectionIndex = ELF::SHN_COMMON;
5470b57cec5SDimitry Andric       }
5480b57cec5SDimitry Andric     } else if (Symbol.isUndefined()) {
5490b57cec5SDimitry Andric       if (isSignature && !Used) {
5500b57cec5SDimitry Andric         MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
5510b57cec5SDimitry Andric         if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
5520b57cec5SDimitry Andric           HasLargeSectionIndex = true;
5530b57cec5SDimitry Andric       } else {
5540b57cec5SDimitry Andric         MSD.SectionIndex = ELF::SHN_UNDEF;
5550b57cec5SDimitry Andric       }
5560b57cec5SDimitry Andric     } else {
5570b57cec5SDimitry Andric       const MCSectionELF &Section =
5580b57cec5SDimitry Andric           static_cast<const MCSectionELF &>(Symbol.getSection());
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric       // We may end up with a situation when section symbol is technically
5610b57cec5SDimitry Andric       // defined, but should not be. That happens because we explicitly
5620b57cec5SDimitry Andric       // pre-create few .debug_* sections to have accessors.
5630b57cec5SDimitry Andric       // And if these sections were not really defined in the code, but were
5640b57cec5SDimitry Andric       // referenced, we simply error out.
5650b57cec5SDimitry Andric       if (!Section.isRegistered()) {
5660b57cec5SDimitry Andric         assert(static_cast<const MCSymbolELF &>(Symbol).getType() ==
5670b57cec5SDimitry Andric                ELF::STT_SECTION);
5680b57cec5SDimitry Andric         Ctx.reportError(SMLoc(),
5690b57cec5SDimitry Andric                         "Undefined section reference: " + Symbol.getName());
5700b57cec5SDimitry Andric         continue;
5710b57cec5SDimitry Andric       }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric       if (Mode == NonDwoOnly && isDwoSection(Section))
5740b57cec5SDimitry Andric         continue;
575*0fca6ea1SDimitry Andric       MSD.SectionIndex = Section.getOrdinal();
5760b57cec5SDimitry Andric       assert(MSD.SectionIndex && "Invalid section index!");
5770b57cec5SDimitry Andric       if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
5780b57cec5SDimitry Andric         HasLargeSectionIndex = true;
5790b57cec5SDimitry Andric     }
5800b57cec5SDimitry Andric 
581*0fca6ea1SDimitry Andric     // Temporary symbols generated for certain assembler features (.eh_frame,
582*0fca6ea1SDimitry Andric     // .debug_line) of an empty name may be referenced by relocations due to
583*0fca6ea1SDimitry Andric     // linker relaxation. Rename them to ".L0 " to match the gas fake label name
584*0fca6ea1SDimitry Andric     // and allow ld/objcopy --discard-locals to discard such symbols.
5850b57cec5SDimitry Andric     StringRef Name = Symbol.getName();
586*0fca6ea1SDimitry Andric     if (Name.empty())
587*0fca6ea1SDimitry Andric       Name = ".L0 ";
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric     // Sections have their own string table
5900b57cec5SDimitry Andric     if (Symbol.getType() != ELF::STT_SECTION) {
5910b57cec5SDimitry Andric       MSD.Name = Name;
5920b57cec5SDimitry Andric       StrTabBuilder.add(Name);
5930b57cec5SDimitry Andric     }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric     if (Local)
5960b57cec5SDimitry Andric       LocalSymbolData.push_back(MSD);
5970b57cec5SDimitry Andric     else
5980b57cec5SDimitry Andric       ExternalSymbolData.push_back(MSD);
5990b57cec5SDimitry Andric   }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   // This holds the .symtab_shndx section index.
6020b57cec5SDimitry Andric   unsigned SymtabShndxSectionIndex = 0;
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   if (HasLargeSectionIndex) {
6050b57cec5SDimitry Andric     MCSectionELF *SymtabShndxSection =
606fe6060f1SDimitry Andric         Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4);
6070b57cec5SDimitry Andric     SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
6088bcb0991SDimitry Andric     SymtabShndxSection->setAlignment(Align(4));
6090b57cec5SDimitry Andric   }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   StrTabBuilder.finalize();
6120b57cec5SDimitry Andric 
613fe6060f1SDimitry Andric   // Make the first STT_FILE precede previous local symbols.
614fe6060f1SDimitry Andric   unsigned Index = 1;
615fe6060f1SDimitry Andric   auto FileNameIt = FileNames.begin();
616fe6060f1SDimitry Andric   if (!FileNames.empty())
617fe6060f1SDimitry Andric     FileNames[0].second = 0;
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   for (ELFSymbolData &MSD : LocalSymbolData) {
620fe6060f1SDimitry Andric     // Emit STT_FILE symbols before their associated local symbols.
621fe6060f1SDimitry Andric     for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;
622fe6060f1SDimitry Andric          ++FileNameIt) {
623fe6060f1SDimitry Andric       Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
624fe6060f1SDimitry Andric                          ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
625fe6060f1SDimitry Andric                          ELF::SHN_ABS, true);
626fe6060f1SDimitry Andric       ++Index;
627fe6060f1SDimitry Andric     }
628fe6060f1SDimitry Andric 
6290b57cec5SDimitry Andric     unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
6300b57cec5SDimitry Andric                                ? 0
6310b57cec5SDimitry Andric                                : StrTabBuilder.getOffset(MSD.Name);
6320b57cec5SDimitry Andric     MSD.Symbol->setIndex(Index++);
633*0fca6ea1SDimitry Andric     writeSymbol(Asm, Writer, StringIndex, MSD);
6340b57cec5SDimitry Andric   }
635fe6060f1SDimitry Andric   for (; FileNameIt != FileNames.end(); ++FileNameIt) {
636fe6060f1SDimitry Andric     Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
637fe6060f1SDimitry Andric                        ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
638fe6060f1SDimitry Andric                        ELF::SHN_ABS, true);
639fe6060f1SDimitry Andric     ++Index;
640fe6060f1SDimitry Andric   }
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   // Write the symbol table entries.
6430b57cec5SDimitry Andric   LastLocalSymbolIndex = Index;
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   for (ELFSymbolData &MSD : ExternalSymbolData) {
6460b57cec5SDimitry Andric     unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
6470b57cec5SDimitry Andric     MSD.Symbol->setIndex(Index++);
648*0fca6ea1SDimitry Andric     writeSymbol(Asm, Writer, StringIndex, MSD);
6490b57cec5SDimitry Andric     assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
6500b57cec5SDimitry Andric   }
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   uint64_t SecEnd = W.OS.tell();
653*0fca6ea1SDimitry Andric   SymtabSection->setOffsets(SecStart, SecEnd);
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
6560b57cec5SDimitry Andric   if (ShndxIndexes.empty()) {
6570b57cec5SDimitry Andric     assert(SymtabShndxSectionIndex == 0);
6580b57cec5SDimitry Andric     return;
6590b57cec5SDimitry Andric   }
6600b57cec5SDimitry Andric   assert(SymtabShndxSectionIndex != 0);
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   SecStart = W.OS.tell();
663*0fca6ea1SDimitry Andric   MCSectionELF *SymtabShndxSection = SectionTable[SymtabShndxSectionIndex - 1];
6640b57cec5SDimitry Andric   for (uint32_t Index : ShndxIndexes)
6650b57cec5SDimitry Andric     write(Index);
6660b57cec5SDimitry Andric   SecEnd = W.OS.tell();
667*0fca6ea1SDimitry Andric   SymtabShndxSection->setOffsets(SecStart, SecEnd);
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric void ELFWriter::writeAddrsigSection() {
671*0fca6ea1SDimitry Andric   for (const MCSymbol *Sym : OWriter.getAddrsigSyms())
672bdd1243dSDimitry Andric     if (Sym->getIndex() != 0)
6730b57cec5SDimitry Andric       encodeULEB128(Sym->getIndex(), W.OS);
6740b57cec5SDimitry Andric }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
6770b57cec5SDimitry Andric                                                  const MCSectionELF &Sec) {
6780b57cec5SDimitry Andric   if (OWriter.Relocations[&Sec].empty())
6790b57cec5SDimitry Andric     return nullptr;
6800b57cec5SDimitry Andric 
681*0fca6ea1SDimitry Andric   unsigned Flags = ELF::SHF_INFO_LINK;
682*0fca6ea1SDimitry Andric   if (Sec.getFlags() & ELF::SHF_GROUP)
683*0fca6ea1SDimitry Andric     Flags = ELF::SHF_GROUP;
6840b57cec5SDimitry Andric 
685*0fca6ea1SDimitry Andric   const StringRef SectionName = Sec.getName();
686*0fca6ea1SDimitry Andric   const MCTargetOptions *TO = Ctx.getTargetOptions();
687*0fca6ea1SDimitry Andric   if (TO && TO->Crel) {
688*0fca6ea1SDimitry Andric     MCSectionELF *RelaSection =
689*0fca6ea1SDimitry Andric         Ctx.createELFRelSection(".crel" + SectionName, ELF::SHT_CREL, Flags,
690*0fca6ea1SDimitry Andric                                 /*EntrySize=*/1, Sec.getGroup(), &Sec);
691*0fca6ea1SDimitry Andric     return RelaSection;
692*0fca6ea1SDimitry Andric   }
693*0fca6ea1SDimitry Andric 
694*0fca6ea1SDimitry Andric   const bool Rela = OWriter.usesRela(TO, Sec);
6950b57cec5SDimitry Andric   unsigned EntrySize;
696fe6060f1SDimitry Andric   if (Rela)
6970b57cec5SDimitry Andric     EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
6980b57cec5SDimitry Andric   else
6990b57cec5SDimitry Andric     EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);
7000b57cec5SDimitry Andric 
701*0fca6ea1SDimitry Andric   MCSectionELF *RelaSection =
702*0fca6ea1SDimitry Andric       Ctx.createELFRelSection(((Rela ? ".rela" : ".rel") + SectionName),
703*0fca6ea1SDimitry Andric                               Rela ? ELF::SHT_RELA : ELF::SHT_REL, Flags,
704*0fca6ea1SDimitry Andric                               EntrySize, Sec.getGroup(), &Sec);
7058bcb0991SDimitry Andric   RelaSection->setAlignment(is64Bit() ? Align(8) : Align(4));
7060b57cec5SDimitry Andric   return RelaSection;
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric // Include the debug info compression header.
7100b57cec5SDimitry Andric bool ELFWriter::maybeWriteCompression(
711fcaf7f86SDimitry Andric     uint32_t ChType, uint64_t Size,
712bdd1243dSDimitry Andric     SmallVectorImpl<uint8_t> &CompressedContents, Align Alignment) {
7130b57cec5SDimitry Andric   uint64_t HdrSize =
7145f757f3fSDimitry Andric       is64Bit() ? sizeof(ELF::Elf64_Chdr) : sizeof(ELF::Elf32_Chdr);
7150b57cec5SDimitry Andric   if (Size <= HdrSize + CompressedContents.size())
7160b57cec5SDimitry Andric     return false;
7170b57cec5SDimitry Andric   // Platform specific header is followed by compressed data.
7180b57cec5SDimitry Andric   if (is64Bit()) {
7190b57cec5SDimitry Andric     // Write Elf64_Chdr header.
720fcaf7f86SDimitry Andric     write(static_cast<ELF::Elf64_Word>(ChType));
7210b57cec5SDimitry Andric     write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field.
7220b57cec5SDimitry Andric     write(static_cast<ELF::Elf64_Xword>(Size));
723bdd1243dSDimitry Andric     write(static_cast<ELF::Elf64_Xword>(Alignment.value()));
7240b57cec5SDimitry Andric   } else {
7250b57cec5SDimitry Andric     // Write Elf32_Chdr header otherwise.
726fcaf7f86SDimitry Andric     write(static_cast<ELF::Elf32_Word>(ChType));
7270b57cec5SDimitry Andric     write(static_cast<ELF::Elf32_Word>(Size));
728bdd1243dSDimitry Andric     write(static_cast<ELF::Elf32_Word>(Alignment.value()));
7290b57cec5SDimitry Andric   }
7300b57cec5SDimitry Andric   return true;
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric 
733*0fca6ea1SDimitry Andric void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec) {
7340b57cec5SDimitry Andric   MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
7355ffd83dbSDimitry Andric   StringRef SectionName = Section.getName();
736*0fca6ea1SDimitry Andric   auto &Ctx = Asm.getContext();
737*0fca6ea1SDimitry Andric   const DebugCompressionType CompressionType =
738*0fca6ea1SDimitry Andric       Ctx.getTargetOptions() ? Ctx.getTargetOptions()->CompressDebugSections
739*0fca6ea1SDimitry Andric                              : DebugCompressionType::None;
740bdd1243dSDimitry Andric   if (CompressionType == DebugCompressionType::None ||
7415f757f3fSDimitry Andric       !SectionName.starts_with(".debug_")) {
742*0fca6ea1SDimitry Andric     Asm.writeSectionData(W.OS, &Section);
7430b57cec5SDimitry Andric     return;
7440b57cec5SDimitry Andric   }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   SmallVector<char, 128> UncompressedData;
7470b57cec5SDimitry Andric   raw_svector_ostream VecOS(UncompressedData);
748*0fca6ea1SDimitry Andric   Asm.writeSectionData(VecOS, &Section);
749bdd1243dSDimitry Andric   ArrayRef<uint8_t> Uncompressed =
750bdd1243dSDimitry Andric       ArrayRef(reinterpret_cast<uint8_t *>(UncompressedData.data()),
751bdd1243dSDimitry Andric                UncompressedData.size());
7520b57cec5SDimitry Andric 
753fcaf7f86SDimitry Andric   SmallVector<uint8_t, 128> Compressed;
754bdd1243dSDimitry Andric   uint32_t ChType;
755bdd1243dSDimitry Andric   switch (CompressionType) {
756bdd1243dSDimitry Andric   case DebugCompressionType::None:
757bdd1243dSDimitry Andric     llvm_unreachable("has been handled");
758bdd1243dSDimitry Andric   case DebugCompressionType::Zlib:
759bdd1243dSDimitry Andric     ChType = ELF::ELFCOMPRESS_ZLIB;
760bdd1243dSDimitry Andric     break;
761bdd1243dSDimitry Andric   case DebugCompressionType::Zstd:
762bdd1243dSDimitry Andric     ChType = ELF::ELFCOMPRESS_ZSTD;
763bdd1243dSDimitry Andric     break;
764bdd1243dSDimitry Andric   }
765bdd1243dSDimitry Andric   compression::compress(compression::Params(CompressionType), Uncompressed,
766fcaf7f86SDimitry Andric                         Compressed);
767fcaf7f86SDimitry Andric   if (!maybeWriteCompression(ChType, UncompressedData.size(), Compressed,
768bdd1243dSDimitry Andric                              Sec.getAlign())) {
7690b57cec5SDimitry Andric     W.OS << UncompressedData;
7700b57cec5SDimitry Andric     return;
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
7740b57cec5SDimitry Andric   // Alignment field should reflect the requirements of
7750b57cec5SDimitry Andric   // the compressed section header.
7768bcb0991SDimitry Andric   Section.setAlignment(is64Bit() ? Align(8) : Align(4));
777fcaf7f86SDimitry Andric   W.OS << toStringRef(Compressed);
7780b57cec5SDimitry Andric }
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
7810b57cec5SDimitry Andric                                  uint64_t Address, uint64_t Offset,
7820b57cec5SDimitry Andric                                  uint64_t Size, uint32_t Link, uint32_t Info,
783bdd1243dSDimitry Andric                                  MaybeAlign Alignment, uint64_t EntrySize) {
7840b57cec5SDimitry Andric   W.write<uint32_t>(Name);        // sh_name: index into string table
7850b57cec5SDimitry Andric   W.write<uint32_t>(Type);        // sh_type
7860b57cec5SDimitry Andric   WriteWord(Flags);     // sh_flags
7870b57cec5SDimitry Andric   WriteWord(Address);   // sh_addr
7880b57cec5SDimitry Andric   WriteWord(Offset);    // sh_offset
7890b57cec5SDimitry Andric   WriteWord(Size);      // sh_size
7900b57cec5SDimitry Andric   W.write<uint32_t>(Link);        // sh_link
7910b57cec5SDimitry Andric   W.write<uint32_t>(Info);        // sh_info
792bdd1243dSDimitry Andric   WriteWord(Alignment ? Alignment->value() : 0); // sh_addralign
7930b57cec5SDimitry Andric   WriteWord(EntrySize); // sh_entsize
7940b57cec5SDimitry Andric }
7950b57cec5SDimitry Andric 
796*0fca6ea1SDimitry Andric template <bool Is64>
797*0fca6ea1SDimitry Andric static void encodeCrel(ArrayRef<ELFRelocationEntry> Relocs, raw_ostream &OS) {
798*0fca6ea1SDimitry Andric   using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
799*0fca6ea1SDimitry Andric   ELF::encodeCrel<Is64>(OS, Relocs, [&](const ELFRelocationEntry &R) {
800*0fca6ea1SDimitry Andric     uint32_t SymIdx = R.Symbol ? R.Symbol->getIndex() : 0;
801*0fca6ea1SDimitry Andric     return ELF::Elf_Crel<Is64>{static_cast<uint>(R.Offset), SymIdx, R.Type,
802*0fca6ea1SDimitry Andric                                std::make_signed_t<uint>(R.Addend)};
803*0fca6ea1SDimitry Andric   });
804*0fca6ea1SDimitry Andric }
805*0fca6ea1SDimitry Andric 
8060b57cec5SDimitry Andric void ELFWriter::writeRelocations(const MCAssembler &Asm,
8070b57cec5SDimitry Andric                                        const MCSectionELF &Sec) {
8080b57cec5SDimitry Andric   std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec];
809*0fca6ea1SDimitry Andric   const MCTargetOptions *TO = Asm.getContext().getTargetOptions();
810*0fca6ea1SDimitry Andric   const bool Rela = OWriter.usesRela(TO, Sec);
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric   // Sort the relocation entries. MIPS needs this.
8130b57cec5SDimitry Andric   OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs);
8140b57cec5SDimitry Andric 
815*0fca6ea1SDimitry Andric   if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
816*0fca6ea1SDimitry Andric     for (const ELFRelocationEntry &Entry : Relocs) {
817*0fca6ea1SDimitry Andric       uint32_t SymIdx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
8180b57cec5SDimitry Andric       if (is64Bit()) {
8190b57cec5SDimitry Andric         write(Entry.Offset);
820*0fca6ea1SDimitry Andric         write(uint32_t(SymIdx));
8210b57cec5SDimitry Andric         write(OWriter.TargetObjectWriter->getRSsym(Entry.Type));
8220b57cec5SDimitry Andric         write(OWriter.TargetObjectWriter->getRType3(Entry.Type));
8230b57cec5SDimitry Andric         write(OWriter.TargetObjectWriter->getRType2(Entry.Type));
8240b57cec5SDimitry Andric         write(OWriter.TargetObjectWriter->getRType(Entry.Type));
825fe6060f1SDimitry Andric         if (Rela)
8260b57cec5SDimitry Andric           write(Entry.Addend);
8270b57cec5SDimitry Andric       } else {
8280b57cec5SDimitry Andric         write(uint32_t(Entry.Offset));
829*0fca6ea1SDimitry Andric         ELF::Elf32_Rela ERE32;
830*0fca6ea1SDimitry Andric         ERE32.setSymbolAndType(SymIdx, Entry.Type);
8310b57cec5SDimitry Andric         write(ERE32.r_info);
832fe6060f1SDimitry Andric         if (Rela)
8330b57cec5SDimitry Andric           write(uint32_t(Entry.Addend));
8340b57cec5SDimitry Andric         if (uint32_t RType =
8350b57cec5SDimitry Andric                 OWriter.TargetObjectWriter->getRType2(Entry.Type)) {
8360b57cec5SDimitry Andric           write(uint32_t(Entry.Offset));
8370b57cec5SDimitry Andric           ERE32.setSymbolAndType(0, RType);
8380b57cec5SDimitry Andric           write(ERE32.r_info);
8390b57cec5SDimitry Andric           write(uint32_t(0));
8400b57cec5SDimitry Andric         }
8410b57cec5SDimitry Andric         if (uint32_t RType =
8420b57cec5SDimitry Andric                 OWriter.TargetObjectWriter->getRType3(Entry.Type)) {
8430b57cec5SDimitry Andric           write(uint32_t(Entry.Offset));
8440b57cec5SDimitry Andric           ERE32.setSymbolAndType(0, RType);
8450b57cec5SDimitry Andric           write(ERE32.r_info);
8460b57cec5SDimitry Andric           write(uint32_t(0));
8470b57cec5SDimitry Andric         }
8480b57cec5SDimitry Andric       }
8490b57cec5SDimitry Andric     }
850*0fca6ea1SDimitry Andric   } else if (TO && TO->Crel) {
851*0fca6ea1SDimitry Andric     if (is64Bit())
852*0fca6ea1SDimitry Andric       encodeCrel<true>(Relocs, W.OS);
853*0fca6ea1SDimitry Andric     else
854*0fca6ea1SDimitry Andric       encodeCrel<false>(Relocs, W.OS);
855*0fca6ea1SDimitry Andric   } else {
856*0fca6ea1SDimitry Andric     for (const ELFRelocationEntry &Entry : Relocs) {
857*0fca6ea1SDimitry Andric       uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
858*0fca6ea1SDimitry Andric       if (is64Bit()) {
859*0fca6ea1SDimitry Andric         write(Entry.Offset);
860*0fca6ea1SDimitry Andric         ELF::Elf64_Rela ERE;
861*0fca6ea1SDimitry Andric         ERE.setSymbolAndType(Symidx, Entry.Type);
862*0fca6ea1SDimitry Andric         write(ERE.r_info);
863*0fca6ea1SDimitry Andric         if (Rela)
864*0fca6ea1SDimitry Andric           write(Entry.Addend);
865*0fca6ea1SDimitry Andric       } else {
866*0fca6ea1SDimitry Andric         write(uint32_t(Entry.Offset));
867*0fca6ea1SDimitry Andric         ELF::Elf32_Rela ERE;
868*0fca6ea1SDimitry Andric         ERE.setSymbolAndType(Symidx, Entry.Type);
869*0fca6ea1SDimitry Andric         write(ERE.r_info);
870*0fca6ea1SDimitry Andric         if (Rela)
871*0fca6ea1SDimitry Andric           write(uint32_t(Entry.Addend));
872*0fca6ea1SDimitry Andric       }
873*0fca6ea1SDimitry Andric     }
8740b57cec5SDimitry Andric   }
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
877*0fca6ea1SDimitry Andric void ELFWriter::writeSection(uint32_t GroupSymbolIndex, uint64_t Offset,
8780b57cec5SDimitry Andric                              uint64_t Size, const MCSectionELF &Section) {
8790b57cec5SDimitry Andric   uint64_t sh_link = 0;
8800b57cec5SDimitry Andric   uint64_t sh_info = 0;
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   switch(Section.getType()) {
8830b57cec5SDimitry Andric   default:
8840b57cec5SDimitry Andric     // Nothing to do.
8850b57cec5SDimitry Andric     break;
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   case ELF::SHT_DYNAMIC:
8880b57cec5SDimitry Andric     llvm_unreachable("SHT_DYNAMIC in a relocatable object");
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   case ELF::SHT_REL:
891*0fca6ea1SDimitry Andric   case ELF::SHT_RELA:
892*0fca6ea1SDimitry Andric   case ELF::SHT_CREL: {
8930b57cec5SDimitry Andric     sh_link = SymbolTableIndex;
8940b57cec5SDimitry Andric     assert(sh_link && ".symtab not found");
8955ffd83dbSDimitry Andric     const MCSection *InfoSection = Section.getLinkedToSection();
896*0fca6ea1SDimitry Andric     sh_info = InfoSection->getOrdinal();
8970b57cec5SDimitry Andric     break;
8980b57cec5SDimitry Andric   }
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   case ELF::SHT_SYMTAB:
9010b57cec5SDimitry Andric     sh_link = StringTableIndex;
9020b57cec5SDimitry Andric     sh_info = LastLocalSymbolIndex;
9030b57cec5SDimitry Andric     break;
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric   case ELF::SHT_SYMTAB_SHNDX:
9060b57cec5SDimitry Andric   case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
9070b57cec5SDimitry Andric   case ELF::SHT_LLVM_ADDRSIG:
9080b57cec5SDimitry Andric     sh_link = SymbolTableIndex;
9090b57cec5SDimitry Andric     break;
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   case ELF::SHT_GROUP:
9120b57cec5SDimitry Andric     sh_link = SymbolTableIndex;
9130b57cec5SDimitry Andric     sh_info = GroupSymbolIndex;
9140b57cec5SDimitry Andric     break;
9150b57cec5SDimitry Andric   }
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric   if (Section.getFlags() & ELF::SHF_LINK_ORDER) {
918e8d8bef9SDimitry Andric     // If the value in the associated metadata is not a definition, Sym will be
919e8d8bef9SDimitry Andric     // undefined. Represent this with sh_link=0.
9205ffd83dbSDimitry Andric     const MCSymbol *Sym = Section.getLinkedToSymbol();
921*0fca6ea1SDimitry Andric     if (Sym && Sym->isInSection())
922*0fca6ea1SDimitry Andric       sh_link = Sym->getSection().getOrdinal();
923e8d8bef9SDimitry Andric   }
9240b57cec5SDimitry Andric 
9255ffd83dbSDimitry Andric   WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getName()),
9260b57cec5SDimitry Andric                    Section.getType(), Section.getFlags(), 0, Offset, Size,
927bdd1243dSDimitry Andric                    sh_link, sh_info, Section.getAlign(),
9280b57cec5SDimitry Andric                    Section.getEntrySize());
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric 
931*0fca6ea1SDimitry Andric void ELFWriter::writeSectionHeader(const MCAssembler &Asm) {
9320b57cec5SDimitry Andric   const unsigned NumSections = SectionTable.size();
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   // Null section first.
9350b57cec5SDimitry Andric   uint64_t FirstSectionSize =
9360b57cec5SDimitry Andric       (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
937bdd1243dSDimitry Andric   WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, std::nullopt, 0);
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric   for (const MCSectionELF *Section : SectionTable) {
9400b57cec5SDimitry Andric     uint32_t GroupSymbolIndex;
9410b57cec5SDimitry Andric     unsigned Type = Section->getType();
9420b57cec5SDimitry Andric     if (Type != ELF::SHT_GROUP)
9430b57cec5SDimitry Andric       GroupSymbolIndex = 0;
9440b57cec5SDimitry Andric     else
9450b57cec5SDimitry Andric       GroupSymbolIndex = Section->getGroup()->getIndex();
9460b57cec5SDimitry Andric 
947*0fca6ea1SDimitry Andric     std::pair<uint64_t, uint64_t> Offsets = Section->getOffsets();
9480b57cec5SDimitry Andric     uint64_t Size;
9490b57cec5SDimitry Andric     if (Type == ELF::SHT_NOBITS)
950*0fca6ea1SDimitry Andric       Size = Asm.getSectionAddressSize(*Section);
9510b57cec5SDimitry Andric     else
9520b57cec5SDimitry Andric       Size = Offsets.second - Offsets.first;
9530b57cec5SDimitry Andric 
954*0fca6ea1SDimitry Andric     writeSection(GroupSymbolIndex, Offsets.first, Size, *Section);
9550b57cec5SDimitry Andric   }
9560b57cec5SDimitry Andric }
9570b57cec5SDimitry Andric 
958*0fca6ea1SDimitry Andric uint64_t ELFWriter::writeObject(MCAssembler &Asm) {
9590b57cec5SDimitry Andric   uint64_t StartOffset = W.OS.tell();
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   MCContext &Ctx = Asm.getContext();
9620b57cec5SDimitry Andric   MCSectionELF *StrtabSection =
9630b57cec5SDimitry Andric       Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
9640b57cec5SDimitry Andric   StringTableIndex = addToSectionTable(StrtabSection);
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric   RevGroupMapTy RevGroupMap;
9670b57cec5SDimitry Andric 
9680b57cec5SDimitry Andric   // Write out the ELF header ...
9690b57cec5SDimitry Andric   writeHeader(Asm);
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric   // ... then the sections ...
972*0fca6ea1SDimitry Andric   SmallVector<std::pair<MCSectionELF *, SmallVector<unsigned>>, 0> Groups;
973*0fca6ea1SDimitry Andric   // Map from group section index to group
974*0fca6ea1SDimitry Andric   SmallVector<unsigned, 0> GroupMap;
975*0fca6ea1SDimitry Andric   SmallVector<MCSectionELF *> Relocations;
9760b57cec5SDimitry Andric   for (MCSection &Sec : Asm) {
9770b57cec5SDimitry Andric     MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
9780b57cec5SDimitry Andric     if (Mode == NonDwoOnly && isDwoSection(Section))
9790b57cec5SDimitry Andric       continue;
9800b57cec5SDimitry Andric     if (Mode == DwoOnly && !isDwoSection(Section))
9810b57cec5SDimitry Andric       continue;
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric     // Remember the offset into the file for this section.
984bdd1243dSDimitry Andric     const uint64_t SecStart = align(Section.getAlign());
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric     const MCSymbolELF *SignatureSymbol = Section.getGroup();
987*0fca6ea1SDimitry Andric     writeSectionData(Asm, Section);
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric     uint64_t SecEnd = W.OS.tell();
990*0fca6ea1SDimitry Andric     Section.setOffsets(SecStart, SecEnd);
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric     MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
9930b57cec5SDimitry Andric 
994*0fca6ea1SDimitry Andric     unsigned *GroupIdxEntry = nullptr;
9950b57cec5SDimitry Andric     if (SignatureSymbol) {
996*0fca6ea1SDimitry Andric       GroupIdxEntry = &RevGroupMap[SignatureSymbol];
997*0fca6ea1SDimitry Andric       if (!*GroupIdxEntry) {
998fe6060f1SDimitry Andric         MCSectionELF *Group =
999fe6060f1SDimitry Andric             Ctx.createELFGroupSection(SignatureSymbol, Section.isComdat());
1000*0fca6ea1SDimitry Andric         *GroupIdxEntry = addToSectionTable(Group);
10018bcb0991SDimitry Andric         Group->setAlignment(Align(4));
1002*0fca6ea1SDimitry Andric 
1003*0fca6ea1SDimitry Andric         GroupMap.resize(*GroupIdxEntry + 1);
1004*0fca6ea1SDimitry Andric         GroupMap[*GroupIdxEntry] = Groups.size();
1005*0fca6ea1SDimitry Andric         Groups.emplace_back(Group, SmallVector<unsigned>{});
10060b57cec5SDimitry Andric       }
10070b57cec5SDimitry Andric     }
10080b57cec5SDimitry Andric 
1009*0fca6ea1SDimitry Andric     Section.setOrdinal(addToSectionTable(&Section));
10100b57cec5SDimitry Andric     if (RelSection) {
1011*0fca6ea1SDimitry Andric       RelSection->setOrdinal(addToSectionTable(RelSection));
10120b57cec5SDimitry Andric       Relocations.push_back(RelSection);
10130b57cec5SDimitry Andric     }
10140b57cec5SDimitry Andric 
1015*0fca6ea1SDimitry Andric     if (GroupIdxEntry) {
1016*0fca6ea1SDimitry Andric       auto &Members = Groups[GroupMap[*GroupIdxEntry]];
1017*0fca6ea1SDimitry Andric       Members.second.push_back(Section.getOrdinal());
1018*0fca6ea1SDimitry Andric       if (RelSection)
1019*0fca6ea1SDimitry Andric         Members.second.push_back(RelSection->getOrdinal());
1020*0fca6ea1SDimitry Andric     }
1021*0fca6ea1SDimitry Andric 
10220b57cec5SDimitry Andric     OWriter.TargetObjectWriter->addTargetSectionFlags(Ctx, Section);
10230b57cec5SDimitry Andric   }
10240b57cec5SDimitry Andric 
1025*0fca6ea1SDimitry Andric   for (auto &[Group, Members] : Groups) {
10260b57cec5SDimitry Andric     // Remember the offset into the file for this section.
1027bdd1243dSDimitry Andric     const uint64_t SecStart = align(Group->getAlign());
10280b57cec5SDimitry Andric 
1029fe6060f1SDimitry Andric     write(uint32_t(Group->isComdat() ? unsigned(ELF::GRP_COMDAT) : 0));
1030*0fca6ea1SDimitry Andric     W.write<unsigned>(Members);
10310b57cec5SDimitry Andric 
10320b57cec5SDimitry Andric     uint64_t SecEnd = W.OS.tell();
1033*0fca6ea1SDimitry Andric     Group->setOffsets(SecStart, SecEnd);
10340b57cec5SDimitry Andric   }
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric   if (Mode == DwoOnly) {
10370b57cec5SDimitry Andric     // dwo files don't have symbol tables or relocations, but they do have
10380b57cec5SDimitry Andric     // string tables.
10390b57cec5SDimitry Andric     StrTabBuilder.finalize();
10400b57cec5SDimitry Andric   } else {
10410b57cec5SDimitry Andric     MCSectionELF *AddrsigSection;
1042*0fca6ea1SDimitry Andric     if (OWriter.getEmitAddrsigSection()) {
10430b57cec5SDimitry Andric       AddrsigSection = Ctx.getELFSection(".llvm_addrsig", ELF::SHT_LLVM_ADDRSIG,
10440b57cec5SDimitry Andric                                          ELF::SHF_EXCLUDE);
10450b57cec5SDimitry Andric       addToSectionTable(AddrsigSection);
10460b57cec5SDimitry Andric     }
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric     // Compute symbol table information.
1049*0fca6ea1SDimitry Andric     computeSymbolTable(Asm, RevGroupMap);
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric     for (MCSectionELF *RelSection : Relocations) {
10520b57cec5SDimitry Andric       // Remember the offset into the file for this section.
1053bdd1243dSDimitry Andric       const uint64_t SecStart = align(RelSection->getAlign());
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric       writeRelocations(Asm,
10565ffd83dbSDimitry Andric                        cast<MCSectionELF>(*RelSection->getLinkedToSection()));
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric       uint64_t SecEnd = W.OS.tell();
1059*0fca6ea1SDimitry Andric       RelSection->setOffsets(SecStart, SecEnd);
10600b57cec5SDimitry Andric     }
10610b57cec5SDimitry Andric 
1062*0fca6ea1SDimitry Andric     if (OWriter.getEmitAddrsigSection()) {
10630b57cec5SDimitry Andric       uint64_t SecStart = W.OS.tell();
10640b57cec5SDimitry Andric       writeAddrsigSection();
10650b57cec5SDimitry Andric       uint64_t SecEnd = W.OS.tell();
1066*0fca6ea1SDimitry Andric       AddrsigSection->setOffsets(SecStart, SecEnd);
10670b57cec5SDimitry Andric     }
10680b57cec5SDimitry Andric   }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric   {
10710b57cec5SDimitry Andric     uint64_t SecStart = W.OS.tell();
1072fe6060f1SDimitry Andric     StrTabBuilder.write(W.OS);
1073*0fca6ea1SDimitry Andric     StrtabSection->setOffsets(SecStart, W.OS.tell());
10740b57cec5SDimitry Andric   }
10750b57cec5SDimitry Andric 
1076bdd1243dSDimitry Andric   const uint64_t SectionHeaderOffset = align(is64Bit() ? Align(8) : Align(4));
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   // ... then the section header table ...
1079*0fca6ea1SDimitry Andric   writeSectionHeader(Asm);
10800b57cec5SDimitry Andric 
10810b57cec5SDimitry Andric   uint16_t NumSections = support::endian::byte_swap<uint16_t>(
10820b57cec5SDimitry Andric       (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF
10830b57cec5SDimitry Andric                                                       : SectionTable.size() + 1,
10840b57cec5SDimitry Andric       W.Endian);
10850b57cec5SDimitry Andric   unsigned NumSectionsOffset;
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric   auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
10880b57cec5SDimitry Andric   if (is64Bit()) {
10890b57cec5SDimitry Andric     uint64_t Val =
10900b57cec5SDimitry Andric         support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian);
10910b57cec5SDimitry Andric     Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
10920b57cec5SDimitry Andric                   offsetof(ELF::Elf64_Ehdr, e_shoff));
10930b57cec5SDimitry Andric     NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
10940b57cec5SDimitry Andric   } else {
10950b57cec5SDimitry Andric     uint32_t Val =
10960b57cec5SDimitry Andric         support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian);
10970b57cec5SDimitry Andric     Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
10980b57cec5SDimitry Andric                   offsetof(ELF::Elf32_Ehdr, e_shoff));
10990b57cec5SDimitry Andric     NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
11000b57cec5SDimitry Andric   }
11010b57cec5SDimitry Andric   Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
11020b57cec5SDimitry Andric                 NumSectionsOffset);
11030b57cec5SDimitry Andric 
11040b57cec5SDimitry Andric   return W.OS.tell() - StartOffset;
11050b57cec5SDimitry Andric }
11060b57cec5SDimitry Andric 
1107*0fca6ea1SDimitry Andric ELFObjectWriter::ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
1108*0fca6ea1SDimitry Andric                                  raw_pwrite_stream &OS, bool IsLittleEndian)
1109*0fca6ea1SDimitry Andric     : TargetObjectWriter(std::move(MOTW)), OS(OS),
1110*0fca6ea1SDimitry Andric       IsLittleEndian(IsLittleEndian) {}
1111*0fca6ea1SDimitry Andric ELFObjectWriter::ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
1112*0fca6ea1SDimitry Andric                                  raw_pwrite_stream &OS,
1113*0fca6ea1SDimitry Andric                                  raw_pwrite_stream &DwoOS, bool IsLittleEndian)
1114*0fca6ea1SDimitry Andric     : TargetObjectWriter(std::move(MOTW)), OS(OS), DwoOS(&DwoOS),
1115*0fca6ea1SDimitry Andric       IsLittleEndian(IsLittleEndian) {}
1116*0fca6ea1SDimitry Andric 
1117*0fca6ea1SDimitry Andric void ELFObjectWriter::reset() {
1118*0fca6ea1SDimitry Andric   ELFHeaderEFlags = 0;
1119*0fca6ea1SDimitry Andric   SeenGnuAbi = false;
1120*0fca6ea1SDimitry Andric   OverrideABIVersion.reset();
1121*0fca6ea1SDimitry Andric   Relocations.clear();
1122*0fca6ea1SDimitry Andric   Renames.clear();
1123*0fca6ea1SDimitry Andric   Symvers.clear();
1124*0fca6ea1SDimitry Andric   MCObjectWriter::reset();
1125*0fca6ea1SDimitry Andric }
1126*0fca6ea1SDimitry Andric 
11270b57cec5SDimitry Andric bool ELFObjectWriter::hasRelocationAddend() const {
11280b57cec5SDimitry Andric   return TargetObjectWriter->hasRelocationAddend();
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric 
1131*0fca6ea1SDimitry Andric void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm) {
11320b57cec5SDimitry Andric   // The presence of symbol versions causes undefined symbols and
11330b57cec5SDimitry Andric   // versions declared with @@@ to be renamed.
1134*0fca6ea1SDimitry Andric   for (const Symver &S : Symvers) {
1135e8d8bef9SDimitry Andric     StringRef AliasName = S.Name;
1136e8d8bef9SDimitry Andric     const auto &Symbol = cast<MCSymbolELF>(*S.Sym);
11370b57cec5SDimitry Andric     size_t Pos = AliasName.find('@');
11380b57cec5SDimitry Andric     assert(Pos != StringRef::npos);
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric     StringRef Prefix = AliasName.substr(0, Pos);
11410b57cec5SDimitry Andric     StringRef Rest = AliasName.substr(Pos);
11420b57cec5SDimitry Andric     StringRef Tail = Rest;
11435f757f3fSDimitry Andric     if (Rest.starts_with("@@@"))
11440b57cec5SDimitry Andric       Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1);
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric     auto *Alias =
11470b57cec5SDimitry Andric         cast<MCSymbolELF>(Asm.getContext().getOrCreateSymbol(Prefix + Tail));
11480b57cec5SDimitry Andric     Asm.registerSymbol(*Alias);
11490b57cec5SDimitry Andric     const MCExpr *Value = MCSymbolRefExpr::create(&Symbol, Asm.getContext());
11500b57cec5SDimitry Andric     Alias->setVariableValue(Value);
11510b57cec5SDimitry Andric 
11520b57cec5SDimitry Andric     // Aliases defined with .symvar copy the binding from the symbol they alias.
11530b57cec5SDimitry Andric     // This is the first place we are able to copy this information.
11540b57cec5SDimitry Andric     Alias->setBinding(Symbol.getBinding());
1155e8d8bef9SDimitry Andric     Alias->setVisibility(Symbol.getVisibility());
11560b57cec5SDimitry Andric     Alias->setOther(Symbol.getOther());
11570b57cec5SDimitry Andric 
1158fe6060f1SDimitry Andric     if (!Symbol.isUndefined() && S.KeepOriginalSym)
11590b57cec5SDimitry Andric       continue;
11600b57cec5SDimitry Andric 
11615f757f3fSDimitry Andric     if (Symbol.isUndefined() && Rest.starts_with("@@") &&
11625f757f3fSDimitry Andric         !Rest.starts_with("@@@")) {
1163e8d8bef9SDimitry Andric       Asm.getContext().reportError(S.Loc, "default version symbol " +
1164e8d8bef9SDimitry Andric                                               AliasName + " must be defined");
11650b57cec5SDimitry Andric       continue;
11660b57cec5SDimitry Andric     }
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric     if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) {
1169e8d8bef9SDimitry Andric       Asm.getContext().reportError(S.Loc, Twine("multiple versions for ") +
11700b57cec5SDimitry Andric                                               Symbol.getName());
11710b57cec5SDimitry Andric       continue;
11720b57cec5SDimitry Andric     }
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric     Renames.insert(std::make_pair(&Symbol, Alias));
11750b57cec5SDimitry Andric   }
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   for (const MCSymbol *&Sym : AddrsigSyms) {
11780b57cec5SDimitry Andric     if (const MCSymbol *R = Renames.lookup(cast<MCSymbolELF>(Sym)))
11790b57cec5SDimitry Andric       Sym = R;
11805f757f3fSDimitry Andric     if (Sym->isInSection() && Sym->getName().starts_with(".L"))
11810b57cec5SDimitry Andric       Sym = Sym->getSection().getBeginSymbol();
11820b57cec5SDimitry Andric     Sym->setUsedInReloc();
11830b57cec5SDimitry Andric   }
11840b57cec5SDimitry Andric }
11850b57cec5SDimitry Andric 
11860b57cec5SDimitry Andric // It is always valid to create a relocation with a symbol. It is preferable
11870b57cec5SDimitry Andric // to use a relocation with a section if that is possible. Using the section
11880b57cec5SDimitry Andric // allows us to omit some local symbols from the symbol table.
11890b57cec5SDimitry Andric bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
11905f757f3fSDimitry Andric                                                const MCValue &Val,
11910b57cec5SDimitry Andric                                                const MCSymbolELF *Sym,
11920b57cec5SDimitry Andric                                                uint64_t C,
11930b57cec5SDimitry Andric                                                unsigned Type) const {
11945f757f3fSDimitry Andric   const MCSymbolRefExpr *RefA = Val.getSymA();
11950b57cec5SDimitry Andric   // A PCRel relocation to an absolute value has no symbol (or section). We
11960b57cec5SDimitry Andric   // represent that with a relocation to a null section.
11970b57cec5SDimitry Andric   if (!RefA)
11980b57cec5SDimitry Andric     return false;
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   MCSymbolRefExpr::VariantKind Kind = RefA->getKind();
12010b57cec5SDimitry Andric   switch (Kind) {
12020b57cec5SDimitry Andric   default:
12030b57cec5SDimitry Andric     break;
12040b57cec5SDimitry Andric   // The .odp creation emits a relocation against the symbol ".TOC." which
12050b57cec5SDimitry Andric   // create a R_PPC64_TOC relocation. However the relocation symbol name
12060b57cec5SDimitry Andric   // in final object creation should be NULL, since the symbol does not
12070b57cec5SDimitry Andric   // really exist, it is just the reference to TOC base for the current
12080b57cec5SDimitry Andric   // object file. Since the symbol is undefined, returning false results
12090b57cec5SDimitry Andric   // in a relocation with a null section which is the desired result.
12100b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_TOCBASE:
12110b57cec5SDimitry Andric     return false;
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric   // These VariantKind cause the relocation to refer to something other than
12140b57cec5SDimitry Andric   // the symbol itself, like a linker generated table. Since the address of
12150b57cec5SDimitry Andric   // symbol is not relevant, we cannot replace the symbol with the
12160b57cec5SDimitry Andric   // section and patch the difference in the addend.
12170b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_GOT:
12180b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PLT:
12190b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_GOTPCREL:
1220349cc55cSDimitry Andric   case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:
12210b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_GOT_LO:
12220b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_GOT_HI:
12230b57cec5SDimitry Andric   case MCSymbolRefExpr::VK_PPC_GOT_HA:
12240b57cec5SDimitry Andric     return true;
12250b57cec5SDimitry Andric   }
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric   // An undefined symbol is not in any section, so the relocation has to point
12280b57cec5SDimitry Andric   // to the symbol itself.
12290b57cec5SDimitry Andric   assert(Sym && "Expected a symbol");
12300b57cec5SDimitry Andric   if (Sym->isUndefined())
12310b57cec5SDimitry Andric     return true;
12320b57cec5SDimitry Andric 
1233bdd1243dSDimitry Andric   // For memory-tagged symbols, ensure that the relocation uses the symbol. For
1234bdd1243dSDimitry Andric   // tagged symbols, we emit an empty relocation (R_AARCH64_NONE) in a special
1235bdd1243dSDimitry Andric   // section (SHT_AARCH64_MEMTAG_GLOBALS_STATIC) to indicate to the linker that
1236bdd1243dSDimitry Andric   // this global needs to be tagged. In addition, the linker needs to know
1237bdd1243dSDimitry Andric   // whether to emit a special addend when relocating `end` symbols, and this
1238bdd1243dSDimitry Andric   // can only be determined by the attributes of the symbol itself.
1239bdd1243dSDimitry Andric   if (Sym->isMemtag())
1240bdd1243dSDimitry Andric     return true;
1241bdd1243dSDimitry Andric 
12420b57cec5SDimitry Andric   unsigned Binding = Sym->getBinding();
12430b57cec5SDimitry Andric   switch(Binding) {
12440b57cec5SDimitry Andric   default:
12450b57cec5SDimitry Andric     llvm_unreachable("Invalid Binding");
12460b57cec5SDimitry Andric   case ELF::STB_LOCAL:
12470b57cec5SDimitry Andric     break;
12480b57cec5SDimitry Andric   case ELF::STB_WEAK:
12490b57cec5SDimitry Andric     // If the symbol is weak, it might be overridden by a symbol in another
12500b57cec5SDimitry Andric     // file. The relocation has to point to the symbol so that the linker
12510b57cec5SDimitry Andric     // can update it.
12520b57cec5SDimitry Andric     return true;
12530b57cec5SDimitry Andric   case ELF::STB_GLOBAL:
12543a9a9c0cSDimitry Andric   case ELF::STB_GNU_UNIQUE:
12550b57cec5SDimitry Andric     // Global ELF symbols can be preempted by the dynamic linker. The relocation
12560b57cec5SDimitry Andric     // has to point to the symbol for a reason analogous to the STB_WEAK case.
12570b57cec5SDimitry Andric     return true;
12580b57cec5SDimitry Andric   }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   // Keep symbol type for a local ifunc because it may result in an IRELATIVE
12610b57cec5SDimitry Andric   // reloc that the dynamic loader will use to resolve the address at startup
12620b57cec5SDimitry Andric   // time.
12630b57cec5SDimitry Andric   if (Sym->getType() == ELF::STT_GNU_IFUNC)
12640b57cec5SDimitry Andric     return true;
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric   // If a relocation points to a mergeable section, we have to be careful.
12670b57cec5SDimitry Andric   // If the offset is zero, a relocation with the section will encode the
12680b57cec5SDimitry Andric   // same information. With a non-zero offset, the situation is different.
12690b57cec5SDimitry Andric   // For example, a relocation can point 42 bytes past the end of a string.
12700b57cec5SDimitry Andric   // If we change such a relocation to use the section, the linker would think
12710b57cec5SDimitry Andric   // that it pointed to another string and subtracting 42 at runtime will
12720b57cec5SDimitry Andric   // produce the wrong value.
12730b57cec5SDimitry Andric   if (Sym->isInSection()) {
12740b57cec5SDimitry Andric     auto &Sec = cast<MCSectionELF>(Sym->getSection());
12750b57cec5SDimitry Andric     unsigned Flags = Sec.getFlags();
12760b57cec5SDimitry Andric     if (Flags & ELF::SHF_MERGE) {
12770b57cec5SDimitry Andric       if (C != 0)
12780b57cec5SDimitry Andric         return true;
12790b57cec5SDimitry Andric 
1280e8d8bef9SDimitry Andric       // gold<2.34 incorrectly ignored the addend for R_386_GOTOFF (9)
1281e8d8bef9SDimitry Andric       // (http://sourceware.org/PR16794).
1282e8d8bef9SDimitry Andric       if (TargetObjectWriter->getEMachine() == ELF::EM_386 &&
1283e8d8bef9SDimitry Andric           Type == ELF::R_386_GOTOFF)
12840b57cec5SDimitry Andric         return true;
1285d409305fSDimitry Andric 
1286d409305fSDimitry Andric       // ld.lld handles R_MIPS_HI16/R_MIPS_LO16 separately, not as a whole, so
1287d409305fSDimitry Andric       // it doesn't know that an R_MIPS_HI16 with implicit addend 1 and an
1288d409305fSDimitry Andric       // R_MIPS_LO16 with implicit addend -32768 represents 32768, which is in
1289d409305fSDimitry Andric       // range of a MergeInputSection. We could introduce a new RelExpr member
1290d409305fSDimitry Andric       // (like R_RISCV_PC_INDIRECT for R_RISCV_PCREL_HI20 / R_RISCV_PCREL_LO12)
1291d409305fSDimitry Andric       // but the complexity is unnecessary given that GNU as keeps the original
1292d409305fSDimitry Andric       // symbol for this case as well.
1293d409305fSDimitry Andric       if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS &&
1294d409305fSDimitry Andric           !hasRelocationAddend())
1295d409305fSDimitry Andric         return true;
12960b57cec5SDimitry Andric     }
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric     // Most TLS relocations use a got, so they need the symbol. Even those that
12990b57cec5SDimitry Andric     // are just an offset (@tpoff), require a symbol in gold versions before
13000b57cec5SDimitry Andric     // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed
13010b57cec5SDimitry Andric     // http://sourceware.org/PR16773.
13020b57cec5SDimitry Andric     if (Flags & ELF::SHF_TLS)
13030b57cec5SDimitry Andric       return true;
13040b57cec5SDimitry Andric   }
13050b57cec5SDimitry Andric 
13060b57cec5SDimitry Andric   // If the symbol is a thumb function the final relocation must set the lowest
13070b57cec5SDimitry Andric   // bit. With a symbol that is done by just having the symbol have that bit
13080b57cec5SDimitry Andric   // set, so we would lose the bit if we relocated with the section.
13090b57cec5SDimitry Andric   // FIXME: We could use the section but add the bit to the relocation value.
13100b57cec5SDimitry Andric   if (Asm.isThumbFunc(Sym))
13110b57cec5SDimitry Andric     return true;
13120b57cec5SDimitry Andric 
13135f757f3fSDimitry Andric   if (TargetObjectWriter->needsRelocateWithSymbol(Val, *Sym, Type))
13140b57cec5SDimitry Andric     return true;
13150b57cec5SDimitry Andric   return false;
13160b57cec5SDimitry Andric }
13170b57cec5SDimitry Andric 
1318*0fca6ea1SDimitry Andric bool ELFObjectWriter::checkRelocation(MCContext &Ctx, SMLoc Loc,
1319*0fca6ea1SDimitry Andric                                       const MCSectionELF *From,
1320*0fca6ea1SDimitry Andric                                       const MCSectionELF *To) {
1321*0fca6ea1SDimitry Andric   if (DwoOS) {
1322*0fca6ea1SDimitry Andric     if (isDwoSection(*From)) {
1323*0fca6ea1SDimitry Andric       Ctx.reportError(Loc, "A dwo section may not contain relocations");
1324*0fca6ea1SDimitry Andric       return false;
1325*0fca6ea1SDimitry Andric     }
1326*0fca6ea1SDimitry Andric     if (To && isDwoSection(*To)) {
1327*0fca6ea1SDimitry Andric       Ctx.reportError(Loc, "A relocation may not refer to a dwo section");
1328*0fca6ea1SDimitry Andric       return false;
1329*0fca6ea1SDimitry Andric     }
1330*0fca6ea1SDimitry Andric   }
1331*0fca6ea1SDimitry Andric   return true;
1332*0fca6ea1SDimitry Andric }
1333*0fca6ea1SDimitry Andric 
13340b57cec5SDimitry Andric void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
13350b57cec5SDimitry Andric                                        const MCFragment *Fragment,
13360b57cec5SDimitry Andric                                        const MCFixup &Fixup, MCValue Target,
13370b57cec5SDimitry Andric                                        uint64_t &FixedValue) {
13380b57cec5SDimitry Andric   MCAsmBackend &Backend = Asm.getBackend();
13390b57cec5SDimitry Andric   bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
13400b57cec5SDimitry Andric                  MCFixupKindInfo::FKF_IsPCRel;
13410b57cec5SDimitry Andric   const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
13420b57cec5SDimitry Andric   uint64_t C = Target.getConstant();
1343*0fca6ea1SDimitry Andric   uint64_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
13440b57cec5SDimitry Andric   MCContext &Ctx = Asm.getContext();
1345*0fca6ea1SDimitry Andric   const MCTargetOptions *TO = Ctx.getTargetOptions();
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric   if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
13480b57cec5SDimitry Andric     const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
13490b57cec5SDimitry Andric     if (SymB.isUndefined()) {
13500b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(),
13510b57cec5SDimitry Andric                       Twine("symbol '") + SymB.getName() +
13520b57cec5SDimitry Andric                           "' can not be undefined in a subtraction expression");
13530b57cec5SDimitry Andric       return;
13540b57cec5SDimitry Andric     }
13550b57cec5SDimitry Andric 
13560b57cec5SDimitry Andric     assert(!SymB.isAbsolute() && "Should have been folded");
13570b57cec5SDimitry Andric     const MCSection &SecB = SymB.getSection();
13580b57cec5SDimitry Andric     if (&SecB != &FixupSection) {
13590b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(),
13600b57cec5SDimitry Andric                       "Cannot represent a difference across sections");
13610b57cec5SDimitry Andric       return;
13620b57cec5SDimitry Andric     }
13630b57cec5SDimitry Andric 
13648bcb0991SDimitry Andric     assert(!IsPCRel && "should have been folded");
13650b57cec5SDimitry Andric     IsPCRel = true;
1366*0fca6ea1SDimitry Andric     C += FixupOffset - Asm.getSymbolOffset(SymB);
13670b57cec5SDimitry Andric   }
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric   // We either rejected the fixup or folded B into C at this point.
13700b57cec5SDimitry Andric   const MCSymbolRefExpr *RefA = Target.getSymA();
13710b57cec5SDimitry Andric   const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric   bool ViaWeakRef = false;
13740b57cec5SDimitry Andric   if (SymA && SymA->isVariable()) {
13750b57cec5SDimitry Andric     const MCExpr *Expr = SymA->getVariableValue();
13760b57cec5SDimitry Andric     if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
13770b57cec5SDimitry Andric       if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
13780b57cec5SDimitry Andric         SymA = cast<MCSymbolELF>(&Inner->getSymbol());
13790b57cec5SDimitry Andric         ViaWeakRef = true;
13800b57cec5SDimitry Andric       }
13810b57cec5SDimitry Andric     }
13820b57cec5SDimitry Andric   }
13830b57cec5SDimitry Andric 
13840b57cec5SDimitry Andric   const MCSectionELF *SecA = (SymA && SymA->isInSection())
13850b57cec5SDimitry Andric                                  ? cast<MCSectionELF>(&SymA->getSection())
13860b57cec5SDimitry Andric                                  : nullptr;
13870b57cec5SDimitry Andric   if (!checkRelocation(Ctx, Fixup.getLoc(), &FixupSection, SecA))
13880b57cec5SDimitry Andric     return;
13890b57cec5SDimitry Andric 
13908bcb0991SDimitry Andric   unsigned Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
1391fe6060f1SDimitry Andric   const auto *Parent = cast<MCSectionELF>(Fragment->getParent());
1392fe6060f1SDimitry Andric   // Emiting relocation with sybmol for CG Profile to  help with --cg-profile.
1393fe6060f1SDimitry Andric   bool RelocateWithSymbol =
13945f757f3fSDimitry Andric       shouldRelocateWithSymbol(Asm, Target, SymA, C, Type) ||
1395fe6060f1SDimitry Andric       (Parent->getType() == ELF::SHT_LLVM_CALL_GRAPH_PROFILE);
13968bcb0991SDimitry Andric   uint64_t Addend = 0;
13978bcb0991SDimitry Andric 
13988bcb0991SDimitry Andric   FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined()
1399*0fca6ea1SDimitry Andric                    ? C + Asm.getSymbolOffset(*SymA)
14008bcb0991SDimitry Andric                    : C;
1401*0fca6ea1SDimitry Andric   if (usesRela(TO, FixupSection)) {
14028bcb0991SDimitry Andric     Addend = FixedValue;
14038bcb0991SDimitry Andric     FixedValue = 0;
14048bcb0991SDimitry Andric   }
14058bcb0991SDimitry Andric 
14060b57cec5SDimitry Andric   if (!RelocateWithSymbol) {
14070b57cec5SDimitry Andric     const auto *SectionSymbol =
14080b57cec5SDimitry Andric         SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr;
14090b57cec5SDimitry Andric     if (SectionSymbol)
14100b57cec5SDimitry Andric       SectionSymbol->setUsedInReloc();
14118bcb0991SDimitry Andric     ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA, C);
14120b57cec5SDimitry Andric     Relocations[&FixupSection].push_back(Rec);
14130b57cec5SDimitry Andric     return;
14140b57cec5SDimitry Andric   }
14150b57cec5SDimitry Andric 
14168bcb0991SDimitry Andric   const MCSymbolELF *RenamedSymA = SymA;
14170b57cec5SDimitry Andric   if (SymA) {
14180b57cec5SDimitry Andric     if (const MCSymbolELF *R = Renames.lookup(SymA))
14190b57cec5SDimitry Andric       RenamedSymA = R;
14200b57cec5SDimitry Andric 
14210b57cec5SDimitry Andric     if (ViaWeakRef)
14220b57cec5SDimitry Andric       RenamedSymA->setIsWeakrefUsedInReloc();
14230b57cec5SDimitry Andric     else
14240b57cec5SDimitry Andric       RenamedSymA->setUsedInReloc();
14250b57cec5SDimitry Andric   }
14268bcb0991SDimitry Andric   ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA, C);
14270b57cec5SDimitry Andric   Relocations[&FixupSection].push_back(Rec);
14280b57cec5SDimitry Andric }
14290b57cec5SDimitry Andric 
1430*0fca6ea1SDimitry Andric bool ELFObjectWriter::usesRela(const MCTargetOptions *TO,
1431*0fca6ea1SDimitry Andric                                const MCSectionELF &Sec) const {
1432*0fca6ea1SDimitry Andric   return (hasRelocationAddend() &&
1433*0fca6ea1SDimitry Andric           Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE) ||
1434*0fca6ea1SDimitry Andric          (TO && TO->Crel);
1435*0fca6ea1SDimitry Andric }
1436*0fca6ea1SDimitry Andric 
14370b57cec5SDimitry Andric bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
14380b57cec5SDimitry Andric     const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB,
14390b57cec5SDimitry Andric     bool InSet, bool IsPCRel) const {
14400b57cec5SDimitry Andric   const auto &SymA = cast<MCSymbolELF>(SA);
14410b57cec5SDimitry Andric   if (IsPCRel) {
14420b57cec5SDimitry Andric     assert(!InSet);
1443480093f4SDimitry Andric     if (SymA.getBinding() != ELF::STB_LOCAL ||
1444480093f4SDimitry Andric         SymA.getType() == ELF::STT_GNU_IFUNC)
14450b57cec5SDimitry Andric       return false;
14460b57cec5SDimitry Andric   }
1447*0fca6ea1SDimitry Andric   return &SymA.getSection() == FB.getParent();
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric 
1450*0fca6ea1SDimitry Andric uint64_t ELFObjectWriter::writeObject(MCAssembler &Asm) {
1451*0fca6ea1SDimitry Andric   uint64_t Size =
1452*0fca6ea1SDimitry Andric       ELFWriter(*this, OS, IsLittleEndian,
1453*0fca6ea1SDimitry Andric                 DwoOS ? ELFWriter::NonDwoOnly : ELFWriter::AllSections)
1454*0fca6ea1SDimitry Andric           .writeObject(Asm);
1455*0fca6ea1SDimitry Andric   if (DwoOS)
1456*0fca6ea1SDimitry Andric     Size += ELFWriter(*this, *DwoOS, IsLittleEndian, ELFWriter::DwoOnly)
1457*0fca6ea1SDimitry Andric                 .writeObject(Asm);
1458*0fca6ea1SDimitry Andric   return Size;
14590b57cec5SDimitry Andric }
1460