Home | History | Annotate | Download | only in impl
      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> *
     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>
     81 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 *
     95 ELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
     96   return stab[i];
     97 }
     98 
     99 template <unsigned Bitwidth>
    100 inline ELFSection<Bitwidth> *
    101 ELFObject<Bitwidth>::getSectionByIndex(size_t i) {
    102   return stab[i];
    103 }
    104 
    105 template <unsigned Bitwidth>
    106 inline ELFSection<Bitwidth> const *
    107 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> *
    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>::
    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>::
    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>::
    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>::
    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>::
    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>
    728 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