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 "mcld/LD/ELFFileFormat.h"
10 #include "mcld/Support/MsgHandling.h"
11 #include "mcld/Target/ELFDynamic.h"
12 #include "mcld/Target/GNULDBackend.h"
13 #include "mcld/LinkerConfig.h"
14
15 #include <llvm/Support/ErrorHandling.h>
16 #include <llvm/Support/Host.h>
17
18 namespace mcld {
19 namespace elf_dynamic {
20
21 //===----------------------------------------------------------------------===//
22 // elf_dynamic::EntryIF
23 //===----------------------------------------------------------------------===//
EntryIF()24 EntryIF::EntryIF() {
25 }
26
~EntryIF()27 EntryIF::~EntryIF() {
28 }
29
30 } // namespace elf_dynamic
31
32 //===----------------------------------------------------------------------===//
33 // ELFDynamic
34 //===----------------------------------------------------------------------===//
ELFDynamic(const GNULDBackend & pParent,const LinkerConfig & pConfig)35 ELFDynamic::ELFDynamic(const GNULDBackend& pParent, const LinkerConfig& pConfig)
36 : m_pEntryFactory(NULL), m_Backend(pParent), m_Config(pConfig), m_Idx(0) {
37 // FIXME: support big-endian machine.
38 if (m_Config.targets().is32Bits()) {
39 if (m_Config.targets().isLittleEndian())
40 m_pEntryFactory = new elf_dynamic::Entry<32, true>();
41 } else if (m_Config.targets().is64Bits()) {
42 if (m_Config.targets().isLittleEndian())
43 m_pEntryFactory = new elf_dynamic::Entry<64, true>();
44 } else {
45 fatal(diag::unsupported_bitclass) << m_Config.targets().triple().str()
46 << m_Config.targets().bitclass();
47 }
48 }
49
~ELFDynamic()50 ELFDynamic::~ELFDynamic() {
51 if (m_pEntryFactory != NULL)
52 delete m_pEntryFactory;
53
54 EntryListType::iterator entry, entryEnd = m_EntryList.end();
55 for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) {
56 if (*entry != NULL)
57 delete (*entry);
58 }
59
60 entryEnd = m_NeedList.end();
61 for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) {
62 if (*entry != NULL)
63 delete (*entry);
64 }
65 }
66
size() const67 size_t ELFDynamic::size() const {
68 return (m_NeedList.size() + m_EntryList.size());
69 }
70
numOfBytes() const71 size_t ELFDynamic::numOfBytes() const {
72 return size() * entrySize();
73 }
74
entrySize() const75 size_t ELFDynamic::entrySize() const {
76 return m_pEntryFactory->size();
77 }
78
reserveOne(uint64_t pTag)79 void ELFDynamic::reserveOne(uint64_t pTag) {
80 assert(m_pEntryFactory != NULL);
81 m_EntryList.push_back(m_pEntryFactory->clone());
82 }
83
applyOne(uint64_t pTag,uint64_t pValue)84 void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue) {
85 assert(m_Idx < m_EntryList.size());
86 m_EntryList[m_Idx]->setValue(pTag, pValue);
87 ++m_Idx;
88 }
89
90 /// reserveEntries - reserve entries
reserveEntries(const ELFFileFormat & pFormat)91 void ELFDynamic::reserveEntries(const ELFFileFormat& pFormat) {
92 if (LinkerConfig::DynObj == m_Config.codeGenType()) {
93 reserveOne(llvm::ELF::DT_SONAME);
94
95 if (m_Config.options().Bsymbolic())
96 reserveOne(llvm::ELF::DT_SYMBOLIC);
97 }
98
99 if (pFormat.hasInit())
100 reserveOne(llvm::ELF::DT_INIT);
101
102 if (pFormat.hasFini())
103 reserveOne(llvm::ELF::DT_FINI);
104
105 if (pFormat.hasPreInitArray()) {
106 reserveOne(llvm::ELF::DT_PREINIT_ARRAY);
107 reserveOne(llvm::ELF::DT_PREINIT_ARRAYSZ);
108 }
109
110 if (pFormat.hasInitArray()) {
111 reserveOne(llvm::ELF::DT_INIT_ARRAY);
112 reserveOne(llvm::ELF::DT_INIT_ARRAYSZ);
113 }
114
115 if (pFormat.hasFiniArray()) {
116 reserveOne(llvm::ELF::DT_FINI_ARRAY);
117 reserveOne(llvm::ELF::DT_FINI_ARRAYSZ);
118 }
119
120 if (pFormat.hasHashTab())
121 reserveOne(llvm::ELF::DT_HASH);
122
123 if (pFormat.hasGNUHashTab())
124 reserveOne(llvm::ELF::DT_GNU_HASH);
125
126 if (pFormat.hasDynSymTab()) {
127 reserveOne(llvm::ELF::DT_SYMTAB);
128 reserveOne(llvm::ELF::DT_SYMENT);
129 }
130
131 if (pFormat.hasDynStrTab()) {
132 reserveOne(llvm::ELF::DT_STRTAB);
133 reserveOne(llvm::ELF::DT_STRSZ);
134 }
135
136 reserveTargetEntries(pFormat);
137
138 if (pFormat.hasRelPlt() || pFormat.hasRelaPlt()) {
139 reserveOne(llvm::ELF::DT_PLTREL);
140 reserveOne(llvm::ELF::DT_JMPREL);
141 reserveOne(llvm::ELF::DT_PLTRELSZ);
142 }
143
144 if (pFormat.hasRelDyn()) {
145 reserveOne(llvm::ELF::DT_REL);
146 reserveOne(llvm::ELF::DT_RELSZ);
147 reserveOne(llvm::ELF::DT_RELENT);
148 }
149
150 if (pFormat.hasRelaDyn()) {
151 reserveOne(llvm::ELF::DT_RELA);
152 reserveOne(llvm::ELF::DT_RELASZ);
153 reserveOne(llvm::ELF::DT_RELAENT);
154 }
155
156 uint64_t dt_flags = 0x0;
157 if (m_Config.options().hasOrigin())
158 dt_flags |= llvm::ELF::DF_ORIGIN;
159 if (m_Config.options().Bsymbolic())
160 dt_flags |= llvm::ELF::DF_SYMBOLIC;
161 if (m_Config.options().hasNow())
162 dt_flags |= llvm::ELF::DF_BIND_NOW;
163 if (m_Backend.hasTextRel())
164 dt_flags |= llvm::ELF::DF_TEXTREL;
165 if (m_Backend.hasStaticTLS() &&
166 (LinkerConfig::DynObj == m_Config.codeGenType()))
167 dt_flags |= llvm::ELF::DF_STATIC_TLS;
168
169 if ((m_Config.options().hasNewDTags() && dt_flags != 0x0) ||
170 (dt_flags & llvm::ELF::DF_STATIC_TLS) != 0x0)
171 reserveOne(llvm::ELF::DT_FLAGS);
172
173 if (m_Backend.hasTextRel())
174 reserveOne(llvm::ELF::DT_TEXTREL);
175
176 if (m_Config.options().hasNow() || m_Config.options().hasLoadFltr() ||
177 m_Config.options().hasOrigin() || m_Config.options().hasInterPose() ||
178 m_Config.options().hasNoDefaultLib() || m_Config.options().hasNoDump() ||
179 m_Config.options().Bgroup() ||
180 ((LinkerConfig::DynObj == m_Config.codeGenType()) &&
181 (m_Config.options().hasNoDelete() || m_Config.options().hasInitFirst() ||
182 m_Config.options().hasNoDLOpen()))) {
183 reserveOne(llvm::ELF::DT_FLAGS_1);
184 }
185
186 unsigned num_spare_dtags = m_Config.options().getNumSpareDTags();
187 for (unsigned i = 0; i < num_spare_dtags; ++i) {
188 reserveOne(llvm::ELF::DT_NULL);
189 }
190 }
191
192 /// applyEntries - apply entries
applyEntries(const ELFFileFormat & pFormat)193 void ELFDynamic::applyEntries(const ELFFileFormat& pFormat) {
194 if (LinkerConfig::DynObj == m_Config.codeGenType() &&
195 m_Config.options().Bsymbolic()) {
196 applyOne(llvm::ELF::DT_SYMBOLIC, 0x0);
197 }
198
199 if (pFormat.hasInit())
200 applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr());
201
202 if (pFormat.hasFini())
203 applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr());
204
205 if (pFormat.hasPreInitArray()) {
206 applyOne(llvm::ELF::DT_PREINIT_ARRAY, pFormat.getPreInitArray().addr());
207 applyOne(llvm::ELF::DT_PREINIT_ARRAYSZ, pFormat.getPreInitArray().size());
208 }
209
210 if (pFormat.hasInitArray()) {
211 applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
212 applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
213 }
214
215 if (pFormat.hasFiniArray()) {
216 applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
217 applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
218 }
219
220 if (pFormat.hasHashTab())
221 applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr());
222
223 if (pFormat.hasGNUHashTab())
224 applyOne(llvm::ELF::DT_GNU_HASH, pFormat.getGNUHashTab().addr());
225
226 if (pFormat.hasDynSymTab()) {
227 applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr());
228 applyOne(llvm::ELF::DT_SYMENT, symbolSize());
229 }
230
231 if (pFormat.hasDynStrTab()) {
232 applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr());
233 applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size());
234 }
235
236 applyTargetEntries(pFormat);
237
238 if (pFormat.hasRelPlt()) {
239 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL);
240 applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr());
241 applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size());
242 } else if (pFormat.hasRelaPlt()) {
243 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA);
244 applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelaPlt().addr());
245 applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelaPlt().size());
246 }
247
248 if (pFormat.hasRelDyn()) {
249 applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr());
250 applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size());
251 applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize());
252 }
253
254 if (pFormat.hasRelaDyn()) {
255 applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr());
256 applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size());
257 applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize());
258 }
259
260 if (m_Backend.hasTextRel()) {
261 applyOne(llvm::ELF::DT_TEXTREL, 0x0);
262
263 if (m_Config.options().warnSharedTextrel() &&
264 LinkerConfig::DynObj == m_Config.codeGenType())
265 mcld::warning(mcld::diag::warn_shared_textrel);
266 }
267
268 uint64_t dt_flags = 0x0;
269 if (m_Config.options().hasOrigin())
270 dt_flags |= llvm::ELF::DF_ORIGIN;
271 if (m_Config.options().Bsymbolic())
272 dt_flags |= llvm::ELF::DF_SYMBOLIC;
273 if (m_Config.options().hasNow())
274 dt_flags |= llvm::ELF::DF_BIND_NOW;
275 if (m_Backend.hasTextRel())
276 dt_flags |= llvm::ELF::DF_TEXTREL;
277 if (m_Backend.hasStaticTLS() &&
278 (LinkerConfig::DynObj == m_Config.codeGenType()))
279 dt_flags |= llvm::ELF::DF_STATIC_TLS;
280
281 if ((m_Config.options().hasNewDTags() && dt_flags != 0x0) ||
282 (dt_flags & llvm::ELF::DF_STATIC_TLS) != 0)
283 applyOne(llvm::ELF::DT_FLAGS, dt_flags);
284
285 uint64_t dt_flags_1 = 0x0;
286 if (m_Config.options().hasNow())
287 dt_flags_1 |= llvm::ELF::DF_1_NOW;
288 if (m_Config.options().hasLoadFltr())
289 dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
290 if (m_Config.options().hasOrigin())
291 dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
292 if (m_Config.options().hasInterPose())
293 dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
294 if (m_Config.options().hasNoDefaultLib())
295 dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
296 if (m_Config.options().hasNoDump())
297 dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
298 if (m_Config.options().Bgroup())
299 dt_flags_1 |= llvm::ELF::DF_1_GROUP;
300 if (LinkerConfig::DynObj == m_Config.codeGenType()) {
301 if (m_Config.options().hasNoDelete())
302 dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
303 if (m_Config.options().hasInitFirst())
304 dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
305 if (m_Config.options().hasNoDLOpen())
306 dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
307 }
308 if (dt_flags_1 != 0x0)
309 applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1);
310
311 unsigned num_spare_dtags = m_Config.options().getNumSpareDTags();
312 for (unsigned i = 0; i < num_spare_dtags; ++i) {
313 applyOne(llvm::ELF::DT_NULL, 0x0);
314 }
315 }
316
317 /// symbolSize
symbolSize() const318 size_t ELFDynamic::symbolSize() const {
319 return m_pEntryFactory->symbolSize();
320 }
321
322 /// reserveNeedEntry - reserve on DT_NEED entry.
reserveNeedEntry()323 void ELFDynamic::reserveNeedEntry() {
324 m_NeedList.push_back(m_pEntryFactory->clone());
325 }
326
327 /// emit
emit(const LDSection & pSection,MemoryRegion & pRegion) const328 void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const {
329 if (pRegion.size() < pSection.size()) {
330 llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
331 llvm::Twine(" than the section's demaind.\n"));
332 }
333
334 uint8_t* address = reinterpret_cast<uint8_t*>(pRegion.begin());
335 EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
336 for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
337 address += (*entry)->emit(address);
338
339 entryEnd = m_EntryList.end();
340 for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
341 address += (*entry)->emit(address);
342 }
343
applySoname(uint64_t pStrTabIdx)344 void ELFDynamic::applySoname(uint64_t pStrTabIdx) {
345 applyOne(llvm::ELF::DT_SONAME, pStrTabIdx);
346 }
347
348 } // namespace mcld
349