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 |