Home | History | Annotate | Download | only in Target
      1 //===- ELFDynamic.h -------------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #ifndef MCLD_TARGET_ELFDYNAMIC_H
     10 #define MCLD_TARGET_ELFDYNAMIC_H
     11 
     12 #include <mcld/LD/LDSection.h>
     13 #include <mcld/Support/FileOutputBuffer.h>
     14 #include <llvm/Support/ELF.h>
     15 #include <vector>
     16 #include <cstring>
     17 
     18 namespace mcld {
     19 
     20 class ELFFileFormat;
     21 class GNULDBackend;
     22 class LinkerConfig;
     23 
     24 namespace elf_dynamic {
     25 
     26 /** \class EntryIF
     27 *  \brief EntryIF provides a common interface for one entry in the dynamic
     28 *  section
     29 */
     30 class EntryIF
     31 {
     32 protected:
     33   EntryIF();
     34 
     35 public:
     36   virtual ~EntryIF();
     37 
     38   virtual EntryIF* clone() const = 0;
     39   virtual size_t size() const = 0;
     40   virtual size_t symbolSize() const = 0;
     41   virtual size_t relSize() const = 0;
     42   virtual size_t relaSize() const = 0;
     43   virtual size_t emit(uint8_t* pAddress) const = 0;
     44   virtual void setValue(uint64_t pTag, uint64_t pValue) = 0;
     45 };
     46 
     47 template<size_t BITNUMBER, bool LITTLEENDIAN>
     48 class Entry
     49 { };
     50 
     51 template<>
     52 class Entry<32, true> : public EntryIF
     53 {
     54 public:
     55   typedef llvm::ELF::Elf32_Dyn  Pair;
     56   typedef llvm::ELF::Elf32_Sym  Symbol;
     57   typedef llvm::ELF::Elf32_Rel  Rel;
     58   typedef llvm::ELF::Elf32_Rela Rela;
     59 
     60 public:
     61   inline Entry();
     62 
     63   inline ~Entry();
     64 
     65   Entry* clone() const
     66   { return new Entry(); }
     67 
     68   size_t size() const
     69   { return sizeof(Pair); }
     70 
     71   size_t symbolSize() const
     72   { return sizeof(Symbol); }
     73 
     74   size_t relSize() const
     75   { return sizeof(Rel); }
     76 
     77   size_t relaSize() const
     78   { return sizeof(Rela); }
     79 
     80   inline void setValue(uint64_t pTag, uint64_t pValue);
     81 
     82   inline size_t emit(uint8_t* pAddress) const;
     83 
     84 private:
     85   Pair m_Pair;
     86 };
     87 
     88 template<>
     89 class Entry<64, true> : public EntryIF
     90 {
     91 public:
     92   typedef llvm::ELF::Elf64_Dyn  Pair;
     93   typedef llvm::ELF::Elf64_Sym  Symbol;
     94   typedef llvm::ELF::Elf64_Rel  Rel;
     95   typedef llvm::ELF::Elf64_Rela Rela;
     96 
     97 public:
     98   inline Entry();
     99 
    100   inline ~Entry();
    101 
    102   Entry* clone() const
    103   { return new Entry(); }
    104 
    105   size_t size() const
    106   { return sizeof(Pair); }
    107 
    108   size_t symbolSize() const
    109   { return sizeof(Symbol); }
    110 
    111   size_t relSize() const
    112   { return sizeof(Rel); }
    113 
    114   size_t relaSize() const
    115   { return sizeof(Rela); }
    116 
    117   inline void setValue(uint64_t pTag, uint64_t pValue);
    118 
    119   inline size_t emit(uint8_t* pAddress) const;
    120 
    121 private:
    122   Pair m_Pair;
    123 };
    124 
    125 #include "ELFDynamic.tcc"
    126 
    127 } // namespace of elf_dynamic
    128 
    129 /** \class ELFDynamic
    130  *  \brief ELFDynamic is the .dynamic section in ELF shared and executable
    131  *  files.
    132  */
    133 class ELFDynamic
    134 {
    135 public:
    136   typedef std::vector<elf_dynamic::EntryIF*> EntryListType;
    137   typedef EntryListType::iterator iterator;
    138   typedef EntryListType::const_iterator const_iterator;
    139 
    140 public:
    141   ELFDynamic(const GNULDBackend& pBackend, const LinkerConfig& pConfig);
    142 
    143   virtual ~ELFDynamic();
    144 
    145   size_t size() const;
    146 
    147   size_t entrySize() const;
    148 
    149   size_t numOfBytes() const;
    150 
    151   /// reserveEntries - reserve entries
    152   void reserveEntries(const ELFFileFormat& pFormat);
    153 
    154   /// reserveNeedEntry - reserve on DT_NEED entry.
    155   void reserveNeedEntry();
    156 
    157   /// applyEntries - apply entries
    158   void applyEntries(const ELFFileFormat& pFormat);
    159 
    160   void applySoname(uint64_t pStrTabIdx);
    161 
    162   const_iterator needBegin() const { return m_NeedList.begin(); }
    163   iterator       needBegin()       { return m_NeedList.begin(); }
    164 
    165   const_iterator needEnd() const { return m_NeedList.end(); }
    166   iterator       needEnd()       { return m_NeedList.end(); }
    167 
    168   /// emit
    169   void emit(const LDSection& pSection, MemoryRegion& pRegion) const;
    170 
    171 protected:
    172   /// reserveTargetEntries - reserve target dependent entries
    173   virtual void reserveTargetEntries(const ELFFileFormat& pFormat) = 0;
    174 
    175   /// applyTargetEntries - apply target-dependant
    176   virtual void applyTargetEntries(const ELFFileFormat& pFormat) = 0;
    177 
    178 protected:
    179   void reserveOne(uint64_t pTag);
    180 
    181   void applyOne(uint64_t pTag, uint64_t pValue);
    182 
    183   size_t symbolSize() const;
    184 
    185   const LinkerConfig& config() const { return m_Config; }
    186 
    187 private:
    188   EntryListType m_EntryList;
    189   EntryListType m_NeedList;
    190   elf_dynamic::EntryIF* m_pEntryFactory;
    191   const GNULDBackend& m_Backend;
    192   const LinkerConfig& m_Config;
    193 
    194   // The entry reserved and the entry being applied are not must matched.
    195   // For better performance, we use a simple counter and apply entry one-by-one
    196   // by the counter. m_Idx is the counter indicating to the entry being applied.
    197   size_t m_Idx;
    198 };
    199 
    200 } // namespace of mcld
    201 
    202 #endif
    203 
    204