| OLD | NEW |
| 1 //===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -------------------===// | 1 //===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -------------------===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 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 // This file implements ELF object file writer information. | 10 // This file implements ELF object file writer information. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 case MCSymbolRefExpr::VK_TLSLDM: | 94 case MCSymbolRefExpr::VK_TLSLDM: |
| 95 case MCSymbolRefExpr::VK_DTPOFF: | 95 case MCSymbolRefExpr::VK_DTPOFF: |
| 96 case MCSymbolRefExpr::VK_TLSLD: | 96 case MCSymbolRefExpr::VK_TLSLD: |
| 97 return true; | 97 return true; |
| 98 } | 98 } |
| 99 } | 99 } |
| 100 | 100 |
| 101 namespace { | 101 namespace { |
| 102 | 102 |
| 103 class ELFObjectWriterImpl { | 103 class ELFObjectWriterImpl { |
| 104 protected: |
| 104 /*static bool isFixupKindX86RIPRel(unsigned Kind) { | 105 /*static bool isFixupKindX86RIPRel(unsigned Kind) { |
| 105 return Kind == X86::reloc_riprel_4byte || | 106 return Kind == X86::reloc_riprel_4byte || |
| 106 Kind == X86::reloc_riprel_4byte_movq_load; | 107 Kind == X86::reloc_riprel_4byte_movq_load; |
| 107 }*/ | 108 }*/ |
| 108 | 109 |
| 109 | 110 |
| 110 /// ELFSymbolData - Helper struct for containing some precomputed informatio
n | 111 /// ELFSymbolData - Helper struct for containing some precomputed informatio
n |
| 111 /// on symbols. | 112 /// on symbols. |
| 112 struct ELFSymbolData { | 113 struct ELFSymbolData { |
| 113 MCSymbolData *SymbolData; | 114 MCSymbolData *SymbolData; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 191 |
| 191 public: | 192 public: |
| 192 ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit, | 193 ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit, |
| 193 uint16_t _EMachine, bool _HasRelAddend, | 194 uint16_t _EMachine, bool _HasRelAddend, |
| 194 Triple::OSType _OSType) | 195 Triple::OSType _OSType) |
| 195 : NeedsGOT(false), NeedsSymtabShndx(false), Writer(_Writer), | 196 : NeedsGOT(false), NeedsSymtabShndx(false), Writer(_Writer), |
| 196 OS(Writer->getStream()), | 197 OS(Writer->getStream()), |
| 197 Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend), | 198 Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend), |
| 198 OSType(_OSType), EMachine(_EMachine) { | 199 OSType(_OSType), EMachine(_EMachine) { |
| 199 } | 200 } |
| 200 | 201 virtual ~ELFObjectWriterImpl(); |
| 201 void Write8(uint8_t Value) { Writer->Write8(Value); } | 202 void Write8(uint8_t Value) { Writer->Write8(Value); } |
| 202 void Write16(uint16_t Value) { Writer->Write16(Value); } | 203 void Write16(uint16_t Value) { Writer->Write16(Value); } |
| 203 void Write32(uint32_t Value) { Writer->Write32(Value); } | 204 void Write32(uint32_t Value) { Writer->Write32(Value); } |
| 204 //void Write64(uint64_t Value) { Writer->Write64(Value); } | 205 //void Write64(uint64_t Value) { Writer->Write64(Value); } |
| 205 void WriteZeros(unsigned N) { Writer->WriteZeros(N); } | 206 void WriteZeros(unsigned N) { Writer->WriteZeros(N); } |
| 206 //void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { | 207 //void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { |
| 207 // Writer->WriteBytes(Str, ZeroFillSize); | 208 // Writer->WriteBytes(Str, ZeroFillSize); |
| 208 //} | 209 //} |
| 209 | 210 |
| 210 void WriteWord(uint64_t W) { | 211 void WriteWord(uint64_t W) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 | 271 |
| 271 void String64(MCDataFragment &F, uint64_t Value) { | 272 void String64(MCDataFragment &F, uint64_t Value) { |
| 272 char buf[8]; | 273 char buf[8]; |
| 273 if (Writer->isLittleEndian()) | 274 if (Writer->isLittleEndian()) |
| 274 StringLE64(buf, Value); | 275 StringLE64(buf, Value); |
| 275 else | 276 else |
| 276 StringBE64(buf, Value); | 277 StringBE64(buf, Value); |
| 277 F.getContents() += StringRef(buf, 8); | 278 F.getContents() += StringRef(buf, 8); |
| 278 } | 279 } |
| 279 | 280 |
| 280 void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); | 281 /// @name new virtuals |
| 282 /// @{ |
| 283 virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections
); |
| 281 | 284 |
| 282 void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, | 285 virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *Shndx
F, |
| 283 uint64_t name, uint8_t info, | 286 uint64_t name, uint8_t info, |
| 284 uint64_t value, uint64_t size, | 287 uint64_t value, uint64_t size, |
| 285 uint8_t other, uint32_t shndx, | 288 uint8_t other, uint32_t shndx, |
| 286 bool Reserved); | 289 bool Reserved); |
| 287 | 290 |
| 288 void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, | 291 virtual void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, |
| 289 ELFSymbolData &MSD, | 292 ELFSymbolData &MSD, |
| 290 const MCAsmLayout &Layout); | 293 const MCAsmLayout &Layout); |
| 291 | 294 |
| 292 void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, | 295 virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *Shndx
F, |
| 293 const MCAssembler &Asm, | 296 const MCAssembler &Asm, |
| 294 const MCAsmLayout &Layout, | 297 const MCAsmLayout &Layout, |
| 295 unsigned NumRegularSections); | 298 unsigned NumRegularSections); |
| 296 | 299 |
| 297 void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, | 300 virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Lay
out, |
| 298 const MCFragment *Fragment, const MCFixup &Fixup, | 301 const MCFragment *Fragment, const MCFixup &Fixup, |
| 299 MCValue Target, uint64_t &FixedValue); | 302 MCValue Target, uint64_t &FixedValue) { |
| 303 assert(0 && "RecordRelocation is not specific enough"); |
| 304 }; |
| 300 | 305 |
| 301 uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, | 306 virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, |
| 302 const MCSymbol *S); | 307 const MCSymbol *S); |
| 303 | 308 |
| 304 /// ComputeSymbolTable - Compute the symbol table data | 309 /// ComputeSymbolTable - Compute the symbol table data |
| 305 /// | 310 /// |
| 306 /// \param StringTable [out] - The string table data. | 311 /// \param StringTable [out] - The string table data. |
| 307 /// \param StringIndexMap [out] - Map from symbol names to offsets in the | 312 /// \param StringIndexMap [out] - Map from symbol names to offsets in the |
| 308 /// string table. | 313 /// string table. |
| 309 void ComputeSymbolTable(MCAssembler &Asm); | 314 virtual void ComputeSymbolTable(MCAssembler &Asm); |
| 310 | 315 |
| 311 void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, | 316 virtual void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, |
| 312 const MCSectionData &SD); | 317 const MCSectionData &SD); |
| 313 | 318 |
| 314 void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) { | 319 virtual void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) { |
| 315 for (MCAssembler::const_iterator it = Asm.begin(), | 320 for (MCAssembler::const_iterator it = Asm.begin(), |
| 316 ie = Asm.end(); it != ie; ++it) { | 321 ie = Asm.end(); it != ie; ++it) { |
| 317 WriteRelocation(Asm, Layout, *it); | 322 WriteRelocation(Asm, Layout, *it); |
| 318 } | 323 } |
| 319 } | 324 } |
| 320 | 325 |
| 321 void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout); | 326 virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout); |
| 322 | 327 |
| 323 void ExecutePostLayoutBinding(MCAssembler &Asm); | 328 virtual void ExecutePostLayoutBinding(MCAssembler &Asm); |
| 324 | 329 |
| 325 void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, | 330 virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, |
| 326 uint64_t Address, uint64_t Offset, | 331 uint64_t Address, uint64_t Offset, |
| 327 uint64_t Size, uint32_t Link, uint32_t Info, | 332 uint64_t Size, uint32_t Link, uint32_t Info, |
| 328 uint64_t Alignment, uint64_t EntrySize); | 333 uint64_t Alignment, uint64_t EntrySize); |
| 329 | 334 |
| 330 void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, | 335 virtual void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment
*F, |
| 331 const MCSectionData *SD); | 336 const MCSectionData *SD); |
| 332 | 337 |
| 333 bool IsFixupFullyResolved(const MCAssembler &Asm, | 338 virtual bool IsFixupFullyResolved(const MCAssembler &Asm, |
| 334 const MCValue Target, | 339 const MCValue Target, |
| 335 bool IsPCRel, | 340 bool IsPCRel, |
| 336 const MCFragment *DF) const; | 341 const MCFragment *DF) const; |
| 337 | 342 |
| 338 void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); | 343 virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); |
| 344 /// @} |
| 339 }; | 345 }; |
| 340 | 346 |
| 347 |
| 348 class X86ELFObjectWriterImpl : public ELFObjectWriterImpl { |
| 349 public: |
| 350 X86ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit, |
| 351 uint16_t _EMachine, bool _HasRelAddend, |
| 352 Triple::OSType _OSType); |
| 353 virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layou
t, |
| 354 const MCFragment *Fragment, const MCFixup &Fixup
, |
| 355 MCValue Target, uint64_t &FixedValue); |
| 356 virtual ~X86ELFObjectWriterImpl(); |
| 357 }; |
| 358 |
| 359 class ARMELFObjectWriterImpl : public ELFObjectWriterImpl { |
| 360 public: |
| 361 ARMELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit, |
| 362 uint16_t _EMachine, bool _HasRelAddend, |
| 363 Triple::OSType _OSType); |
| 364 virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layou
t, |
| 365 const MCFragment *Fragment, const MCFixup &Fixup
, |
| 366 MCValue Target, uint64_t &FixedValue); |
| 367 ~ARMELFObjectWriterImpl(); |
| 368 }; |
| 369 |
| 341 } | 370 } |
| 342 | 371 |
| 372 // new virtual destructor |
| 373 ELFObjectWriterImpl::~ELFObjectWriterImpl() |
| 374 {} |
| 375 |
| 343 // Emit the ELF header. | 376 // Emit the ELF header. |
| 344 void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize, | 377 void ELFObjectWriterImpl::WriteHeader(uint64_t SectionDataSize, |
| 345 unsigned NumberOfSections) { | 378 unsigned NumberOfSections) { |
| 346 // ELF Header | 379 // ELF Header |
| 347 // ---------- | 380 // ---------- |
| 348 // | 381 // |
| 349 // Note | 382 // Note |
| 350 // ---- | 383 // ---- |
| 351 // emitWord method behaves differently for ELF32 and ELF64, writing | 384 // emitWord method behaves differently for ELF32 and ELF64, writing |
| 352 // 4 bytes in the former and 8 in the latter. | 385 // 4 bytes in the former and 8 in the latter. |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 Kind == MCSymbolRefExpr::VK_GOTPCREL || | 675 Kind == MCSymbolRefExpr::VK_GOTPCREL || |
| 643 Kind == MCSymbolRefExpr::VK_GOTOFF)) | 676 Kind == MCSymbolRefExpr::VK_GOTOFF)) |
| 644 return true; | 677 return true; |
| 645 | 678 |
| 646 if (Section.getFlags() & MCSectionELF::SHF_MERGE) | 679 if (Section.getFlags() & MCSectionELF::SHF_MERGE) |
| 647 return Target.getConstant() != 0; | 680 return Target.getConstant() != 0; |
| 648 | 681 |
| 649 return false; | 682 return false; |
| 650 } | 683 } |
| 651 | 684 |
| 652 // FIXME: this is currently X86/X86_64 only | |
| 653 void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm, | |
| 654 const MCAsmLayout &Layout, | |
| 655 const MCFragment *Fragment, | |
| 656 const MCFixup &Fixup, | |
| 657 MCValue Target, | |
| 658 uint64_t &FixedValue) { | |
| 659 int64_t Addend = 0; | |
| 660 int Index = 0; | |
| 661 int64_t Value = Target.getConstant(); | |
| 662 const MCSymbol *Symbol = 0; | |
| 663 const MCSymbol *Renamed = 0; | |
| 664 | |
| 665 bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind()); | |
| 666 if (!Target.isAbsolute()) { | |
| 667 Symbol = &AliasedSymbol(Target.getSymA()->getSymbol()); | |
| 668 Renamed = Renames.lookup(Symbol); | |
| 669 if (!Renamed) | |
| 670 Renamed = &Target.getSymA()->getSymbol(); | |
| 671 MCSymbolData &SD = Asm.getSymbolData(*Symbol); | |
| 672 MCFragment *F = SD.getFragment(); | |
| 673 | |
| 674 if (const MCSymbolRefExpr *RefB = Target.getSymB()) { | |
| 675 const MCSymbol &SymbolB = RefB->getSymbol(); | |
| 676 MCSymbolData &SDB = Asm.getSymbolData(SymbolB); | |
| 677 IsPCRel = true; | |
| 678 MCSectionData *Sec = Fragment->getParent(); | |
| 679 | |
| 680 // Offset of the symbol in the section | |
| 681 int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec); | |
| 682 | |
| 683 // Ofeset of the relocation in the section | |
| 684 int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); | |
| 685 Value += b - a; | |
| 686 } | |
| 687 | |
| 688 // Check that this case has already been fully resolved before we get | |
| 689 // here. | |
| 690 if (Symbol->isDefined() && !SD.isExternal() && | |
| 691 IsPCRel && | |
| 692 &Fragment->getParent()->getSection() == &Symbol->getSection()) { | |
| 693 llvm_unreachable("We don't need a relocation in this case."); | |
| 694 return; | |
| 695 } | |
| 696 | |
| 697 bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target, *Fragment); | |
| 698 if (!RelocOnSymbol) { | |
| 699 Index = F->getParent()->getOrdinal(); | |
| 700 | |
| 701 MCSectionData *FSD = F->getParent(); | |
| 702 // Offset of the symbol in the section | |
| 703 Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); | |
| 704 } else { | |
| 705 UsedInReloc.insert(Renamed); | |
| 706 MCSymbolData &RenamedSD = Asm.getSymbolData(*Renamed); | |
| 707 if (RenamedSD.getFlags() & ELF_Other_Weakref) { | |
| 708 WeakrefUsedInReloc.insert(Symbol); | |
| 709 } | |
| 710 Index = -1; | |
| 711 } | |
| 712 Addend = Value; | |
| 713 // Compensate for the addend on i386. | |
| 714 if (Is64Bit) | |
| 715 Value = 0; | |
| 716 } | |
| 717 | |
| 718 FixedValue = Value; | |
| 719 | |
| 720 // determine the type of the relocation | |
| 721 | |
| 722 MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); | |
| 723 unsigned Type; | |
| 724 if (Is64Bit) { | |
| 725 if (IsPCRel) { | |
| 726 switch (Modifier) { | |
| 727 default: | |
| 728 llvm_unreachable("Unimplemented"); | |
| 729 case MCSymbolRefExpr::VK_None: | |
| 730 Type = ELF::R_X86_64_PC32; | |
| 731 break; | |
| 732 case MCSymbolRefExpr::VK_PLT: | |
| 733 Type = ELF::R_X86_64_PLT32; | |
| 734 break; | |
| 735 case MCSymbolRefExpr::VK_GOTPCREL: | |
| 736 Type = ELF::R_X86_64_GOTPCREL; | |
| 737 break; | |
| 738 case MCSymbolRefExpr::VK_GOTTPOFF: | |
| 739 Type = ELF::R_X86_64_GOTTPOFF; | |
| 740 break; | |
| 741 case MCSymbolRefExpr::VK_TLSGD: | |
| 742 Type = ELF::R_X86_64_TLSGD; | |
| 743 break; | |
| 744 case MCSymbolRefExpr::VK_TLSLD: | |
| 745 Type = ELF::R_X86_64_TLSLD; | |
| 746 break; | |
| 747 } | |
| 748 } else { | |
| 749 switch ((unsigned)Fixup.getKind()) { | |
| 750 default: llvm_unreachable("invalid fixup kind!"); | |
| 751 case FK_Data_8: Type = ELF::R_X86_64_64; break; | |
| 752 case X86::reloc_signed_4byte: | |
| 753 case X86::reloc_pcrel_4byte: | |
| 754 assert(isInt<32>(Target.getConstant())); | |
| 755 switch (Modifier) { | |
| 756 default: | |
| 757 llvm_unreachable("Unimplemented"); | |
| 758 case MCSymbolRefExpr::VK_None: | |
| 759 Type = ELF::R_X86_64_32S; | |
| 760 break; | |
| 761 case MCSymbolRefExpr::VK_GOT: | |
| 762 Type = ELF::R_X86_64_GOT32; | |
| 763 break; | |
| 764 case MCSymbolRefExpr::VK_GOTPCREL: | |
| 765 Type = ELF::R_X86_64_GOTPCREL; | |
| 766 break; | |
| 767 case MCSymbolRefExpr::VK_TPOFF: | |
| 768 Type = ELF::R_X86_64_TPOFF32; | |
| 769 break; | |
| 770 case MCSymbolRefExpr::VK_DTPOFF: | |
| 771 Type = ELF::R_X86_64_DTPOFF32; | |
| 772 break; | |
| 773 } | |
| 774 break; | |
| 775 case FK_Data_4: | |
| 776 Type = ELF::R_X86_64_32; | |
| 777 break; | |
| 778 case FK_Data_2: Type = ELF::R_X86_64_16; break; | |
| 779 case X86::reloc_pcrel_1byte: | |
| 780 case FK_Data_1: Type = ELF::R_X86_64_8; break; | |
| 781 } | |
| 782 } | |
| 783 } else { | |
| 784 if (IsPCRel) { | |
| 785 switch (Modifier) { | |
| 786 default: | |
| 787 llvm_unreachable("Unimplemented"); | |
| 788 case MCSymbolRefExpr::VK_None: | |
| 789 Type = ELF::R_386_PC32; | |
| 790 break; | |
| 791 case MCSymbolRefExpr::VK_PLT: | |
| 792 Type = ELF::R_386_PLT32; | |
| 793 break; | |
| 794 } | |
| 795 } else { | |
| 796 switch ((unsigned)Fixup.getKind()) { | |
| 797 default: llvm_unreachable("invalid fixup kind!"); | |
| 798 | |
| 799 case X86::reloc_global_offset_table: | |
| 800 Type = ELF::R_386_GOTPC; | |
| 801 break; | |
| 802 | |
| 803 // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode | |
| 804 // instead? | |
| 805 case X86::reloc_signed_4byte: | |
| 806 case X86::reloc_pcrel_4byte: | |
| 807 case FK_Data_4: | |
| 808 switch (Modifier) { | |
| 809 default: | |
| 810 llvm_unreachable("Unimplemented"); | |
| 811 case MCSymbolRefExpr::VK_None: | |
| 812 Type = ELF::R_386_32; | |
| 813 break; | |
| 814 case MCSymbolRefExpr::VK_GOT: | |
| 815 Type = ELF::R_386_GOT32; | |
| 816 break; | |
| 817 case MCSymbolRefExpr::VK_GOTOFF: | |
| 818 Type = ELF::R_386_GOTOFF; | |
| 819 break; | |
| 820 case MCSymbolRefExpr::VK_TLSGD: | |
| 821 Type = ELF::R_386_TLS_GD; | |
| 822 break; | |
| 823 case MCSymbolRefExpr::VK_TPOFF: | |
| 824 Type = ELF::R_386_TLS_LE_32; | |
| 825 break; | |
| 826 case MCSymbolRefExpr::VK_INDNTPOFF: | |
| 827 Type = ELF::R_386_TLS_IE; | |
| 828 break; | |
| 829 case MCSymbolRefExpr::VK_NTPOFF: | |
| 830 Type = ELF::R_386_TLS_LE; | |
| 831 break; | |
| 832 case MCSymbolRefExpr::VK_GOTNTPOFF: | |
| 833 Type = ELF::R_386_TLS_GOTIE; | |
| 834 break; | |
| 835 case MCSymbolRefExpr::VK_TLSLDM: | |
| 836 Type = ELF::R_386_TLS_LDM; | |
| 837 break; | |
| 838 case MCSymbolRefExpr::VK_DTPOFF: | |
| 839 Type = ELF::R_386_TLS_LDO_32; | |
| 840 break; | |
| 841 } | |
| 842 break; | |
| 843 case FK_Data_2: Type = ELF::R_386_16; break; | |
| 844 case X86::reloc_pcrel_1byte: | |
| 845 case FK_Data_1: Type = ELF::R_386_8; break; | |
| 846 } | |
| 847 } | |
| 848 } | |
| 849 | |
| 850 if (RelocNeedsGOT(Modifier)) | |
| 851 NeedsGOT = true; | |
| 852 | |
| 853 ELFRelocationEntry ERE; | |
| 854 | |
| 855 ERE.Index = Index; | |
| 856 ERE.Type = Type; | |
| 857 ERE.Symbol = Renamed; | |
| 858 | |
| 859 ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); | |
| 860 | |
| 861 if (HasRelocationAddend) | |
| 862 ERE.r_addend = Addend; | |
| 863 else | |
| 864 ERE.r_addend = 0; // Silence compiler warning. | |
| 865 | |
| 866 Relocations[Fragment->getParent()].push_back(ERE); | |
| 867 } | |
| 868 | 685 |
| 869 uint64_t | 686 uint64_t |
| 870 ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm, | 687 ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm, |
| 871 const MCSymbol *S) { | 688 const MCSymbol *S) { |
| 872 MCSymbolData &SD = Asm.getSymbolData(*S); | 689 MCSymbolData &SD = Asm.getSymbolData(*S); |
| 873 | 690 |
| 874 // Local symbol. | 691 // Local symbol. |
| 875 if (!SD.isExternal() && !S->isUndefined()) | 692 if (!SD.isExternal() && !S->isUndefined()) |
| 876 return SD.getIndex() + /* empty symbol */ 1; | 693 return SD.getIndex() + /* empty symbol */ 1; |
| 877 | 694 |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1367 } | 1184 } |
| 1368 | 1185 |
| 1369 ELFObjectWriter::ELFObjectWriter(raw_ostream &OS, | 1186 ELFObjectWriter::ELFObjectWriter(raw_ostream &OS, |
| 1370 bool Is64Bit, | 1187 bool Is64Bit, |
| 1371 Triple::OSType OSType, | 1188 Triple::OSType OSType, |
| 1372 uint16_t EMachine, | 1189 uint16_t EMachine, |
| 1373 bool IsLittleEndian, | 1190 bool IsLittleEndian, |
| 1374 bool HasRelocationAddend) | 1191 bool HasRelocationAddend) |
| 1375 : MCObjectWriter(OS, IsLittleEndian) | 1192 : MCObjectWriter(OS, IsLittleEndian) |
| 1376 { | 1193 { |
| 1377 Impl = new ELFObjectWriterImpl(this, Is64Bit, EMachine, | 1194 switch (EMachine) { |
| 1195 case ELF::EM_MBLAZE: |
| 1196 case ELF::EM_386: |
| 1197 case ELF::EM_X86_64: |
| 1198 Impl = new X86ELFObjectWriterImpl(this, Is64Bit, EMachine, |
| 1378 HasRelocationAddend, OSType); | 1199 HasRelocationAddend, OSType); |
| 1200 break; |
| 1201 case ELF::EM_ARM: |
| 1202 Impl = new ARMELFObjectWriterImpl(this, Is64Bit, EMachine, |
| 1203 HasRelocationAddend, OSType); |
| 1204 break; |
| 1205 default: |
| 1206 assert(0 && "Unsupported EMachine"); break; |
| 1207 } |
| 1379 } | 1208 } |
| 1380 | 1209 |
| 1381 ELFObjectWriter::~ELFObjectWriter() { | 1210 ELFObjectWriter::~ELFObjectWriter() { |
| 1382 delete (ELFObjectWriterImpl*) Impl; | 1211 delete (ELFObjectWriterImpl*) Impl; |
| 1383 } | 1212 } |
| 1384 | 1213 |
| 1385 void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { | 1214 void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { |
| 1386 ((ELFObjectWriterImpl*) Impl)->ExecutePostLayoutBinding(Asm); | 1215 ((ELFObjectWriterImpl*) Impl)->ExecutePostLayoutBinding(Asm); |
| 1387 } | 1216 } |
| 1388 | 1217 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1400 bool IsPCRel, | 1229 bool IsPCRel, |
| 1401 const MCFragment *DF) const { | 1230 const MCFragment *DF) const { |
| 1402 return ((ELFObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target, | 1231 return ((ELFObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target, |
| 1403 IsPCRel, DF); | 1232 IsPCRel, DF); |
| 1404 } | 1233 } |
| 1405 | 1234 |
| 1406 void ELFObjectWriter::WriteObject(MCAssembler &Asm, | 1235 void ELFObjectWriter::WriteObject(MCAssembler &Asm, |
| 1407 const MCAsmLayout &Layout) { | 1236 const MCAsmLayout &Layout) { |
| 1408 ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout); | 1237 ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout); |
| 1409 } | 1238 } |
| 1239 |
| 1240 |
| 1241 //===- X86ELFObjectWriterImpl ---------------------------------------===// |
| 1242 |
| 1243 X86ELFObjectWriterImpl::X86ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _I
s64Bit, |
| 1244 uint16_t _EMachine, bool _HasRelAddend, |
| 1245 Triple::OSType _OSType) |
| 1246 : ELFObjectWriterImpl(_Writer, _Is64Bit, _EMachine, _HasRelAddend, _OSType) |
| 1247 {} |
| 1248 |
| 1249 |
| 1250 X86ELFObjectWriterImpl::~X86ELFObjectWriterImpl() |
| 1251 {} |
| 1252 |
| 1253 void X86ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm, |
| 1254 const MCAsmLayout &Layout, |
| 1255 const MCFragment *Fragment, |
| 1256 const MCFixup &Fixup, |
| 1257 MCValue Target, |
| 1258 uint64_t &FixedValue) { |
| 1259 int64_t Addend = 0; |
| 1260 int Index = 0; |
| 1261 int64_t Value = Target.getConstant(); |
| 1262 const MCSymbol *Symbol = 0; |
| 1263 const MCSymbol *Renamed = 0; |
| 1264 |
| 1265 bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind()); |
| 1266 if (!Target.isAbsolute()) { |
| 1267 Symbol = &AliasedSymbol(Target.getSymA()->getSymbol()); |
| 1268 Renamed = Renames.lookup(Symbol); |
| 1269 if (!Renamed) |
| 1270 Renamed = &Target.getSymA()->getSymbol(); |
| 1271 MCSymbolData &SD = Asm.getSymbolData(*Symbol); |
| 1272 MCFragment *F = SD.getFragment(); |
| 1273 |
| 1274 if (const MCSymbolRefExpr *RefB = Target.getSymB()) { |
| 1275 const MCSymbol &SymbolB = RefB->getSymbol(); |
| 1276 MCSymbolData &SDB = Asm.getSymbolData(SymbolB); |
| 1277 IsPCRel = true; |
| 1278 MCSectionData *Sec = Fragment->getParent(); |
| 1279 |
| 1280 // Offset of the symbol in the section |
| 1281 int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec); |
| 1282 |
| 1283 // Ofeset of the relocation in the section |
| 1284 int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
| 1285 Value += b - a; |
| 1286 } |
| 1287 |
| 1288 // Check that this case has already been fully resolved before we get |
| 1289 // here. |
| 1290 if (Symbol->isDefined() && !SD.isExternal() && |
| 1291 IsPCRel && |
| 1292 &Fragment->getParent()->getSection() == &Symbol->getSection()) { |
| 1293 llvm_unreachable("We don't need a relocation in this case."); |
| 1294 return; |
| 1295 } |
| 1296 |
| 1297 bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target, *Fragment); |
| 1298 if (!RelocOnSymbol) { |
| 1299 Index = F->getParent()->getOrdinal(); |
| 1300 |
| 1301 MCSectionData *FSD = F->getParent(); |
| 1302 // Offset of the symbol in the section |
| 1303 Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); |
| 1304 } else { |
| 1305 UsedInReloc.insert(Renamed); |
| 1306 MCSymbolData &RenamedSD = Asm.getSymbolData(*Renamed); |
| 1307 if (RenamedSD.getFlags() & ELF_Other_Weakref) { |
| 1308 WeakrefUsedInReloc.insert(Symbol); |
| 1309 } |
| 1310 Index = -1; |
| 1311 } |
| 1312 Addend = Value; |
| 1313 // Compensate for the addend on i386. |
| 1314 if (Is64Bit) |
| 1315 Value = 0; |
| 1316 } |
| 1317 |
| 1318 FixedValue = Value; |
| 1319 |
| 1320 // determine the type of the relocation |
| 1321 |
| 1322 MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); |
| 1323 unsigned Type; |
| 1324 if (Is64Bit) { |
| 1325 if (IsPCRel) { |
| 1326 switch (Modifier) { |
| 1327 default: |
| 1328 llvm_unreachable("Unimplemented"); |
| 1329 case MCSymbolRefExpr::VK_None: |
| 1330 Type = ELF::R_X86_64_PC32; |
| 1331 break; |
| 1332 case MCSymbolRefExpr::VK_PLT: |
| 1333 Type = ELF::R_X86_64_PLT32; |
| 1334 break; |
| 1335 case MCSymbolRefExpr::VK_GOTPCREL: |
| 1336 Type = ELF::R_X86_64_GOTPCREL; |
| 1337 break; |
| 1338 case MCSymbolRefExpr::VK_GOTTPOFF: |
| 1339 Type = ELF::R_X86_64_GOTTPOFF; |
| 1340 break; |
| 1341 case MCSymbolRefExpr::VK_TLSGD: |
| 1342 Type = ELF::R_X86_64_TLSGD; |
| 1343 break; |
| 1344 case MCSymbolRefExpr::VK_TLSLD: |
| 1345 Type = ELF::R_X86_64_TLSLD; |
| 1346 break; |
| 1347 } |
| 1348 } else { |
| 1349 switch ((unsigned)Fixup.getKind()) { |
| 1350 default: llvm_unreachable("invalid fixup kind!"); |
| 1351 case FK_Data_8: Type = ELF::R_X86_64_64; break; |
| 1352 case X86::reloc_signed_4byte: |
| 1353 case X86::reloc_pcrel_4byte: |
| 1354 assert(isInt<32>(Target.getConstant())); |
| 1355 switch (Modifier) { |
| 1356 default: |
| 1357 llvm_unreachable("Unimplemented"); |
| 1358 case MCSymbolRefExpr::VK_None: |
| 1359 Type = ELF::R_X86_64_32S; |
| 1360 break; |
| 1361 case MCSymbolRefExpr::VK_GOT: |
| 1362 Type = ELF::R_X86_64_GOT32; |
| 1363 break; |
| 1364 case MCSymbolRefExpr::VK_GOTPCREL: |
| 1365 Type = ELF::R_X86_64_GOTPCREL; |
| 1366 break; |
| 1367 case MCSymbolRefExpr::VK_TPOFF: |
| 1368 Type = ELF::R_X86_64_TPOFF32; |
| 1369 break; |
| 1370 case MCSymbolRefExpr::VK_DTPOFF: |
| 1371 Type = ELF::R_X86_64_DTPOFF32; |
| 1372 break; |
| 1373 } |
| 1374 break; |
| 1375 case FK_Data_4: |
| 1376 Type = ELF::R_X86_64_32; |
| 1377 break; |
| 1378 case FK_Data_2: Type = ELF::R_X86_64_16; break; |
| 1379 case X86::reloc_pcrel_1byte: |
| 1380 case FK_Data_1: Type = ELF::R_X86_64_8; break; |
| 1381 } |
| 1382 } |
| 1383 } else { |
| 1384 if (IsPCRel) { |
| 1385 switch (Modifier) { |
| 1386 default: |
| 1387 llvm_unreachable("Unimplemented"); |
| 1388 case MCSymbolRefExpr::VK_None: |
| 1389 Type = ELF::R_386_PC32; |
| 1390 break; |
| 1391 case MCSymbolRefExpr::VK_PLT: |
| 1392 Type = ELF::R_386_PLT32; |
| 1393 break; |
| 1394 } |
| 1395 } else { |
| 1396 switch ((unsigned)Fixup.getKind()) { |
| 1397 default: llvm_unreachable("invalid fixup kind!"); |
| 1398 |
| 1399 case X86::reloc_global_offset_table: |
| 1400 Type = ELF::R_386_GOTPC; |
| 1401 break; |
| 1402 |
| 1403 // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode |
| 1404 // instead? |
| 1405 case X86::reloc_signed_4byte: |
| 1406 case X86::reloc_pcrel_4byte: |
| 1407 case FK_Data_4: |
| 1408 switch (Modifier) { |
| 1409 default: |
| 1410 llvm_unreachable("Unimplemented"); |
| 1411 case MCSymbolRefExpr::VK_None: |
| 1412 Type = ELF::R_386_32; |
| 1413 break; |
| 1414 case MCSymbolRefExpr::VK_GOT: |
| 1415 Type = ELF::R_386_GOT32; |
| 1416 break; |
| 1417 case MCSymbolRefExpr::VK_GOTOFF: |
| 1418 Type = ELF::R_386_GOTOFF; |
| 1419 break; |
| 1420 case MCSymbolRefExpr::VK_TLSGD: |
| 1421 Type = ELF::R_386_TLS_GD; |
| 1422 break; |
| 1423 case MCSymbolRefExpr::VK_TPOFF: |
| 1424 Type = ELF::R_386_TLS_LE_32; |
| 1425 break; |
| 1426 case MCSymbolRefExpr::VK_INDNTPOFF: |
| 1427 Type = ELF::R_386_TLS_IE; |
| 1428 break; |
| 1429 case MCSymbolRefExpr::VK_NTPOFF: |
| 1430 Type = ELF::R_386_TLS_LE; |
| 1431 break; |
| 1432 case MCSymbolRefExpr::VK_GOTNTPOFF: |
| 1433 Type = ELF::R_386_TLS_GOTIE; |
| 1434 break; |
| 1435 case MCSymbolRefExpr::VK_TLSLDM: |
| 1436 Type = ELF::R_386_TLS_LDM; |
| 1437 break; |
| 1438 case MCSymbolRefExpr::VK_DTPOFF: |
| 1439 Type = ELF::R_386_TLS_LDO_32; |
| 1440 break; |
| 1441 } |
| 1442 break; |
| 1443 case FK_Data_2: Type = ELF::R_386_16; break; |
| 1444 case X86::reloc_pcrel_1byte: |
| 1445 case FK_Data_1: Type = ELF::R_386_8; break; |
| 1446 } |
| 1447 } |
| 1448 } |
| 1449 |
| 1450 if (RelocNeedsGOT(Modifier)) |
| 1451 NeedsGOT = true; |
| 1452 |
| 1453 ELFRelocationEntry ERE; |
| 1454 |
| 1455 ERE.Index = Index; |
| 1456 ERE.Type = Type; |
| 1457 ERE.Symbol = Renamed; |
| 1458 |
| 1459 ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
| 1460 |
| 1461 if (HasRelocationAddend) |
| 1462 ERE.r_addend = Addend; |
| 1463 else |
| 1464 ERE.r_addend = 0; // Silence compiler warning. |
| 1465 |
| 1466 Relocations[Fragment->getParent()].push_back(ERE); |
| 1467 } |
| 1468 |
| 1469 |
| 1470 |
| 1471 //===- ARMELFObjectWriterImpl ---------------------------------------===// |
| 1472 |
| 1473 ARMELFObjectWriterImpl::ARMELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _I
s64Bit, |
| 1474 uint16_t _EMachine, bool _HasRelAddend, |
| 1475 Triple::OSType _OSType) |
| 1476 : ELFObjectWriterImpl(_Writer, _Is64Bit, _EMachine, _HasRelAddend, _OSType) |
| 1477 {} |
| 1478 |
| 1479 |
| 1480 ARMELFObjectWriterImpl::~ARMELFObjectWriterImpl() |
| 1481 {} |
| 1482 |
| 1483 void ARMELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm, |
| 1484 const MCAsmLayout &Layout, |
| 1485 const MCFragment *Fragment, |
| 1486 const MCFixup &Fixup, |
| 1487 MCValue Target, |
| 1488 uint64_t &FixedValue) { |
| 1489 assert(0 && "ARM RecordRelocation unimplemented"); |
| 1490 } |
| OLD | NEW |