ELFDynamic.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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
18namespace mcld {
19namespace elf_dynamic {
20
21//===----------------------------------------------------------------------===//
22// elf_dynamic::EntryIF
23//===----------------------------------------------------------------------===//
24EntryIF::EntryIF() {
25}
26
27EntryIF::~EntryIF() {
28}
29
30}  // namespace elf_dynamic
31
32//===----------------------------------------------------------------------===//
33// ELFDynamic
34//===----------------------------------------------------------------------===//
35ELFDynamic::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
50ELFDynamic::~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
67size_t ELFDynamic::size() const {
68  return (m_NeedList.size() + m_EntryList.size());
69}
70
71size_t ELFDynamic::numOfBytes() const {
72  return size() * entrySize();
73}
74
75size_t ELFDynamic::entrySize() const {
76  return m_pEntryFactory->size();
77}
78
79void ELFDynamic::reserveOne(uint64_t pTag) {
80  assert(m_pEntryFactory != NULL);
81  m_EntryList.push_back(m_pEntryFactory->clone());
82}
83
84void 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
91void 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  reserveOne(llvm::ELF::DT_NULL);
187}
188
189/// applyEntries - apply entries
190void ELFDynamic::applyEntries(const ELFFileFormat& pFormat) {
191  if (LinkerConfig::DynObj == m_Config.codeGenType() &&
192      m_Config.options().Bsymbolic()) {
193    applyOne(llvm::ELF::DT_SYMBOLIC, 0x0);
194  }
195
196  if (pFormat.hasInit())
197    applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr());
198
199  if (pFormat.hasFini())
200    applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr());
201
202  if (pFormat.hasPreInitArray()) {
203    applyOne(llvm::ELF::DT_PREINIT_ARRAY, pFormat.getPreInitArray().addr());
204    applyOne(llvm::ELF::DT_PREINIT_ARRAYSZ, pFormat.getPreInitArray().size());
205  }
206
207  if (pFormat.hasInitArray()) {
208    applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
209    applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
210  }
211
212  if (pFormat.hasFiniArray()) {
213    applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
214    applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
215  }
216
217  if (pFormat.hasHashTab())
218    applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr());
219
220  if (pFormat.hasGNUHashTab())
221    applyOne(llvm::ELF::DT_GNU_HASH, pFormat.getGNUHashTab().addr());
222
223  if (pFormat.hasDynSymTab()) {
224    applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr());
225    applyOne(llvm::ELF::DT_SYMENT, symbolSize());
226  }
227
228  if (pFormat.hasDynStrTab()) {
229    applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr());
230    applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size());
231  }
232
233  applyTargetEntries(pFormat);
234
235  if (pFormat.hasRelPlt()) {
236    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL);
237    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr());
238    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size());
239  } else if (pFormat.hasRelaPlt()) {
240    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA);
241    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelaPlt().addr());
242    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelaPlt().size());
243  }
244
245  if (pFormat.hasRelDyn()) {
246    applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr());
247    applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size());
248    applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize());
249  }
250
251  if (pFormat.hasRelaDyn()) {
252    applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr());
253    applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size());
254    applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize());
255  }
256
257  if (m_Backend.hasTextRel()) {
258    applyOne(llvm::ELF::DT_TEXTREL, 0x0);
259
260    if (m_Config.options().warnSharedTextrel() &&
261        LinkerConfig::DynObj == m_Config.codeGenType())
262      mcld::warning(mcld::diag::warn_shared_textrel);
263  }
264
265  uint64_t dt_flags = 0x0;
266  if (m_Config.options().hasOrigin())
267    dt_flags |= llvm::ELF::DF_ORIGIN;
268  if (m_Config.options().Bsymbolic())
269    dt_flags |= llvm::ELF::DF_SYMBOLIC;
270  if (m_Config.options().hasNow())
271    dt_flags |= llvm::ELF::DF_BIND_NOW;
272  if (m_Backend.hasTextRel())
273    dt_flags |= llvm::ELF::DF_TEXTREL;
274  if (m_Backend.hasStaticTLS() &&
275      (LinkerConfig::DynObj == m_Config.codeGenType()))
276    dt_flags |= llvm::ELF::DF_STATIC_TLS;
277
278  if ((m_Config.options().hasNewDTags() && dt_flags != 0x0) ||
279      (dt_flags & llvm::ELF::DF_STATIC_TLS) != 0)
280    applyOne(llvm::ELF::DT_FLAGS, dt_flags);
281
282  uint64_t dt_flags_1 = 0x0;
283  if (m_Config.options().hasNow())
284    dt_flags_1 |= llvm::ELF::DF_1_NOW;
285  if (m_Config.options().hasLoadFltr())
286    dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
287  if (m_Config.options().hasOrigin())
288    dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
289  if (m_Config.options().hasInterPose())
290    dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
291  if (m_Config.options().hasNoDefaultLib())
292    dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
293  if (m_Config.options().hasNoDump())
294    dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
295  if (m_Config.options().Bgroup())
296    dt_flags_1 |= llvm::ELF::DF_1_GROUP;
297  if (LinkerConfig::DynObj == m_Config.codeGenType()) {
298    if (m_Config.options().hasNoDelete())
299      dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
300    if (m_Config.options().hasInitFirst())
301      dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
302    if (m_Config.options().hasNoDLOpen())
303      dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
304  }
305  if (dt_flags_1 != 0x0)
306    applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1);
307
308  applyOne(llvm::ELF::DT_NULL, 0x0);
309}
310
311/// symbolSize
312size_t ELFDynamic::symbolSize() const {
313  return m_pEntryFactory->symbolSize();
314}
315
316/// reserveNeedEntry - reserve on DT_NEED entry.
317void ELFDynamic::reserveNeedEntry() {
318  m_NeedList.push_back(m_pEntryFactory->clone());
319}
320
321/// emit
322void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const {
323  if (pRegion.size() < pSection.size()) {
324    llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
325                             llvm::Twine(" than the section's demaind.\n"));
326  }
327
328  uint8_t* address = reinterpret_cast<uint8_t*>(pRegion.begin());
329  EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
330  for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
331    address += (*entry)->emit(address);
332
333  entryEnd = m_EntryList.end();
334  for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
335    address += (*entry)->emit(address);
336}
337
338void ELFDynamic::applySoname(uint64_t pStrTabIdx) {
339  applyOne(llvm::ELF::DT_SONAME, pStrTabIdx);
340}
341
342}  // namespace mcld
343