• 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 <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 
17 using namespace mcld;
18 using namespace elf_dynamic;
19 
20 //===----------------------------------------------------------------------===//
21 // elf_dynamic::EntryIF
22 //===----------------------------------------------------------------------===//
EntryIF()23 EntryIF::EntryIF()
24 {
25 }
26 
~EntryIF()27 EntryIF::~EntryIF()
28 {
29 }
30 
31 //===----------------------------------------------------------------------===//
32 // ELFDynamic
33 //===----------------------------------------------------------------------===//
ELFDynamic(const GNULDBackend & pParent,const LinkerConfig & pConfig)34 ELFDynamic::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 
~ELFDynamic()51 ELFDynamic::~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 
size() const69 size_t ELFDynamic::size() const
70 {
71   return (m_NeedList.size() + m_EntryList.size());
72 }
73 
numOfBytes() const74 size_t ELFDynamic::numOfBytes() const
75 {
76   return size()*entrySize();
77 }
78 
entrySize() const79 size_t ELFDynamic::entrySize() const
80 {
81   return m_pEntryFactory->size();
82 }
83 
reserveOne(uint64_t pTag)84 void ELFDynamic::reserveOne(uint64_t pTag)
85 {
86   assert(NULL != m_pEntryFactory);
87   m_EntryList.push_back(m_pEntryFactory->clone());
88 }
89 
applyOne(uint64_t pTag,uint64_t pValue)90 void 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
reserveEntries(const ELFFileFormat & pFormat)98 void 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
applyEntries(const ELFFileFormat & pFormat)203 void 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
symbolSize() const336 size_t ELFDynamic::symbolSize() const
337 {
338   return m_pEntryFactory->symbolSize();
339 }
340 
341 /// reserveNeedEntry - reserve on DT_NEED entry.
reserveNeedEntry()342 void ELFDynamic::reserveNeedEntry()
343 {
344   m_NeedList.push_back(m_pEntryFactory->clone());
345 }
346 
347 /// emit
emit(const LDSection & pSection,MemoryRegion & pRegion) const348 void 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 
applySoname(uint64_t pStrTabIdx)365 void ELFDynamic::applySoname(uint64_t pStrTabIdx)
366 {
367   applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
368 }
369 
370