| //===- lib/MC/ELFObjectWriter.h - ELF File Writer -------------------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This file implements ELF object file writer information. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #ifndef LLVM_MC_ELFOBJECTWRITER_H | 
 | #define LLVM_MC_ELFOBJECTWRITER_H | 
 |  | 
 | #include "MCELF.h" | 
 | #include "llvm/ADT/OwningPtr.h" | 
 | #include "llvm/ADT/SmallPtrSet.h" | 
 | #include "llvm/ADT/SmallString.h" | 
 | #include "llvm/ADT/STLExtras.h" | 
 | #include "llvm/MC/MCAssembler.h" | 
 | #include "llvm/MC/MCELFObjectWriter.h" | 
 | #include "llvm/MC/MCELFSymbolFlags.h" | 
 | #include "llvm/MC/MCObjectWriter.h" | 
 | #include "llvm/MC/MCExpr.h" | 
 | #include "llvm/MC/MCSymbol.h" | 
 |  | 
 | #include <vector> | 
 |  | 
 | namespace llvm { | 
 |  | 
 | class MCSection; | 
 | class MCDataFragment; | 
 | class MCSectionELF; | 
 |  | 
 | class ELFObjectWriter : public MCObjectWriter { | 
 |   protected: | 
 |  | 
 |     static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); | 
 |     static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant); | 
 |     static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout); | 
 |     static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, | 
 |                            bool Used, bool Renamed); | 
 |     static bool isLocal(const MCSymbolData &Data, bool isSignature, | 
 |                         bool isUsedInReloc); | 
 |     static bool IsELFMetaDataSection(const MCSectionData &SD); | 
 |     static uint64_t DataSectionSize(const MCSectionData &SD); | 
 |     static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, | 
 |                                        const MCSectionData &SD); | 
 |     static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, | 
 |                                           const MCSectionData &SD); | 
 |  | 
 |     void WriteDataSectionData(MCAssembler &Asm, | 
 |                               const MCAsmLayout &Layout, | 
 |                               const MCSectionELF &Section); | 
 |  | 
 |     /*static bool isFixupKindX86RIPRel(unsigned Kind) { | 
 |       return Kind == X86::reloc_riprel_4byte || | 
 |         Kind == X86::reloc_riprel_4byte_movq_load; | 
 |     }*/ | 
 |  | 
 |     /// ELFSymbolData - Helper struct for containing some precomputed | 
 |     /// information on symbols. | 
 |     struct ELFSymbolData { | 
 |       MCSymbolData *SymbolData; | 
 |       uint64_t StringIndex; | 
 |       uint32_t SectionIndex; | 
 |  | 
 |       // Support lexicographic sorting. | 
 |       bool operator<(const ELFSymbolData &RHS) const { | 
 |         if (MCELF::GetType(*SymbolData) == ELF::STT_FILE) | 
 |           return true; | 
 |         if (MCELF::GetType(*RHS.SymbolData) == ELF::STT_FILE) | 
 |           return false; | 
 |         return SymbolData->getSymbol().getName() < | 
 |                RHS.SymbolData->getSymbol().getName(); | 
 |       } | 
 |     }; | 
 |  | 
 |     /// @name Relocation Data | 
 |     /// @{ | 
 |  | 
 |     struct ELFRelocationEntry { | 
 |       // Make these big enough for both 32-bit and 64-bit | 
 |       uint64_t r_offset; | 
 |       int Index; | 
 |       unsigned Type; | 
 |       const MCSymbol *Symbol; | 
 |       uint64_t r_addend; | 
 |  | 
 |       ELFRelocationEntry() | 
 |         : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0) {} | 
 |  | 
 |       ELFRelocationEntry(uint64_t RelocOffset, int Idx, | 
 |                          unsigned RelType, const MCSymbol *Sym, | 
 |                          uint64_t Addend) | 
 |         : r_offset(RelocOffset), Index(Idx), Type(RelType), | 
 |           Symbol(Sym), r_addend(Addend) {} | 
 |  | 
 |       // Support lexicographic sorting. | 
 |       bool operator<(const ELFRelocationEntry &RE) const { | 
 |         return RE.r_offset < r_offset; | 
 |       } | 
 |     }; | 
 |  | 
 |     /// The target specific ELF writer instance. | 
 |     llvm::OwningPtr<MCELFObjectTargetWriter> TargetObjectWriter; | 
 |  | 
 |     SmallPtrSet<const MCSymbol *, 16> UsedInReloc; | 
 |     SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc; | 
 |     DenseMap<const MCSymbol *, const MCSymbol *> Renames; | 
 |  | 
 |     llvm::DenseMap<const MCSectionData*, | 
 |                    std::vector<ELFRelocationEntry> > Relocations; | 
 |     DenseMap<const MCSection*, uint64_t> SectionStringTableIndex; | 
 |  | 
 |     /// @} | 
 |     /// @name Symbol Table Data | 
 |     /// @{ | 
 |  | 
 |     SmallString<256> StringTable; | 
 |     std::vector<ELFSymbolData> LocalSymbolData; | 
 |     std::vector<ELFSymbolData> ExternalSymbolData; | 
 |     std::vector<ELFSymbolData> UndefinedSymbolData; | 
 |  | 
 |     /// @} | 
 |  | 
 |     bool NeedsGOT; | 
 |  | 
 |     bool NeedsSymtabShndx; | 
 |  | 
 |     // This holds the symbol table index of the last local symbol. | 
 |     unsigned LastLocalSymbolIndex; | 
 |     // This holds the .strtab section index. | 
 |     unsigned StringTableIndex; | 
 |     // This holds the .symtab section index. | 
 |     unsigned SymbolTableIndex; | 
 |  | 
 |     unsigned ShstrtabIndex; | 
 |  | 
 |  | 
 |     virtual const MCSymbol *SymbolToReloc(const MCAssembler &Asm, | 
 |                                           const MCValue &Target, | 
 |                                           const MCFragment &F, | 
 |                                           const MCFixup &Fixup, | 
 |                                           bool IsPCRel) const; | 
 |  | 
 |     // For arch-specific emission of explicit reloc symbol | 
 |     virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, | 
 |                                            const MCValue &Target, | 
 |                                            const MCFragment &F, | 
 |                                            const MCFixup &Fixup, | 
 |                                            bool IsPCRel) const { | 
 |       return NULL; | 
 |     } | 
 |  | 
 |     bool is64Bit() const { return TargetObjectWriter->is64Bit(); } | 
 |     bool hasRelocationAddend() const { | 
 |       return TargetObjectWriter->hasRelocationAddend(); | 
 |     } | 
 |  | 
 |   public: | 
 |     ELFObjectWriter(MCELFObjectTargetWriter *MOTW, | 
 |                     raw_ostream &_OS, bool IsLittleEndian) | 
 |       : MCObjectWriter(_OS, IsLittleEndian), | 
 |         TargetObjectWriter(MOTW), | 
 |         NeedsGOT(false), NeedsSymtabShndx(false){ | 
 |     } | 
 |  | 
 |     virtual ~ELFObjectWriter(); | 
 |  | 
 |     void WriteWord(uint64_t W) { | 
 |       if (is64Bit()) | 
 |         Write64(W); | 
 |       else | 
 |         Write32(W); | 
 |     } | 
 |  | 
 |     void StringLE16(char *buf, uint16_t Value) { | 
 |       buf[0] = char(Value >> 0); | 
 |       buf[1] = char(Value >> 8); | 
 |     } | 
 |  | 
 |     void StringLE32(char *buf, uint32_t Value) { | 
 |       StringLE16(buf, uint16_t(Value >> 0)); | 
 |       StringLE16(buf + 2, uint16_t(Value >> 16)); | 
 |     } | 
 |  | 
 |     void StringLE64(char *buf, uint64_t Value) { | 
 |       StringLE32(buf, uint32_t(Value >> 0)); | 
 |       StringLE32(buf + 4, uint32_t(Value >> 32)); | 
 |     } | 
 |  | 
 |     void StringBE16(char *buf ,uint16_t Value) { | 
 |       buf[0] = char(Value >> 8); | 
 |       buf[1] = char(Value >> 0); | 
 |     } | 
 |  | 
 |     void StringBE32(char *buf, uint32_t Value) { | 
 |       StringBE16(buf, uint16_t(Value >> 16)); | 
 |       StringBE16(buf + 2, uint16_t(Value >> 0)); | 
 |     } | 
 |  | 
 |     void StringBE64(char *buf, uint64_t Value) { | 
 |       StringBE32(buf, uint32_t(Value >> 32)); | 
 |       StringBE32(buf + 4, uint32_t(Value >> 0)); | 
 |     } | 
 |  | 
 |     void String8(MCDataFragment &F, uint8_t Value) { | 
 |       char buf[1]; | 
 |       buf[0] = Value; | 
 |       F.getContents() += StringRef(buf, 1); | 
 |     } | 
 |  | 
 |     void String16(MCDataFragment &F, uint16_t Value) { | 
 |       char buf[2]; | 
 |       if (isLittleEndian()) | 
 |         StringLE16(buf, Value); | 
 |       else | 
 |         StringBE16(buf, Value); | 
 |       F.getContents() += StringRef(buf, 2); | 
 |     } | 
 |  | 
 |     void String32(MCDataFragment &F, uint32_t Value) { | 
 |       char buf[4]; | 
 |       if (isLittleEndian()) | 
 |         StringLE32(buf, Value); | 
 |       else | 
 |         StringBE32(buf, Value); | 
 |       F.getContents() += StringRef(buf, 4); | 
 |     } | 
 |  | 
 |     void String64(MCDataFragment &F, uint64_t Value) { | 
 |       char buf[8]; | 
 |       if (isLittleEndian()) | 
 |         StringLE64(buf, Value); | 
 |       else | 
 |         StringBE64(buf, Value); | 
 |       F.getContents() += StringRef(buf, 8); | 
 |     } | 
 |  | 
 |     virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); | 
 |  | 
 |     /// Default e_flags = 0 | 
 |     virtual void WriteEFlags() { Write32(0); } | 
 |  | 
 |     virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, | 
 |                           uint64_t name, uint8_t info, | 
 |                           uint64_t value, uint64_t size, | 
 |                           uint8_t other, uint32_t shndx, | 
 |                           bool Reserved); | 
 |  | 
 |     virtual void WriteSymbol(MCDataFragment *SymtabF,  MCDataFragment *ShndxF, | 
 |                      ELFSymbolData &MSD, | 
 |                      const MCAsmLayout &Layout); | 
 |  | 
 |     typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy; | 
 |     virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, | 
 |                           const MCAssembler &Asm, | 
 |                           const MCAsmLayout &Layout, | 
 |                           const SectionIndexMapTy &SectionIndexMap); | 
 |  | 
 |     virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, | 
 |                                   const MCFragment *Fragment, const MCFixup &Fixup, | 
 |                                   MCValue Target, uint64_t &FixedValue); | 
 |  | 
 |     virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, | 
 |                                          const MCSymbol *S); | 
 |  | 
 |     // Map from a group section to the signature symbol | 
 |     typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy; | 
 |     // Map from a signature symbol to the group section | 
 |     typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy; | 
 |     // Map from a section to the section with the relocations | 
 |     typedef DenseMap<const MCSectionELF*, const MCSectionELF*> RelMapTy; | 
 |     // Map from a section to its offset | 
 |     typedef DenseMap<const MCSectionELF*, uint64_t> SectionOffsetMapTy; | 
 |  | 
 |     /// ComputeSymbolTable - Compute the symbol table data | 
 |     /// | 
 |     /// \param StringTable [out] - The string table data. | 
 |     /// \param StringIndexMap [out] - Map from symbol names to offsets in the | 
 |     /// string table. | 
 |     virtual void ComputeSymbolTable(MCAssembler &Asm, | 
 |                             const SectionIndexMapTy &SectionIndexMap, | 
 |                                     RevGroupMapTy RevGroupMap, | 
 |                                     unsigned NumRegularSections); | 
 |  | 
 |     virtual void ComputeIndexMap(MCAssembler &Asm, | 
 |                                  SectionIndexMapTy &SectionIndexMap, | 
 |                                  const RelMapTy &RelMap); | 
 |  | 
 |     void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout, | 
 |                                   RelMapTy &RelMap); | 
 |  | 
 |     void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, | 
 |                           const RelMapTy &RelMap); | 
 |  | 
 |     virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, | 
 |                                         SectionIndexMapTy &SectionIndexMap, | 
 |                                         const RelMapTy &RelMap); | 
 |  | 
 |     // Create the sections that show up in the symbol table. Currently | 
 |     // those are the .note.GNU-stack section and the group sections. | 
 |     virtual void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, | 
 |                                        GroupMapTy &GroupMap, | 
 |                                        RevGroupMapTy &RevGroupMap, | 
 |                                        SectionIndexMapTy &SectionIndexMap, | 
 |                                        const RelMapTy &RelMap); | 
 |  | 
 |     virtual void ExecutePostLayoutBinding(MCAssembler &Asm, | 
 |                                           const MCAsmLayout &Layout); | 
 |  | 
 |     void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, | 
 |                             const MCAsmLayout &Layout, | 
 |                             const SectionIndexMapTy &SectionIndexMap, | 
 |                             const SectionOffsetMapTy &SectionOffsetMap); | 
 |  | 
 |     void ComputeSectionOrder(MCAssembler &Asm, | 
 |                              std::vector<const MCSectionELF*> &Sections); | 
 |  | 
 |     virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, | 
 |                           uint64_t Address, uint64_t Offset, | 
 |                           uint64_t Size, uint32_t Link, uint32_t Info, | 
 |                           uint64_t Alignment, uint64_t EntrySize); | 
 |  | 
 |     virtual void WriteRelocationsFragment(const MCAssembler &Asm, | 
 |                                           MCDataFragment *F, | 
 |                                           const MCSectionData *SD); | 
 |  | 
 |     virtual bool | 
 |     IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, | 
 |                                            const MCSymbolData &DataA, | 
 |                                            const MCFragment &FB, | 
 |                                            bool InSet, | 
 |                                            bool IsPCRel) const; | 
 |  | 
 |     virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); | 
 |     virtual void WriteSection(MCAssembler &Asm, | 
 |                       const SectionIndexMapTy &SectionIndexMap, | 
 |                       uint32_t GroupSymbolIndex, | 
 |                       uint64_t Offset, uint64_t Size, uint64_t Alignment, | 
 |                       const MCSectionELF &Section); | 
 |  | 
 |   protected: | 
 |     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | 
 |                                   bool IsPCRel, bool IsRelocWithSymbol, | 
 |                                   int64_t Addend) = 0; | 
 |     virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { } | 
 |   }; | 
 |  | 
 |   //===- X86ELFObjectWriter -------------------------------------------===// | 
 |  | 
 |   class X86ELFObjectWriter : public ELFObjectWriter { | 
 |   public: | 
 |     X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, | 
 |                        raw_ostream &_OS, | 
 |                        bool IsLittleEndian); | 
 |  | 
 |     virtual ~X86ELFObjectWriter(); | 
 |   protected: | 
 |     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | 
 |                                   bool IsPCRel, bool IsRelocWithSymbol, | 
 |                                   int64_t Addend); | 
 |   }; | 
 |  | 
 |  | 
 |   //===- ARMELFObjectWriter -------------------------------------------===// | 
 |  | 
 |   class ARMELFObjectWriter : public ELFObjectWriter { | 
 |   public: | 
 |     // FIXME: MCAssembler can't yet return the Subtarget, | 
 |     enum { DefaultEABIVersion = 0x05000000U }; | 
 |  | 
 |     ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, | 
 |                        raw_ostream &_OS, | 
 |                        bool IsLittleEndian); | 
 |  | 
 |     virtual ~ARMELFObjectWriter(); | 
 |  | 
 |     virtual void WriteEFlags(); | 
 |   protected: | 
 |     virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, | 
 |                                            const MCValue &Target, | 
 |                                            const MCFragment &F, | 
 |                                            const MCFixup &Fixup, | 
 |                                            bool IsPCRel) const; | 
 |  | 
 |     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | 
 |                                   bool IsPCRel, bool IsRelocWithSymbol, | 
 |                                   int64_t Addend); | 
 |   private: | 
 |     unsigned GetRelocTypeInner(const MCValue &Target, | 
 |                                const MCFixup &Fixup, bool IsPCRel) const; | 
 |      | 
 |   }; | 
 |  | 
 |   //===- PPCELFObjectWriter -------------------------------------------===// | 
 |  | 
 |   class PPCELFObjectWriter : public ELFObjectWriter { | 
 |   public: | 
 |     PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW, | 
 |                           raw_ostream &_OS, | 
 |                           bool IsLittleEndian); | 
 |  | 
 |     virtual ~PPCELFObjectWriter(); | 
 |   protected: | 
 |     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | 
 |                                   bool IsPCRel, bool IsRelocWithSymbol, | 
 |                                   int64_t Addend); | 
 |     virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); | 
 |   }; | 
 |  | 
 |   //===- MBlazeELFObjectWriter -------------------------------------------===// | 
 |  | 
 |   class MBlazeELFObjectWriter : public ELFObjectWriter { | 
 |   public: | 
 |     MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, | 
 |                           raw_ostream &_OS, | 
 |                           bool IsLittleEndian); | 
 |  | 
 |     virtual ~MBlazeELFObjectWriter(); | 
 |   protected: | 
 |     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | 
 |                                   bool IsPCRel, bool IsRelocWithSymbol, | 
 |                                   int64_t Addend); | 
 |   }; | 
 |  | 
 |   //===- MipsELFObjectWriter -------------------------------------------===// | 
 |  | 
 |   class MipsELFObjectWriter : public ELFObjectWriter { | 
 |   public: | 
 |     MipsELFObjectWriter(MCELFObjectTargetWriter *MOTW, | 
 |                         raw_ostream &_OS, | 
 |                         bool IsLittleEndian); | 
 |  | 
 |     virtual ~MipsELFObjectWriter(); | 
 |   protected: | 
 |     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | 
 |                                   bool IsPCRel, bool IsRelocWithSymbol, | 
 |                                   int64_t Addend); | 
 |   }; | 
 | } | 
 |  | 
 | #endif |