Chromium Code Reviews| 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 Ice::TimerStackIdT StackID = Ice::GlobalContext::TSK_Funcs; | |
|
John
2016/03/07 22:40:39
No need to fully qualify these.
Karl
2016/03/08 21:52:47
Done.
| |
| 224 Ice::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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 Reloc->getOffset()); | 446 Reloc->getOffset()); |
| 436 break; | 447 break; |
| 437 } | 448 } |
| 438 } | 449 } |
| 439 } | 450 } |
| 440 } | 451 } |
| 441 } | 452 } |
| 442 } | 453 } |
| 443 | 454 |
| 444 void ELFObjectWriter::writeInitialELFHeader() { | 455 void ELFObjectWriter::writeInitialELFHeader() { |
| 456 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); | |
| 445 assert(!SectionNumbersAssigned); | 457 assert(!SectionNumbersAssigned); |
| 446 constexpr Elf64_Off DummySHOffset = 0; | 458 constexpr Elf64_Off DummySHOffset = 0; |
| 447 constexpr SizeT DummySHStrIndex = 0; | 459 constexpr SizeT DummySHStrIndex = 0; |
| 448 constexpr SizeT DummyNumSections = 0; | 460 constexpr SizeT DummyNumSections = 0; |
| 449 if (ELF64) { | 461 if (ELF64) { |
| 450 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex, | 462 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex, |
| 451 DummyNumSections); | 463 DummyNumSections); |
| 452 } else { | 464 } else { |
| 453 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex, | 465 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex, |
| 454 DummyNumSections); | 466 DummyNumSections); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 Str.writeLE16(0); // e_phnum | 508 Str.writeLE16(0); // e_phnum |
| 497 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr) | 509 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr) |
| 498 : sizeof(Elf32_Shdr)); // e_shentsize | 510 : sizeof(Elf32_Shdr)); // e_shentsize |
| 499 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40, | 511 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40, |
| 500 "Elf_Shdr sizes cannot be derived from sizeof"); | 512 "Elf_Shdr sizes cannot be derived from sizeof"); |
| 501 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum | 513 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum |
| 502 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx | 514 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx |
| 503 } | 515 } |
| 504 | 516 |
| 505 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) { | 517 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) { |
| 518 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); | |
| 506 ConstantList Pool = Ctx.getConstantPool(Ty); | 519 ConstantList Pool = Ctx.getConstantPool(Ty); |
| 507 if (Pool.empty()) { | 520 if (Pool.empty()) { |
| 508 return; | 521 return; |
| 509 } | 522 } |
| 510 SizeT Align = typeAlignInBytes(Ty); | 523 SizeT Align = typeAlignInBytes(Ty); |
| 511 size_t EntSize = typeWidthInBytes(Ty); | 524 size_t EntSize = typeWidthInBytes(Ty); |
| 512 char Buf[20]; | 525 char Buf[20]; |
| 513 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf)); | 526 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf)); |
| 514 // Check that we write the full PrimType. | 527 // Check that we write the full PrimType. |
| 515 assert(WriteAmt == EntSize); | 528 assert(WriteAmt == EntSize); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty); | 585 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty); |
| 573 | 586 |
| 574 void ELFObjectWriter::writeAllRelocationSections() { | 587 void ELFObjectWriter::writeAllRelocationSections() { |
| 575 writeRelocationSections(RelTextSections); | 588 writeRelocationSections(RelTextSections); |
| 576 writeRelocationSections(RelDataSections); | 589 writeRelocationSections(RelDataSections); |
| 577 writeRelocationSections(RelRODataSections); | 590 writeRelocationSections(RelRODataSections); |
| 578 } | 591 } |
| 579 | 592 |
| 580 void ELFObjectWriter::writeJumpTable(const JumpTableData &JT, | 593 void ELFObjectWriter::writeJumpTable(const JumpTableData &JT, |
| 581 FixupKind RelocationKind, bool IsPIC) { | 594 FixupKind RelocationKind, bool IsPIC) { |
| 595 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); | |
| 582 ELFDataSection *Section; | 596 ELFDataSection *Section; |
| 583 ELFRelocationSection *RelSection; | 597 ELFRelocationSection *RelSection; |
| 584 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType()); | 598 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType()); |
| 585 const Elf64_Xword ShAddralign = PointerSize; | 599 const Elf64_Xword ShAddralign = PointerSize; |
| 586 const Elf64_Xword ShEntsize = PointerSize; | 600 const Elf64_Xword ShEntsize = PointerSize; |
| 587 const IceString SectionName = MangleSectionName( | 601 const IceString SectionName = MangleSectionName( |
| 588 IsPIC ? ".data.rel.ro" : ".rodata", JT.getFunctionName() + "$jumptable"); | 602 IsPIC ? ".data.rel.ro" : ".rodata", JT.getFunctionName() + "$jumptable"); |
| 589 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, | 603 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, |
| 590 ShAddralign, ShEntsize); | 604 ShAddralign, ShEntsize); |
| 591 Section->setFileOffset(alignFileOffset(ShAddralign)); | 605 Section->setFileOffset(alignFileOffset(ShAddralign)); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 608 NewFixup.set_position(Section->getCurrentSize()); | 622 NewFixup.set_position(Section->getCurrentSize()); |
| 609 NewFixup.set_kind(RelocationKind); | 623 NewFixup.set_kind(RelocationKind); |
| 610 constexpr bool SuppressMangling = true; | 624 constexpr bool SuppressMangling = true; |
| 611 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName(), | 625 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName(), |
| 612 SuppressMangling)); | 626 SuppressMangling)); |
| 613 RelSection->addRelocation(NewFixup); | 627 RelSection->addRelocation(NewFixup); |
| 614 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset); | 628 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset); |
| 615 } | 629 } |
| 616 } | 630 } |
| 617 | 631 |
| 618 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) { | 632 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) { |
|
Jim Stichnoth
2016/03/07 23:20:12
I think you need a TT_writeELF marker here as well
Karl
2016/03/08 21:52:47
Done.
| |
| 619 for (const Constant *S : UndefSyms) { | 633 for (const Constant *S : UndefSyms) { |
| 620 const auto *Sym = llvm::cast<ConstantRelocatable>(S); | 634 const auto *Sym = llvm::cast<ConstantRelocatable>(S); |
| 621 const IceString &Name = Sym->getName(); | 635 const IceString &Name = Sym->getName(); |
| 622 bool BadIntrinsic; | 636 bool BadIntrinsic; |
| 623 const Intrinsics::FullIntrinsicInfo *Info = | 637 const Intrinsics::FullIntrinsicInfo *Info = |
| 624 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic); | 638 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic); |
| 625 if (Info) | 639 if (Info) |
| 626 continue; | 640 continue; |
| 627 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but | 641 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but |
| 628 // doesn't match a known intrinsic. If we want this to turn into an error, | 642 // doesn't match a known intrinsic. If we want this to turn into an error, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 641 RelSec->setSize(RelSec->getSectionDataSize()); | 655 RelSec->setSize(RelSec->getSectionDataSize()); |
| 642 if (ELF64) { | 656 if (ELF64) { |
| 643 RelSec->writeData<true>(Ctx, Str, SymTab); | 657 RelSec->writeData<true>(Ctx, Str, SymTab); |
| 644 } else { | 658 } else { |
| 645 RelSec->writeData<false>(Ctx, Str, SymTab); | 659 RelSec->writeData<false>(Ctx, Str, SymTab); |
| 646 } | 660 } |
| 647 } | 661 } |
| 648 } | 662 } |
| 649 | 663 |
| 650 void ELFObjectWriter::writeNonUserSections() { | 664 void ELFObjectWriter::writeNonUserSections() { |
| 665 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); | |
| 666 | |
| 651 // Write out the shstrtab now that all sections are known. | 667 // Write out the shstrtab now that all sections are known. |
| 652 ShStrTab->doLayout(); | 668 ShStrTab->doLayout(); |
| 653 ShStrTab->setSize(ShStrTab->getSectionDataSize()); | 669 ShStrTab->setSize(ShStrTab->getSectionDataSize()); |
| 654 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); | 670 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); |
| 655 ShStrTab->setFileOffset(ShStrTabOffset); | 671 ShStrTab->setFileOffset(ShStrTabOffset); |
| 656 Str.writeBytes(ShStrTab->getSectionData()); | 672 Str.writeBytes(ShStrTab->getSectionData()); |
| 657 | 673 |
| 658 SectionList AllSections; | 674 SectionList AllSections; |
| 659 assignSectionNumbersInfo(AllSections); | 675 assignSectionNumbersInfo(AllSections); |
| 660 | 676 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 690 if (ELF64) { | 706 if (ELF64) { |
| 691 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), | 707 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), |
| 692 AllSections.size()); | 708 AllSections.size()); |
| 693 } else { | 709 } else { |
| 694 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), | 710 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), |
| 695 AllSections.size()); | 711 AllSections.size()); |
| 696 } | 712 } |
| 697 } | 713 } |
| 698 | 714 |
| 699 } // end of namespace Ice | 715 } // end of namespace Ice |
| OLD | NEW |