• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
clone()68   Entry* clone() const
69   { return new Entry(); }
70 
size()71   size_t size() const
72   { return sizeof(Pair); }
73 
symbolSize()74   size_t symbolSize() const
75   { return sizeof(Symbol); }
76 
relSize()77   size_t relSize() const
78   { return sizeof(Rel); }
79 
relaSize()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 
clone()105   Entry* clone() const
106   { return new Entry(); }
107 
size()108   size_t size() const
109   { return sizeof(Pair); }
110 
symbolSize()111   size_t symbolSize() const
112   { return sizeof(Symbol); }
113 
relSize()114   size_t relSize() const
115   { return sizeof(Rel); }
116 
relaSize()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 
needBegin()165   const_iterator needBegin() const { return m_NeedList.begin(); }
needBegin()166   iterator       needBegin()       { return m_NeedList.begin(); }
167 
needEnd()168   const_iterator needEnd() const { return m_NeedList.end(); }
needEnd()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