ELFDynamic.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
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.hasPreInitArray()) {
114    reserveOne(llvm::ELF::DT_PREINIT_ARRAY); // DT_PREINIT_ARRAY
115    reserveOne(llvm::ELF::DT_PREINIT_ARRAYSZ); // DT_PREINIT_ARRAYSZ
116  }
117
118  if (pFormat.hasInitArray()) {
119    reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY
120    reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ
121  }
122
123  if (pFormat.hasFiniArray()) {
124    reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY
125    reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ
126  }
127
128  if (pFormat.hasHashTab())
129    reserveOne(llvm::ELF::DT_HASH); // DT_HASH
130
131  // FIXME: use llvm enum constant
132  if (pFormat.hasGNUHashTab())
133    reserveOne(0x6ffffef5); // DT_GNU_HASH
134
135  if (pFormat.hasDynSymTab()) {
136    reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
137    reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
138  }
139
140  if (pFormat.hasDynStrTab()) {
141    reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB
142    reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ
143  }
144
145  reserveTargetEntries(pFormat); // DT_PLTGOT
146
147  if (pFormat.hasRelPlt() || pFormat.hasRelaPlt()) {
148    reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
149    reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
150    reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
151  }
152
153  if (pFormat.hasRelDyn()) {
154    reserveOne(llvm::ELF::DT_REL); // DT_REL
155    reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ
156    reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT
157  }
158
159  if (pFormat.hasRelaDyn()) {
160    reserveOne(llvm::ELF::DT_RELA); // DT_RELA
161    reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
162    reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
163  }
164
165  uint64_t dt_flags = 0x0;
166  if (m_Config.options().hasOrigin())
167    dt_flags |= llvm::ELF::DF_ORIGIN;
168  if (m_Config.options().Bsymbolic())
169    dt_flags |= llvm::ELF::DF_SYMBOLIC;
170  if (m_Config.options().hasNow())
171    dt_flags |= llvm::ELF::DF_BIND_NOW;
172  if (m_Backend.hasTextRel())
173    dt_flags |= llvm::ELF::DF_TEXTREL;
174  if (m_Backend.hasStaticTLS() &&
175      (LinkerConfig::DynObj == m_Config.codeGenType()))
176    dt_flags |= llvm::ELF::DF_STATIC_TLS;
177
178  if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
179      0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
180    reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
181
182  if (m_Backend.hasTextRel())
183    reserveOne(llvm::ELF::DT_TEXTREL); // DT_TEXTREL
184
185  if (m_Config.options().hasNow()          ||
186      m_Config.options().hasLoadFltr()     ||
187      m_Config.options().hasOrigin()       ||
188      m_Config.options().hasInterPose()    ||
189      m_Config.options().hasNoDefaultLib() ||
190      m_Config.options().hasNoDump()       ||
191      m_Config.options().Bgroup()          ||
192      ((LinkerConfig::DynObj == m_Config.codeGenType()) &&
193       (m_Config.options().hasNoDelete()  ||
194        m_Config.options().hasInitFirst() ||
195        m_Config.options().hasNoDLOpen()))) {
196    reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
197  }
198
199  reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
200}
201
202/// applyEntries - apply entries
203void ELFDynamic::applyEntries(const ELFFileFormat& pFormat)
204{
205  if (LinkerConfig::DynObj == m_Config.codeGenType() &&
206      m_Config.options().Bsymbolic()) {
207      applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
208  }
209
210  if (pFormat.hasInit())
211    applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT
212
213  if (pFormat.hasFini())
214    applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI
215
216  if (pFormat.hasPreInitArray()) {
217    // DT_PREINIT_ARRAY
218    applyOne(llvm::ELF::DT_PREINIT_ARRAY, pFormat.getPreInitArray().addr());
219    // DT_PREINIT_ARRAYSZ
220    applyOne(llvm::ELF::DT_PREINIT_ARRAYSZ, pFormat.getPreInitArray().size());
221  }
222
223  if (pFormat.hasInitArray()) {
224    // DT_INIT_ARRAY
225    applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
226
227    // DT_INIT_ARRAYSZ
228    applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
229  }
230
231  if (pFormat.hasFiniArray()) {
232    // DT_FINI_ARRAY
233    applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
234
235    // DT_FINI_ARRAYSZ
236    applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
237  }
238
239  if (pFormat.hasHashTab())
240    applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
241
242  // FIXME: use llvm enum constant
243  if (pFormat.hasGNUHashTab())
244    applyOne(0x6ffffef5, pFormat.getGNUHashTab().addr()); // DT_GNU_HASH
245
246  if (pFormat.hasDynSymTab()) {
247    applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
248    applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
249  }
250
251  if (pFormat.hasDynStrTab()) {
252    applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB
253    applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ
254  }
255
256  applyTargetEntries(pFormat); // DT_PLTGOT
257
258  if (pFormat.hasRelPlt()) {
259    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
260    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
261    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
262  }
263  else if (pFormat.hasRelaPlt()) {
264    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
265    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelaPlt().addr()); // DT_JMPREL
266    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelaPlt().size()); // DT_PLTRELSZ
267  }
268
269  if (pFormat.hasRelDyn()) {
270    applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
271    applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ
272    applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT
273  }
274
275  if (pFormat.hasRelaDyn()) {
276    applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA
277    applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ
278    applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
279  }
280
281  if (m_Backend.hasTextRel()) {
282    applyOne(llvm::ELF::DT_TEXTREL, 0x0); // DT_TEXTREL
283
284    if (m_Config.options().warnSharedTextrel() &&
285        LinkerConfig::DynObj == m_Config.codeGenType())
286      mcld::warning(mcld::diag::warn_shared_textrel);
287  }
288
289  uint64_t dt_flags = 0x0;
290  if (m_Config.options().hasOrigin())
291    dt_flags |= llvm::ELF::DF_ORIGIN;
292  if (m_Config.options().Bsymbolic())
293    dt_flags |= llvm::ELF::DF_SYMBOLIC;
294  if (m_Config.options().hasNow())
295    dt_flags |= llvm::ELF::DF_BIND_NOW;
296  if (m_Backend.hasTextRel())
297    dt_flags |= llvm::ELF::DF_TEXTREL;
298  if (m_Backend.hasStaticTLS() &&
299      (LinkerConfig::DynObj == m_Config.codeGenType()))
300    dt_flags |= llvm::ELF::DF_STATIC_TLS;
301
302  if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
303      0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
304    applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
305
306  uint64_t dt_flags_1 = 0x0;
307  if (m_Config.options().hasNow())
308    dt_flags_1 |= llvm::ELF::DF_1_NOW;
309  if (m_Config.options().hasLoadFltr())
310    dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
311  if (m_Config.options().hasOrigin())
312    dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
313  if (m_Config.options().hasInterPose())
314    dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
315  if (m_Config.options().hasNoDefaultLib())
316    dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
317  if (m_Config.options().hasNoDump())
318    dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
319  if (m_Config.options().Bgroup())
320    dt_flags_1 |= llvm::ELF::DF_1_GROUP;
321  if (LinkerConfig::DynObj == m_Config.codeGenType()) {
322    if (m_Config.options().hasNoDelete())
323      dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
324    if (m_Config.options().hasInitFirst())
325      dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
326    if (m_Config.options().hasNoDLOpen())
327      dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
328  }
329  if (0x0 != dt_flags_1)
330    applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1); // DT_FLAGS_1
331
332  applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
333}
334
335/// symbolSize
336size_t ELFDynamic::symbolSize() const
337{
338  return m_pEntryFactory->symbolSize();
339}
340
341/// reserveNeedEntry - reserve on DT_NEED entry.
342void ELFDynamic::reserveNeedEntry()
343{
344  m_NeedList.push_back(m_pEntryFactory->clone());
345}
346
347/// emit
348void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const
349{
350  if (pRegion.size() < pSection.size()) {
351    llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
352                             llvm::Twine(" than the section's demaind.\n"));
353  }
354
355  uint8_t* address = (uint8_t*)pRegion.begin();
356  EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
357  for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
358    address += (*entry)->emit(address);
359
360  entryEnd = m_EntryList.end();
361  for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
362    address += (*entry)->emit(address);
363}
364
365void ELFDynamic::applySoname(uint64_t pStrTabIdx)
366{
367  applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
368}
369
370