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