ELFDynamic.cpp revision 04c59f3b00def22b7c75f5a490c323cec58a7c71
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  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
193void 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
318size_t ELFDynamic::symbolSize() const {
319  return m_pEntryFactory->symbolSize();
320}
321
322/// reserveNeedEntry - reserve on DT_NEED entry.
323void ELFDynamic::reserveNeedEntry() {
324  m_NeedList.push_back(m_pEntryFactory->clone());
325}
326
327/// emit
328void 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
344void ELFDynamic::applySoname(uint64_t pStrTabIdx) {
345  applyOne(llvm::ELF::DT_SONAME, pStrTabIdx);
346}
347
348}  // namespace mcld
349