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 */ 164fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stacks and their uses (e.g. native --> interpreted method calls). 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the majestic ASCII art in Stack.h. 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "jni.h" 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdarg.h> 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the interpreter stack in a new thread. 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently this doesn't do much, since we don't need to zero out the 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack (and we really don't want to if it was created with mmap). 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitInterpStack(Thread* thread, int stackSize) 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(thread->interpStackStart != NULL); 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(thread->curFrame == NULL); 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling an interpreted method from an internal VM function or 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a frame for an interpreted method onto the stack. This is only 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used when calling into interpreted code from native code. (The 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreter does its own stack frame manipulation for interp-->interp 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls.) 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The size we need to reserve is the sum of parameters, local variables, 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved goodies, and outbound parameters. 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We start by inserting a "break" frame, which ensures that the interpreter 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hands control back to us after the function we call returns or an 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uncaught exception is thrown. 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPushInterpFrame(Thread* self, const Method* method) 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsNativeMethod(method)); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(method)); 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params + locals 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2 // break frame + regular frame 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + method->outsSize * 4; // args to other methods 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame != NULL) 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame); 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGW("Stack overflow on call to interp " 8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project "(req=%d top=%p cur=%p size=%d %s.%s)\n", 8299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project stackReq, self->interpStackStart, self->curFrame, 8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->clazz->descriptor, method->name); 846ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for the function's 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * args/registers and save area. 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack, unless we want valgrind's help */ 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr - (method->outsSize*4), 0xaf, stackReq); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame); 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevFrame = self->curFrame; 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 109d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden breakSaveBlock->xtra.localRefCookie = 0; // not required 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->xtra.currentPc = NULL; // not required? 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("PUSH frame: old=%p new=%p (size=%d)\n", 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, FP_FROM_SAVEAREA(saveBlock), 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = FP_FROM_SAVEAREA(saveBlock); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling a JNI native method from an internal VM fuction or 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. This is also used to create the "fake" native-method 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames at the top of the interpreted stack. 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This actually pushes two frames; the first is a "break" frame. 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top frame has additional space for JNI local reference tracking. 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushJNIFrame(Thread* self, const Method* method) 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params only 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2; // break frame + regular frame 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame != NULL) 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 15399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGW("Stack overflow on call to native " 15499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project "(req=%d top=%p cur=%p size=%d '%s')\n", 15599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project stackReq, self->interpStackStart, self->curFrame, 15699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->name); 1576ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We leave space for the method args, which are copied in later. 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame == NULL) 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = NULL; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame); 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevFrame = self->curFrame; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 186d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden breakSaveBlock->xtra.localRefCookie = 0; // not required 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 190d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#ifdef USE_INDIRECT_REF 191d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 192d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#else 193d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry; 194d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#endif 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n", 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, FP_FROM_SAVEAREA(saveBlock), 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = FP_FROM_SAVEAREA(saveBlock); 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by the JNI PushLocalFrame call. We push a new frame onto 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack that has no ins, outs, or locals, and no break frame above it. 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's strictly used for tracking JNI local refs, and will be popped off 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by dvmPopFrame if it's not removed explicitly. 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushLocalFrame(Thread* self, const Method* method) 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = sizeof(StackSaveArea); // regular frame 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->curFrame != NULL); 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space; let JNI throw the exception */ 22799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGW("Stack overflow on PushLocal " 22899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project "(req=%d top=%p cur=%p size=%d '%s')\n", 22999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project stackReq, self->interpStackStart, self->curFrame, 23099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->name); 2316ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame); 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = self->curFrame; 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 253d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#ifdef USE_INDIRECT_REF 254d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 255d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#else 256d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry; 257d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#endif 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n", 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, FP_FROM_SAVEAREA(saveBlock), 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = FP_FROM_SAVEAREA(saveBlock); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop one frame pushed on by JNI PushLocalFrame. 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we've gone too far, the previous frame is either a break frame or 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an interpreted frame. Either way, the method pointer won't match. 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPopLocalFrame(Thread* self) 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame); 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsBreakFrame(self->curFrame)); 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) { 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The previous frame doesn't have the same method pointer -- we've 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been asked to pop too much. 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsBreakFrame(saveBlock->prevFrame) || 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project !dvmIsNativeMethod( 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SAVEAREA_FROM_FP(saveBlock->prevFrame)->method)); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("POP JNI local frame: removing %s, now %s\n", 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->name, 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name); 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, saveBlock); 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = saveBlock->prevFrame; 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop a frame we added. There should be one method frame and one break 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame. 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If JNI Push/PopLocalFrame calls were mismatched, we might end up 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popping multiple method frames before we find the break. 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" if there was no frame to pop. 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPopFrame(Thread* self) 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->curFrame == NULL) 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = SAVEAREA_FROM_FP(self->curFrame); 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsBreakFrame(self->curFrame)); 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove everything up to the break frame. If this was a call into 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * native code, pop the JNI local references table. 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) { 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* probably a native->native JNI call */ 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(saveBlock->method)) { 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("Popping JNI stack frame for %s.%s%s\n", 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->clazz->descriptor, 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->name, 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ? 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "" : " (JNI local)"); 332d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden assert(saveBlock->xtra.localRefCookie != 0); 333d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden //assert(saveBlock->xtra.localRefCookie >= self->jniLocalRefTable.table && 334d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden // saveBlock->xtra.localRefCookie <=self->jniLocalRefTable.nextEntry); 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, saveBlock); 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame); 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveBlock->method != NULL) { 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("PopFrame missed the break\n"); 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); // stack trashed -- nowhere to go in this thread 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("POP frame: cur=%p new=%p\n", 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame, saveBlock->prevFrame); 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = saveBlock->prevFrame; 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Common code for dvmCallMethodV/A and dvmInvokeMethod. 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pushes a call frame on, advancing self->curFrame. 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* callPrep(Thread* self, const Method* method, Object* obj, 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool checkAccess) 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->status != THREAD_RUNNING) { 36699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGW("threadid=%d: status=%d on call to %s.%s -\n", 36799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->threadId, self->status, 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, method->name); 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self != NULL); 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(method != NULL); 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = obj->clazz; 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = method->clazz; 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project IF_LOGVV() { 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("thread=%d native code calling %s.%s %s\n", self->threadId, 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (checkAccess) { 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* needed for java.lang.reflect.Method.invoke */ 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->curFrame), 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method)) 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* note this throws IAException, not IAError */ 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalAccessException;", 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "access to method denied"); 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a call frame on. If there isn't enough room for ins, locals, 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * outs, and the saved state, it will throw an exception. 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This updates self->curFrame. 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling native code the hard way */ 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushJNIFrame(self, method)) { 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling interpreted code */ 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushInterpFrame(self, method)) { 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return clazz; 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call. 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Note this can't be inlined because it takes a variable number of args.) 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethod(Thread* self, const Method* method, Object* obj, 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue* pResult, ...) 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_list args; 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_start(args, pResult); 434d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden dvmCallMethodV(self, method, obj, false, pResult, args); 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_end(args); 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with a variable number of arguments. We process 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to take the class as an argument because, in Dalvik, 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't need to worry about static synchronized methods. 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodV(Thread* self, const Method* method, Object* obj, 448d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden bool fromJni, JValue* pResult, va_list args) 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL && dvmIsValidObject(obj)); 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (u4) obj; 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4730083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden JNIEnv* env = self->jniEnv; 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (*(desc++)) { 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'D': case 'J': { 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u8 val = va_arg(args, u8); 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(ins, &val, 8); // EABI prevents direct store 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += 2; 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += 2; 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'F': { 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* floats were normalized to doubles; convert back */ 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project float f = (float) va_arg(args, double); 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = dvmFloatToU4(f); 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'L': { /* 'shorty' descr uses L for all refs, incl array */ 4910083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden void* argObj = va_arg(args, void*); 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj == NULL || dvmIsValidObject(obj)); 493d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden if (fromJni) 494d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) dvmDecodeIndirectRef(env, argObj); 495d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden else 496d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) argObj; 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 5010083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden /* Z B C S I -- all passed as 32-bit integers */ 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = va_arg(args, u4); 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThreadStack(dvmThreadSelf()); 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 52199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*method->nativeFunc)(self->curFrame, pResult, method, self); 52799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 532e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#ifndef NDEBUG 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 534e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#endif 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with arguments provided in an array. We process 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The values were likely placed into an uninitialized jvalue array using 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the field specifiers, which means that sub-32-bit fields (e.g. short, 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boolean) may not have 32 or 64 bits of valid data. This is different 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the varargs invocation where the C compiler does a widening 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion when calling a function. As a result, we have to be a 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * little more precise when pulling stuff out. 5488e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * 5498e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * "args" may be NULL if the method has no arguments. 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodA(Thread* self, const Method* method, Object* obj, 552d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden bool fromJni, JValue* pResult, const jvalue* args) 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 5690083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = (u4) obj; /* obj is a "real" ref */ 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5730083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden JNIEnv* env = self->jniEnv; 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 5750083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden switch (*desc++) { 5760083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'D': /* 64-bit quantity; have to use */ 5770083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'J': /* memcpy() in case of mis-alignment */ 5780083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden memcpy(ins, &args->j, 8); 5790083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden ins += 2; 5800083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden verifyCount++; /* this needs an extra push */ 5810083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5820083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'L': /* includes array refs */ 583d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden if (fromJni) 584d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) dvmDecodeIndirectRef(env, args->l); 585d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden else 586d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) args->l; 5870083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5880083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'F': 5890083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'I': 5900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->i; /* full 32 bits */ 5910083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5920083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'S': 5930083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->s; /* 16 bits, sign-extended */ 5940083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5950083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'C': 5960083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->c; /* 16 bits, unsigned */ 5970083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5980083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'B': 5990083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->b; /* 8 bits, sign-extended */ 6000083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 6010083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'Z': 6020083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->z; /* 8 bits, zero or non-zero */ 6030083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 6040083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden default: 6050083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden LOGE("Invalid char %c in short signature of %s.%s\n", 6060083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *(desc-1), clazz->descriptor, method->name); 6070083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden assert(false); 6080083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden goto bail; 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 6100083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden 6110083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden verifyCount++; 6120083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden args++; 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 62599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*method->nativeFunc)(self->curFrame, pResult, method, self); 63199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke a method, using the specified arguments and return type, through 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the reflection interfaces. Could be a virtual or direct method 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (including constructors). Used for reflection. 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deals with boxing/unboxing primitives and performs widening conversions. 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "invokeObj" will be null for a static method. 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the invocation returns with an exception raised, we have to wrap it. 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmInvokeMethod(Object* obj, const Method* method, 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayObject* argList, ArrayObject* params, ClassObject* returnType, 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool noAccessCheck) 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* retObj = NULL; 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s4* ins; 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount, argListLength; 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue retval; 6617b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden bool needPop = false; 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* verify arg count */ 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argList != NULL) 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = argList->length; 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = 0; 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argListLength != (int) params->length) { 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("invoke: expected %d args, received %d args\n", 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project params->length, argListLength); 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalArgumentException;", 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "wrong number of arguments"); 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, !noAccessCheck); 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 6797b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden needPop = true; 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize); 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount = 0; 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (s4) obj; 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy the args onto the stack. Primitive types are converted when 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * necessary, and object types are verified. 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DataObject** args; 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject** types; 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project args = (DataObject**) argList->contents; 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project types = (ClassObject**) params->contents; 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < argListLength; i++) { 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int width; 706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project width = dvmConvertArgument(*args++, *types++, ins); 708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (width < 0) { 709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (*(args-1) != NULL) { 710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n", 711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i, (*(args-1))->obj.clazz->descriptor, 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*(types-1))->descriptor); 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); // throw wants to pull PC out of stack 7157b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden needPop = false; 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/IllegalArgumentException;", 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "argument type mismatch"); 7187b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden goto bail; 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += width; 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += width; 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThreadStack(dvmThreadSelf()); 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 73499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*method->nativeFunc)(self->curFrame, &retval, method, self); 74099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, &retval); 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 7467b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden * Pop the frame immediately. The "wrap" calls below can cause 7477b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden * allocations, and we don't want the GC to walk the now-dead frame. 7487b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden */ 7497b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden dvmPopFrame(self); 7507b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden needPop = false; 7517b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden 7527b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden /* 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If an exception is raised, wrap and replace. This is necessary 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the invoked method could have thrown a checked exception 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the caller wasn't prepared for. 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to do this up in the interpreted code, but that will 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * leave us with a shortened stack trace in the top-level exception. 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) { 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this isn't a void method or constructor, convert the return type 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to an appropriate object. 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't do this when an exception is raised because the value 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in "retval" is undefined. 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (returnType != NULL) { 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project retObj = (Object*)dvmWrapPrimitive(retval, returnType); 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(retObj, NULL); 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 7777b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden if (needPop) { 7787b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden dvmPopFrame(self); 7797b4c1d52a946506d49c6da5649d1677e92263d66Andy McFadden } 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return retObj; 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct LineNumFromPcContext { 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 address; 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 lineNum; 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} LineNumFromPcContext; 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum) 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt; 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 792de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro // We know that this callback will be called in 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ascending address order, so keep going until we find 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // a match or we've just gone past it. 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address > pContext->address) { 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The line number from the previous positions callback 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // wil be the final result. 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pContext->lineNum = lineNum; 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (address == pContext->address) ? 1 : 0; 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine the source file line number based on the program counter. 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pc" is an offset, in 16-bit units, from the start of the method's code. 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if no match was found (possibly because the source files were 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compiled without "-g", so no line number information is present). 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -2 for native methods (as expected in exception traces). 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmLineNumFromPC(const Method* method, u4 relPc) 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pDexCode = dvmGetMethodCode(method); 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexCode == NULL) { 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method)) 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -2; 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; /* can happen for abstract method stub */ 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext context; 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(&context, 0, sizeof(context)); 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.address = relPc; 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A method with no line number info should return -1 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.lineNum = -1; 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode, 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->prototype.protoIdx, 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->accessFlags, 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumForPcCb, NULL, &context); 836de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return context.lineNum; 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the frame depth. 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Excludes "break" frames. 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeExactFrameDepth(const void* fp) 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = 0; 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsBreakFrame(fp)) 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count++; 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return count; 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "vague" frame depth, which is just a pointer subtraction. 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is NOT an overly generous assessment of the number of 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames; the only meaningful use is to compare against the result of 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an earlier invocation. 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Useful for implementing single-step debugger modes, which may need to 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call this for every instruction. 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeVagueFrameDepth(Thread* thread, const void* fp) 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* interpStackStart = thread->interpStackStart; 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 870e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp >= interpStackStart - thread->interpStackSize); 871e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp < interpStackStart); 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return interpStackStart - (u1*) fp; 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the calling frame. Pass in the current fp. 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Skip "break" frames and reflection invoke frames. 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmGetCallerFP(const void* curFrame) 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectretry: 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(caller)) { 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* pop up one more */ 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = SAVEAREA_FROM_FP(caller)->prevFrame; 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; /* hit the top */ 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we got here by java.lang.reflect.Method.invoke(), we don't 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to return Method's class loader. Shift up one and try 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * again. 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(caller); 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsReflectionMethod(saveArea->method)) { 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = saveArea->prevFrame; 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(caller != NULL); 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto retry; 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return caller; 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's class. Pass in the current fp. 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class. 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCallerClass(const void* curFrame) 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller; 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(curFrame); 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's class. Pass in the current fp. 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller2Class(const void* curFrame) 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* callerCaller; 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* go one more */ 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project callerCaller = dvmGetCallerFP(caller); 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (callerCaller == NULL) 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(callerCaller)->method->clazz; 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's caller's class. Pass in the current fp. 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller3Class(const void* curFrame) 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Walk up two frames if possible. */ 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < 2; i++) { 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(caller); 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 968de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a flat array of methods that comprise the current interpreter 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack trace. Pass in the current frame ptr. 975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocates a new array and fills it with method pointers. Break frames 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are skipped, but reflection invocations are not. The caller must free 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "*pArray". 979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current frame will be in element 0. 981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success, "false" on failure (e.g. malloc failed). 983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmCreateStackTraceArray(const void* fp, const Method*** pArray, 985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int* pLength) 986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method** array; 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int idx, depth; 989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project depth = dvmComputeExactFrameDepth(fp); 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project array = (const Method**) malloc(depth * sizeof(Method*)); 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (array == NULL) 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsBreakFrame(fp)) 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project array[idx++] = SAVEAREA_FROM_FP(fp)->method; 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(idx == depth); 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pArray = array; 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pLength = depth; 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open up the reserved area and throw an exception. The reserved area 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be needed to create and initialize the exception itself. 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we already opened it and we're continuing to overflow, abort the VM. 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to leave the "reserved" area open until the "catch" handler has 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finished doing its processing. This is because the catch handler may 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to resolve classes, which requires calling into the class loader if 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the classes aren't already in the "initiating loader" list. 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10176ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFaddenvoid dvmHandleStackOverflow(Thread* self, const Method* method) 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Can we make the reserved area available? 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->stackOverflowed) { 1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Already did, nothing to do but bail. 1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting\n", 1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId); 1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* open it up to the full range */ 10336ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden LOGI("threadid=%d: stack overflow on call to %s.%s:%s\n", 10346ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden self->threadId, 10356ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->clazz->descriptor, method->name, method->shorty); 10366ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->curFrame); 10376ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden LOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)\n", 10386ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4, 10396ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea), 10406ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden saveArea, (u1*) saveArea - self->interpStackEnd); 10416ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden LOGI(" expanding stack end (%p to %p)\n", self->interpStackEnd, 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart - self->interpStackSize); 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThread(self, false); 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = self->interpStackStart - self->interpStackSize; 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = true; 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we were trying to throw an exception when the stack overflowed, 1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we will blow up when doing the class lookup on StackOverflowError 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because of the pending exception. So, we clear it and make it 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the cause of the SOE. 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* excep = dvmGetException(self); 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (excep != NULL) { 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Stack overflow while throwing exception\n"); 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 10584fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden dvmThrowChainedExceptionByClass(gDvm.classJavaLangStackOverflowError, 10594fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden NULL, excep); 1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduce the available stack size. By this point we should have finished 1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our overflow processing. 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10664fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFaddenvoid dvmCleanupStackOverflow(Thread* self, const Object* exception) 1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* newStackEnd; 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->stackOverflowed); 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 10724fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden if (exception->clazz != gDvm.classJavaLangStackOverflowError) { 10734fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden /* exception caused during SOE, not the SOE itself */ 10744fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden return; 10754fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden } 10764fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStackEnd = (self->interpStackStart - self->interpStackSize) 1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + STACK_OVERFLOW_RESERVE; 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((u1*)self->curFrame <= newStackEnd) { 1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n", 1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd, self->curFrame); 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = newStackEnd; 1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = false; 1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd, 1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame); 1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1095fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Extract the object that is the target of a monitor-enter instruction 1096fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * in the top stack frame of "thread". 1097fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1098fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The other thread might be alive, so this has to work carefully. 1099fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1100fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * We assume the thread list lock is currently held. 1101fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1102fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Returns "true" if we successfully recover the object. "*pOwner" will 1103fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * be NULL if we can't determine the owner for some reason (e.g. race 1104fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * condition on ownership transfer). 1105fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1106fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenstatic bool extractMonitorEnterObject(Thread* thread, Object** pLockObj, 1107fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread** pOwner) 1108fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{ 1109fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden void* framePtr = thread->curFrame; 1110fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1111fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (framePtr == NULL || dvmIsBreakFrame(framePtr)) 1112fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1113fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1114fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr); 1115fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const Method* method = saveArea->method; 1116fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const u2* currentPc = saveArea->xtra.currentPc; 1117fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1118fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check Method* */ 1119fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (!dvmLinearAllocContains(method, sizeof(Method))) { 1120fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden LOGD("ExtrMon: method %p not valid\n", method); 1121fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1122fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1123fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1124fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check currentPc */ 1125fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4 insnsSize = dvmGetMethodInsnsSize(method); 1126fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (currentPc < method->insns || 1127fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc >= method->insns + insnsSize) 1128fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 1129fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden LOGD("ExtrMon: insns %p not valid (%p - %p)\n", 1130fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, method->insns, method->insns + insnsSize); 1131fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1132fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1133fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1134fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check the instruction */ 1135fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if ((*currentPc & 0xff) != OP_MONITOR_ENTER) { 1136fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden LOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)\n", 1137fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, *currentPc & 0xff); 1138fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1139fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1140fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1141fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the register index */ 1142fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden unsigned int reg = *currentPc >> 8; 1143fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (reg >= method->registersSize) { 1144fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden LOGD("ExtrMon: invalid register %d (max %d)\n", 1145fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden reg, method->registersSize); 1146fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1147fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1148fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1149fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the object in that register */ 1150fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4* fp = (u4*) framePtr; 1151fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = (Object*) fp[reg]; 1152fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (!dvmIsValidObject(obj)) { 1153fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden LOGD("ExtrMon: invalid object %p at %p[%d]\n", obj, fp, reg); 1154fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1155fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1156fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pLockObj = obj; 1157fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1158fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1159fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Try to determine the object's lock holder; it's okay if this fails. 1160fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1161fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * We're assuming the thread list lock is already held by this thread. 1162fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * If it's not, we may be living dangerously if we have to scan through 1163fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the thread list to find a match. (The VM will generally be in a 1164fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * suspended state when executing here, so this is a minor concern 1165fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * unless we're dumping while threads are running, in which case there's 1166fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * a good chance of stuff blowing up anyway.) 1167fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1168fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pOwner = dvmGetObjectLockHolder(obj); 1169fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1170fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return true; 1171fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden} 1172fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1173fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/* 1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump stack frames, starting from the specified frame and moving down. 1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Each frame holds a pointer to the currently executing method, and the 1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved program counter from the caller ("previous" frame). This means 1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't have the PC for the current method on the stack, which is 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pretty reasonable since it's in the "PC register" for the VM. Because 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exceptions need to show the correct line number we actually *do* have 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an updated version in the fame's "xtra.currentPc", but it's unreliable. 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note "framePtr" could be NULL in rare circumstances. 1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpFrames(const DebugOutputTarget* target, void* framePtr, 1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* thread) 1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea; 1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method; 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int checkCount = 0; 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u2* currentPc = NULL; 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool first = true; 1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "currentPc" is updated whenever we execute an instruction that 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * might throw an exception. Show it here. 1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (framePtr != NULL && !dvmIsBreakFrame(framePtr)) { 1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->xtra.currentPc != NULL) 1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->xtra.currentPc; 1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (framePtr != NULL) { 1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method = saveArea->method; 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(framePtr)) { 1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmPrintDebugMessage(target, " (break frame)\n"); 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int relPc; 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (currentPc != NULL) 1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = currentPc - saveArea->method->insns; 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = -1; 1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* className = dvmDescriptorToDot(method->clazz->descriptor); 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) 1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at %s.%s(Native Method)\n", className, method->name); 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else { 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at %s.%s(%s:%s%d)\n", 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project className, method->name, dvmGetMethodSourceFile(method), 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (relPc >= 0 && first) ? "~" : "", 1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); 1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(className); 1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1232fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (first) { 1233fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1234fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Decorate WAIT and MONITOR threads with some detail on 1235fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the first frame. 1236fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1237fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * warning: wait status not stable, even in suspend 1238fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1239fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (thread->status == THREAD_WAIT || 1240fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden thread->status == THREAD_TIMED_WAIT) 1241fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 1242fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Monitor* mon = thread->waitMonitor; 1243fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = dvmGetMonitorObject(mon); 1244fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (obj != NULL) { 1245fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden className = dvmDescriptorToDot(obj->clazz->descriptor); 1246fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden dvmPrintDebugMessage(target, 1247fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden " - waiting on <%p> (a %s)\n", obj, className); 1248fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden free(className); 1249fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1250fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } else if (thread->status == THREAD_MONITOR) { 1251fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj; 1252fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread* owner; 1253fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (extractMonitorEnterObject(thread, &obj, &owner)) { 1254fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden className = dvmDescriptorToDot(obj->clazz->descriptor); 1255fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (owner != NULL) { 1256fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden char* threadName = dvmGetThreadName(owner); 1257fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden dvmPrintDebugMessage(target, 1258fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden " - waiting to lock <%p> (a %s) held by threadid=%d (%s)\n", 1259fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden obj, className, owner->threadId, threadName); 1260fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden free(threadName); 1261fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } else { 1262fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden dvmPrintDebugMessage(target, 1263fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden " - waiting to lock <%p> (a %s) held by ???\n", 1264fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden obj, className); 1265fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1266fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden free(className); 1267fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get saved PC for previous frame. There's no savedPc in a "break" 1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame, because that represents native or interpreted code 1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoked by the VM. The saved PC is sitting in the "PC register", 1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a local variable on the native stack. 1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->savedPc; 1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12820083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) { 12830083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden LOGW("Warning: loop in stack trace at frame %d (%p -> %p)\n", 12840083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden checkCount, framePtr, saveArea->prevFrame); 12850083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 12860083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden } 1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project framePtr = saveArea->prevFrame; 1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount++; 12900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (checkCount > 300) { 1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " ***** printed %d frames, not showing any more\n", 1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount); 1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "\n"); 1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread. 1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) 1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dumpFrames(target, thread->curFrame, thread); 1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread, which is still running. 1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very dangerous, because stack frames are being pushed on and 1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popped off, and if the thread exits we'll be looking at freed memory. 1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The plan here is to take a snapshot of the stack and then dump that 1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to try to minimize the chances of catching it mid-update. This should 1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work reasonably well on a single-CPU system. 1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is a small chance that calling here will crash the VM. 1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread) 1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* origStack; 1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackCopy = NULL; 1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int origSize, fpOffset; 1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* fp; 1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int depthLimit = 200; 1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thread == NULL || thread->curFrame == NULL) { 1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n", 1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thread, (thread != NULL) ? thread->threadId : 0); 1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* wait for a full quantum */ 1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sched_yield(); 1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* copy the info we need, then the stack itself */ 1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origSize = thread->interpStackSize; 1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origStack = (const u1*) thread->interpStackStart - origSize; 1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackCopy = (u1*) malloc(origSize); 1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fpOffset = (u1*) thread->curFrame - origStack; 1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(stackCopy, origStack, origSize); 1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Run through the stack and rewrite the "prev" pointers. 1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame); 1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = stackCopy + fpOffset; 1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (true) { 1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int prevOffset; 1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (depthLimit-- < 0) { 1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* we're probably screwed */ 1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n"); 1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->prevFrame == NULL) 1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset = (u1*) saveArea->prevFrame - origStack; 1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (prevOffset < 0 || prevOffset > origSize) { 1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: bad offset found: %d (from %p %p)\n", 1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset, origStack, saveArea->prevFrame); 1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->prevFrame = NULL; 1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->prevFrame = stackCopy + prevOffset; 1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We still need to pass the Thread for some monitor wait stuff. 1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dumpFrames(target, stackCopy + fpOffset, thread); 1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(stackCopy); 1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1382