ELFDynamic.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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
18using namespace mcld;
19using namespace elf_dynamic;
20
21//===----------------------------------------------------------------------===//
22// elf_dynamic::EntryIF
23//===----------------------------------------------------------------------===//
24EntryIF::EntryIF()
25{
26}
27
28EntryIF::~EntryIF()
29{
30}
31
32//===----------------------------------------------------------------------===//
33// ELFDynamic
34//===----------------------------------------------------------------------===//
35ELFDynamic::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
52ELFDynamic::~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
70size_t ELFDynamic::size() const
71{
72  return (m_NeedList.size() + m_EntryList.size());
73}
74
75size_t ELFDynamic::numOfBytes() const
76{
77  return size()*entrySize();
78}
79
80size_t ELFDynamic::entrySize() const
81{
82  return m_pEntryFactory->size();
83}
84
85void ELFDynamic::reserveOne(uint64_t pTag)
86{
87  assert(NULL != m_pEntryFactory);
88  m_EntryList.push_back(m_pEntryFactory->clone());
89}
90
91void 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
99void 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
201void 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
327size_t ELFDynamic::symbolSize() const
328{
329  return m_pEntryFactory->symbolSize();
330}
331
332/// reserveNeedEntry - reserve on DT_NEED entry.
333void ELFDynamic::reserveNeedEntry()
334{
335  m_NeedList.push_back(m_pEntryFactory->clone());
336}
337
338/// emit
339void 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
356void ELFDynamic::applySoname(uint64_t pStrTabIdx)
357{
358  applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
359}
360
361