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 22 #include <stdint.h> 23 #include <stdlib.h> 24 #include <sys/mman.h> 25 26 #ifdef __arm__ 27 #define STUB_SIZE 8 // 8 bytes (2 words) 28 #endif 29 30 StubLayout::StubLayout() : table(NULL), count(0) { 31 } 32 33 void StubLayout::initStubTable(unsigned char *table_, size_t count_) { 34 table = table_; 35 count = count_; 36 } 37 38 void *StubLayout::allocateStub(void *addr) { 39 #ifdef __arm__ 40 if (count == 0) { 41 // No free stub slot is available 42 return NULL; 43 } 44 45 // Initialize the stub 46 unsigned char *stub = table; 47 setStubAddress(stub, addr); 48 49 // Increase the free stub slot pointer 50 table += STUB_SIZE; 51 count--; 52 53 return stub; 54 55 #else 56 return NULL; 57 #endif 58 } 59 60 void StubLayout::setStubAddress(void *stub_, void *addr) { 61 #ifdef __arm__ 62 uint8_t *stub = (uint8_t *)stub_; 63 stub[0] = 0x04; // ldr pc, [pc, #-4] 64 stub[1] = 0xf0; // ldr pc, [pc, #-4] 65 stub[2] = 0x1f; // ldr pc, [pc, #-4] 66 stub[3] = 0xe5; // ldr pc, [pc, #-4] 67 68 void **target = (void **)(stub + 4); 69 *target = addr; 70 #endif 71 } 72 73 size_t StubLayout::calcStubTableSize(size_t count) const { 74 #ifdef __arm__ 75 return count * STUB_SIZE; 76 #else 77 return 0; 78 #endif 79 } 80