Home | History | Annotate | Download | only in lib
      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 #include "StubLayout.h"
     18 
     19 #include "utils/flush_cpu_cache.h"
     20 #include "utils/raw_ostream.h"
     21 #include "utils/rsl_assert.h"
     22 
     23 #include <stdint.h>
     24 #include <stdlib.h>
     25 #include <sys/mman.h>
     26 
     27 StubLayout::StubLayout() : table(NULL), count(0) {
     28 }
     29 
     30 void StubLayout::initStubTable(unsigned char *table_, size_t count_) {
     31   table = table_;
     32   count = count_;
     33 }
     34 
     35 void *StubLayout::allocateStub(void *addr) {
     36   // Check if we have created this stub or not.
     37   std::map<void *, void *>::iterator index_iter = stub_index.find(addr);
     38 
     39   if (index_iter != stub_index.end()) {
     40     return index_iter->second;
     41   }
     42 
     43   // We have to create a new stub
     44   if (count == 0) {
     45     // No free stub slot is available
     46     return NULL;
     47   }
     48 
     49   // Initialize the stub
     50   unsigned char *stub = table;
     51   setStubAddress(stub, addr);
     52   stub_index.insert(std::make_pair(addr, stub));
     53 
     54   // Increase the free stub slot pointer
     55   table += getUnitStubSize();
     56   count--;
     57 
     58   return stub;
     59 }
     60 
     61 size_t StubLayout::calcStubTableSize(size_t count) const {
     62   return count * getUnitStubSize();
     63 }
     64 
     65 size_t StubLayoutARM::getUnitStubSize() const {
     66   return 8;
     67 }
     68 
     69 void StubLayoutARM::setStubAddress(void *stub_, void *addr) {
     70   uint8_t *stub = (uint8_t *)stub_;
     71   stub[0] = 0x04; // ldr pc, [pc, #-4]
     72   stub[1] = 0xf0; // ldr pc, [pc, #-4]
     73   stub[2] = 0x1f; // ldr pc, [pc, #-4]
     74   stub[3] = 0xe5; // ldr pc, [pc, #-4]
     75 
     76   void **target = (void **)(stub + 4);
     77   *target = addr;
     78 }
     79 
     80 size_t StubLayoutMIPS::getUnitStubSize() const {
     81   return 16;
     82 }
     83 
     84 void StubLayoutMIPS::setStubAddress(void *stub_, void *addr) {
     85   uint32_t addr32 = (uint32_t)(uintptr_t)addr;
     86   uint16_t addr_hi16 = (addr32 >> 16) &  0xffff;
     87   uint16_t addr_lo16 = addr32 & 0xffff;
     88 
     89   uint32_t *stub = (uint32_t *)stub_;
     90   stub[0] = 0x3c190000ul | addr_hi16; // lui
     91   stub[1] = 0x37390000ul | addr_lo16; // ori
     92   stub[2] = 0x03200008ul; // jr (jump register)
     93   stub[3] = 0x00000000ul; // nop
     94 }
     95