• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011-2012, 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 "GOT.h"
26 #include "ELF.h"
27 
28 #include <llvm/ADT/SmallVector.h>
29 
30 #include "utils/rsl_assert.h"
31 
32 template <unsigned Bitwidth>
33 template <typename Archiver>
34 inline ELFObject<Bitwidth> *
read(Archiver & AR)35 ELFObject<Bitwidth>::read(Archiver &AR) {
36   llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy());
37 
38   // Read header
39   object->header.reset(ELFHeaderTy::read(AR));
40   if (!object->header) {
41     return 0;
42   }
43 
44   // Read section table
45   object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get()));
46   if (!object->shtab) {
47     return 0;
48   }
49 
50   // Read each section
51   llvm::SmallVector<size_t, 4> progbits_ndx;
52   for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) {
53     if ((*object->shtab)[i]->getType() == SHT_PROGBITS) {
54       object->stab.push_back(NULL);
55       progbits_ndx.push_back(i);
56     } else {
57       llvm::OwningPtr<ELFSectionTy> sec(
58         ELFSectionTy::read(AR, object.get(), (*object->shtab)[i]));
59       object->stab.push_back(sec.take());
60     }
61   }
62 
63   object->shtab->buildNameMap();
64   ELFSectionSymTabTy *symtab =
65     static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab"));
66   rsl_assert(symtab && "Symtab is required.");
67   symtab->buildNameMap();
68 
69   for (size_t i = 0; i < progbits_ndx.size(); ++i) {
70     size_t index = progbits_ndx[i];
71 
72     llvm::OwningPtr<ELFSectionTy> sec(
73       ELFSectionTy::read(AR, object.get(), (*object->shtab)[index]));
74     object->stab[index] = sec.take();
75   }
76 
77   return object.take();
78 }
79 
80 template <unsigned Bitwidth>
getSectionName(size_t i) const81 inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const {
82   ELFSectionTy const *sec = stab[header->getStringSectionIndex()];
83 
84   if (sec) {
85     ELFSectionStrTabTy const &st =
86       static_cast<ELFSectionStrTabTy const &>(*sec);
87     return st[i];
88   }
89 
90   return NULL;
91 }
92 
93 template <unsigned Bitwidth>
94 inline ELFSection<Bitwidth> const *
getSectionByIndex(size_t i) const95 ELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
96   return stab[i];
97 }
98 
99 template <unsigned Bitwidth>
100 inline ELFSection<Bitwidth> *
getSectionByIndex(size_t i)101 ELFObject<Bitwidth>::getSectionByIndex(size_t i) {
102   return stab[i];
103 }
104 
105 template <unsigned Bitwidth>
106 inline ELFSection<Bitwidth> const *
getSectionByName(std::string const & str) const107 ELFObject<Bitwidth>::getSectionByName(std::string const &str) const {
108   size_t idx = getSectionHeaderTable()->getByName(str)->getIndex();
109   return stab[idx];
110 }
111 
112 template <unsigned Bitwidth>
113 inline ELFSection<Bitwidth> *
getSectionByName(std::string const & str)114 ELFObject<Bitwidth>::getSectionByName(std::string const &str) {
115   ELFObjectTy const *const_this = this;
116   ELFSectionTy const *sptr = const_this->getSectionByName(str);
117   // Const cast for the same API's const and non-const versions.
118   return const_cast<ELFSectionTy *>(sptr);
119 }
120 
121 
122 template <unsigned Bitwidth>
123 inline void ELFObject<Bitwidth>::
relocateARM(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)124 relocateARM(void *(*find_sym)(void *context, char const *name),
125             void *context,
126             ELFSectionRelTableTy *reltab,
127             ELFSectionProgBitsTy *text) {
128   // FIXME: Should be implement in independent files.
129   rsl_assert(Bitwidth == 32 && "ARM only have 32 bits.");
130 
131   ELFSectionSymTabTy *symtab =
132     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
133   rsl_assert(symtab && "Symtab is required.");
134 
135   for (size_t i = 0; i < reltab->size(); ++i) {
136     // FIXME: Can not implement here, use Fixup!
137     ELFRelocTy *rel = (*reltab)[i];
138     ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
139 
140     // FIXME: May be not uint32_t *.
141     typedef int32_t Inst_t;
142     Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
143     Inst_t P = (Inst_t)(int64_t)inst;
144     Inst_t A = 0;
145     Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_ARM);
146     Inst_t T = 0;
147 
148     if (sym->isConcreteFunc() && (sym->getValue() & 0x1)) {
149       T = 1;
150     }
151 
152     word_t reltype = rel->getType();
153     switch (reltype) {
154     default:
155       rsl_assert(0 && "Not implemented relocation type.");
156       break;
157 
158     case R_ARM_ABS32:
159       {
160         if (S == 0 && sym->getType() == STT_NOTYPE) {
161           void *ext_sym = find_sym(context, sym->getName());
162           if (!ext_sym) {
163             missingSymbols = true;
164           }
165           S = (Inst_t)(uintptr_t)ext_sym;
166           sym->setAddress(ext_sym);
167         }
168         A = *inst;
169         *inst = (S + A) | T;
170       }
171       break;
172 
173       // FIXME: Predefine relocation codes.
174     case R_ARM_CALL:
175     case R_ARM_THM_CALL:
176     case R_ARM_JUMP24:
177     case R_ARM_THM_JUMP24:
178       {
179 #define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
180         if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
181           A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
182           A <<= 2;
183         } else {
184           // Hack for two 16bit.
185           *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
186           Inst_t s  = (*inst >> 26) & 0x1u,    // 26
187                  u  = (*inst >> 16) & 0x3FFu,  // 25-16
188                  l  =  *inst        & 0x7FFu, // 10-0
189                  j1 = (*inst >> 13) & 0x1u,    // 13
190                  j2 = (*inst >> 11) & 0x1u;    // 11
191           Inst_t i1 = (~(j1 ^ s)) & 0x1u,
192                  i2 = (~(j2 ^ s)) & 0x1u;
193           // [31-25][24][23][22][21-12][11-1][0]
194           //      0   s  i1  i2      u     l  0
195           A = SIGN_EXTEND((s << 23) | (i1 << 22) | (i2 << 21) | (u << 11) | l, 24);
196           A <<= 1;
197         }
198 #undef SIGN_EXTEND
199 
200         void *callee_addr = sym->getAddress(EM_ARM);
201 
202         switch (sym->getType()) {
203         default:
204           rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
205           abort();
206           break;
207 
208         case STT_FUNC:
209           // NOTE: Callee function is in the object file, but it may be
210           // in different PROGBITS section (which may be far call).
211 
212           if (callee_addr == 0) {
213             rsl_assert(0 && "We should get function address at previous "
214                    "sym->getAddress(EM_ARM) function call.");
215             abort();
216           }
217           break;
218 
219         case STT_NOTYPE:
220           // NOTE: Callee function is an external function.  Call find_sym
221           // if it has not resolved yet.
222 
223           if (callee_addr == 0) {
224             callee_addr = find_sym(context, sym->getName());
225             if (!callee_addr) {
226               missingSymbols = true;
227             }
228             sym->setAddress(callee_addr);
229           }
230           break;
231         }
232 
233         // Get the stub for this function
234         StubLayout *stub_layout = text->getStubLayout();
235 
236         if (!stub_layout) {
237           llvm::errs() << "unable to get stub layout." << "\n";
238           abort();
239         }
240 
241         void *stub = stub_layout->allocateStub(callee_addr);
242 
243         if (!stub) {
244           llvm::errs() << "unable to allocate stub." << "\n";
245           abort();
246         }
247 
248         //LOGI("Function %s: using stub %p\n", sym->getName(), stub);
249         S = (uint32_t)(uintptr_t)stub;
250 
251         if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
252           // Relocate the R_ARM_CALL relocation type
253           uint32_t result = (S + A - P) >> 2;
254 
255           if (result > 0x007FFFFF && result < 0xFF800000) {
256             rsl_assert(0 && "Stub is still too far");
257             abort();
258           }
259 
260           *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
261         } else {
262           P &= ~0x3;  // Base address align to 4 bytes.  (For BLX.)
263 
264           // Relocate the R_ARM_THM_CALL relocation type
265           uint32_t result = (S + A - P) >> 1;
266 
267           if (result > 0x007FFFFF && result < 0xFF800000) {
268             rsl_assert(0 && "Stub is still too far");
269             abort();
270           }
271 
272           //*inst &= 0xF800D000u;
273           // Rewrite instruction to BLX.  (Stub is always ARM.)
274           *inst &= 0xF800C000u;
275           // [31-25][24][23][22][21-12][11-1][0]
276           //      0   s  i1  i2      u     l  0
277           Inst_t s  = (result >> 23) & 0x1u,   // 26
278                  u  = (result >> 11) & 0x3FFu, // 25-16
279                  // For BLX, bit [0] is 0.
280                  l  =  result        & 0x7FEu, // 10-0
281                  i1 = (result >> 22) & 0x1u,
282                  i2 = (result >> 21) & 0x1u;
283           Inst_t j1 = ((~i1) ^ s) & 0x01u,       // 13
284                  j2 = ((~i2) ^ s) & 0x01u;       // 11
285           *inst |= s << 26;
286           *inst |= u << 16;
287           *inst |= l;
288           *inst |= j1 << 13;
289           *inst |= j2 << 11;
290           // Hack for two 16bit.
291           *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
292         }
293       }
294       break;
295     case R_ARM_MOVT_ABS:
296     case R_ARM_MOVW_ABS_NC:
297     case R_ARM_THM_MOVW_ABS_NC:
298     case R_ARM_THM_MOVT_ABS:
299       {
300         if (S == 0 && sym->getType() == STT_NOTYPE) {
301           void *ext_sym = find_sym(context, sym->getName());
302           if (!ext_sym) {
303             missingSymbols = true;
304           }
305           S = (Inst_t)(uintptr_t)ext_sym;
306           sym->setAddress(ext_sym);
307         }
308         if (reltype == R_ARM_MOVT_ABS
309             || reltype == R_ARM_THM_MOVT_ABS) {
310           S >>= 16;
311         }
312 
313         if (reltype == R_ARM_MOVT_ABS
314             || reltype == R_ARM_MOVW_ABS_NC) {
315           // No need sign extend.
316           A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
317           uint32_t result = (S + A);
318           *inst = (((result) & 0xF000) << 4) |
319             ((result) & 0xFFF) |
320             (*inst & 0xFFF0F000);
321         } else {
322           // Hack for two 16bit.
323           *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
324           // imm16: [19-16][26][14-12][7-0]
325           A = (((*inst >>  4) & 0xF000u) |
326                ((*inst >> 15) & 0x0800u) |
327                ((*inst >>  4) & 0x0700u) |
328                ( *inst        & 0x00FFu));
329           uint32_t result;
330           if (reltype == R_ARM_THM_MOVT_ABS) {
331             result = (S + A);
332           } else {
333             result = (S + A) | T;
334           }
335           // imm16: [19-16][26][14-12][7-0]
336           *inst &= 0xFBF08F00u;
337           *inst |= (result & 0xF000u) << 4;
338           *inst |= (result & 0x0800u) << 15;
339           *inst |= (result & 0x0700u) << 4;
340           *inst |= (result & 0x00FFu);
341           // Hack for two 16bit.
342           *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
343         }
344       }
345       break;
346     }
347     //llvm::errs() << "S:     " << (void *)S << '\n';
348     //llvm::errs() << "A:     " << (void *)A << '\n';
349     //llvm::errs() << "P:     " << (void *)P << '\n';
350     //llvm::errs() << "S+A:   " << (void *)(S+A) << '\n';
351     //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
352   }
353 }
354 
355 template <unsigned Bitwidth>
356 inline void ELFObject<Bitwidth>::
relocateX86_64(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)357 relocateX86_64(void *(*find_sym)(void *context, char const *name),
358                void *context,
359                ELFSectionRelTableTy *reltab,
360                ELFSectionProgBitsTy *text) {
361   rsl_assert(Bitwidth == 64 && "Only support X86_64.");
362 
363   ELFSectionSymTabTy *symtab =
364     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
365   rsl_assert(symtab && "Symtab is required.");
366 
367   for (size_t i = 0; i < reltab->size(); ++i) {
368     // FIXME: Can not implement here, use Fixup!
369     ELFRelocTy *rel = (*reltab)[i];
370     ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
371 
372     //typedef uint64_t Inst_t;
373     typedef int32_t Inst_t;
374     Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
375     Inst_t P = (Inst_t)(int64_t)inst;
376     Inst_t A = (Inst_t)(int64_t)rel->getAddend();
377     Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_X86_64);
378 
379     if (S == 0) {
380       S = (Inst_t)(int64_t)find_sym(context, sym->getName());
381       if (!S) {
382         missingSymbols = true;
383       }
384       sym->setAddress((void *)S);
385     }
386 
387     switch (rel->getType()) {
388       default:
389         rsl_assert(0 && "Not implemented relocation type.");
390         break;
391 
392       // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
393       case 1: // R_X86_64_64
394         *inst = (S+A);
395         break;
396 
397       case 2: // R_X86_64_PC32
398         *inst = (S+A-P);
399         break;
400 
401       case 10: // R_X86_64_32
402       case 11: // R_X86_64_32S
403         *inst = (S+A);
404         break;
405     }
406   }
407 }
408 
409 template <unsigned Bitwidth>
410 inline void ELFObject<Bitwidth>::
relocateX86_32(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)411 relocateX86_32(void *(*find_sym)(void *context, char const *name),
412                void *context,
413                ELFSectionRelTableTy *reltab,
414                ELFSectionProgBitsTy *text) {
415   rsl_assert(Bitwidth == 32 && "Only support X86.");
416 
417   ELFSectionSymTabTy *symtab =
418     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
419   rsl_assert(symtab && "Symtab is required.");
420 
421   for (size_t i = 0; i < reltab->size(); ++i) {
422     // FIXME: Can not implement here, use Fixup!
423     ELFRelocTy *rel = (*reltab)[i];
424     ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
425 
426     //typedef uint64_t Inst_t;
427     typedef int32_t Inst_t;
428     Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
429     Inst_t P = (Inst_t)(uintptr_t)inst;
430     Inst_t A = (Inst_t)(uintptr_t)*inst;
431     Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_386);
432 
433     if (S == 0) {
434       S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
435       if (!S) {
436         missingSymbols = true;
437       }
438       sym->setAddress((void *)S);
439     }
440 
441     switch (rel->getType()) {
442     default:
443       rsl_assert(0 && "Not implemented relocation type.");
444       break;
445 
446     case R_386_PC32:
447       *inst = (S+A-P);
448       break;
449 
450     case R_386_32:
451       *inst = (S+A);
452       break;
453     }
454   }
455 }
456 
457 template <unsigned Bitwidth>
458 inline void ELFObject<Bitwidth>::
relocateMIPS(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)459 relocateMIPS(void *(*find_sym)(void *context, char const *name),
460              void *context,
461              ELFSectionRelTableTy *reltab,
462              ELFSectionProgBitsTy *text) {
463   rsl_assert(Bitwidth == 32 && "Only support 32-bit MIPS.");
464 
465   ELFSectionSymTabTy *symtab =
466     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
467   rsl_assert(symtab && "Symtab is required.");
468 
469   for (size_t i = 0; i < reltab->size(); ++i) {
470     // FIXME: Can not implement here, use Fixup!
471     ELFRelocTy *rel = (*reltab)[i];
472     ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
473 
474     typedef int32_t Inst_t;
475     Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
476     Inst_t P = (Inst_t)(uintptr_t)inst;
477     Inst_t A = (Inst_t)(uintptr_t)*inst;
478     Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_MIPS);
479 
480     bool need_stub = false;
481 
482     if (S == 0 && strcmp (sym->getName(), "_gp_disp") != 0) {
483       need_stub = true;
484       S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
485       if (!S) {
486         missingSymbols = true;
487       }
488       sym->setAddress((void *)S);
489     }
490 
491     switch (rel->getType()) {
492     default:
493       rsl_assert(0 && "Not implemented relocation type.");
494       break;
495 
496     case R_MIPS_NONE:
497     case R_MIPS_JALR: // ignore this
498       break;
499 
500     case R_MIPS_16:
501       *inst &= 0xFFFF0000;
502       A = A & 0xFFFF;
503       A = S + (short)A;
504       rsl_assert(A >= -32768 && A <= 32767 && "R_MIPS_16 overflow.");
505       *inst |= (A & 0xFFFF);
506       break;
507 
508     case R_MIPS_32:
509       *inst = S + A;
510       break;
511 
512     case R_MIPS_26:
513       *inst &= 0xFC000000;
514       if (need_stub == false) {
515         A = (A & 0x3FFFFFF) << 2;
516         if (sym->getBindingAttribute() == STB_LOCAL) { // local binding
517           A |= ((P + 4) & 0xF0000000);
518           A += S;
519           *inst |= ((A >> 2) & 0x3FFFFFF);
520         } else { // external binding
521           if (A & 0x08000000) // Sign extend from bit 27
522             A |= 0xF0000000;
523           A += S;
524           *inst |= ((A >> 2) & 0x3FFFFFF);
525           if (((P + 4) >> 28) != (A >> 28)) { // far local call
526             void *stub = text->getStubLayout()->allocateStub((void *)A);
527             rsl_assert(stub && "cannot allocate stub.");
528             sym->setAddress(stub);
529             S = (int32_t)(intptr_t)stub;
530             *inst |= ((S >> 2) & 0x3FFFFFF);
531             rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
532           }
533         }
534       } else { // shared-library call
535         A = (A & 0x3FFFFFF) << 2;
536         rsl_assert(A == 0 && "R_MIPS_26 addend is not zero.");
537         void *stub = text->getStubLayout()->allocateStub((void *)S);
538         rsl_assert(stub && "cannot allocate stub.");
539         sym->setAddress(stub);
540         S = (int32_t)(intptr_t)stub;
541         *inst |= ((S >> 2) & 0x3FFFFFF);
542         rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
543       }
544       break;
545 
546     case R_MIPS_HI16:
547       *inst &= 0xFFFF0000;
548       A = (A & 0xFFFF) << 16;
549       // Find the nearest LO16 relocation type after this entry
550       for (size_t j = i + 1; j < reltab->size(); j++) {
551         ELFRelocTy *this_rel = (*reltab)[j];
552         ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
553         if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
554           Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
555           Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
556           this_A = this_A & 0xFFFF;
557           A += (short)this_A;
558           break;
559         }
560       }
561       if (strcmp (sym->getName(), "_gp_disp") == 0) {
562           S = (int)(intptr_t)got_address() + GP_OFFSET - (int)P;
563           sym->setAddress((void *)S);
564       }
565       *inst |= (((S + A + (int)0x8000) >> 16) & 0xFFFF);
566       break;
567 
568     case R_MIPS_LO16:
569       *inst &= 0xFFFF0000;
570       A = A & 0xFFFF;
571       if (strcmp (sym->getName(), "_gp_disp") == 0) {
572           S = (Inst_t)(intptr_t)sym->getAddress(EM_MIPS);
573       }
574       *inst |= ((S + A) & 0xFFFF);
575       break;
576 
577     case R_MIPS_GOT16:
578     case R_MIPS_CALL16:
579       {
580         *inst &= 0xFFFF0000;
581         A = A & 0xFFFF;
582         if (rel->getType() == R_MIPS_GOT16) {
583           if (sym->getBindingAttribute() == STB_LOCAL) {
584             A <<= 16;
585 
586             // Find the nearest LO16 relocation type after this entry
587             for (size_t j = i + 1; j < reltab->size(); j++) {
588               ELFRelocTy *this_rel = (*reltab)[j];
589               ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
590               if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
591                 Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
592                 Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
593                 this_A = this_A & 0xFFFF;
594                 A += (short)this_A;
595                 break;
596               }
597             }
598           } else {
599             rsl_assert(A == 0 && "R_MIPS_GOT16 addend is not 0.");
600           }
601         } else { // R_MIPS_CALL16
602           rsl_assert(A == 0 && "R_MIPS_CALL16 addend is not 0.");
603         }
604         int got_index = search_got((int)rel->getSymTabIndex(), (void *)(S + A),
605                                    sym->getBindingAttribute());
606         int got_offset = (got_index << 2) - GP_OFFSET;
607         *inst |= (got_offset & 0xFFFF);
608       }
609       break;
610 
611     case R_MIPS_GPREL32:
612       *inst = A + S - ((int)(intptr_t)got_address() + GP_OFFSET);
613       break;
614     }
615   }
616 }
617 
618 
619 // TODO: Refactor all relocations.
620 template <unsigned Bitwidth>
621 inline void ELFObject<Bitwidth>::
relocate(void * (* find_sym)(void * context,char const * name),void * context)622 relocate(void *(*find_sym)(void *context, char const *name), void *context) {
623   // Init SHNCommonDataSize.
624   // Need refactoring
625   size_t SHNCommonDataSize = 0;
626 
627   ELFSectionSymTabTy *symtab =
628     static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
629   rsl_assert(symtab && "Symtab is required.");
630 
631   for (size_t i = 0; i < symtab->size(); ++i) {
632     ELFSymbolTy *sym = (*symtab)[i];
633 
634     if (sym->getType() != STT_OBJECT) {
635       continue;
636     }
637 
638     size_t idx = (size_t)sym->getSectionIndex();
639     switch (idx) {
640     default:
641       if ((*shtab)[idx]->getType() == SHT_NOBITS) {
642         // FIXME(logan): This is a workaround for .lcomm directives
643         // bug of LLVM ARM MC code generator.  Remove this when the
644         // LLVM bug is fixed.
645 
646         size_t align = 16;
647         SHNCommonDataSize += (size_t)sym->getSize() + align;
648       }
649       break;
650 
651     case SHN_COMMON:
652       {
653         size_t align = (size_t)sym->getValue();
654         SHNCommonDataSize += (size_t)sym->getSize() + align;
655       }
656       break;
657 
658     case SHN_ABS:
659     case SHN_UNDEF:
660     case SHN_XINDEX:
661       break;
662     }
663   }
664   if (!initSHNCommonDataSize(SHNCommonDataSize)) {
665     rsl_assert("Allocate memory for common variable fail!");
666     // TODO: Refactor object loading to use proper status/error returns.
667     // We mark the object as having missing symbols and return early in this
668     // case to signal a loading error (usually due to running out of
669     // available memory to allocate).
670     missingSymbols = true;
671     return;
672   }
673 
674   for (size_t i = 0; i < stab.size(); ++i) {
675     ELFSectionHeaderTy *sh = (*shtab)[i];
676     if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
677       continue;
678     }
679     ELFSectionRelTableTy *reltab =
680       static_cast<ELFSectionRelTableTy *>(stab[i]);
681     rsl_assert(reltab && "Relocation section can't be NULL.");
682 
683     const char *reltab_name = sh->getName();
684     const char *need_rel_name;
685     if (sh->getType() == SHT_REL) {
686       need_rel_name = reltab_name + 4;
687       // ".rel.xxxx"
688       //      ^ start from here.
689     } else {
690       need_rel_name = reltab_name + 5;
691     }
692 
693     ELFSectionProgBitsTy *need_rel =
694       static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
695     rsl_assert(need_rel && "Need be relocated section can't be NULL.");
696 
697     switch (getHeader()->getMachine()) {
698       case EM_ARM:
699         relocateARM(find_sym, context, reltab, need_rel);
700         break;
701       case EM_386:
702         relocateX86_32(find_sym, context, reltab, need_rel);
703         break;
704       case EM_X86_64:
705         relocateX86_64(find_sym, context, reltab, need_rel);
706         break;
707       case EM_MIPS:
708         relocateMIPS(find_sym, context, reltab, need_rel);
709         break;
710 
711       default:
712         rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
713         break;
714     }
715   }
716 
717   for (size_t i = 0; i < stab.size(); ++i) {
718     ELFSectionHeaderTy *sh = (*shtab)[i];
719     if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
720       if (stab[i]) {
721         static_cast<ELFSectionBitsTy *>(stab[i])->protect();
722       }
723     }
724   }
725 }
726 
727 template <unsigned Bitwidth>
print() const728 inline void ELFObject<Bitwidth>::print() const {
729   header->print();
730   shtab->print();
731 
732   for (size_t i = 0; i < stab.size(); ++i) {
733     ELFSectionTy *sec = stab[i];
734     if (sec) {
735       sec->print();
736     }
737   }
738 }
739 
740 #endif // ELF_OBJECT_HXX
741