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