1 //===- ELFDynamic.cpp ------------- ------------------------------------===//
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 #include <llvm/Support/Host.h>
10 #include <llvm/Support/ErrorHandling.h>
11 #include <mcld/Target/ELFDynamic.h>
12 #include <mcld/Target/GNULDBackend.h>
13 #include <mcld/LD/ELFFileFormat.h>
14 #include <mcld/MC/MCLDInfo.h>
15 #include <mcld/Support/MemoryRegion.h>
16
17 using namespace mcld;
18 using namespace elf_dynamic;
19
20 //===----------------------------------------------------------------------===//
21 // elf_dynamic::EntryIF
EntryIF()22 EntryIF::EntryIF()
23 {
24 }
25
~EntryIF()26 EntryIF::~EntryIF()
27 {
28 }
29
30 //===----------------------------------------------------------------------===//
31 // ELFDynamic
ELFDynamic(const GNULDBackend & pParent)32 ELFDynamic::ELFDynamic(const GNULDBackend& pParent)
33 : m_pEntryFactory(NULL), m_Idx(0) {
34 if (32 == pParent.bitclass() && pParent.isLittleEndian()) {
35 m_pEntryFactory = new Entry<32, true>();
36 }
37 // FIXME: support big-endian and 64-bit machine.
38 }
39
40
~ELFDynamic()41 ELFDynamic::~ELFDynamic()
42 {
43 if (NULL != m_pEntryFactory)
44 delete m_pEntryFactory;
45
46 EntryListType::iterator entry, entryEnd = m_EntryList.end();
47 for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) {
48 if (NULL != *entry)
49 delete (*entry);
50 }
51
52 entryEnd = m_NeedList.end();
53 for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) {
54 if (NULL != *entry)
55 delete (*entry);
56 }
57 }
58
size() const59 size_t ELFDynamic::size() const
60 {
61 return (m_NeedList.size() + m_EntryList.size());
62 }
63
numOfBytes() const64 size_t ELFDynamic::numOfBytes() const
65 {
66 return size()*entrySize();
67 }
68
entrySize() const69 size_t ELFDynamic::entrySize() const
70 {
71 return m_pEntryFactory->size();
72 }
73
reserveOne(uint64_t pTag)74 void ELFDynamic::reserveOne(uint64_t pTag)
75 {
76 assert(NULL != m_pEntryFactory);
77 m_EntryList.push_back(new elf_dynamic::Entry<32, true>());
78 }
79
applyOne(uint64_t pTag,uint64_t pValue)80 void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue)
81 {
82 assert(m_Idx < m_EntryList.size());
83 m_EntryList[m_Idx]->setValue(pTag, pValue);
84 ++m_Idx;
85 }
86
87
88 /// reserveEntries - reserve entries
reserveEntries(const MCLDInfo & pLDInfo,const ELFFileFormat & pFormat)89 void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
90 const ELFFileFormat& pFormat)
91 {
92 if (pLDInfo.output().type() == Output::DynObj) {
93 reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
94
95 if (pLDInfo.options().Bsymbolic())
96 reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
97 }
98
99 if (pFormat.hasInit())
100 reserveOne(llvm::ELF::DT_INIT); // DT_INIT
101
102 if (pFormat.hasFini())
103 reserveOne(llvm::ELF::DT_FINI); // DT_FINI
104
105 if (pFormat.hasInitArray()) {
106 reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY
107 reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ
108 }
109
110 if (pFormat.hasFiniArray()) {
111 reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY
112 reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ
113 }
114
115 if (pFormat.hasHashTab())
116 reserveOne(llvm::ELF::DT_HASH); // DT_HASH
117
118 if (pFormat.hasDynSymTab()) {
119 reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
120 reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
121 }
122
123 if (pFormat.hasDynStrTab()) {
124 reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB
125 reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ
126 }
127
128 reserveTargetEntries(pFormat); // DT_PLTGOT
129
130 if (pFormat.hasRelPlt() || pFormat.hasRelaPlt())
131 reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
132
133 if (pFormat.hasPLT()) {
134 reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
135 reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
136 }
137
138 if (pFormat.hasRelDyn()) {
139 reserveOne(llvm::ELF::DT_REL); // DT_REL
140 reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ
141 reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT
142 }
143
144 if (pFormat.hasRelaDyn()) {
145 reserveOne(llvm::ELF::DT_RELA); // DT_RELA
146 reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
147 reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
148 }
149 reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
150 }
151
152 /// applyEntries - apply entries
applyEntries(const MCLDInfo & pInfo,const ELFFileFormat & pFormat)153 void ELFDynamic::applyEntries(const MCLDInfo& pInfo,
154 const ELFFileFormat& pFormat)
155 {
156 if (pInfo.output().type() == Output::DynObj &&
157 pInfo.options().Bsymbolic()) {
158 applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
159 }
160
161 if (pFormat.hasInit())
162 applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT
163
164 if (pFormat.hasFini())
165 applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI
166
167 if (pFormat.hasInitArray()) {
168 // DT_INIT_ARRAY
169 applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
170
171 // DT_INIT_ARRAYSZ
172 applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
173 }
174
175 if (pFormat.hasFiniArray()) {
176 // DT_FINI_ARRAY
177 applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
178
179 // DT_FINI_ARRAYSZ
180 applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
181 }
182
183 if (pFormat.hasHashTab())
184 applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
185
186 if (pFormat.hasDynSymTab()) {
187 applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
188 applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
189 }
190
191 if (pFormat.hasDynStrTab()) {
192 applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB
193 applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ
194 }
195
196 applyTargetEntries(pFormat); // DT_PLTGOT
197
198 if (pFormat.hasRelPlt())
199 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
200 else if (pFormat.hasRelaPlt())
201 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
202
203 if (pFormat.hasRelPlt()) {
204 applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
205 applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
206 }
207
208 if (pFormat.hasRelDyn()) {
209 applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
210 applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ
211 applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT
212 }
213
214 if (pFormat.hasRelaDyn()) {
215 applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA
216 applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ
217 applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
218 }
219
220 applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
221 }
222
223 /// symbolSize
symbolSize() const224 size_t ELFDynamic::symbolSize() const
225 {
226 return m_pEntryFactory->symbolSize();
227 }
228
229 /// reserveNeedEntry - reserve on DT_NEED entry.
reserveNeedEntry()230 void ELFDynamic::reserveNeedEntry()
231 {
232 m_NeedList.push_back(m_pEntryFactory->clone());
233 }
234
235 /// emit
emit(const LDSection & pSection,MemoryRegion & pRegion) const236 void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const
237 {
238 if (pRegion.size() < pSection.size()) {
239 llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
240 llvm::Twine(" than the section's demaind.\n"));
241 }
242
243 uint8_t* address = (uint8_t*)pRegion.start();
244 EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
245 for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
246 address += (*entry)->emit(address);
247
248 entryEnd = m_EntryList.end();
249 for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
250 address += (*entry)->emit(address);
251 }
252
applySoname(uint64_t pStrTabIdx)253 void ELFDynamic::applySoname(uint64_t pStrTabIdx)
254 {
255 applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
256 }
257
258