• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ELF_OBJECT_HXX
18 #define ELF_OBJECT_HXX
19 
20 #include "ELFHeader.h"
21 #include "ELFReloc.h"
22 #include "ELFSection.h"
23 #include "ELFSectionHeaderTable.h"
24 #include "StubLayout.h"
25 #include "ELF.h"
26 
27 #include <llvm/ADT/SmallVector.h>
28 
29 #include "utils/rsl_assert.h"
30 
31 template <unsigned Bitwidth>
32 template <typename Archiver>
33 inline ELFObject<Bitwidth> *
read(Archiver & AR)34 ELFObject<Bitwidth>::read(Archiver &AR) {
35   llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy());
36 
37   // Read header
38   object->header.reset(ELFHeaderTy::read(AR));
39   if (!object->header) {
40     return 0;
41   }
42 
43   // Read section table
44   object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get()));
45   if (!object->shtab) {
46     return 0;
47   }
48 
49   // Read each section
50   llvm::SmallVector<size_t, 4> progbits_ndx;
51   for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) {
52     if ((*object->shtab)[i]->getType() == SHT_PROGBITS) {
53       object->stab.push_back(NULL);
54       progbits_ndx.push_back(i);
55     } else {
56       llvm::OwningPtr<ELFSectionTy> sec(
57         ELFSectionTy::read(AR, object.get(), (*object->shtab)[i]));
58       object->stab.push_back(sec.take());
59     }
60   }
61 
62   object->shtab->buildNameMap();
63   ELFSectionSymTabTy *symtab =
64     static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab"));
65   rsl_assert(symtab && "Symtab is required.");
66   symtab->buildNameMap();
67 
68   for (size_t i = 0; i < progbits_ndx.size(); ++i) {
69     size_t index = progbits_ndx[i];
70 
71     llvm::OwningPtr<ELFSectionTy> sec(
72       ELFSectionTy::read(AR, object.get(), (*object->shtab)[index]));
73     object->stab[index] = sec.take();
74   }
75 
76   return object.take();
77 }
78 
79 template <unsigned Bitwidth>
getSectionName(size_t i) const80 inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const {
81   ELFSectionTy const *sec = stab[header->getStringSectionIndex()];
82 
83   if (sec) {
84     ELFSectionStrTabTy const &st =
85       static_cast<ELFSectionStrTabTy const &>(*sec);
86     return st[i];
87   }
88 
89   return NULL;
90 }
91 
92 template <unsigned Bitwidth>
93 inline ELFSection<Bitwidth> const *
getSectionByIndex(size_t i) const94 ELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
95   return stab[i];
96 }
97 
98 template <unsigned Bitwidth>
99 inline ELFSection<Bitwidth> *
getSectionByIndex(size_t i)100 ELFObject<Bitwidth>::getSectionByIndex(size_t i) {
101   return stab[i];
102 }
103 
104 template <unsigned Bitwidth>
105 inline ELFSection<Bitwidth> const *
getSectionByName(std::string const & str) const106 ELFObject<Bitwidth>::getSectionByName(std::string const &str) const {
107   size_t idx = getSectionHeaderTable()->getByName(str)->getIndex();
108   return stab[idx];
109 }
110 
111 template <unsigned Bitwidth>
112 inline ELFSection<Bitwidth> *
getSectionByName(std::string const & str)113 ELFObject<Bitwidth>::getSectionByName(std::string const &str) {
114   ELFObjectTy const *const_this = this;
115   ELFSectionTy const *sptr = const_this->getSectionByName(str);
116   // Const cast for the same API's const and non-const versions.
117   return const_cast<ELFSectionTy *>(sptr);
118 }
119 
120 
121 template <unsigned Bitwidth>
122 inline void ELFObject<Bitwidth>::
relocateARM(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)123 relocateARM(void *(*find_sym)(void *context, char const *name),
124             void *context,
125             ELFSectionRelTableTy *reltab,
126             ELFSectionProgBitsTy *text) {
127   // FIXME: Should be implement in independent files.
128   rsl_assert(Bitwidth == 32 && "ARM only have 32 bits.");
129 
130   ELFSectionSymTabTy *symtab =
131     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
132   rsl_assert(symtab && "Symtab is required.");
133 
134   for (size_t i = 0; i < reltab->size(); ++i) {
135     // FIXME: Can not implement here, use Fixup!
136     ELFRelocTy *rel = (*reltab)[i];
137     ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
138 
139     // FIXME: May be not uint32_t *.
140     typedef int32_t Inst_t;
141     Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
142     Inst_t P = (Inst_t)(int64_t)inst;
143     Inst_t A = 0;
144     Inst_t S = (Inst_t)(int64_t)sym->getAddress();
145 
146     switch (rel->getType()) {
147     default:
148       rsl_assert(0 && "Not implemented relocation type.");
149       break;
150 
151     case R_ARM_ABS32:
152       {
153         A = *inst;
154         *inst = (S+A);
155       }
156       break;
157 
158       // FIXME: Predefine relocation codes.
159     case R_ARM_CALL:
160       {
161 #define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
162         A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
163 #undef SIGN_EXTEND
164 
165         switch (sym->getType()) {
166         default:
167           rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
168           abort();
169           break;
170 
171         case STT_FUNC:
172           if (S == 0) {
173             rsl_assert(0 && "We should get function address at previous "
174                    "sym->getAddress() function call.");
175             abort();
176           }
177           break;
178 
179         case STT_NOTYPE:
180           if (S == 0) {
181             void *ext_func = find_sym(context, sym->getName());
182 #ifdef SUPPORT_NEAR_JUMP_EVEN_IF_BLc2BLX_NEEDED
183             S = (Inst_t)(uintptr_t)ext_func;
184             sym->setAddress(ext_func);
185 
186             uint32_t result = (S >> 2) - (P >> 2) + A;
187             if (result > 0x007fffff && result < 0xff800000) {
188 #endif
189 #ifndef __arm__
190               // We have not implement function stub in this runtime env
191               rsl_assert(0 && "Target address is far from call instruction");
192               abort();
193 #else
194               void *stub = text->getStubLayout()->allocateStub(ext_func);
195               if (!stub) {
196                 llvm::errs() << "unable to allocate stub." << "\n";
197                 exit(EXIT_FAILURE);
198               }
199 
200               //out() << "stub: for " << ext_func << " at " << stub << "\n";
201               sym->setAddress(stub);
202               S = (uint32_t)stub;
203 #endif
204 #ifdef SUPPORT_NEAR_JUMP_EVEN_IF_BLc2BLX_NEEDED
205             }
206 #endif
207           }
208           break;
209         }
210 
211         uint32_t result = (S >> 2) - (P >> 2) + A;
212 
213         if (result > 0x007fffff && result < 0xff800000) {
214           rsl_assert(0 && "Stub is still too far");
215           abort();
216         }
217 
218         *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
219       }
220       break;
221     case R_ARM_MOVT_ABS:
222     case R_ARM_MOVW_ABS_NC:
223       {
224         if (S==0 && sym->getType() == STT_NOTYPE)
225         {
226           void *ext_sym = find_sym(context, sym->getName());
227           S = (Inst_t)(uintptr_t)ext_sym;
228           sym->setAddress(ext_sym);
229         }
230         if (rel->getType() == R_ARM_MOVT_ABS) {
231           S >>= 16;
232         }
233 
234         // No need sign extend.
235         A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
236         uint32_t result = (S+A);
237         *inst = (((result) & 0xF000) << 4) |
238           ((result) & 0xFFF) |
239           (*inst & 0xFFF0F000);
240       }
241       break;
242     }
243     //llvm::errs() << "S:     " << (void *)S << '\n';
244     //llvm::errs() << "A:     " << (void *)A << '\n';
245     //llvm::errs() << "P:     " << (void *)P << '\n';
246     //llvm::errs() << "S+A:   " << (void *)(S+A) << '\n';
247     //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
248   }
249 }
250 
251 template <unsigned Bitwidth>
252 inline void ELFObject<Bitwidth>::
relocateX86_64(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)253 relocateX86_64(void *(*find_sym)(void *context, char const *name),
254                void *context,
255                ELFSectionRelTableTy *reltab,
256                ELFSectionProgBitsTy *text) {
257   rsl_assert(Bitwidth == 64 && "Only support X86_64.");
258 
259   ELFSectionSymTabTy *symtab =
260     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
261   rsl_assert(symtab && "Symtab is required.");
262 
263   for (size_t i = 0; i < reltab->size(); ++i) {
264     // FIXME: Can not implement here, use Fixup!
265     ELFRelocTy *rel = (*reltab)[i];
266     ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
267 
268     //typedef uint64_t Inst_t;
269     typedef int32_t Inst_t;
270     Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
271     Inst_t P = (Inst_t)(int64_t)inst;
272     Inst_t A = (Inst_t)(int64_t)rel->getAddend();
273     Inst_t S = (Inst_t)(int64_t)sym->getAddress();
274 
275     if (S == 0) {
276       S = (Inst_t)(int64_t)find_sym(context, sym->getName());
277       sym->setAddress((void *)S);
278     }
279 
280     switch (rel->getType()) {
281       default:
282         rsl_assert(0 && "Not implemented relocation type.");
283         break;
284 
285       // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
286       case 1: // R_X86_64_64
287         *inst = (S+A);
288         break;
289 
290       case 2: // R_X86_64_PC32
291         *inst = (S+A-P);
292         break;
293 
294       case 10: // R_X86_64_32
295       case 11: // R_X86_64_32S
296         *inst = (S+A);
297         break;
298     }
299   }
300 }
301 
302 template <unsigned Bitwidth>
303 inline void ELFObject<Bitwidth>::
relocateX86_32(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)304 relocateX86_32(void *(*find_sym)(void *context, char const *name),
305                void *context,
306                ELFSectionRelTableTy *reltab,
307                ELFSectionProgBitsTy *text) {
308   rsl_assert(Bitwidth == 32 && "Only support X86.");
309 
310   ELFSectionSymTabTy *symtab =
311     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
312   rsl_assert(symtab && "Symtab is required.");
313 
314   for (size_t i = 0; i < reltab->size(); ++i) {
315     // FIXME: Can not implement here, use Fixup!
316     ELFRelocTy *rel = (*reltab)[i];
317     ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
318 
319     //typedef uint64_t Inst_t;
320     typedef int32_t Inst_t;
321     Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
322     Inst_t P = (Inst_t)(uintptr_t)inst;
323     Inst_t A = (Inst_t)(uintptr_t)*inst;
324     Inst_t S = (Inst_t)(uintptr_t)sym->getAddress();
325 
326     if (S == 0) {
327       S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
328       sym->setAddress((void *)S);
329     }
330 
331     switch (rel->getType()) {
332     default:
333       rsl_assert(0 && "Not implemented relocation type.");
334       break;
335 
336     case R_386_PC32:
337       *inst = (S+A-P);
338       break;
339 
340     case R_386_32:
341       *inst = (S+A);
342       break;
343     }
344   }
345 }
346 
347 // TODO: Refactor all relocations.
348 template <unsigned Bitwidth>
349 inline void ELFObject<Bitwidth>::
relocate(void * (* find_sym)(void * context,char const * name),void * context)350 relocate(void *(*find_sym)(void *context, char const *name), void *context) {
351   // Init SHNCommonDataSize.
352   // Need refactoring
353   size_t SHNCommonDataSize = 0;
354 
355   ELFSectionSymTabTy *symtab =
356     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
357   rsl_assert(symtab && "Symtab is required.");
358 
359   for (size_t i = 0; i < symtab->size(); ++i) {
360     ELFSymbolTy *sym = (*symtab)[i];
361 
362     if (sym->getType() != STT_OBJECT) {
363       continue;
364     }
365 
366     size_t idx = (size_t)sym->getSectionIndex();
367     switch (idx) {
368     default:
369       if ((*shtab)[idx]->getType() == SHT_NOBITS) {
370         // FIXME(logan): This is a workaround for .lcomm directives
371         // bug of LLVM ARM MC code generator.  Remove this when the
372         // LLVM bug is fixed.
373 
374         size_t align = 16;
375         SHNCommonDataSize += (size_t)sym->getSize() + align;
376       }
377       break;
378 
379     case SHN_COMMON:
380       {
381         size_t align = (size_t)sym->getValue();
382         SHNCommonDataSize += (size_t)sym->getSize() + align;
383       }
384       break;
385 
386     case SHN_ABS:
387     case SHN_UNDEF:
388     case SHN_XINDEX:
389       break;
390     }
391   }
392   if (!initSHNCommonDataSize(SHNCommonDataSize)) {
393     rsl_assert("Allocate memory for common variable fail!");
394   }
395 
396   for (size_t i = 0; i < stab.size(); ++i) {
397     ELFSectionHeaderTy *sh = (*shtab)[i];
398     if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
399       continue;
400     }
401     ELFSectionRelTableTy *reltab =
402       static_cast<ELFSectionRelTableTy *>(stab[i]);
403     rsl_assert(reltab && "Relocation section can't be NULL.");
404 
405     const char *reltab_name = sh->getName();
406     const char *need_rel_name;
407     if (sh->getType() == SHT_REL) {
408       need_rel_name = reltab_name + 4;
409       // ".rel.xxxx"
410       //      ^ start from here.
411     } else {
412       need_rel_name = reltab_name + 5;
413     }
414 
415     ELFSectionProgBitsTy *need_rel =
416       static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
417     rsl_assert(need_rel && "Need be relocated section can't be NULL.");
418 
419     switch (getHeader()->getMachine()) {
420       case EM_ARM:
421         relocateARM(find_sym, context, reltab, need_rel);
422         break;
423       case EM_386:
424         relocateX86_32(find_sym, context, reltab, need_rel);
425         break;
426       case EM_X86_64:
427         relocateX86_64(find_sym, context, reltab, need_rel);
428         break;
429 
430       default:
431         rsl_assert(0 && "Only support ARM, X86, and X86_64 relocation.");
432         break;
433     }
434   }
435 
436   for (size_t i = 0; i < stab.size(); ++i) {
437     ELFSectionHeaderTy *sh = (*shtab)[i];
438     if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
439       if (stab[i]) {
440         static_cast<ELFSectionBitsTy *>(stab[i])->protect();
441       }
442     }
443   }
444 }
445 
446 template <unsigned Bitwidth>
print() const447 inline void ELFObject<Bitwidth>::print() const {
448   header->print();
449   shtab->print();
450 
451   for (size_t i = 0; i < stab.size(); ++i) {
452     ELFSectionTy *sec = stab[i];
453     if (sec) {
454       sec->print();
455     }
456   }
457 }
458 
459 #endif // ELF_OBJECT_HXX
460