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