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