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 |