Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Defines the writer for ELF relocatable object files.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "IceELFObjectWriter.h"
     16 
     17 #include "IceAssembler.h"
     18 #include "IceDefs.h"
     19 #include "IceELFSection.h"
     20 #include "IceELFStreamer.h"
     21 #include "IceGlobalContext.h"
     22 #include "IceGlobalInits.h"
     23 #include "IceInst.h"
     24 #include "IceOperand.h"
     25 
     26 #include "llvm/Support/ELF.h"
     27 #include "llvm/Support/MathExtras.h"
     28 
     29 namespace Ice {
     30 
     31 namespace {
     32 
     33 constexpr struct {
     34   bool IsELF64;
     35   uint16_t ELFMachine;
     36   uint32_t ELFFlags;
     37 } ELFTargetInfo[TargetArch_NUM] = {
     38 #define X(tag, str, is_elf64, e_machine, e_flags)                              \
     39   { is_elf64, e_machine, e_flags }                                             \
     40   ,
     41     TARGETARCH_TABLE
     42 #undef X
     43 };
     44 
     45 bool isELF64(const ClFlags &Flags) {
     46   const TargetArch Arch = Flags.getTargetArch();
     47   if (Arch >= TargetArch_NUM) {
     48     llvm_unreachable("Invalid target arch for isELF64");
     49     return false;
     50   }
     51 
     52   if (Flags.getApplicationBinaryInterface() == ABI_PNaCl &&
     53       !Flags.getUseSandboxing()) {
     54     // Unsandboxed PNaCl code is always ELF32 (pexes are ILP32.)
     55     return false;
     56   }
     57 
     58   return ELFTargetInfo[Arch].IsELF64;
     59 }
     60 
     61 uint16_t getELFMachine(TargetArch Arch) {
     62   if (Arch < TargetArch_NUM)
     63     return ELFTargetInfo[Arch].ELFMachine;
     64   llvm_unreachable("Invalid target arch for getELFMachine");
     65   return EM_NONE;
     66 }
     67 
     68 uint32_t getELFFlags(TargetArch Arch) {
     69   if (Arch < TargetArch_NUM)
     70     return ELFTargetInfo[Arch].ELFFlags;
     71   llvm_unreachable("Invalid target arch for getELFFlags");
     72   return 0;
     73 }
     74 
     75 } // end of anonymous namespace
     76 
     77 ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out)
     78     : Ctx(Ctx), Str(Out), ELF64(isELF64(getFlags())) {
     79   // Create the special bookkeeping sections now.
     80   constexpr char NullSectionName[] = "";
     81   NullSection = new (Ctx.allocate<ELFSection>())
     82       ELFSection(NullSectionName, SHT_NULL, 0, 0, 0);
     83 
     84   constexpr char ShStrTabName[] = ".shstrtab";
     85   ShStrTab = new (Ctx.allocate<ELFStringTableSection>())
     86       ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0);
     87   ShStrTab->add(ShStrTabName);
     88 
     89   constexpr char SymTabName[] = ".symtab";
     90   const Elf64_Xword SymTabAlign = ELF64 ? 8 : 4;
     91   const Elf64_Xword SymTabEntSize =
     92       ELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
     93   static_assert(sizeof(Elf64_Sym) == 24 && sizeof(Elf32_Sym) == 16,
     94                 "Elf_Sym sizes cannot be derived from sizeof");
     95   SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0,
     96                                                 SymTabAlign, SymTabEntSize);
     97   SymTab->createNullSymbol(NullSection, &Ctx);
     98 
     99   constexpr char StrTabName[] = ".strtab";
    100   StrTab =
    101       createSection<ELFStringTableSection>(StrTabName, SHT_STRTAB, 0, 1, 0);
    102 }
    103 
    104 template <typename T>
    105 T *ELFObjectWriter::createSection(const std::string &Name, Elf64_Word ShType,
    106                                   Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
    107                                   Elf64_Xword ShEntsize) {
    108   assert(!SectionNumbersAssigned);
    109   T *NewSection =
    110       new (Ctx.allocate<T>()) T(Name, ShType, ShFlags, ShAddralign, ShEntsize);
    111   ShStrTab->add(Name);
    112   return NewSection;
    113 }
    114 
    115 ELFRelocationSection *
    116 ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) {
    117   // Choice of RELA vs REL is actually separate from elf64 vs elf32, but in
    118   // practice we've only had .rela for elf64 (x86-64). In the future, the two
    119   // properties may need to be decoupled and the ShEntSize can vary more.
    120   const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL;
    121   const std::string RelPrefix = ELF64 ? ".rela" : ".rel";
    122   const std::string RelSectionName = RelPrefix + RelatedSection->getName();
    123   const Elf64_Xword ShAlign = ELF64 ? 8 : 4;
    124   const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
    125   static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8,
    126                 "Elf_Rel/Rela sizes cannot be derived from sizeof");
    127   constexpr Elf64_Xword ShFlags = 0;
    128   ELFRelocationSection *RelSection = createSection<ELFRelocationSection>(
    129       RelSectionName, ShType, ShFlags, ShAlign, ShEntSize);
    130   RelSection->setRelatedSection(RelatedSection);
    131   return RelSection;
    132 }
    133 
    134 template <typename UserSectionList>
    135 void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber,
    136                                                  UserSectionList &UserSections,
    137                                                  RelSectionList &RelSections,
    138                                                  SectionList &AllSections) {
    139   RelSectionList::iterator RelIt = RelSections.begin();
    140   RelSectionList::iterator RelE = RelSections.end();
    141   for (ELFSection *UserSection : UserSections) {
    142     UserSection->setNumber(CurSectionNumber++);
    143     UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName()));
    144     AllSections.push_back(UserSection);
    145     if (RelIt != RelE) {
    146       ELFRelocationSection *RelSection = *RelIt;
    147       if (RelSection->getRelatedSection() == UserSection) {
    148         RelSection->setInfoNum(UserSection->getNumber());
    149         RelSection->setNumber(CurSectionNumber++);
    150         RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName()));
    151         AllSections.push_back(RelSection);
    152         ++RelIt;
    153       }
    154     }
    155   }
    156   // Should finish with UserIt at the same time as RelIt.
    157   assert(RelIt == RelE);
    158   return;
    159 }
    160 
    161 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber,
    162                                        RelSectionList &RelSections) {
    163   for (ELFRelocationSection *S : RelSections) {
    164     S->setLinkNum(SymTabNumber);
    165   }
    166 }
    167 
    168 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) {
    169   // Go through each section, assigning them section numbers and and fill in
    170   // the size for sections that aren't incrementally updated.
    171   assert(!SectionNumbersAssigned);
    172   SizeT CurSectionNumber = 0;
    173   NullSection->setNumber(CurSectionNumber++);
    174   // The rest of the fields are initialized to 0, and stay that way.
    175   AllSections.push_back(NullSection);
    176 
    177   assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections,
    178                                               RelTextSections, AllSections);
    179   assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections,
    180                                               RelDataSections, AllSections);
    181   for (ELFSection *BSSSection : BSSSections) {
    182     BSSSection->setNumber(CurSectionNumber++);
    183     BSSSection->setNameStrIndex(ShStrTab->getIndex(BSSSection->getName()));
    184     AllSections.push_back(BSSSection);
    185   }
    186   assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, RODataSections,
    187                                               RelRODataSections, AllSections);
    188 
    189   ShStrTab->setNumber(CurSectionNumber++);
    190   ShStrTab->setNameStrIndex(ShStrTab->getIndex(ShStrTab->getName()));
    191   AllSections.push_back(ShStrTab);
    192 
    193   SymTab->setNumber(CurSectionNumber++);
    194   SymTab->setNameStrIndex(ShStrTab->getIndex(SymTab->getName()));
    195   AllSections.push_back(SymTab);
    196 
    197   StrTab->setNumber(CurSectionNumber++);
    198   StrTab->setNameStrIndex(ShStrTab->getIndex(StrTab->getName()));
    199   AllSections.push_back(StrTab);
    200 
    201   SymTab->setLinkNum(StrTab->getNumber());
    202   SymTab->setInfoNum(SymTab->getNumLocals());
    203 
    204   assignRelLinkNum(SymTab->getNumber(), RelTextSections);
    205   assignRelLinkNum(SymTab->getNumber(), RelDataSections);
    206   assignRelLinkNum(SymTab->getNumber(), RelRODataSections);
    207   SectionNumbersAssigned = true;
    208 }
    209 
    210 Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) {
    211   Elf64_Off OffsetInFile = Str.tell();
    212   Elf64_Xword AlignDiff = Utils::OffsetToAlignment(OffsetInFile, Align);
    213   if (AlignDiff == 0)
    214     return OffsetInFile;
    215   Str.writeZeroPadding(AlignDiff);
    216   OffsetInFile += AlignDiff;
    217   return OffsetInFile;
    218 }
    219 
    220 void ELFObjectWriter::writeFunctionCode(GlobalString FuncName, bool IsInternal,
    221                                         Assembler *Asm) {
    222   assert(!SectionNumbersAssigned);
    223   TimerMarker T_func(&Ctx, FuncName.toStringOrEmpty());
    224   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    225   ELFTextSection *Section = nullptr;
    226   ELFRelocationSection *RelSection = nullptr;
    227   const bool FunctionSections = getFlags().getFunctionSections();
    228   if (TextSections.empty() || FunctionSections) {
    229     std::string SectionName = ".text";
    230     if (FunctionSections)
    231       SectionName += "." + FuncName;
    232     constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR;
    233     const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes();
    234     Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags,
    235                                             ShAlign, 0);
    236     Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign());
    237     Section->setFileOffset(OffsetInFile);
    238     TextSections.push_back(Section);
    239     RelSection = createRelocationSection(Section);
    240     RelTextSections.push_back(RelSection);
    241   } else {
    242     Section = TextSections[0];
    243     RelSection = RelTextSections[0];
    244   }
    245   const RelocOffsetT OffsetInSection = Section->getCurrentSize();
    246   // Function symbols are set to 0 size in the symbol table, in contrast to
    247   // data symbols which have a proper size.
    248   constexpr SizeT SymbolSize = 0;
    249   uint8_t SymbolType;
    250   uint8_t SymbolBinding;
    251   if (IsInternal && !getFlags().getDisableInternal()) {
    252     SymbolType = STT_NOTYPE;
    253     SymbolBinding = STB_LOCAL;
    254   } else {
    255     SymbolType = STT_FUNC;
    256     SymbolBinding = STB_GLOBAL;
    257   }
    258   SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section,
    259                            OffsetInSection, SymbolSize);
    260   StrTab->add(FuncName);
    261 
    262   // Copy the fixup information from per-function Assembler memory to the
    263   // object writer's memory, for writing later.
    264   const auto &Fixups = Asm->fixups();
    265   if (!Fixups.empty()) {
    266     if (!RelSection->isRela()) {
    267       // This is a non-rela section, so we need to update the instruction stream
    268       // with the relocation addends.
    269       for (const auto *Fixup : Fixups) {
    270         Fixup->emitOffset(Asm);
    271       }
    272     }
    273     RelSection->addRelocations(OffsetInSection, Asm->fixups(), SymTab);
    274   }
    275   Section->appendData(Str, Asm->getBufferView());
    276 }
    277 
    278 namespace {
    279 
    280 ELFObjectWriter::SectionType
    281 classifyGlobalSection(const VariableDeclaration *Var) {
    282   if (Var->getIsConstant())
    283     return ELFObjectWriter::ROData;
    284   if (Var->hasNonzeroInitializer())
    285     return ELFObjectWriter::Data;
    286   return ELFObjectWriter::BSS;
    287 }
    288 
    289 // Partition the Vars list by SectionType into VarsBySection. If TranslateOnly
    290 // is non-empty, then only the TranslateOnly variable is kept for emission.
    291 void partitionGlobalsBySection(const VariableDeclarationList &Vars,
    292                                VariableDeclarationPartition VarsBySection[]) {
    293   for (VariableDeclaration *Var : Vars) {
    294     if (getFlags().matchTranslateOnly(Var->getName(), 0)) {
    295       size_t Section = classifyGlobalSection(Var);
    296       assert(Section < ELFObjectWriter::NumSectionTypes);
    297       VarsBySection[Section].push_back(Var);
    298     }
    299   }
    300 }
    301 
    302 } // end of anonymous namespace
    303 
    304 void ELFObjectWriter::writeTargetRODataSection(const std::string &Name,
    305                                                Elf64_Word ShType,
    306                                                Elf64_Xword ShFlags,
    307                                                Elf64_Xword ShAddralign,
    308                                                Elf64_Xword ShEntsize,
    309                                                const llvm::StringRef &SecData) {
    310   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    311   assert(!SectionNumbersAssigned);
    312   ELFDataSection *Section = createSection<ELFDataSection>(
    313       Name, ShType, ShFlags, ShAddralign, ShEntsize);
    314   Section->setFileOffset(alignFileOffset(ShAddralign));
    315   Section->appendData(Str, llvm::StringRef(SecData.data(), SecData.size()));
    316   RODataSections.push_back(Section);
    317 }
    318 
    319 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
    320                                        FixupKind RelocationKind,
    321                                        const std::string &SectionSuffix,
    322                                        bool IsPIC) {
    323   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    324   assert(!SectionNumbersAssigned);
    325   VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes];
    326   for (auto &SectionList : VarsBySection)
    327     SectionList.reserve(Vars.size());
    328   partitionGlobalsBySection(Vars, VarsBySection);
    329   size_t I = 0;
    330   for (auto &SectionList : VarsBySection) {
    331     writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
    332                     SectionSuffix, IsPIC);
    333   }
    334 }
    335 
    336 namespace {
    337 std::string MangleSectionName(const char Base[], const std::string &Suffix) {
    338   if (Suffix.empty())
    339     return Base;
    340   return Base + ("." + Suffix);
    341 }
    342 } // end of anonymous namespace
    343 
    344 // TODO(jvoung): Handle fdata-sections.
    345 void ELFObjectWriter::writeDataOfType(SectionType ST,
    346                                       const VariableDeclarationPartition &Vars,
    347                                       FixupKind RelocationKind,
    348                                       const std::string &SectionSuffix,
    349                                       bool IsPIC) {
    350   if (Vars.empty())
    351     return;
    352   ELFDataSection *Section;
    353   ELFRelocationSection *RelSection;
    354   Elf64_Xword ShAddralign = 1;
    355   for (VariableDeclaration *Var : Vars) {
    356     Elf64_Xword Align = Var->getAlignment();
    357     ShAddralign = std::max(ShAddralign, Align);
    358   }
    359   constexpr Elf64_Xword ShEntsize = 0; // non-uniform data element size.
    360   // Lift this out, so it can be re-used if we do fdata-sections?
    361   switch (ST) {
    362   case ROData: {
    363     const std::string SectionName =
    364         MangleSectionName(IsPIC ? ".data.rel.ro" : ".rodata", SectionSuffix);
    365     const Elf64_Xword ShFlags = IsPIC ? (SHF_ALLOC | SHF_WRITE) : SHF_ALLOC;
    366     Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
    367                                             ShAddralign, ShEntsize);
    368     Section->setFileOffset(alignFileOffset(ShAddralign));
    369     RODataSections.push_back(Section);
    370     RelSection = createRelocationSection(Section);
    371     RelRODataSections.push_back(RelSection);
    372     break;
    373   }
    374   case Data: {
    375     const std::string SectionName = MangleSectionName(".data", SectionSuffix);
    376     constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
    377     Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
    378                                             ShAddralign, ShEntsize);
    379     Section->setFileOffset(alignFileOffset(ShAddralign));
    380     DataSections.push_back(Section);
    381     RelSection = createRelocationSection(Section);
    382     RelDataSections.push_back(RelSection);
    383     break;
    384   }
    385   case BSS: {
    386     const std::string SectionName = MangleSectionName(".bss", SectionSuffix);
    387     constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
    388     Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags,
    389                                             ShAddralign, ShEntsize);
    390     Section->setFileOffset(alignFileOffset(ShAddralign));
    391     BSSSections.push_back(Section);
    392     break;
    393   }
    394   case NumSectionTypes:
    395     llvm::report_fatal_error("Unknown SectionType");
    396     break;
    397   }
    398 
    399   constexpr uint8_t SymbolType = STT_OBJECT;
    400   for (VariableDeclaration *Var : Vars) {
    401     // If the variable declaration does not have an initializer, its symtab
    402     // entry will be created separately.
    403     if (!Var->hasInitializer())
    404       continue;
    405     constexpr Elf64_Xword MinAlign = 1;
    406     const auto Align = std::max<Elf64_Xword>(MinAlign, Var->getAlignment());
    407     Section->padToAlignment(Str, Align);
    408     SizeT SymbolSize = Var->getNumBytes();
    409     bool IsExternal = Var->isExternal() || getFlags().getDisableInternal();
    410     const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
    411     GlobalString Name = Var->getName();
    412     SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section,
    413                              Section->getCurrentSize(), SymbolSize);
    414     StrTab->add(Name);
    415     if (!Var->hasNonzeroInitializer()) {
    416       assert(ST == BSS || ST == ROData);
    417       if (ST == ROData)
    418         Section->appendZeros(Str, SymbolSize);
    419       else
    420         Section->setSize(Section->getCurrentSize() + SymbolSize);
    421     } else {
    422       assert(ST != BSS);
    423       for (const auto *Init : Var->getInitializers()) {
    424         switch (Init->getKind()) {
    425         case VariableDeclaration::Initializer::DataInitializerKind: {
    426           const auto &Data =
    427               llvm::cast<VariableDeclaration::DataInitializer>(Init)
    428                   ->getContents();
    429           Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
    430           break;
    431         }
    432         case VariableDeclaration::Initializer::ZeroInitializerKind:
    433           Section->appendZeros(Str, Init->getNumBytes());
    434           break;
    435         case VariableDeclaration::Initializer::RelocInitializerKind: {
    436           const auto *Reloc =
    437               llvm::cast<VariableDeclaration::RelocInitializer>(Init);
    438           AssemblerFixup NewFixup;
    439           NewFixup.set_position(Section->getCurrentSize());
    440           NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup()
    441                                               : RelocationKind);
    442           assert(NewFixup.kind() != llvm::ELF::R_ARM_NONE);
    443           NewFixup.set_value(Ctx.getConstantSym(
    444               Reloc->getOffset(), Reloc->getDeclaration()->getName()));
    445           RelSection->addRelocation(NewFixup);
    446           Section->appendRelocationOffset(Str, RelSection->isRela(),
    447                                           Reloc->getOffset());
    448           break;
    449         }
    450         }
    451       }
    452     }
    453   }
    454 }
    455 
    456 void ELFObjectWriter::writeInitialELFHeader() {
    457   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    458   assert(!SectionNumbersAssigned);
    459   constexpr Elf64_Off DummySHOffset = 0;
    460   constexpr SizeT DummySHStrIndex = 0;
    461   constexpr SizeT DummyNumSections = 0;
    462   if (ELF64) {
    463     writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex,
    464                                  DummyNumSections);
    465   } else {
    466     writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex,
    467                                   DummyNumSections);
    468   }
    469 }
    470 
    471 template <bool IsELF64>
    472 void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
    473                                              SizeT SectHeaderStrIndex,
    474                                              SizeT NumSections) {
    475   // Write the e_ident: magic number, class, etc. The e_ident is byte order and
    476   // ELF class independent.
    477   Str.writeBytes(llvm::StringRef(ElfMagic, strlen(ElfMagic)));
    478   Str.write8(IsELF64 ? ELFCLASS64 : ELFCLASS32);
    479   Str.write8(ELFDATA2LSB);
    480   Str.write8(EV_CURRENT);
    481   Str.write8(ELFOSABI_NONE);
    482   constexpr uint8_t ELF_ABIVersion = 0;
    483   Str.write8(ELF_ABIVersion);
    484   Str.writeZeroPadding(EI_NIDENT - EI_PAD);
    485 
    486   // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc:
    487   // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html e_shnum should
    488   // be 0 and then actual number of sections is stored in the sh_size member of
    489   // the 0th section.
    490   assert(NumSections < SHN_LORESERVE);
    491   assert(SectHeaderStrIndex < SHN_LORESERVE);
    492 
    493   const TargetArch Arch = getFlags().getTargetArch();
    494   // Write the rest of the file header, which does depend on byte order and ELF
    495   // class.
    496   Str.writeLE16(ET_REL);                                    // e_type
    497   Str.writeLE16(getELFMachine(getFlags().getTargetArch())); // e_machine
    498   Str.writeELFWord<IsELF64>(1);                             // e_version
    499   // Since this is for a relocatable object, there is no entry point, and no
    500   // program headers.
    501   Str.writeAddrOrOffset<IsELF64>(0);                                // e_entry
    502   Str.writeAddrOrOffset<IsELF64>(0);                                // e_phoff
    503   Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset);              // e_shoff
    504   Str.writeELFWord<IsELF64>(getELFFlags(Arch));                     // e_flags
    505   Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize
    506   static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52,
    507                 "Elf_Ehdr sizes cannot be derived from sizeof");
    508   Str.writeLE16(0); // e_phentsize
    509   Str.writeLE16(0); // e_phnum
    510   Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr)
    511                         : sizeof(Elf32_Shdr)); // e_shentsize
    512   static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40,
    513                 "Elf_Shdr sizes cannot be derived from sizeof");
    514   Str.writeLE16(static_cast<Elf64_Half>(NumSections));        // e_shnum
    515   Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx
    516 }
    517 
    518 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
    519   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    520   ConstantList Pool = Ctx.getConstantPool(Ty);
    521   if (Pool.empty()) {
    522     return;
    523   }
    524   SizeT Align = typeAlignInBytes(Ty);
    525   size_t EntSize = typeWidthInBytes(Ty);
    526   char Buf[20];
    527   SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf));
    528   // Check that we write the full PrimType.
    529   assert(WriteAmt == EntSize);
    530   // Assume that writing WriteAmt bytes at a time allows us to avoid aligning
    531   // between entries.
    532   assert(WriteAmt % Align == 0);
    533   constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE;
    534   std::string SecBuffer;
    535   llvm::raw_string_ostream SecStrBuf(SecBuffer);
    536   SecStrBuf << ".rodata.cst" << WriteAmt;
    537   ELFDataSection *Section = createSection<ELFDataSection>(
    538       SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt);
    539   RODataSections.push_back(Section);
    540   SizeT OffsetInSection = 0;
    541   // The symbol table entry doesn't need to know the defined symbol's size
    542   // since this is in a section with a fixed Entry Size.
    543   constexpr SizeT SymbolSize = 0;
    544   Section->setFileOffset(alignFileOffset(Align));
    545 
    546   // If the -reorder-pooled-constant option is set to true, we should shuffle
    547   // the constants before we emit them.
    548   if (getFlags().getReorderPooledConstants() && !Pool.empty()) {
    549     // Use the constant's kind value as the salt for creating random number
    550     // generator.
    551     Operand::OperandKind K = (*Pool.begin())->getKind();
    552     RandomNumberGenerator RNG(getFlags().getRandomSeed(),
    553                               RPE_PooledConstantReordering, K);
    554     RandomShuffle(Pool.begin(), Pool.end(),
    555                   [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
    556   }
    557   // Write the data.
    558   for (Constant *C : Pool) {
    559     if (!C->getShouldBePooled())
    560       continue;
    561     auto *Const = llvm::cast<ConstType>(C);
    562     GlobalString SymName = Const->getLabelName();
    563     SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section,
    564                              OffsetInSection, SymbolSize);
    565     StrTab->add(SymName);
    566     typename ConstType::PrimType Value = Const->getValue();
    567     memcpy(Buf, &Value, WriteAmt);
    568     Str.writeBytes(llvm::StringRef(Buf, WriteAmt));
    569     OffsetInSection += WriteAmt;
    570   }
    571   Section->setSize(OffsetInSection);
    572 }
    573 
    574 // Instantiate known needed versions of the template, since we are defining the
    575 // function in the .cpp file instead of the .h file. We may need to instantiate
    576 // constant pools for integers as well if we do constant-pooling of large
    577 // integers to remove them from the instruction stream (fewer bytes controlled
    578 // by an attacker).
    579 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty);
    580 
    581 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
    582 
    583 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty);
    584 
    585 void ELFObjectWriter::writeAllRelocationSections() {
    586   writeRelocationSections(RelTextSections);
    587   writeRelocationSections(RelDataSections);
    588   writeRelocationSections(RelRODataSections);
    589 }
    590 
    591 void ELFObjectWriter::writeJumpTable(const JumpTableData &JT,
    592                                      FixupKind RelocationKind, bool IsPIC) {
    593   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    594   ELFDataSection *Section;
    595   ELFRelocationSection *RelSection;
    596   const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType());
    597   const Elf64_Xword ShAddralign = PointerSize;
    598   const Elf64_Xword ShEntsize = PointerSize;
    599   const std::string SectionName = MangleSectionName(
    600       IsPIC ? ".data.rel.ro" : ".rodata", JT.getSectionName());
    601   Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC,
    602                                           ShAddralign, ShEntsize);
    603   Section->setFileOffset(alignFileOffset(ShAddralign));
    604   RODataSections.push_back(Section);
    605   RelSection = createRelocationSection(Section);
    606   RelRODataSections.push_back(RelSection);
    607 
    608   constexpr uint8_t SymbolType = STT_OBJECT;
    609   Section->padToAlignment(Str, PointerSize);
    610   const bool IsExternal = getFlags().getDisableInternal();
    611   const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL;
    612   const auto JumpTableName = JT.getName();
    613   SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section,
    614                            Section->getCurrentSize(), PointerSize);
    615   StrTab->add(JumpTableName);
    616 
    617   for (intptr_t TargetOffset : JT.getTargetOffsets()) {
    618     AssemblerFixup NewFixup;
    619     NewFixup.set_position(Section->getCurrentSize());
    620     NewFixup.set_kind(RelocationKind);
    621     NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName()));
    622     RelSection->addRelocation(NewFixup);
    623     Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset);
    624   }
    625 }
    626 
    627 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
    628   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    629   for (const Constant *S : UndefSyms) {
    630     const auto *Sym = llvm::cast<ConstantRelocatable>(S);
    631     GlobalString Name = Sym->getName();
    632     assert(Name.hasStdString());
    633     bool BadIntrinsic;
    634     const Intrinsics::FullIntrinsicInfo *Info =
    635         Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic);
    636     if (Info)
    637       continue;
    638     // Ignore BadIntrinsic, which is set if the name begins with "llvm." but
    639     // doesn't match a known intrinsic.  If we want this to turn into an error,
    640     // we should catch it early on.
    641     assert(Sym->getOffset() == 0);
    642     SymTab->noteUndefinedSym(Name, NullSection);
    643     StrTab->add(Name);
    644   }
    645 }
    646 
    647 void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) {
    648   for (ELFRelocationSection *RelSec : RelSections) {
    649     Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
    650     RelSec->setFileOffset(Offset);
    651     RelSec->setSize(RelSec->getSectionDataSize());
    652     if (ELF64) {
    653       RelSec->writeData<true>(Str, SymTab);
    654     } else {
    655       RelSec->writeData<false>(Str, SymTab);
    656     }
    657   }
    658 }
    659 
    660 void ELFObjectWriter::writeNonUserSections() {
    661   TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
    662 
    663   // Write out the shstrtab now that all sections are known.
    664   ShStrTab->doLayout();
    665   ShStrTab->setSize(ShStrTab->getSectionDataSize());
    666   Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign());
    667   ShStrTab->setFileOffset(ShStrTabOffset);
    668   Str.writeBytes(ShStrTab->getSectionData());
    669 
    670   SectionList AllSections;
    671   assignSectionNumbersInfo(AllSections);
    672 
    673   // Finalize the regular StrTab and fix up references in the SymTab.
    674   StrTab->doLayout();
    675   StrTab->setSize(StrTab->getSectionDataSize());
    676 
    677   SymTab->updateIndices(StrTab);
    678 
    679   Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign());
    680   SymTab->setFileOffset(SymTabOffset);
    681   SymTab->setSize(SymTab->getSectionDataSize());
    682   SymTab->writeData(Str, ELF64);
    683 
    684   Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign());
    685   StrTab->setFileOffset(StrTabOffset);
    686   Str.writeBytes(StrTab->getSectionData());
    687 
    688   writeAllRelocationSections();
    689 
    690   // Write out the section headers.
    691   const size_t ShdrAlign = ELF64 ? 8 : 4;
    692   Elf64_Off ShOffset = alignFileOffset(ShdrAlign);
    693   for (const auto S : AllSections) {
    694     if (ELF64)
    695       S->writeHeader<true>(Str);
    696     else
    697       S->writeHeader<false>(Str);
    698   }
    699 
    700   // Finally write the updated ELF header w/ the correct number of sections.
    701   Str.seek(0);
    702   if (ELF64) {
    703     writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(),
    704                                  AllSections.size());
    705   } else {
    706     writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(),
    707                                   AllSections.size());
    708   }
    709 }
    710 
    711 } // end of namespace Ice
    712