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
20namespace mcld
21{
22
23class GNULDBackend;
24class ELFFileFormat;
25class MCLDInfo;
26class MemoryRegion;
27
28namespace elf_dynamic {
29
30/** \class EntryIF
31*  \brief EntryIF provides a common interface for one entry in the dynamic
32*  section
33*/
34class EntryIF
35{
36protected:
37  EntryIF();
38
39public:
40  virtual ~EntryIF();
41
42  virtual EntryIF* clone() const = 0;
43  virtual size_t size() const = 0;
44  virtual size_t symbolSize() const = 0;
45  virtual size_t relSize() const = 0;
46  virtual size_t relaSize() const = 0;
47  virtual size_t emit(uint8_t* pAddress) const = 0;
48  virtual void setValue(uint64_t pTag, uint64_t pValue) = 0;
49};
50
51template<size_t BITNUMBER, bool LITTLEENDIAN>
52class Entry
53{ };
54
55template<>
56class Entry<32, true> : public EntryIF
57{
58public:
59  typedef llvm::ELF::Elf32_Dyn  Pair;
60  typedef llvm::ELF::Elf32_Sym  Symbol;
61  typedef llvm::ELF::Elf32_Rel  Rel;
62  typedef llvm::ELF::Elf32_Rela Rela;
63
64public:
65  inline Entry();
66
67  inline ~Entry();
68
69  Entry* clone() const
70  { return new Entry(); }
71
72  size_t size() const
73  { return sizeof(Pair); }
74
75  size_t symbolSize() const
76  { return sizeof(Symbol); }
77
78  size_t relSize() const
79  { return sizeof(Rel); }
80
81  size_t relaSize() const
82  { return sizeof(Rela); }
83
84  inline void setValue(uint64_t pTag, uint64_t pValue);
85
86  inline size_t emit(uint8_t* pAddress) const;
87
88private:
89  Pair m_Pair;
90};
91
92#include "ELFDynamic.tcc"
93
94} // namespace of elf_dynamic
95
96/** \class ELFDynamic
97 *  \brief ELFDynamic is the .dynamic section in ELF shared and executable
98 *  files.
99 */
100class ELFDynamic
101{
102public:
103  typedef std::vector<elf_dynamic::EntryIF*> EntryListType;
104  typedef EntryListType::iterator iterator;
105  typedef EntryListType::const_iterator const_iterator;
106
107public:
108  ELFDynamic(const GNULDBackend& pParent);
109
110  virtual ~ELFDynamic();
111
112  size_t size() const;
113
114  size_t entrySize() const;
115
116  size_t numOfBytes() const;
117
118  /// reserveEntries - reserve entries
119  void reserveEntries(const MCLDInfo& pInfo,
120                      const ELFFileFormat& pFormat);
121
122  /// reserveNeedEntry - reserve on DT_NEED entry.
123  void reserveNeedEntry();
124
125  /// applyEntries - apply entries
126  void applyEntries(const MCLDInfo& pInfo,
127                    const ELFFileFormat& pFormat);
128
129  void applySoname(uint64_t pStrTabIdx);
130
131  iterator needBegin()
132  { return m_NeedList.begin(); }
133
134  iterator needEnd()
135  { return m_NeedList.end(); }
136
137  const_iterator needBegin() const
138  { return m_NeedList.begin(); }
139
140  const_iterator needEnd() const
141  { return m_NeedList.end(); }
142
143  /// emit
144  void emit(const LDSection& pSection, MemoryRegion& pRegion) const;
145
146protected:
147  /// reserveTargetEntries - reserve target dependent entries
148  virtual void reserveTargetEntries(const ELFFileFormat& pFormat) = 0;
149
150  /// applyTargetEntries - apply target-dependant
151  virtual void applyTargetEntries(const ELFFileFormat& pFormat) = 0;
152
153protected:
154  void reserveOne(uint64_t pTag);
155
156  void applyOne(uint64_t pTag, uint64_t pValue);
157
158  size_t symbolSize() const;
159
160private:
161  EntryListType m_EntryList;
162  EntryListType m_NeedList;
163  elf_dynamic::EntryIF* m_pEntryFactory;
164
165  // The entry reserved and the entry being applied are not must matched.
166  // For better performance, we use a simple counter and apply entry one-by-one
167  // by the counter. m_Idx is the counter indicating to the entry being applied.
168  size_t m_Idx;
169};
170
171} // namespace of mcld
172
173#endif
174
175