• 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/MemoryRegion.h>
16 #include <mcld/Support/MsgHandling.h>
17 
18 using namespace mcld;
19 using namespace elf_dynamic;
20 
21 //===----------------------------------------------------------------------===//
22 // elf_dynamic::EntryIF
23 //===----------------------------------------------------------------------===//
EntryIF()24 EntryIF::EntryIF()
25 {
26 }
27 
~EntryIF()28 EntryIF::~EntryIF()
29 {
30 }
31 
32 //===----------------------------------------------------------------------===//
33 // ELFDynamic
34 //===----------------------------------------------------------------------===//
ELFDynamic(const GNULDBackend & pParent,const LinkerConfig & pConfig)35 ELFDynamic::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 
~ELFDynamic()52 ELFDynamic::~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 
size() const70 size_t ELFDynamic::size() const
71 {
72   return (m_NeedList.size() + m_EntryList.size());
73 }
74 
numOfBytes() const75 size_t ELFDynamic::numOfBytes() const
76 {
77   return size()*entrySize();
78 }
79 
entrySize() const80 size_t ELFDynamic::entrySize() const
81 {
82   return m_pEntryFactory->size();
83 }
84 
reserveOne(uint64_t pTag)85 void ELFDynamic::reserveOne(uint64_t pTag)
86 {
87   assert(NULL != m_pEntryFactory);
88   m_EntryList.push_back(m_pEntryFactory->clone());
89 }
90 
applyOne(uint64_t pTag,uint64_t pValue)91 void 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
reserveEntries(const ELFFileFormat & pFormat)99 void 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
applyEntries(const ELFFileFormat & pFormat)201 void 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
symbolSize() const327 size_t ELFDynamic::symbolSize() const
328 {
329   return m_pEntryFactory->symbolSize();
330 }
331 
332 /// reserveNeedEntry - reserve on DT_NEED entry.
reserveNeedEntry()333 void ELFDynamic::reserveNeedEntry()
334 {
335   m_NeedList.push_back(m_pEntryFactory->clone());
336 }
337 
338 /// emit
emit(const LDSection & pSection,MemoryRegion & pRegion) const339 void 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 
applySoname(uint64_t pStrTabIdx)356 void ELFDynamic::applySoname(uint64_t pStrTabIdx)
357 {
358   applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
359 }
360 
361