ELFDynamic.h revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
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#ifdef ENABLE_UNITTEST
12#include <gtest.h>
13#endif
14
15#include <mcld/LD/LDSection.h>
16#include <mcld/Support/FileOutputBuffer.h>
17#include <llvm/Support/ELF.h>
18#include <vector>
19#include <cstring>
20
21namespace mcld {
22
23class ELFFileFormat;
24class GNULDBackend;
25class LinkerConfig;
26
27namespace elf_dynamic {
28
29/** \class EntryIF
30*  \brief EntryIF provides a common interface for one entry in the dynamic
31*  section
32*/
33class EntryIF
34{
35protected:
36  EntryIF();
37
38public:
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
50template<size_t BITNUMBER, bool LITTLEENDIAN>
51class Entry
52{ };
53
54template<>
55class Entry<32, true> : public EntryIF
56{
57public:
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
63public:
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
87private:
88  Pair m_Pair;
89};
90
91template<>
92class Entry<64, true> : public EntryIF
93{
94public:
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
100public:
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
124private:
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 */
136class ELFDynamic
137{
138public:
139  typedef std::vector<elf_dynamic::EntryIF*> EntryListType;
140  typedef EntryListType::iterator iterator;
141  typedef EntryListType::const_iterator const_iterator;
142
143public:
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
174protected:
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
181protected:
182  void reserveOne(uint64_t pTag);
183
184  void applyOne(uint64_t pTag, uint64_t pValue);
185
186  size_t symbolSize() const;
187
188  const LinkerConfig& config() const { return m_Config; }
189
190private:
191  EntryListType m_EntryList;
192  EntryListType m_NeedList;
193  elf_dynamic::EntryIF* m_pEntryFactory;
194  const GNULDBackend& m_Backend;
195  const LinkerConfig& m_Config;
196
197  // The entry reserved and the entry being applied are not must matched.
198  // For better performance, we use a simple counter and apply entry one-by-one
199  // by the counter. m_Idx is the counter indicating to the entry being applied.
200  size_t m_Idx;
201};
202
203} // namespace of mcld
204
205#endif
206
207