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