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