| 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 if (AlignDiff == 0) | 212 if (AlignDiff == 0) |
| 213 return OffsetInFile; | 213 return OffsetInFile; |
| 214 Str.writeZeroPadding(AlignDiff); | 214 Str.writeZeroPadding(AlignDiff); |
| 215 OffsetInFile += AlignDiff; | 215 OffsetInFile += AlignDiff; |
| 216 return OffsetInFile; | 216 return OffsetInFile; |
| 217 } | 217 } |
| 218 | 218 |
| 219 void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, | 219 void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, |
| 220 bool IsInternal, Assembler *Asm) { | 220 bool IsInternal, Assembler *Asm) { |
| 221 assert(!SectionNumbersAssigned); | 221 assert(!SectionNumbersAssigned); |
| 222 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
| 223 constexpr TimerStackIdT StackID = GlobalContext::TSK_Funcs; |
| 224 TimerIdT TimerID = 0; |
| 225 bool TimeThisFunction = Ctx.getFlags().getTimeEachFunction(); |
| 226 if (TimeThisFunction) { |
| 227 TimerID = Ctx.getTimerID(StackID, FuncName); |
| 228 Ctx.pushTimer(TimerID, StackID); |
| 229 } |
| 222 ELFTextSection *Section = nullptr; | 230 ELFTextSection *Section = nullptr; |
| 223 ELFRelocationSection *RelSection = nullptr; | 231 ELFRelocationSection *RelSection = nullptr; |
| 224 const bool FunctionSections = Ctx.getFlags().getFunctionSections(); | 232 const bool FunctionSections = Ctx.getFlags().getFunctionSections(); |
| 225 if (TextSections.empty() || FunctionSections) { | 233 if (TextSections.empty() || FunctionSections) { |
| 226 IceString SectionName = ".text"; | 234 IceString SectionName = ".text"; |
| 227 if (FunctionSections) | 235 if (FunctionSections) |
| 228 SectionName += "." + FuncName; | 236 SectionName += "." + FuncName; |
| 229 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; | 237 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; |
| 230 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes(); | 238 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes(); |
| 231 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags, | 239 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 if (!RelSection->isRela()) { | 271 if (!RelSection->isRela()) { |
| 264 // This is a non-rela section, so we need to update the instruction stream | 272 // This is a non-rela section, so we need to update the instruction stream |
| 265 // with the relocation addends. | 273 // with the relocation addends. |
| 266 for (const auto *Fixup : Fixups) { | 274 for (const auto *Fixup : Fixups) { |
| 267 Fixup->emitOffset(Asm); | 275 Fixup->emitOffset(Asm); |
| 268 } | 276 } |
| 269 } | 277 } |
| 270 RelSection->addRelocations(OffsetInSection, Asm->fixups()); | 278 RelSection->addRelocations(OffsetInSection, Asm->fixups()); |
| 271 } | 279 } |
| 272 Section->appendData(Str, Asm->getBufferView()); | 280 Section->appendData(Str, Asm->getBufferView()); |
| 281 if (TimeThisFunction) |
| 282 Ctx.popTimer(TimerID, StackID); |
| 273 } | 283 } |
| 274 | 284 |
| 275 namespace { | 285 namespace { |
| 276 | 286 |
| 277 ELFObjectWriter::SectionType | 287 ELFObjectWriter::SectionType |
| 278 classifyGlobalSection(const VariableDeclaration *Var) { | 288 classifyGlobalSection(const VariableDeclaration *Var) { |
| 279 if (Var->getIsConstant()) | 289 if (Var->getIsConstant()) |
| 280 return ELFObjectWriter::ROData; | 290 return ELFObjectWriter::ROData; |
| 281 if (Var->hasNonzeroInitializer()) | 291 if (Var->hasNonzeroInitializer()) |
| 282 return ELFObjectWriter::Data; | 292 return ELFObjectWriter::Data; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 296 } | 306 } |
| 297 } | 307 } |
| 298 } | 308 } |
| 299 | 309 |
| 300 } // end of anonymous namespace | 310 } // end of anonymous namespace |
| 301 | 311 |
| 302 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars, | 312 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars, |
| 303 FixupKind RelocationKind, | 313 FixupKind RelocationKind, |
| 304 const IceString &SectionSuffix, | 314 const IceString &SectionSuffix, |
| 305 bool IsPIC) { | 315 bool IsPIC) { |
| 316 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
| 306 assert(!SectionNumbersAssigned); | 317 assert(!SectionNumbersAssigned); |
| 307 VariableDeclarationList VarsBySection[ELFObjectWriter::NumSectionTypes]; | 318 VariableDeclarationList VarsBySection[ELFObjectWriter::NumSectionTypes]; |
| 308 for (auto &SectionList : VarsBySection) | 319 for (auto &SectionList : VarsBySection) |
| 309 SectionList.reserve(Vars.size()); | 320 SectionList.reserve(Vars.size()); |
| 310 partitionGlobalsBySection(Vars, VarsBySection, | 321 partitionGlobalsBySection(Vars, VarsBySection, |
| 311 Ctx.getFlags().getTranslateOnly()); | 322 Ctx.getFlags().getTranslateOnly()); |
| 312 size_t I = 0; | 323 size_t I = 0; |
| 313 for (auto &SectionList : VarsBySection) { | 324 for (auto &SectionList : VarsBySection) { |
| 314 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind, | 325 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind, |
| 315 SectionSuffix, IsPIC); | 326 SectionSuffix, IsPIC); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 Reloc->getOffset()); | 443 Reloc->getOffset()); |
| 433 break; | 444 break; |
| 434 } | 445 } |
| 435 } | 446 } |
| 436 } | 447 } |
| 437 } | 448 } |
| 438 } | 449 } |
| 439 } | 450 } |
| 440 | 451 |
| 441 void ELFObjectWriter::writeInitialELFHeader() { | 452 void ELFObjectWriter::writeInitialELFHeader() { |
| 453 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
| 442 assert(!SectionNumbersAssigned); | 454 assert(!SectionNumbersAssigned); |
| 443 constexpr Elf64_Off DummySHOffset = 0; | 455 constexpr Elf64_Off DummySHOffset = 0; |
| 444 constexpr SizeT DummySHStrIndex = 0; | 456 constexpr SizeT DummySHStrIndex = 0; |
| 445 constexpr SizeT DummyNumSections = 0; | 457 constexpr SizeT DummyNumSections = 0; |
| 446 if (ELF64) { | 458 if (ELF64) { |
| 447 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex, | 459 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex, |
| 448 DummyNumSections); | 460 DummyNumSections); |
| 449 } else { | 461 } else { |
| 450 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex, | 462 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex, |
| 451 DummyNumSections); | 463 DummyNumSections); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 Str.writeLE16(0); // e_phnum | 505 Str.writeLE16(0); // e_phnum |
| 494 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr) | 506 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr) |
| 495 : sizeof(Elf32_Shdr)); // e_shentsize | 507 : sizeof(Elf32_Shdr)); // e_shentsize |
| 496 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40, | 508 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40, |
| 497 "Elf_Shdr sizes cannot be derived from sizeof"); | 509 "Elf_Shdr sizes cannot be derived from sizeof"); |
| 498 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum | 510 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum |
| 499 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx | 511 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx |
| 500 } | 512 } |
| 501 | 513 |
| 502 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) { | 514 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) { |
| 515 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
| 503 ConstantList Pool = Ctx.getConstantPool(Ty); | 516 ConstantList Pool = Ctx.getConstantPool(Ty); |
| 504 if (Pool.empty()) { | 517 if (Pool.empty()) { |
| 505 return; | 518 return; |
| 506 } | 519 } |
| 507 SizeT Align = typeAlignInBytes(Ty); | 520 SizeT Align = typeAlignInBytes(Ty); |
| 508 size_t EntSize = typeWidthInBytes(Ty); | 521 size_t EntSize = typeWidthInBytes(Ty); |
| 509 char Buf[20]; | 522 char Buf[20]; |
| 510 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf)); | 523 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf)); |
| 511 // Check that we write the full PrimType. | 524 // Check that we write the full PrimType. |
| 512 assert(WriteAmt == EntSize); | 525 assert(WriteAmt == EntSize); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty); | 582 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty); |
| 570 | 583 |
| 571 void ELFObjectWriter::writeAllRelocationSections() { | 584 void ELFObjectWriter::writeAllRelocationSections() { |
| 572 writeRelocationSections(RelTextSections); | 585 writeRelocationSections(RelTextSections); |
| 573 writeRelocationSections(RelDataSections); | 586 writeRelocationSections(RelDataSections); |
| 574 writeRelocationSections(RelRODataSections); | 587 writeRelocationSections(RelRODataSections); |
| 575 } | 588 } |
| 576 | 589 |
| 577 void ELFObjectWriter::writeJumpTable(const JumpTableData &JT, | 590 void ELFObjectWriter::writeJumpTable(const JumpTableData &JT, |
| 578 FixupKind RelocationKind, bool IsPIC) { | 591 FixupKind RelocationKind, bool IsPIC) { |
| 592 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
| 579 ELFDataSection *Section; | 593 ELFDataSection *Section; |
| 580 ELFRelocationSection *RelSection; | 594 ELFRelocationSection *RelSection; |
| 581 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType()); | 595 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType()); |
| 582 const Elf64_Xword ShAddralign = PointerSize; | 596 const Elf64_Xword ShAddralign = PointerSize; |
| 583 const Elf64_Xword ShEntsize = PointerSize; | 597 const Elf64_Xword ShEntsize = PointerSize; |
| 584 const IceString SectionName = MangleSectionName( | 598 const IceString SectionName = MangleSectionName( |
| 585 IsPIC ? ".data.rel.ro" : ".rodata", JT.getFunctionName() + "$jumptable"); | 599 IsPIC ? ".data.rel.ro" : ".rodata", JT.getFunctionName() + "$jumptable"); |
| 586 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, | 600 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, |
| 587 ShAddralign, ShEntsize); | 601 ShAddralign, ShEntsize); |
| 588 Section->setFileOffset(alignFileOffset(ShAddralign)); | 602 Section->setFileOffset(alignFileOffset(ShAddralign)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 604 AssemblerFixup NewFixup; | 618 AssemblerFixup NewFixup; |
| 605 NewFixup.set_position(Section->getCurrentSize()); | 619 NewFixup.set_position(Section->getCurrentSize()); |
| 606 NewFixup.set_kind(RelocationKind); | 620 NewFixup.set_kind(RelocationKind); |
| 607 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName())); | 621 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName())); |
| 608 RelSection->addRelocation(NewFixup); | 622 RelSection->addRelocation(NewFixup); |
| 609 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset); | 623 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset); |
| 610 } | 624 } |
| 611 } | 625 } |
| 612 | 626 |
| 613 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) { | 627 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) { |
| 628 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
| 614 for (const Constant *S : UndefSyms) { | 629 for (const Constant *S : UndefSyms) { |
| 615 const auto *Sym = llvm::cast<ConstantRelocatable>(S); | 630 const auto *Sym = llvm::cast<ConstantRelocatable>(S); |
| 616 const IceString &Name = Sym->getName(); | 631 const IceString &Name = Sym->getName(); |
| 617 bool BadIntrinsic; | 632 bool BadIntrinsic; |
| 618 const Intrinsics::FullIntrinsicInfo *Info = | 633 const Intrinsics::FullIntrinsicInfo *Info = |
| 619 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic); | 634 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic); |
| 620 if (Info) | 635 if (Info) |
| 621 continue; | 636 continue; |
| 622 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but | 637 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but |
| 623 // doesn't match a known intrinsic. If we want this to turn into an error, | 638 // doesn't match a known intrinsic. If we want this to turn into an error, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 635 RelSec->setSize(RelSec->getSectionDataSize()); | 650 RelSec->setSize(RelSec->getSectionDataSize()); |
| 636 if (ELF64) { | 651 if (ELF64) { |
| 637 RelSec->writeData<true>(Str, SymTab); | 652 RelSec->writeData<true>(Str, SymTab); |
| 638 } else { | 653 } else { |
| 639 RelSec->writeData<false>(Str, SymTab); | 654 RelSec->writeData<false>(Str, SymTab); |
| 640 } | 655 } |
| 641 } | 656 } |
| 642 } | 657 } |
| 643 | 658 |
| 644 void ELFObjectWriter::writeNonUserSections() { | 659 void ELFObjectWriter::writeNonUserSections() { |
| 660 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
| 661 |
| 645 // Write out the shstrtab now that all sections are known. | 662 // Write out the shstrtab now that all sections are known. |
| 646 ShStrTab->doLayout(); | 663 ShStrTab->doLayout(); |
| 647 ShStrTab->setSize(ShStrTab->getSectionDataSize()); | 664 ShStrTab->setSize(ShStrTab->getSectionDataSize()); |
| 648 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); | 665 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); |
| 649 ShStrTab->setFileOffset(ShStrTabOffset); | 666 ShStrTab->setFileOffset(ShStrTabOffset); |
| 650 Str.writeBytes(ShStrTab->getSectionData()); | 667 Str.writeBytes(ShStrTab->getSectionData()); |
| 651 | 668 |
| 652 SectionList AllSections; | 669 SectionList AllSections; |
| 653 assignSectionNumbersInfo(AllSections); | 670 assignSectionNumbersInfo(AllSections); |
| 654 | 671 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 684 if (ELF64) { | 701 if (ELF64) { |
| 685 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), | 702 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), |
| 686 AllSections.size()); | 703 AllSections.size()); |
| 687 } else { | 704 } else { |
| 688 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), | 705 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), |
| 689 AllSections.size()); | 706 AllSections.size()); |
| 690 } | 707 } |
| 691 } | 708 } |
| 692 | 709 |
| 693 } // end of namespace Ice | 710 } // end of namespace Ice |
| OLD | NEW |