1 /* 2 * Copyright (C) 2013 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 "trampoline_compiler.h" 18 19 #include "jni_internal.h" 20 #include "utils/arm/assembler_arm.h" 21 #include "utils/mips/assembler_mips.h" 22 #include "utils/x86/assembler_x86.h" 23 24 #define __ assembler-> 25 26 namespace art { 27 28 namespace arm { 29 static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi, 30 ThreadOffset offset) { 31 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm))); 32 33 switch (abi) { 34 case kInterpreterAbi: // Thread* is first argument (R0) in interpreter ABI. 35 __ LoadFromOffset(kLoadWord, PC, R0, offset.Int32Value()); 36 break; 37 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (R0). 38 __ LoadFromOffset(kLoadWord, IP, R0, JNIEnvExt::SelfOffset().Int32Value()); 39 __ LoadFromOffset(kLoadWord, PC, IP, offset.Int32Value()); 40 break; 41 case kPortableAbi: // R9 holds Thread*. 42 case kQuickAbi: // Fall-through. 43 __ LoadFromOffset(kLoadWord, PC, R9, offset.Int32Value()); 44 } 45 __ bkpt(0); 46 47 size_t cs = assembler->CodeSize(); 48 UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs)); 49 MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 50 assembler->FinalizeInstructions(code); 51 52 return entry_stub.release(); 53 } 54 } // namespace arm 55 56 namespace mips { 57 static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi, 58 ThreadOffset offset) { 59 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips))); 60 61 switch (abi) { 62 case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI. 63 __ LoadFromOffset(kLoadWord, T9, A0, offset.Int32Value()); 64 break; 65 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0). 66 __ LoadFromOffset(kLoadWord, T9, A0, JNIEnvExt::SelfOffset().Int32Value()); 67 __ LoadFromOffset(kLoadWord, T9, T9, offset.Int32Value()); 68 break; 69 case kPortableAbi: // S1 holds Thread*. 70 case kQuickAbi: // Fall-through. 71 __ LoadFromOffset(kLoadWord, T9, S1, offset.Int32Value()); 72 } 73 __ Jr(T9); 74 __ Nop(); 75 __ Break(); 76 77 size_t cs = assembler->CodeSize(); 78 UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs)); 79 MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 80 assembler->FinalizeInstructions(code); 81 82 return entry_stub.release(); 83 } 84 } // namespace mips 85 86 namespace x86 { 87 static const std::vector<uint8_t>* CreateTrampoline(ThreadOffset offset) { 88 UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86))); 89 90 // All x86 trampolines call via the Thread* held in fs. 91 __ fs()->jmp(Address::Absolute(offset)); 92 __ int3(); 93 94 size_t cs = assembler->CodeSize(); 95 UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs)); 96 MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 97 assembler->FinalizeInstructions(code); 98 99 return entry_stub.release(); 100 } 101 } // namespace x86 102 103 const std::vector<uint8_t>* CreateTrampoline(InstructionSet isa, EntryPointCallingConvention abi, 104 ThreadOffset offset) { 105 switch (isa) { 106 case kArm: 107 case kThumb2: 108 return arm::CreateTrampoline(abi, offset); 109 case kMips: 110 return mips::CreateTrampoline(abi, offset); 111 case kX86: 112 return x86::CreateTrampoline(offset); 113 default: 114 LOG(FATAL) << "Unknown InstructionSet: " << isa; 115 return NULL; 116 } 117 } 118 119 } // namespace art 120