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