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 
clone()65   Entry* clone() const
66   { return new Entry(); }
67 
size()68   size_t size() const
69   { return sizeof(Pair); }
70 
symbolSize()71   size_t symbolSize() const
72   { return sizeof(Symbol); }
73 
relSize()74   size_t relSize() const
75   { return sizeof(Rel); }
76 
relaSize()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 
clone()102   Entry* clone() const
103   { return new Entry(); }
104 
size()105   size_t size() const
106   { return sizeof(Pair); }
107 
symbolSize()108   size_t symbolSize() const
109   { return sizeof(Symbol); }
110 
relSize()111   size_t relSize() const
112   { return sizeof(Rel); }
113 
relaSize()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 
needBegin()162   const_iterator needBegin() const { return m_NeedList.begin(); }
needBegin()163   iterator       needBegin()       { return m_NeedList.begin(); }
164 
needEnd()165   const_iterator needEnd() const { return m_NeedList.end(); }
needEnd()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 
config()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