| OLD | NEW |
| 1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===// | 1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 Elf64_Xword ShEntsize) { | 98 Elf64_Xword ShEntsize) { |
| 99 assert(!SectionNumbersAssigned); | 99 assert(!SectionNumbersAssigned); |
| 100 T *NewSection = | 100 T *NewSection = |
| 101 new (Ctx.allocate<T>()) T(Name, ShType, ShFlags, ShAddralign, ShEntsize); | 101 new (Ctx.allocate<T>()) T(Name, ShType, ShFlags, ShAddralign, ShEntsize); |
| 102 ShStrTab->add(Name); | 102 ShStrTab->add(Name); |
| 103 return NewSection; | 103 return NewSection; |
| 104 } | 104 } |
| 105 | 105 |
| 106 ELFRelocationSection * | 106 ELFRelocationSection * |
| 107 ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) { | 107 ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) { |
| 108 // Choice of RELA vs REL is actually separate from elf64 vs elf32, | 108 // Choice of RELA vs REL is actually separate from elf64 vs elf32, but in |
| 109 // but in practice we've only had .rela for elf64 (x86-64). | 109 // practice we've only had .rela for elf64 (x86-64). In the future, the two |
| 110 // In the future, the two properties may need to be decoupled | 110 // properties may need to be decoupled and the ShEntSize can vary more. |
| 111 // and the ShEntSize can vary more. | |
| 112 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL; | 111 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL; |
| 113 IceString RelPrefix = ELF64 ? ".rela" : ".rel"; | 112 IceString RelPrefix = ELF64 ? ".rela" : ".rel"; |
| 114 IceString RelSectionName = RelPrefix + RelatedSection->getName(); | 113 IceString RelSectionName = RelPrefix + RelatedSection->getName(); |
| 115 const Elf64_Xword ShAlign = ELF64 ? 8 : 4; | 114 const Elf64_Xword ShAlign = ELF64 ? 8 : 4; |
| 116 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel); | 115 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel); |
| 117 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8, | 116 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8, |
| 118 "Elf_Rel/Rela sizes cannot be derived from sizeof"); | 117 "Elf_Rel/Rela sizes cannot be derived from sizeof"); |
| 119 const Elf64_Xword ShFlags = 0; | 118 const Elf64_Xword ShFlags = 0; |
| 120 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>( | 119 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>( |
| 121 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize); | 120 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 151 } | 150 } |
| 152 | 151 |
| 153 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber, | 152 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber, |
| 154 RelSectionList &RelSections) { | 153 RelSectionList &RelSections) { |
| 155 for (ELFRelocationSection *S : RelSections) { | 154 for (ELFRelocationSection *S : RelSections) { |
| 156 S->setLinkNum(SymTabNumber); | 155 S->setLinkNum(SymTabNumber); |
| 157 } | 156 } |
| 158 } | 157 } |
| 159 | 158 |
| 160 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) { | 159 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) { |
| 161 // Go through each section, assigning them section numbers and | 160 // Go through each section, assigning them section numbers and and fill in |
| 162 // and fill in the size for sections that aren't incrementally updated. | 161 // the size for sections that aren't incrementally updated. |
| 163 assert(!SectionNumbersAssigned); | 162 assert(!SectionNumbersAssigned); |
| 164 SizeT CurSectionNumber = 0; | 163 SizeT CurSectionNumber = 0; |
| 165 NullSection->setNumber(CurSectionNumber++); | 164 NullSection->setNumber(CurSectionNumber++); |
| 166 // The rest of the fields are initialized to 0, and stay that way. | 165 // The rest of the fields are initialized to 0, and stay that way. |
| 167 AllSections.push_back(NullSection); | 166 AllSections.push_back(NullSection); |
| 168 | 167 |
| 169 assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections, | 168 assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections, |
| 170 RelTextSections, AllSections); | 169 RelTextSections, AllSections); |
| 171 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections, | 170 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections, |
| 172 RelDataSections, AllSections); | 171 RelDataSections, AllSections); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign()); | 225 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign()); |
| 227 Section->setFileOffset(OffsetInFile); | 226 Section->setFileOffset(OffsetInFile); |
| 228 TextSections.push_back(Section); | 227 TextSections.push_back(Section); |
| 229 RelSection = createRelocationSection(Section); | 228 RelSection = createRelocationSection(Section); |
| 230 RelTextSections.push_back(RelSection); | 229 RelTextSections.push_back(RelSection); |
| 231 } else { | 230 } else { |
| 232 Section = TextSections[0]; | 231 Section = TextSections[0]; |
| 233 RelSection = RelTextSections[0]; | 232 RelSection = RelTextSections[0]; |
| 234 } | 233 } |
| 235 RelocOffsetT OffsetInSection = Section->getCurrentSize(); | 234 RelocOffsetT OffsetInSection = Section->getCurrentSize(); |
| 236 // Function symbols are set to 0 size in the symbol table, | 235 // Function symbols are set to 0 size in the symbol table, in contrast to |
| 237 // in contrast to data symbols which have a proper size. | 236 // data symbols which have a proper size. |
| 238 SizeT SymbolSize = 0; | 237 SizeT SymbolSize = 0; |
| 239 Section->appendData(Str, Asm->getBufferView()); | 238 Section->appendData(Str, Asm->getBufferView()); |
| 240 uint8_t SymbolType; | 239 uint8_t SymbolType; |
| 241 uint8_t SymbolBinding; | 240 uint8_t SymbolBinding; |
| 242 if (IsInternal && !Ctx.getFlags().getDisableInternal()) { | 241 if (IsInternal && !Ctx.getFlags().getDisableInternal()) { |
| 243 SymbolType = STT_NOTYPE; | 242 SymbolType = STT_NOTYPE; |
| 244 SymbolBinding = STB_LOCAL; | 243 SymbolBinding = STB_LOCAL; |
| 245 } else { | 244 } else { |
| 246 SymbolType = STT_FUNC; | 245 SymbolType = STT_FUNC; |
| 247 SymbolBinding = STB_GLOBAL; | 246 SymbolBinding = STB_GLOBAL; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 261 | 260 |
| 262 ELFObjectWriter::SectionType | 261 ELFObjectWriter::SectionType |
| 263 classifyGlobalSection(const VariableDeclaration *Var) { | 262 classifyGlobalSection(const VariableDeclaration *Var) { |
| 264 if (Var->getIsConstant()) | 263 if (Var->getIsConstant()) |
| 265 return ELFObjectWriter::ROData; | 264 return ELFObjectWriter::ROData; |
| 266 if (Var->hasNonzeroInitializer()) | 265 if (Var->hasNonzeroInitializer()) |
| 267 return ELFObjectWriter::Data; | 266 return ELFObjectWriter::Data; |
| 268 return ELFObjectWriter::BSS; | 267 return ELFObjectWriter::BSS; |
| 269 } | 268 } |
| 270 | 269 |
| 271 // Partition the Vars list by SectionType into VarsBySection. | 270 // Partition the Vars list by SectionType into VarsBySection. If TranslateOnly |
| 272 // If TranslateOnly is non-empty, then only the TranslateOnly variable | 271 // is non-empty, then only the TranslateOnly variable is kept for emission. |
| 273 // is kept for emission. | |
| 274 void partitionGlobalsBySection(const VariableDeclarationList &Vars, | 272 void partitionGlobalsBySection(const VariableDeclarationList &Vars, |
| 275 VariableDeclarationList VarsBySection[], | 273 VariableDeclarationList VarsBySection[], |
| 276 const IceString &TranslateOnly) { | 274 const IceString &TranslateOnly) { |
| 277 for (VariableDeclaration *Var : Vars) { | 275 for (VariableDeclaration *Var : Vars) { |
| 278 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 276 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
| 279 size_t Section = classifyGlobalSection(Var); | 277 size_t Section = classifyGlobalSection(Var); |
| 280 assert(Section < ELFObjectWriter::NumSectionTypes); | 278 assert(Section < ELFObjectWriter::NumSectionTypes); |
| 281 VarsBySection[Section].push_back(Var); | 279 VarsBySection[Section].push_back(Var); |
| 282 } | 280 } |
| 283 } | 281 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 } else { | 431 } else { |
| 434 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex, | 432 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex, |
| 435 DummyNumSections); | 433 DummyNumSections); |
| 436 } | 434 } |
| 437 } | 435 } |
| 438 | 436 |
| 439 template <bool IsELF64> | 437 template <bool IsELF64> |
| 440 void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, | 438 void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, |
| 441 SizeT SectHeaderStrIndex, | 439 SizeT SectHeaderStrIndex, |
| 442 SizeT NumSections) { | 440 SizeT NumSections) { |
| 443 // Write the e_ident: magic number, class, etc. | 441 // Write the e_ident: magic number, class, etc. The e_ident is byte order and |
| 444 // The e_ident is byte order and ELF class independent. | 442 // ELF class independent. |
| 445 Str.writeBytes(llvm::StringRef(ElfMagic, strlen(ElfMagic))); | 443 Str.writeBytes(llvm::StringRef(ElfMagic, strlen(ElfMagic))); |
| 446 Str.write8(IsELF64 ? ELFCLASS64 : ELFCLASS32); | 444 Str.write8(IsELF64 ? ELFCLASS64 : ELFCLASS32); |
| 447 Str.write8(ELFDATA2LSB); | 445 Str.write8(ELFDATA2LSB); |
| 448 Str.write8(EV_CURRENT); | 446 Str.write8(EV_CURRENT); |
| 449 Str.write8(ELFOSABI_NONE); | 447 Str.write8(ELFOSABI_NONE); |
| 450 const uint8_t ELF_ABIVersion = 0; | 448 const uint8_t ELF_ABIVersion = 0; |
| 451 Str.write8(ELF_ABIVersion); | 449 Str.write8(ELF_ABIVersion); |
| 452 Str.writeZeroPadding(EI_NIDENT - EI_PAD); | 450 Str.writeZeroPadding(EI_NIDENT - EI_PAD); |
| 453 | 451 |
| 454 // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc: | 452 // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc: |
| 455 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html | 453 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html e_shnum should |
| 456 // e_shnum should be 0 and then actual number of sections is | 454 // be 0 and then actual number of sections is stored in the sh_size member of |
| 457 // stored in the sh_size member of the 0th section. | 455 // the 0th section. |
| 458 assert(NumSections < SHN_LORESERVE); | 456 assert(NumSections < SHN_LORESERVE); |
| 459 assert(SectHeaderStrIndex < SHN_LORESERVE); | 457 assert(SectHeaderStrIndex < SHN_LORESERVE); |
| 460 | 458 |
| 461 const TargetArch Arch = Ctx.getFlags().getTargetArch(); | 459 const TargetArch Arch = Ctx.getFlags().getTargetArch(); |
| 462 // Write the rest of the file header, which does depend on byte order | 460 // Write the rest of the file header, which does depend on byte order and ELF |
| 463 // and ELF class. | 461 // class. |
| 464 Str.writeLE16(ET_REL); // e_type | 462 Str.writeLE16(ET_REL); // e_type |
| 465 Str.writeLE16(getELFMachine(Ctx.getFlags().getTargetArch())); // e_machine | 463 Str.writeLE16(getELFMachine(Ctx.getFlags().getTargetArch())); // e_machine |
| 466 Str.writeELFWord<IsELF64>(1); // e_version | 464 Str.writeELFWord<IsELF64>(1); // e_version |
| 467 // Since this is for a relocatable object, there is no entry point, | 465 // Since this is for a relocatable object, there is no entry point, and no |
| 468 // and no program headers. | 466 // program headers. |
| 469 Str.writeAddrOrOffset<IsELF64>(0); // e_entry | 467 Str.writeAddrOrOffset<IsELF64>(0); // e_entry |
| 470 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff | 468 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff |
| 471 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff | 469 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff |
| 472 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags | 470 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags |
| 473 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize | 471 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize |
| 474 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52, | 472 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52, |
| 475 "Elf_Ehdr sizes cannot be derived from sizeof"); | 473 "Elf_Ehdr sizes cannot be derived from sizeof"); |
| 476 Str.writeLE16(0); // e_phentsize | 474 Str.writeLE16(0); // e_phentsize |
| 477 Str.writeLE16(0); // e_phnum | 475 Str.writeLE16(0); // e_phnum |
| 478 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr) | 476 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 498 // between entries. | 496 // between entries. |
| 499 assert(WriteAmt % Align == 0); | 497 assert(WriteAmt % Align == 0); |
| 500 const Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE; | 498 const Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE; |
| 501 std::string SecBuffer; | 499 std::string SecBuffer; |
| 502 llvm::raw_string_ostream SecStrBuf(SecBuffer); | 500 llvm::raw_string_ostream SecStrBuf(SecBuffer); |
| 503 SecStrBuf << ".rodata.cst" << WriteAmt; | 501 SecStrBuf << ".rodata.cst" << WriteAmt; |
| 504 ELFDataSection *Section = createSection<ELFDataSection>( | 502 ELFDataSection *Section = createSection<ELFDataSection>( |
| 505 SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt); | 503 SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt); |
| 506 RODataSections.push_back(Section); | 504 RODataSections.push_back(Section); |
| 507 SizeT OffsetInSection = 0; | 505 SizeT OffsetInSection = 0; |
| 508 // The symbol table entry doesn't need to know the defined symbol's | 506 // The symbol table entry doesn't need to know the defined symbol's size |
| 509 // size since this is in a section with a fixed Entry Size. | 507 // since this is in a section with a fixed Entry Size. |
| 510 const SizeT SymbolSize = 0; | 508 const SizeT SymbolSize = 0; |
| 511 Section->setFileOffset(alignFileOffset(Align)); | 509 Section->setFileOffset(alignFileOffset(Align)); |
| 512 | 510 |
| 513 // If the -reorder-pooled-constant option is set to true, we should shuffle | 511 // If the -reorder-pooled-constant option is set to true, we should shuffle |
| 514 // the constants before we emit them. | 512 // the constants before we emit them. |
| 515 if (Ctx.getFlags().shouldReorderPooledConstants() && !Pool.empty()) { | 513 if (Ctx.getFlags().shouldReorderPooledConstants() && !Pool.empty()) { |
| 516 // Use the constant's kind value as the salt for creating random number | 514 // Use the constant's kind value as the salt for creating random number |
| 517 // generator. | 515 // generator. |
| 518 Operand::OperandKind K = (*Pool.begin())->getKind(); | 516 Operand::OperandKind K = (*Pool.begin())->getKind(); |
| 519 RandomNumberGenerator RNG(Ctx.getFlags().getRandomSeed(), | 517 RandomNumberGenerator RNG(Ctx.getFlags().getRandomSeed(), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 534 OffsetInSection, SymbolSize); | 532 OffsetInSection, SymbolSize); |
| 535 StrTab->add(SymName); | 533 StrTab->add(SymName); |
| 536 typename ConstType::PrimType Value = Const->getValue(); | 534 typename ConstType::PrimType Value = Const->getValue(); |
| 537 memcpy(Buf, &Value, WriteAmt); | 535 memcpy(Buf, &Value, WriteAmt); |
| 538 Str.writeBytes(llvm::StringRef(Buf, WriteAmt)); | 536 Str.writeBytes(llvm::StringRef(Buf, WriteAmt)); |
| 539 OffsetInSection += WriteAmt; | 537 OffsetInSection += WriteAmt; |
| 540 } | 538 } |
| 541 Section->setSize(OffsetInSection); | 539 Section->setSize(OffsetInSection); |
| 542 } | 540 } |
| 543 | 541 |
| 544 // Instantiate known needed versions of the template, since we are | 542 // Instantiate known needed versions of the template, since we are defining the |
| 545 // defining the function in the .cpp file instead of the .h file. | 543 // function in the .cpp file instead of the .h file. We may need to instantiate |
| 546 // We may need to instantiate constant pools for integers as well | 544 // constant pools for integers as well if we do constant-pooling of large |
| 547 // if we do constant-pooling of large integers to remove them | 545 // integers to remove them from the instruction stream (fewer bytes controlled |
| 548 // from the instruction stream (fewer bytes controlled by an attacker). | 546 // by an attacker). |
| 549 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty); | 547 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty); |
| 550 | 548 |
| 551 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty); | 549 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty); |
| 552 | 550 |
| 553 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty); | 551 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty); |
| 554 | 552 |
| 555 void ELFObjectWriter::writeAllRelocationSections() { | 553 void ELFObjectWriter::writeAllRelocationSections() { |
| 556 writeRelocationSections(RelTextSections); | 554 writeRelocationSections(RelTextSections); |
| 557 writeRelocationSections(RelDataSections); | 555 writeRelocationSections(RelDataSections); |
| 558 writeRelocationSections(RelRODataSections); | 556 writeRelocationSections(RelRODataSections); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 if (ELF64) { | 669 if (ELF64) { |
| 672 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), | 670 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), |
| 673 AllSections.size()); | 671 AllSections.size()); |
| 674 } else { | 672 } else { |
| 675 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), | 673 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), |
| 676 AllSections.size()); | 674 AllSections.size()); |
| 677 } | 675 } |
| 678 } | 676 } |
| 679 | 677 |
| 680 } // end of namespace Ice | 678 } // end of namespace Ice |
| OLD | NEW |