• 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/MC/MCLDInfo.h>
15 #include <mcld/Support/MemoryRegion.h>
16 
17 using namespace mcld;
18 using namespace elf_dynamic;
19 
20 //===----------------------------------------------------------------------===//
21 // elf_dynamic::EntryIF
EntryIF()22 EntryIF::EntryIF()
23 {
24 }
25 
~EntryIF()26 EntryIF::~EntryIF()
27 {
28 }
29 
30 //===----------------------------------------------------------------------===//
31 // ELFDynamic
ELFDynamic(const GNULDBackend & pParent)32 ELFDynamic::ELFDynamic(const GNULDBackend& pParent)
33   : m_pEntryFactory(NULL), m_Idx(0) {
34   if (32 == pParent.bitclass() && pParent.isLittleEndian()) {
35     m_pEntryFactory = new Entry<32, true>();
36   }
37   // FIXME: support big-endian and 64-bit machine.
38 }
39 
40 
~ELFDynamic()41 ELFDynamic::~ELFDynamic()
42 {
43   if (NULL != m_pEntryFactory)
44     delete m_pEntryFactory;
45 
46   EntryListType::iterator entry, entryEnd = m_EntryList.end();
47   for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) {
48     if (NULL != *entry)
49       delete (*entry);
50   }
51 
52   entryEnd = m_NeedList.end();
53   for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) {
54     if (NULL != *entry)
55       delete (*entry);
56   }
57 }
58 
size() const59 size_t ELFDynamic::size() const
60 {
61   return (m_NeedList.size() + m_EntryList.size());
62 }
63 
numOfBytes() const64 size_t ELFDynamic::numOfBytes() const
65 {
66   return size()*entrySize();
67 }
68 
entrySize() const69 size_t ELFDynamic::entrySize() const
70 {
71   return m_pEntryFactory->size();
72 }
73 
reserveOne(uint64_t pTag)74 void ELFDynamic::reserveOne(uint64_t pTag)
75 {
76   assert(NULL != m_pEntryFactory);
77   m_EntryList.push_back(new elf_dynamic::Entry<32, true>());
78 }
79 
applyOne(uint64_t pTag,uint64_t pValue)80 void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue)
81 {
82   assert(m_Idx < m_EntryList.size());
83   m_EntryList[m_Idx]->setValue(pTag, pValue);
84   ++m_Idx;
85 }
86 
87 
88 /// reserveEntries - reserve entries
reserveEntries(const MCLDInfo & pLDInfo,const ELFFileFormat & pFormat)89 void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
90                                 const ELFFileFormat& pFormat)
91 {
92   if (pLDInfo.output().type() == Output::DynObj) {
93     reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
94 
95     if (pLDInfo.options().Bsymbolic())
96       reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
97   }
98 
99   if (pFormat.hasInit())
100     reserveOne(llvm::ELF::DT_INIT); // DT_INIT
101 
102   if (pFormat.hasFini())
103     reserveOne(llvm::ELF::DT_FINI); // DT_FINI
104 
105   if (pFormat.hasInitArray()) {
106     reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY
107     reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ
108   }
109 
110   if (pFormat.hasFiniArray()) {
111     reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY
112     reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ
113   }
114 
115   if (pFormat.hasHashTab())
116     reserveOne(llvm::ELF::DT_HASH); // DT_HASH
117 
118   if (pFormat.hasDynSymTab()) {
119     reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
120     reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
121   }
122 
123   if (pFormat.hasDynStrTab()) {
124     reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB
125     reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ
126   }
127 
128   reserveTargetEntries(pFormat); // DT_PLTGOT
129 
130   if (pFormat.hasRelPlt() || pFormat.hasRelaPlt())
131     reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
132 
133   if (pFormat.hasPLT()) {
134     reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
135     reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
136   }
137 
138   if (pFormat.hasRelDyn()) {
139     reserveOne(llvm::ELF::DT_REL); // DT_REL
140     reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ
141     reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT
142   }
143 
144   if (pFormat.hasRelaDyn()) {
145     reserveOne(llvm::ELF::DT_RELA); // DT_RELA
146     reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
147     reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
148   }
149   reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
150 }
151 
152 /// applyEntries - apply entries
applyEntries(const MCLDInfo & pInfo,const ELFFileFormat & pFormat)153 void ELFDynamic::applyEntries(const MCLDInfo& pInfo,
154                               const ELFFileFormat& pFormat)
155 {
156   if (pInfo.output().type() == Output::DynObj &&
157       pInfo.options().Bsymbolic()) {
158       applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
159   }
160 
161   if (pFormat.hasInit())
162     applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT
163 
164   if (pFormat.hasFini())
165     applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI
166 
167   if (pFormat.hasInitArray()) {
168     // DT_INIT_ARRAY
169     applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
170 
171     // DT_INIT_ARRAYSZ
172     applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
173   }
174 
175   if (pFormat.hasFiniArray()) {
176     // DT_FINI_ARRAY
177     applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
178 
179     // DT_FINI_ARRAYSZ
180     applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
181   }
182 
183   if (pFormat.hasHashTab())
184     applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
185 
186   if (pFormat.hasDynSymTab()) {
187     applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
188     applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
189   }
190 
191   if (pFormat.hasDynStrTab()) {
192     applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB
193     applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ
194   }
195 
196   applyTargetEntries(pFormat); // DT_PLTGOT
197 
198   if (pFormat.hasRelPlt())
199     applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
200   else if (pFormat.hasRelaPlt())
201     applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
202 
203   if (pFormat.hasRelPlt()) {
204     applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
205     applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
206   }
207 
208   if (pFormat.hasRelDyn()) {
209     applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
210     applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ
211     applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT
212   }
213 
214   if (pFormat.hasRelaDyn()) {
215     applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA
216     applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ
217     applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
218   }
219 
220   applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
221 }
222 
223 /// symbolSize
symbolSize() const224 size_t ELFDynamic::symbolSize() const
225 {
226   return m_pEntryFactory->symbolSize();
227 }
228 
229 /// reserveNeedEntry - reserve on DT_NEED entry.
reserveNeedEntry()230 void ELFDynamic::reserveNeedEntry()
231 {
232   m_NeedList.push_back(m_pEntryFactory->clone());
233 }
234 
235 /// emit
emit(const LDSection & pSection,MemoryRegion & pRegion) const236 void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const
237 {
238   if (pRegion.size() < pSection.size()) {
239     llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
240                              llvm::Twine(" than the section's demaind.\n"));
241   }
242 
243   uint8_t* address = (uint8_t*)pRegion.start();
244   EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
245   for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
246     address += (*entry)->emit(address);
247 
248   entryEnd = m_EntryList.end();
249   for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
250     address += (*entry)->emit(address);
251 }
252 
applySoname(uint64_t pStrTabIdx)253 void ELFDynamic::applySoname(uint64_t pStrTabIdx)
254 {
255   applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
256 }
257 
258