• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 namespace mcld {
19 namespace elf_dynamic {
20 
21 //===----------------------------------------------------------------------===//
22 // elf_dynamic::EntryIF
23 //===----------------------------------------------------------------------===//
EntryIF()24 EntryIF::EntryIF() {
25 }
26 
~EntryIF()27 EntryIF::~EntryIF() {
28 }
29 
30 }  // namespace elf_dynamic
31 
32 //===----------------------------------------------------------------------===//
33 // ELFDynamic
34 //===----------------------------------------------------------------------===//
ELFDynamic(const GNULDBackend & pParent,const LinkerConfig & pConfig)35 ELFDynamic::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 
~ELFDynamic()50 ELFDynamic::~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 
size() const67 size_t ELFDynamic::size() const {
68   return (m_NeedList.size() + m_EntryList.size());
69 }
70 
numOfBytes() const71 size_t ELFDynamic::numOfBytes() const {
72   return size() * entrySize();
73 }
74 
entrySize() const75 size_t ELFDynamic::entrySize() const {
76   return m_pEntryFactory->size();
77 }
78 
reserveOne(uint64_t pTag)79 void ELFDynamic::reserveOne(uint64_t pTag) {
80   assert(m_pEntryFactory != NULL);
81   m_EntryList.push_back(m_pEntryFactory->clone());
82 }
83 
applyOne(uint64_t pTag,uint64_t pValue)84 void 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
reserveEntries(const ELFFileFormat & pFormat)91 void 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
applyEntries(const ELFFileFormat & pFormat)193 void 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
symbolSize() const318 size_t ELFDynamic::symbolSize() const {
319   return m_pEntryFactory->symbolSize();
320 }
321 
322 /// reserveNeedEntry - reserve on DT_NEED entry.
reserveNeedEntry()323 void ELFDynamic::reserveNeedEntry() {
324   m_NeedList.push_back(m_pEntryFactory->clone());
325 }
326 
327 /// emit
emit(const LDSection & pSection,MemoryRegion & pRegion) const328 void 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 
applySoname(uint64_t pStrTabIdx)344 void ELFDynamic::applySoname(uint64_t pStrTabIdx) {
345   applyOne(llvm::ELF::DT_SONAME, pStrTabIdx);
346 }
347 
348 }  // namespace mcld
349