Stack.c revision 8e5c78470229fd2f5474574081eaa4a2286aafea
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stacks and their uses (e.g. native --> interpreted method calls). 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the majestic ASCII art in Stack.h. 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "jni.h" 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdarg.h> 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the interpreter stack in a new thread. 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently this doesn't do much, since we don't need to zero out the 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack (and we really don't want to if it was created with mmap). 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitInterpStack(Thread* thread, int stackSize) 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(thread->interpStackStart != NULL); 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(thread->curFrame == NULL); 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling an interpreted method from an internal VM function or 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a frame for an interpreted method onto the stack. This is only 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used when calling into interpreted code from native code. (The 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreter does its own stack frame manipulation for interp-->interp 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls.) 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The size we need to reserve is the sum of parameters, local variables, 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved goodies, and outbound parameters. 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We start by inserting a "break" frame, which ensures that the interpreter 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hands control back to us after the function we call returns or an 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uncaught exception is thrown. 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPushInterpFrame(Thread* self, const Method* method) 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsNativeMethod(method)); 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(method)); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params + locals 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2 // break frame + regular frame 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + method->outsSize * 4; // args to other methods 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame != NULL) 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame); 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Stack overflow on call to interp (top=%p cur=%p size=%d %s.%s)\n", 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart, self->curFrame, self->interpStackSize, 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, method->name); 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHandleStackOverflow(self); 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for the function's 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * args/registers and save area. 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack, unless we want valgrind's help */ 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr - (method->outsSize*4), 0xaf, stackReq); 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevFrame = self->curFrame; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->xtra.localRefTop = NULL; // not required 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->xtra.currentPc = NULL; // not required? 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("PUSH frame: old=%p new=%p (size=%d)\n", 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, FP_FROM_SAVEAREA(saveBlock), 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = FP_FROM_SAVEAREA(saveBlock); 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling a JNI native method from an internal VM fuction or 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. This is also used to create the "fake" native-method 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames at the top of the interpreted stack. 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This actually pushes two frames; the first is a "break" frame. 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top frame has additional space for JNI local reference tracking. 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushJNIFrame(Thread* self, const Method* method) 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params only 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2; // break frame + regular frame 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame != NULL) 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame); 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Stack overflow on call to native (top=%p cur=%p size=%d '%s')\n", 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart, self->curFrame, self->interpStackSize, 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->name); 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHandleStackOverflow(self); 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We leave space for the method args, which are copied in later. 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame == NULL) 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = NULL; 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame); 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevFrame = self->curFrame; 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->xtra.localRefTop = NULL; // not required 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry; 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n", 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, FP_FROM_SAVEAREA(saveBlock), 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = FP_FROM_SAVEAREA(saveBlock); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by the JNI PushLocalFrame call. We push a new frame onto 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack that has no ins, outs, or locals, and no break frame above it. 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's strictly used for tracking JNI local refs, and will be popped off 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by dvmPopFrame if it's not removed explicitly. 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushLocalFrame(Thread* self, const Method* method) 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = sizeof(StackSaveArea); // regular frame 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->curFrame != NULL); 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame); 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space; let JNI throw the exception */ 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Stack overflow on PushLocal (top=%p cur=%p size=%d '%s')\n", 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart, self->curFrame, self->interpStackSize, 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->name); 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHandleStackOverflow(self); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = self->curFrame; 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry; 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n", 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, FP_FROM_SAVEAREA(saveBlock), 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = FP_FROM_SAVEAREA(saveBlock); 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop one frame pushed on by JNI PushLocalFrame. 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we've gone too far, the previous frame is either a break frame or 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an interpreted frame. Either way, the method pointer won't match. 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPopLocalFrame(Thread* self) 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame); 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsBreakFrame(self->curFrame)); 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) { 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The previous frame doesn't have the same method pointer -- we've 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been asked to pop too much. 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsBreakFrame(saveBlock->prevFrame) || 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project !dvmIsNativeMethod( 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SAVEAREA_FROM_FP(saveBlock->prevFrame)->method)); 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("POP JNI local frame: removing %s, now %s\n", 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->name, 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name); 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, saveBlock); 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = saveBlock->prevFrame; 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop a frame we added. There should be one method frame and one break 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame. 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If JNI Push/PopLocalFrame calls were mismatched, we might end up 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popping multiple method frames before we find the break. 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" if there was no frame to pop. 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPopFrame(Thread* self) 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame == NULL) 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = SAVEAREA_FROM_FP(self->curFrame); 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsBreakFrame(self->curFrame)); 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove everything up to the break frame. If this was a call into 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * native code, pop the JNI local references table. 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) { 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* probably a native->native JNI call */ 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(saveBlock->method)) { 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("Popping JNI stack frame for %s.%s%s\n", 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->clazz->descriptor, 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->name, 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ? 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "" : " (JNI local)"); 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(saveBlock->xtra.localRefTop != NULL); 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(saveBlock->xtra.localRefTop >=self->jniLocalRefTable.table && 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->xtra.localRefTop <=self->jniLocalRefTable.nextEntry); 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, saveBlock); 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveBlock->method != NULL) { 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("PopFrame missed the break\n"); 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); // stack trashed -- nowhere to go in this thread 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("POP frame: cur=%p new=%p\n", 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, saveBlock->prevFrame); 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = saveBlock->prevFrame; 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Common code for dvmCallMethodV/A and dvmInvokeMethod. 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pushes a call frame on, advancing self->curFrame. 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* callPrep(Thread* self, const Method* method, Object* obj, 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool checkAccess) 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->status != THREAD_RUNNING) { 354fea44bae077d2d5b4d5197132b2556fd3882d241Andy McFadden LOGW("threadid=%d: status=%d on call to %s.%s -\n", 355fea44bae077d2d5b4d5197132b2556fd3882d241Andy McFadden self->threadId, self->status, 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, method->name); 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self != NULL); 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(method != NULL); 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = obj->clazz; 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = method->clazz; 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project IF_LOGVV() { 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("thread=%d native code calling %s.%s %s\n", self->threadId, 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (checkAccess) { 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* needed for java.lang.reflect.Method.invoke */ 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->curFrame), 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method)) 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* note this throws IAException, not IAError */ 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalAccessException;", 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "access to method denied"); 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a call frame on. If there isn't enough room for ins, locals, 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * outs, and the saved state, it will throw an exception. 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This updates self->curFrame. 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling native code the hard way */ 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushJNIFrame(self, method)) { 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling interpreted code */ 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushInterpFrame(self, method)) { 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return clazz; 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call. 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Note this can't be inlined because it takes a variable number of args.) 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethod(Thread* self, const Method* method, Object* obj, 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue* pResult, ...) 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue result; 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_list args; 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_start(args, pResult); 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethodV(self, method, obj, pResult, args); 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_end(args); 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with a variable number of arguments. We process 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to take the class as an argument because, in Dalvik, 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't need to worry about static synchronized methods. 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodV(Thread* self, const Method* method, Object* obj, 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue* pResult, va_list args) 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL && dvmIsValidObject(obj)); 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (u4) obj; 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (*(desc++)) { 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'D': case 'J': { 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u8 val = va_arg(args, u8); 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(ins, &val, 8); // EABI prevents direct store 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += 2; 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += 2; 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'F': { 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* floats were normalized to doubles; convert back */ 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project float f = (float) va_arg(args, double); 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = dvmFloatToU4(f); 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'L': { /* 'shorty' descr uses L for all refs, incl array */ 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* argObj = (Object*) va_arg(args, u4); 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj == NULL || dvmIsValidObject(obj)); 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (u4) argObj; 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = va_arg(args, u4); 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThreadStack(dvmThreadSelf()); 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*method->nativeFunc)(self->curFrame, pResult, method, self); 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with arguments provided in an array. We process 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The values were likely placed into an uninitialized jvalue array using 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the field specifiers, which means that sub-32-bit fields (e.g. short, 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boolean) may not have 32 or 64 bits of valid data. This is different 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the varargs invocation where the C compiler does a widening 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion when calling a function. As a result, we have to be a 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * little more precise when pulling stuff out. 5318e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * 5328e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * "args" may be NULL if the method has no arguments. 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodA(Thread* self, const Method* method, Object* obj, 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue* pResult, const jvalue* args) 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (u4) obj; 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (*(desc++)) { 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'D': case 'J': { 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(ins, &args->j, 8); /* EABI prevents direct store */ 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += 2; 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += 2; 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args++; 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'F': case 'I': case 'L': { /* (no '[' in short signatures) */ 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = args->i; /* get all 32 bits */ 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args++; 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'S': { 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = args->s; /* 16 bits, sign-extended */ 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args++; 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'C': { 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = args->c; /* 16 bits, unsigned */ 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args++; 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'B': { 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = args->b; /* 8 bits, sign-extended */ 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args++; 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'Z': { 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = args->z; /* 8 bits, zero or non-zero */ 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args++; 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Invalid char %c in short signature of %s.%s\n", 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *(desc-1), clazz->descriptor, method->name); 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*method->nativeFunc)(self->curFrame, pResult, method, self); 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke a method, using the specified arguments and return type, through 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the reflection interfaces. Could be a virtual or direct method 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (including constructors). Used for reflection. 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deals with boxing/unboxing primitives and performs widening conversions. 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "invokeObj" will be null for a static method. 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the invocation returns with an exception raised, we have to wrap it. 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmInvokeMethod(Object* obj, const Method* method, 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayObject* argList, ArrayObject* params, ClassObject* returnType, 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool noAccessCheck) 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* retObj = NULL; 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s4* ins; 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount, argListLength; 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue retval; 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* verify arg count */ 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argList != NULL) 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = argList->length; 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = 0; 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argListLength != (int) params->length) { 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("invoke: expected %d args, received %d args\n", 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project params->length, argListLength); 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalArgumentException;", 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "wrong number of arguments"); 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, !noAccessCheck); 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize); 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount = 0; 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (s4) obj; 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy the args onto the stack. Primitive types are converted when 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * necessary, and object types are verified. 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DataObject** args; 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject** types; 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args = (DataObject**) argList->contents; 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project types = (ClassObject**) params->contents; 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < argListLength; i++) { 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int width; 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project width = dvmConvertArgument(*args++, *types++, ins); 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (width < 0) { 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (*(args-1) != NULL) { 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n", 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i, (*(args-1))->obj.clazz->descriptor, 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*(types-1))->descriptor); 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); // throw wants to pull PC out of stack 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalArgumentException;", 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "argument type mismatch"); 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail_popped; 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += width; 706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += width; 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThreadStack(dvmThreadSelf()); 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*method->nativeFunc)(self->curFrame, &retval, method, self); 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, &retval); 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If an exception is raised, wrap and replace. This is necessary 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the invoked method could have thrown a checked exception 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the caller wasn't prepared for. 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to do this up in the interpreted code, but that will 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * leave us with a shortened stack trace in the top-level exception. 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) { 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this isn't a void method or constructor, convert the return type 740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to an appropriate object. 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't do this when an exception is raised because the value 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in "retval" is undefined. 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (returnType != NULL) { 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project retObj = (Object*)dvmWrapPrimitive(retval, returnType); 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(retObj, NULL); 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_popped: 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return retObj; 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct LineNumFromPcContext { 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 address; 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 lineNum; 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} LineNumFromPcContext; 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum) 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt; 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // We know that this callback will be called in 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ascending address order, so keep going until we find 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // a match or we've just gone past it. 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address > pContext->address) { 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The line number from the previous positions callback 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // wil be the final result. 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pContext->lineNum = lineNum; 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (address == pContext->address) ? 1 : 0; 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine the source file line number based on the program counter. 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pc" is an offset, in 16-bit units, from the start of the method's code. 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if no match was found (possibly because the source files were 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compiled without "-g", so no line number information is present). 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -2 for native methods (as expected in exception traces). 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmLineNumFromPC(const Method* method, u4 relPc) 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pDexCode = dvmGetMethodCode(method); 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexCode == NULL) { 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method)) 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -2; 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; /* can happen for abstract method stub */ 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext context; 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(&context, 0, sizeof(context)); 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.address = relPc; 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A method with no line number info should return -1 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.lineNum = -1; 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode, 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->prototype.protoIdx, 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->accessFlags, 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumForPcCb, NULL, &context); 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return context.lineNum; 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the frame depth. 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Excludes "break" frames. 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeExactFrameDepth(const void* fp) 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = 0; 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsBreakFrame(fp)) 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count++; 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return count; 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "vague" frame depth, which is just a pointer subtraction. 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is NOT an overly generous assessment of the number of 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames; the only meaningful use is to compare against the result of 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an earlier invocation. 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Useful for implementing single-step debugger modes, which may need to 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call this for every instruction. 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeVagueFrameDepth(Thread* thread, const void* fp) 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* interpStackStart = thread->interpStackStart; 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* interpStackBottom = interpStackStart - thread->interpStackSize; 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert((u1*) fp >= interpStackBottom && (u1*) fp < interpStackStart); 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return interpStackStart - (u1*) fp; 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the calling frame. Pass in the current fp. 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Skip "break" frames and reflection invoke frames. 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmGetCallerFP(const void* curFrame) 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectretry: 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(caller)) { 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* pop up one more */ 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = SAVEAREA_FROM_FP(caller)->prevFrame; 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; /* hit the top */ 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we got here by java.lang.reflect.Method.invoke(), we don't 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to return Method's class loader. Shift up one and try 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * again. 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(caller); 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsReflectionMethod(saveArea->method)) { 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = saveArea->prevFrame; 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(caller != NULL); 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto retry; 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return caller; 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's class. Pass in the current fp. 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class. 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCallerClass(const void* curFrame) 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller; 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(curFrame); 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's class. Pass in the current fp. 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller2Class(const void* curFrame) 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* callerCaller; 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* go one more */ 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project callerCaller = dvmGetCallerFP(caller); 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (callerCaller == NULL) 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(callerCaller)->method->clazz; 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's caller's class. Pass in the current fp. 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller3Class(const void* curFrame) 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Walk up two frames if possible. */ 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < 2; i++) { 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(caller); 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a flat array of methods that comprise the current interpreter 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack trace. Pass in the current frame ptr. 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocates a new array and fills it with method pointers. Break frames 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are skipped, but reflection invocations are not. The caller must free 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "*pArray". 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current frame will be in element 0. 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success, "false" on failure (e.g. malloc failed). 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmCreateStackTraceArray(const void* fp, const Method*** pArray, 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int* pLength) 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method** array; 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int idx, depth; 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project depth = dvmComputeExactFrameDepth(fp); 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project array = (const Method**) malloc(depth * sizeof(Method*)); 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (array == NULL) 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsBreakFrame(fp)) 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project array[idx++] = SAVEAREA_FROM_FP(fp)->method; 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(idx == depth); 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pArray = array; 976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pLength = depth; 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open up the reserved area and throw an exception. The reserved area 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be needed to create and initialize the exception itself. 983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we already opened it and we're continuing to overflow, abort the VM. 985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to leave the "reserved" area open until the "catch" handler has 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finished doing its processing. This is because the catch handler may 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to resolve classes, which requires calling into the class loader if 989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the classes aren't already in the "initiating loader" list. 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHandleStackOverflow(Thread* self) 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Can we make the reserved area available? 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->stackOverflowed) { 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Already did, nothing to do but bail. 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting\n", 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId); 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* open it up to the full range */ 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("Stack overflow, expanding (%p to %p)\n", self->interpStackEnd, 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart - self->interpStackSize); 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThread(self, false); 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = self->interpStackStart - self->interpStackSize; 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = true; 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we were trying to throw an exception when the stack overflowed, 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we will blow up when doing the class lookup on StackOverflowError 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because of the pending exception. So, we clear it and make it 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the cause of the SOE. 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* excep = dvmGetException(self); 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (excep != NULL) { 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Stack overflow while throwing exception\n"); 1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); 1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowChainedException("Ljava/lang/StackOverflowError;", NULL, excep); 1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduce the available stack size. By this point we should have finished 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our overflow processing. 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCleanupStackOverflow(Thread* self) 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* newStackEnd; 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->stackOverflowed); 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStackEnd = (self->interpStackStart - self->interpStackSize) 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + STACK_OVERFLOW_RESERVE; 1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((u1*)self->curFrame <= newStackEnd) { 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n", 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd, self->curFrame); 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = newStackEnd; 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = false; 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd, 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame); 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump stack frames, starting from the specified frame and moving down. 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Each frame holds a pointer to the currently executing method, and the 1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved program counter from the caller ("previous" frame). This means 1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't have the PC for the current method on the stack, which is 1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pretty reasonable since it's in the "PC register" for the VM. Because 1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exceptions need to show the correct line number we actually *do* have 1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an updated version in the fame's "xtra.currentPc", but it's unreliable. 1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note "framePtr" could be NULL in rare circumstances. 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpFrames(const DebugOutputTarget* target, void* framePtr, 1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* thread) 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea; 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method; 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int checkCount = 0; 1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u2* currentPc = NULL; 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool first = true; 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "currentPc" is updated whenever we execute an instruction that 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * might throw an exception. Show it here. 1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (framePtr != NULL && !dvmIsBreakFrame(framePtr)) { 1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->xtra.currentPc != NULL) 1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->xtra.currentPc; 1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (framePtr != NULL) { 1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method = saveArea->method; 1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(framePtr)) { 1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmPrintDebugMessage(target, " (break frame)\n"); 1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int relPc; 1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (currentPc != NULL) 1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = currentPc - saveArea->method->insns; 1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = -1; 1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* className = dvmDescriptorToDot(method->clazz->descriptor); 1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) 1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at %s.%s(Native Method)\n", className, method->name); 1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else { 1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at %s.%s(%s:%s%d)\n", 1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project className, method->name, dvmGetMethodSourceFile(method), 1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (relPc >= 0 && first) ? "~" : "", 1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); 1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(className); 1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (first && 1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (thread->status == THREAD_WAIT || 1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thread->status == THREAD_TIMED_WAIT)) 1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* warning: wait status not stable, even in suspend */ 1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Monitor* mon = thread->waitMonitor; 1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* obj = dvmGetMonitorObject(mon); 1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) { 1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project className = dvmDescriptorToDot(obj->clazz->descriptor); 1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " - waiting on <%p> (a %s)\n", mon, className); 1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(className); 1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get saved PC for previous frame. There's no savedPc in a "break" 1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame, because that represents native or interpreted code 1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoked by the VM. The saved PC is sitting in the "PC register", 1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a local variable on the native stack. 1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->savedPc; 1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(framePtr != saveArea->prevFrame); 1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project framePtr = saveArea->prevFrame; 1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount++; 1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (checkCount > 200) { 1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " ***** printed %d frames, not showing any more\n", 1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount); 1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "\n"); 1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread. 1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) 1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dumpFrames(target, thread->curFrame, thread); 1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread, which is still running. 1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very dangerous, because stack frames are being pushed on and 1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popped off, and if the thread exits we'll be looking at freed memory. 1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The plan here is to take a snapshot of the stack and then dump that 1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to try to minimize the chances of catching it mid-update. This should 1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work reasonably well on a single-CPU system. 1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is a small chance that calling here will crash the VM. 1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread) 1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* origStack; 1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackCopy = NULL; 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int origSize, fpOffset; 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* fp; 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int depthLimit = 200; 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thread == NULL || thread->curFrame == NULL) { 1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n", 1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thread, (thread != NULL) ? thread->threadId : 0); 1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* wait for a full quantum */ 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sched_yield(); 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* copy the info we need, then the stack itself */ 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origSize = thread->interpStackSize; 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origStack = (const u1*) thread->interpStackStart - origSize; 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackCopy = (u1*) malloc(origSize); 1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fpOffset = (u1*) thread->curFrame - origStack; 1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(stackCopy, origStack, origSize); 1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Run through the stack and rewrite the "prev" pointers. 1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame); 1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = stackCopy + fpOffset; 1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (true) { 1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int prevOffset; 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (depthLimit-- < 0) { 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* we're probably screwed */ 1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n"); 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->prevFrame == NULL) 1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset = (u1*) saveArea->prevFrame - origStack; 1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (prevOffset < 0 || prevOffset > origSize) { 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: bad offset found: %d (from %p %p)\n", 1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset, origStack, saveArea->prevFrame); 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->prevFrame = NULL; 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->prevFrame = stackCopy + prevOffset; 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We still need to pass the Thread for some monitor wait stuff. 1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dumpFrames(target, stackCopy + fpOffset, thread); 1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(stackCopy); 1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1237