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
18namespace mcld {
19
20class ELFFileFormat;
21class GNULDBackend;
22class LinkerConfig;
23
24namespace elf_dynamic {
25
26/** \class EntryIF
27*  \brief EntryIF provides a common interface for one entry in the dynamic
28*  section
29*/
30class EntryIF
31{
32protected:
33  EntryIF();
34
35public:
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
47template<size_t BITNUMBER, bool LITTLEENDIAN>
48class Entry
49{ };
50
51template<>
52class Entry<32, true> : public EntryIF
53{
54public:
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
60public:
61  inline Entry();
62
63  inline ~Entry();
64
65  Entry* clone() const
66  { return new Entry(); }
67
68  size_t size() const
69  { return sizeof(Pair); }
70
71  size_t symbolSize() const
72  { return sizeof(Symbol); }
73
74  size_t relSize() const
75  { return sizeof(Rel); }
76
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
84private:
85  Pair m_Pair;
86};
87
88template<>
89class Entry<64, true> : public EntryIF
90{
91public:
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
97public:
98  inline Entry();
99
100  inline ~Entry();
101
102  Entry* clone() const
103  { return new Entry(); }
104
105  size_t size() const
106  { return sizeof(Pair); }
107
108  size_t symbolSize() const
109  { return sizeof(Symbol); }
110
111  size_t relSize() const
112  { return sizeof(Rel); }
113
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
121private:
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 */
133class ELFDynamic
134{
135public:
136  typedef std::vector<elf_dynamic::EntryIF*> EntryListType;
137  typedef EntryListType::iterator iterator;
138  typedef EntryListType::const_iterator const_iterator;
139
140public:
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
162  const_iterator needBegin() const { return m_NeedList.begin(); }
163  iterator       needBegin()       { return m_NeedList.begin(); }
164
165  const_iterator needEnd() const { return m_NeedList.end(); }
166  iterator       needEnd()       { return m_NeedList.end(); }
167
168  /// emit
169  void emit(const LDSection& pSection, MemoryRegion& pRegion) const;
170
171protected:
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
178protected:
179  void reserveOne(uint64_t pTag);
180
181  void applyOne(uint64_t pTag, uint64_t pValue);
182
183  size_t symbolSize() const;
184
185  const LinkerConfig& config() const { return m_Config; }
186
187private:
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