Home | History | Annotate | Download | only in android
      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 #include "librsloader.h"
     18 
     19 #include "ELFObject.h"
     20 #include "ELFSectionSymTab.h"
     21 #include "ELFSymbol.h"
     22 
     23 #include "utils/serialize.h"
     24 
     25 #define LOG_TAG "bcc"
     26 #include "cutils/log.h"
     27 
     28 #include <llvm/Support/ELF.h>
     29 
     30 #if defined(__LP64__) || defined(__x86_64__)
     31 static inline RSExecRef wrap(ELFObject<64> *object) {
     32   return reinterpret_cast<RSExecRef>(object);
     33 }
     34 #else
     35 static inline RSExecRef wrap(ELFObject<32> *object) {
     36   return reinterpret_cast<RSExecRef>(object);
     37 }
     38 #endif
     39 
     40 #if defined(__LP64__) || defined(__x86_64__)
     41 static inline ELFObject<64> *unwrap(RSExecRef object) {
     42   return reinterpret_cast<ELFObject<64> *>(object);
     43 }
     44 #else
     45 static inline ELFObject<32> *unwrap(RSExecRef object) {
     46   return reinterpret_cast<ELFObject<32> *>(object);
     47 }
     48 #endif
     49 
     50 extern "C" RSExecRef rsloaderCreateExec(unsigned char const *buf,
     51                                         size_t buf_size,
     52                                         RSFindSymbolFn find_symbol,
     53                                         void *find_symbol_context) {
     54   RSExecRef object = rsloaderLoadExecutable(buf, buf_size);
     55   if (!object) {
     56     return NULL;
     57   }
     58 
     59   if (!rsloaderRelocateExecutable(object, find_symbol, find_symbol_context)) {
     60     rsloaderDisposeExec(object);
     61     return NULL;
     62   }
     63 
     64   return object;
     65 }
     66 
     67 extern "C" RSExecRef rsloaderLoadExecutable(unsigned char const *buf,
     68                                             size_t buf_size) {
     69   ArchiveReaderLE AR(buf, buf_size);
     70 
     71 #if defined(__LP64__) || defined(__x86_64__)
     72   std::unique_ptr<ELFObject<64> > object(ELFObject<64>::read(AR));
     73 #else
     74   std::unique_ptr<ELFObject<32> > object(ELFObject<32>::read(AR));
     75 #endif
     76   if (!object) {
     77     ALOGE("Unable to load the ELF object.");
     78     return NULL;
     79   }
     80 
     81   return wrap(object.release());
     82 }
     83 
     84 extern "C" int rsloaderRelocateExecutable(RSExecRef object_,
     85                                           RSFindSymbolFn find_symbol,
     86                                           void *find_symbol_context) {
     87 #if defined(__LP64__) || defined(__x86_64__)
     88   ELFObject<64>* object = unwrap(object_);
     89 #else
     90   ELFObject<32>* object = unwrap(object_);
     91 #endif
     92   object->relocate(find_symbol, find_symbol_context);
     93   return (object->getMissingSymbols() == 0);
     94 }
     95 
     96 extern "C" void rsloaderUpdateSectionHeaders(RSExecRef object_,
     97                                              unsigned char *buf) {
     98 #if defined(__LP64__) || defined(__x86_64__)
     99   ELFObject<64> *object = unwrap(object_);
    100 #else
    101   ELFObject<32> *object = unwrap(object_);
    102 #endif
    103 
    104   // Remap the section header addresses to match the loaded code
    105 #if defined(__LP64__) || defined(__x86_64__)
    106   llvm::ELF::Elf64_Ehdr* header = reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(buf);
    107 #else
    108   llvm::ELF::Elf32_Ehdr* header = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(buf);
    109 #endif
    110 
    111 #if defined(__LP64__) || defined(__x86_64__)
    112   llvm::ELF::Elf64_Shdr* shtab =
    113       reinterpret_cast<llvm::ELF::Elf64_Shdr*>(buf + header->e_shoff);
    114 #else
    115   llvm::ELF::Elf32_Shdr* shtab =
    116       reinterpret_cast<llvm::ELF::Elf32_Shdr*>(buf + header->e_shoff);
    117 #endif
    118 
    119   for (int i = 0; i < header->e_shnum; i++) {
    120     if (shtab[i].sh_flags & SHF_ALLOC) {
    121 #if defined(__LP64__) || defined(__x86_64__)
    122       ELFSectionBits<64>* bits =
    123           static_cast<ELFSectionBits<64>*>(object->getSectionByIndex(i));
    124 #else
    125       ELFSectionBits<32>* bits =
    126           static_cast<ELFSectionBits<32>*>(object->getSectionByIndex(i));
    127 #endif
    128       if (bits) {
    129         const unsigned char* addr = bits->getBuffer();
    130 #if defined(__LP64__) || defined(__x86_64__)
    131         shtab[i].sh_addr = reinterpret_cast<llvm::ELF::Elf64_Addr>(addr);
    132 #else
    133         shtab[i].sh_addr = reinterpret_cast<llvm::ELF::Elf32_Addr>(addr);
    134 #endif
    135       }
    136     }
    137   }
    138 }
    139 
    140 extern "C" void rsloaderDisposeExec(RSExecRef object) {
    141   delete unwrap(object);
    142 }
    143 
    144 extern "C" void *rsloaderGetSymbolAddress(RSExecRef object_,
    145                                           char const *name) {
    146 #if defined(__LP64__) || defined(__x86_64__)
    147   ELFObject<64> *object = unwrap(object_);
    148 
    149   ELFSectionSymTab<64> *symtab =
    150     static_cast<ELFSectionSymTab<64> *>(object->getSectionByName(".symtab"));
    151 #else
    152   ELFObject<32> *object = unwrap(object_);
    153 
    154   ELFSectionSymTab<32> *symtab =
    155     static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
    156 #endif
    157 
    158   if (!symtab) {
    159     return NULL;
    160   }
    161 
    162 #if defined(__LP64__) || defined(__x86_64__)
    163   ELFSymbol<64> *symbol = symtab->getByName(name);
    164 #else
    165   ELFSymbol<32> *symbol = symtab->getByName(name);
    166 #endif
    167 
    168   if (!symbol) {
    169     ALOGV("Symbol not found: %s\n", name);
    170     return NULL;
    171   }
    172 
    173   int machine = object->getHeader()->getMachine();
    174 
    175   return symbol->getAddress(machine, false);
    176 }
    177 
    178 extern "C" size_t rsloaderGetSymbolSize(RSExecRef object_, char const *name) {
    179 #if defined(__LP64__) || defined(__x86_64__)
    180   ELFObject<64> *object = unwrap(object_);
    181 
    182   ELFSectionSymTab<64> *symtab =
    183     static_cast<ELFSectionSymTab<64> *>(object->getSectionByName(".symtab"));
    184 #else
    185   ELFObject<32> *object = unwrap(object_);
    186 
    187   ELFSectionSymTab<32> *symtab =
    188     static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
    189 #endif
    190   if (!symtab) {
    191     return 0;
    192   }
    193 
    194 #if defined(__LP64__) || defined(__x86_64__)
    195   ELFSymbol<64> *symbol = symtab->getByName(name);
    196 #else
    197   ELFSymbol<32> *symbol = symtab->getByName(name);
    198 #endif
    199 
    200   if (!symbol) {
    201     ALOGV("Symbol not found: %s\n", name);
    202     return 0;
    203   }
    204 
    205   return (size_t)symbol->getSize();
    206 }
    207 
    208 extern "C" size_t rsloaderGetFuncCount(RSExecRef object) {
    209 #if defined(__LP64__) || defined(__x86_64__)
    210   ELFSectionSymTab<64> *symtab = static_cast<ELFSectionSymTab<64> *>(
    211 #else
    212   ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
    213 #endif
    214     unwrap(object)->getSectionByName(".symtab"));
    215 
    216   if (!symtab) {
    217     return 0;
    218   }
    219 
    220   return symtab->getFuncCount();
    221 }
    222 
    223 extern "C" void rsloaderGetFuncNameList(RSExecRef object,
    224                                         size_t size,
    225                                         char const **list) {
    226 #if defined(__LP64__) || defined(__x86_64__)
    227   ELFSectionSymTab<64> *symtab = static_cast<ELFSectionSymTab<64> *>(
    228 #else
    229   ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
    230 #endif
    231     unwrap(object)->getSectionByName(".symtab"));
    232 
    233   if (symtab) {
    234     symtab->getFuncNameList(size, list);
    235   }
    236 }
    237