ELFDynamic.h revision 37b74a387bb3993387029859c2d9d051c41c724e
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 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
46template <size_t BITNUMBER, bool LITTLEENDIAN>
47class Entry {};
48
49template <>
50class 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
62  Entry* clone() const { return new Entry(); }
63
64  size_t size() const { return sizeof(Pair); }
65
66  size_t symbolSize() const { return sizeof(Symbol); }
67
68  size_t relSize() const { return sizeof(Rel); }
69
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
80template <>
81class 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
93  Entry* clone() const { return new Entry(); }
94
95  size_t size() const { return sizeof(Pair); }
96
97  size_t symbolSize() const { return sizeof(Symbol); }
98
99  size_t relSize() const { return sizeof(Rel); }
100
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 */
119class 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
147  const_iterator needBegin() const { return m_NeedList.begin(); }
148  iterator needBegin() { return m_NeedList.begin(); }
149
150  const_iterator needEnd() const { return m_NeedList.end(); }
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
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