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 28b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#ifdef HAVE_ANDROID_OS 29b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#include <corkscrew/backtrace.h> 30b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#endif 31b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the interpreter stack in a new thread. 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently this doesn't do much, since we don't need to zero out the 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack (and we really don't want to if it was created with mmap). 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitInterpStack(Thread* thread, int stackSize) 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(thread->interpStackStart != NULL); 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(thread->interpSave.curFrame == NULL); 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling an interpreted method from an internal VM function or 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a frame for an interpreted method onto the stack. This is only 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used when calling into interpreted code from native code. (The 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreter does its own stack frame manipulation for interp-->interp 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls.) 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The size we need to reserve is the sum of parameters, local variables, 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved goodies, and outbound parameters. 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We start by inserting a "break" frame, which ensures that the interpreter 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hands control back to us after the function we call returns or an 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uncaught exception is thrown. 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPushInterpFrame(Thread* self, const Method* method) 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsNativeMethod(method)); 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(method)); 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params + locals 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2 // break frame + regular frame 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + method->outsSize * 4; // args to other methods 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame != NULL) 7830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame); 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 84e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Stack overflow on call to interp " 856f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein "(req=%d top=%p cur=%p size=%d %s.%s)", 8630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackReq, self->interpStackStart, self->interpSave.curFrame, 8799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->clazz->descriptor, method->name); 886ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for the function's 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * args/registers and save area. 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack, unless we want valgrind's help */ 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr - (method->outsSize*4), 0xaf, stackReq); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 10730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee breakSaveBlock->prevSave = 10830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame); 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 11230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee breakSaveBlock->prevFrame = self->interpSave.curFrame; 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 114d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden breakSaveBlock->xtra.localRefCookie = 0; // not required 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->xtra.currentPc = NULL; // not required? 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("PUSH frame: old=%p new=%p (size=%d)", 12230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock), 12330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling a JNI native method from an internal VM fuction or 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. This is also used to create the "fake" native-method 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames at the top of the interpreted stack. 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This actually pushes two frames; the first is a "break" frame. 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top frame has additional space for JNI local reference tracking. 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushJNIFrame(Thread* self, const Method* method) 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params only 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2; // break frame + regular frame 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 15130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame != NULL) 15230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame); 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 158e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Stack overflow on call to native " 1596f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein "(req=%d top=%p cur=%p size=%d '%s')", 16030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackReq, self->interpStackStart, self->interpSave.curFrame, 16199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->name); 1626ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We leave space for the method args, which are copied in later. 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 18230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame == NULL) 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = NULL; 184fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro else { 18530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee void* fp = FP_FROM_SAVEAREA(self->interpSave.curFrame); 186fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro breakSaveBlock->prevSave = (StackSaveArea*)fp; 187fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro } 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee breakSaveBlock->prevFrame = self->interpSave.curFrame; 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 193d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden breakSaveBlock->xtra.localRefCookie = 0; // not required 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 197d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 20060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)", 20130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock), 20230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 20430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock); 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by the JNI PushLocalFrame call. We push a new frame onto 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack that has no ins, outs, or locals, and no break frame above it. 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's strictly used for tracking JNI local refs, and will be popped off 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by dvmPopFrame if it's not removed explicitly. 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushLocalFrame(Thread* self, const Method* method) 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = sizeof(StackSaveArea); // regular frame 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(self->interpSave.curFrame != NULL); 22630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame); 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space; let JNI throw the exception */ 230e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Stack overflow on PushLocal " 2316f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein "(req=%d top=%p cur=%p size=%d '%s')", 23230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackReq, self->interpStackStart, self->interpSave.curFrame, 23399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->name); 2346ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 25130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveBlock->prevSave = 25230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame); 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveBlock->prevFrame = self->interpSave.curFrame; 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 257d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)", 26130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock), 26230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.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{ 27730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame); 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(!dvmIsBreakFrame((u4*)self->interpSave.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 */ 285fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro assert(dvmIsBreakFrame((u4*)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 29160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("POP JNI local frame: removing %s, now %s", 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); 29530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.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 31330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame == NULL) 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 31630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame); 31730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(!dvmIsBreakFrame((u4*)self->interpSave.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)) { 32760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("Popping JNI stack frame for %s.%s%s", 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)"); 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, saveBlock); 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame); 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveBlock->method != NULL) { 338c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("PopFrame missed the break"); 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); // stack trashed -- nowhere to go in this thread 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 34360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("POP frame: cur=%p new=%p", 34430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, saveBlock->prevFrame); 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 34630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = saveBlock->prevFrame; 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Common code for dvmCallMethodV/A and dvmInvokeMethod. 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 35330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * Pushes a call frame on, advancing self->interpSave.curFrame. 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* callPrep(Thread* self, const Method* method, Object* obj, 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool checkAccess) 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->status != THREAD_RUNNING) { 362e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("threadid=%d: status=%d on call to %s.%s -", 36399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->threadId, self->status, 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, method->name); 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self != NULL); 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(method != NULL); 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = obj->clazz; 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = method->clazz; 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project IF_LOGVV() { 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 37860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("thread=%d native code calling %s.%s %s", self->threadId, 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (checkAccess) { 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* needed for java.lang.reflect.Method.invoke */ 38530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->interpSave.curFrame), 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method)) 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* note this throws IAException, not IAError */ 389d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowIllegalAccessException("access to method denied"); 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a call frame on. If there isn't enough room for ins, locals, 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * outs, and the saved state, it will throw an exception. 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 39830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * This updates self->interpSave.curFrame. 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling native code the hard way */ 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushJNIFrame(self, method)) { 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling interpreted code */ 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushInterpFrame(self, method)) { 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return clazz; 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call. 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Note this can't be inlined because it takes a variable number of args.) 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethod(Thread* self, const Method* method, Object* obj, 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue* pResult, ...) 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_list args; 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_start(args, pResult); 429d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden dvmCallMethodV(self, method, obj, false, pResult, args); 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_end(args); 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with a variable number of arguments. We process 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to take the class as an argument because, in Dalvik, 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't need to worry about static synchronized methods. 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodV(Thread* self, const Method* method, Object* obj, 443d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden bool fromJni, JValue* pResult, va_list args) 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 45530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee ins = ((u4*)self->interpSave.curFrame) + 45630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (method->registersSize - method->insSize); 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 458062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block //ALOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins); 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION 4638bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes assert(obj != NULL && dvmIsHeapAddress(obj)); 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (u4) obj; 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (*(desc++)) { 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'D': case 'J': { 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u8 val = va_arg(args, u8); 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(ins, &val, 8); // EABI prevents direct store 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += 2; 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += 2; 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'F': { 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* floats were normalized to doubles; convert back */ 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project float f = (float) va_arg(args, double); 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = dvmFloatToU4(f); 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'L': { /* 'shorty' descr uses L for all refs, incl array */ 4861813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro void* arg = va_arg(args, void*); 4878bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes assert(obj == NULL || dvmIsHeapAddress(obj)); 4881813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro jobject argObj = reinterpret_cast<jobject>(arg); 489d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden if (fromJni) 490de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes *ins++ = (u4) dvmDecodeIndirectRef(self, argObj); 491d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden else 492d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) argObj; 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 4970083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden /* Z B C S I -- all passed as 32-bit integers */ 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = va_arg(args, u4); 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 507c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThreadStack(dvmThreadSelf()); 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 51799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 52230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult, 52330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee method, self); 52499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 529e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#ifndef NDEBUG 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 531e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#endif 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with arguments provided in an array. We process 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The values were likely placed into an uninitialized jvalue array using 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the field specifiers, which means that sub-32-bit fields (e.g. short, 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boolean) may not have 32 or 64 bits of valid data. This is different 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the varargs invocation where the C compiler does a widening 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion when calling a function. As a result, we have to be a 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * little more precise when pulling stuff out. 5458e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * 5468e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * "args" may be NULL if the method has no arguments. 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodA(Thread* self, const Method* method, Object* obj, 549d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden bool fromJni, JValue* pResult, const jvalue* args) 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 56130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee ins = ((u4*)self->interpSave.curFrame) + 56230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (method->registersSize - method->insSize); 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 5670083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = (u4) obj; /* obj is a "real" ref */ 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 5720083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden switch (*desc++) { 5730083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'D': /* 64-bit quantity; have to use */ 5740083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'J': /* memcpy() in case of mis-alignment */ 5750083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden memcpy(ins, &args->j, 8); 5760083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden ins += 2; 5770083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden verifyCount++; /* this needs an extra push */ 5780083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5790083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'L': /* includes array refs */ 580d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden if (fromJni) 581de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes *ins++ = (u4) dvmDecodeIndirectRef(self, args->l); 582d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden else 583d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) args->l; 5840083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5850083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'F': 5860083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'I': 5870083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->i; /* full 32 bits */ 5880083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5890083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'S': 5900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->s; /* 16 bits, sign-extended */ 5910083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5920083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'C': 5930083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->c; /* 16 bits, unsigned */ 5940083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5950083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'B': 5960083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->b; /* 8 bits, sign-extended */ 5970083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5980083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'Z': 5990083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->z; /* 8 bits, zero or non-zero */ 6000083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 6010083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden default: 602c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Invalid char %c in short signature of %s.%s", 6030083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *(desc-1), clazz->descriptor, method->name); 6040083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden assert(false); 6050083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden goto bail; 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 6070083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden 6080083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden verifyCount++; 6090083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden args++; 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 614c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 62299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 62730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult, 62830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee method, self); 62999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 638b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic void throwArgumentTypeMismatch(int argIndex, ClassObject* expected, DataObject* arg) { 639b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string expectedClassName(dvmHumanReadableDescriptor(expected->descriptor)); 6403ff838ee3920ef819d207cbf4148cc9c7939ef69Jesse Wilson std::string actualClassName = dvmHumanReadableType(arg); 641b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, "argument %d should have type %s, got %s", 642b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes argIndex + 1, expectedClassName.c_str(), actualClassName.c_str()); 643be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes} 644be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke a method, using the specified arguments and return type, through 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the reflection interfaces. Could be a virtual or direct method 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (including constructors). Used for reflection. 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deals with boxing/unboxing primitives and performs widening conversions. 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "invokeObj" will be null for a static method. 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the invocation returns with an exception raised, we have to wrap it. 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmInvokeMethod(Object* obj, const Method* method, 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayObject* argList, ArrayObject* params, ClassObject* returnType, 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool noAccessCheck) 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* retObj = NULL; 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s4* ins; 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount, argListLength; 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue retval; 666be420e7ce02692164617fab07facb514147abaa8Andy McFadden bool needPop = false; 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* verify arg count */ 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argList != NULL) 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = argList->length; 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = 0; 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argListLength != (int) params->length) { 6740b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, 675be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes "wrong number of arguments; expected %d, got %d", 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project params->length, argListLength); 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, !noAccessCheck); 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 683be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = true; 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 68630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee ins = ((s4*)self->interpSave.curFrame) + 68730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (method->registersSize - method->insSize); 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount = 0; 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 690062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block //ALOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins); 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (s4) obj; 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy the args onto the stack. Primitive types are converted when 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * necessary, and object types are verified. 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 7031813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro DataObject** args = (DataObject**)(void*)argList->contents; 7041813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro ClassObject** types = (ClassObject**)(void*)params->contents; 7051813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro for (int i = 0; i < argListLength; i++) { 7061813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro int width = dvmConvertArgument(*args++, *types++, ins); 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (width < 0) { 708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); // throw wants to pull PC out of stack 709be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = false; 710be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes throwArgumentTypeMismatch(i, *(types-1), *(args-1)); 711be420e7ce02692164617fab07facb514147abaa8Andy McFadden goto bail; 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += width; 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += width; 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 718c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#ifndef NDEBUG 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 720c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 725c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#endif 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 72899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 73330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (*method->nativeFunc)((u4*)self->interpSave.curFrame, &retval, 73430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee method, self); 73599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, &retval); 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 741be420e7ce02692164617fab07facb514147abaa8Andy McFadden * Pop the frame immediately. The "wrap" calls below can cause 742be420e7ce02692164617fab07facb514147abaa8Andy McFadden * allocations, and we don't want the GC to walk the now-dead frame. 743be420e7ce02692164617fab07facb514147abaa8Andy McFadden */ 744be420e7ce02692164617fab07facb514147abaa8Andy McFadden dvmPopFrame(self); 745be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = false; 746be420e7ce02692164617fab07facb514147abaa8Andy McFadden 747be420e7ce02692164617fab07facb514147abaa8Andy McFadden /* 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If an exception is raised, wrap and replace. This is necessary 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the invoked method could have thrown a checked exception 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the caller wasn't prepared for. 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to do this up in the interpreted code, but that will 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * leave us with a shortened stack trace in the top-level exception. 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) { 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this isn't a void method or constructor, convert the return type 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to an appropriate object. 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't do this when an exception is raised because the value 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in "retval" is undefined. 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (returnType != NULL) { 766c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden retObj = (Object*)dvmBoxPrimitive(retval, returnType); 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(retObj, NULL); 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 772be420e7ce02692164617fab07facb514147abaa8Andy McFadden if (needPop) { 773be420e7ce02692164617fab07facb514147abaa8Andy McFadden dvmPopFrame(self); 774be420e7ce02692164617fab07facb514147abaa8Andy McFadden } 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return retObj; 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 778d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct LineNumFromPcContext { 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 address; 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 lineNum; 781d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro}; 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum) 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt; 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 787de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro // We know that this callback will be called in 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ascending address order, so keep going until we find 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // a match or we've just gone past it. 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address > pContext->address) { 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The line number from the previous positions callback 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // wil be the final result. 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pContext->lineNum = lineNum; 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (address == pContext->address) ? 1 : 0; 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine the source file line number based on the program counter. 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pc" is an offset, in 16-bit units, from the start of the method's code. 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if no match was found (possibly because the source files were 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compiled without "-g", so no line number information is present). 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -2 for native methods (as expected in exception traces). 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmLineNumFromPC(const Method* method, u4 relPc) 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pDexCode = dvmGetMethodCode(method); 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexCode == NULL) { 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method)) 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -2; 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; /* can happen for abstract method stub */ 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext context; 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(&context, 0, sizeof(context)); 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.address = relPc; 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A method with no line number info should return -1 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.lineNum = -1; 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode, 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->prototype.protoIdx, 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->accessFlags, 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumForPcCb, NULL, &context); 831de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return context.lineNum; 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the frame depth. 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Excludes "break" frames. 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeExactFrameDepth(const void* fp) 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = 0; 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 845fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (!dvmIsBreakFrame((u4*)fp)) 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count++; 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return count; 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "vague" frame depth, which is just a pointer subtraction. 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is NOT an overly generous assessment of the number of 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames; the only meaningful use is to compare against the result of 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an earlier invocation. 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Useful for implementing single-step debugger modes, which may need to 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call this for every instruction. 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeVagueFrameDepth(Thread* thread, const void* fp) 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* interpStackStart = thread->interpStackStart; 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 865e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp >= interpStackStart - thread->interpStackSize); 866e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp < interpStackStart); 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return interpStackStart - (u1*) fp; 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the calling frame. Pass in the current fp. 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Skip "break" frames and reflection invoke frames. 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmGetCallerFP(const void* curFrame) 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectretry: 881fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)caller)) { 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* pop up one more */ 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = SAVEAREA_FROM_FP(caller)->prevFrame; 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; /* hit the top */ 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we got here by java.lang.reflect.Method.invoke(), we don't 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to return Method's class loader. Shift up one and try 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * again. 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(caller); 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsReflectionMethod(saveArea->method)) { 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = saveArea->prevFrame; 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(caller != NULL); 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto retry; 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return caller; 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's class. Pass in the current fp. 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class. 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCallerClass(const void* curFrame) 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller; 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(curFrame); 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's class. Pass in the current fp. 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller2Class(const void* curFrame) 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* callerCaller; 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 93130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (dvmIsBreakFrame((u4*)caller) && 93230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* go one more */ 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project callerCaller = dvmGetCallerFP(caller); 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (callerCaller == NULL) 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(callerCaller)->method->clazz; 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's caller's class. Pass in the current fp. 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller3Class(const void* curFrame) 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 95530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (dvmIsBreakFrame((u4*)caller) && 95630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Walk up two frames if possible. */ 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < 2; i++) { 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(caller); 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 965de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 970db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * Fill a flat array of methods that comprise the current interpreter 971db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * stack trace. Pass in the current frame ptr. Break frames are 972db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * skipped, but reflection invocations are not. 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current frame will be in element 0. 975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 976db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapirovoid dvmFillStackTraceArray(const void* fp, const Method** array, size_t length) 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 978db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(fp != NULL); 979db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(array != NULL); 980db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro size_t i = 0; 981db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro while (fp != NULL) { 982db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro if (!dvmIsBreakFrame((u4*)fp)) { 983db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(i < length); 984db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro array[i++] = SAVEAREA_FROM_FP(fp)->method; 985db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro } 986db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro fp = SAVEAREA_FROM_FP(fp)->prevFrame; 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open up the reserved area and throw an exception. The reserved area 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be needed to create and initialize the exception itself. 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we already opened it and we're continuing to overflow, abort the VM. 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to leave the "reserved" area open until the "catch" handler has 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finished doing its processing. This is because the catch handler may 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to resolve classes, which requires calling into the class loader if 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the classes aren't already in the "initiating loader" list. 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10016ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFaddenvoid dvmHandleStackOverflow(Thread* self, const Method* method) 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Can we make the reserved area available? 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->stackOverflowed) { 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Already did, nothing to do but bail. 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1010c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting", 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId); 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* open it up to the full range */ 10174308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("threadid=%d: stack overflow on call to %s.%s:%s", 10186ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden self->threadId, 10196ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->clazz->descriptor, method->name, method->shorty); 102030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); 10214308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)", 10226ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4, 10236ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea), 10246ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden saveArea, (u1*) saveArea - self->interpStackEnd); 10254308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" expanding stack end (%p to %p)", self->interpStackEnd, 1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart - self->interpStackSize); 1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThread(self, false); 1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = self->interpStackStart - self->interpStackSize; 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = true; 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we were trying to throw an exception when the stack overflowed, 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we will blow up when doing the class lookup on StackOverflowError 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because of the pending exception. So, we clear it and make it 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the cause of the SOE. 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* excep = dvmGetException(self); 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (excep != NULL) { 1039e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Stack overflow while throwing exception"); 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 10420b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein dvmThrowChainedException(gDvm.exStackOverflowError, NULL, excep); 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduce the available stack size. By this point we should have finished 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our overflow processing. 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10494fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFaddenvoid dvmCleanupStackOverflow(Thread* self, const Object* exception) 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* newStackEnd; 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->stackOverflowed); 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein if (exception->clazz != gDvm.exStackOverflowError) { 10564fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden /* exception caused during SOE, not the SOE itself */ 10574fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden return; 10584fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden } 10594fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden 1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStackEnd = (self->interpStackStart - self->interpStackSize) 1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + STACK_OVERFLOW_RESERVE; 106230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if ((u1*)self->interpSave.curFrame <= newStackEnd) { 1063c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Can't shrink stack: curFrame is in reserved area (%p %p)", 106430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpStackEnd, self->interpSave.curFrame); 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = newStackEnd; 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = false; 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 10724308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("Shrank stack (to %p, curFrame is %p)", self->interpStackEnd, 107330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame); 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1078fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Extract the object that is the target of a monitor-enter instruction 1079fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * in the top stack frame of "thread". 1080fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1081fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The other thread might be alive, so this has to work carefully. 1082fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1083d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * The thread list lock must be held. 1084fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1085fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Returns "true" if we successfully recover the object. "*pOwner" will 1086fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * be NULL if we can't determine the owner for some reason (e.g. race 1087fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * condition on ownership transfer). 1088fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1089fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenstatic bool extractMonitorEnterObject(Thread* thread, Object** pLockObj, 1090fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread** pOwner) 1091fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{ 109230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee void* framePtr = thread->interpSave.curFrame; 1093fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1094fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr)) 1095fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1096fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1097fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr); 1098fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const Method* method = saveArea->method; 1099fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const u2* currentPc = saveArea->xtra.currentPc; 1100fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1101fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check Method* */ 1102fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (!dvmLinearAllocContains(method, sizeof(Method))) { 1103062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("ExtrMon: method %p not valid", method); 1104fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1105fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1106fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1107fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check currentPc */ 1108fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4 insnsSize = dvmGetMethodInsnsSize(method); 1109fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (currentPc < method->insns || 1110fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc >= method->insns + insnsSize) 1111fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 1112062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("ExtrMon: insns %p not valid (%p - %p)", 1113fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, method->insns, method->insns + insnsSize); 1114fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1115fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1116fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1117fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check the instruction */ 1118fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if ((*currentPc & 0xff) != OP_MONITOR_ENTER) { 1119062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)", 1120fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, *currentPc & 0xff); 1121fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1122fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1123fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1124fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the register index */ 1125fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden unsigned int reg = *currentPc >> 8; 1126fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (reg >= method->registersSize) { 1127062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("ExtrMon: invalid register %d (max %d)", 1128fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden reg, method->registersSize); 1129fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1130fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1131fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1132fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the object in that register */ 1133fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4* fp = (u4*) framePtr; 1134fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = (Object*) fp[reg]; 11358bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes if (obj != NULL && !dvmIsHeapAddress(obj)) { 1136062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("ExtrMon: invalid object %p at %p[%d]", obj, fp, reg); 1137fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1138fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1139fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pLockObj = obj; 1140fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1141fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1142fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Try to determine the object's lock holder; it's okay if this fails. 1143fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1144fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * We're assuming the thread list lock is already held by this thread. 1145fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * If it's not, we may be living dangerously if we have to scan through 1146fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the thread list to find a match. (The VM will generally be in a 1147fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * suspended state when executing here, so this is a minor concern 1148fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * unless we're dumping while threads are running, in which case there's 1149fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * a good chance of stuff blowing up anyway.) 1150fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1151fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pOwner = dvmGetObjectLockHolder(obj); 1152fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1153fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return true; 1154fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden} 1155fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1156708f143f318bb2167c810f9506102f4ad656545cElliott Hughesstatic void printWaitMessage(const DebugOutputTarget* target, const char* detail, Object* obj, 1157708f143f318bb2167c810f9506102f4ad656545cElliott Hughes Thread* thread) 1158708f143f318bb2167c810f9506102f4ad656545cElliott Hughes{ 1159837eabb829417c1542037423c55536649de404b8Elliott Hughes std::string msg(StringPrintf(" - waiting %s <%p> ", detail, obj)); 1160708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1161708f143f318bb2167c810f9506102f4ad656545cElliott Hughes if (obj->clazz != gDvm.classJavaLangClass) { 1162708f143f318bb2167c810f9506102f4ad656545cElliott Hughes // I(16573) - waiting on <0xf5feda38> (a java.util.LinkedList) 1163fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes // I(16573) - waiting on <0xf5ed54f8> (a java.lang.Class<java.lang.ref.ReferenceQueue>) 1164fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes msg += "(a " + dvmHumanReadableType(obj) + ")"; 1165708f143f318bb2167c810f9506102f4ad656545cElliott Hughes } 1166708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1167708f143f318bb2167c810f9506102f4ad656545cElliott Hughes if (thread != NULL) { 1168708f143f318bb2167c810f9506102f4ad656545cElliott Hughes std::string threadName(dvmGetThreadName(thread)); 1169837eabb829417c1542037423c55536649de404b8Elliott Hughes StringAppendF(&msg, " held by tid=%d (%s)", thread->threadId, threadName.c_str()); 1170708f143f318bb2167c810f9506102f4ad656545cElliott Hughes } 1171708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1172708f143f318bb2167c810f9506102f4ad656545cElliott Hughes dvmPrintDebugMessage(target, "%s\n", msg.c_str()); 1173708f143f318bb2167c810f9506102f4ad656545cElliott Hughes} 1174708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1175fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/* 1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump stack frames, starting from the specified frame and moving down. 1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Each frame holds a pointer to the currently executing method, and the 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved program counter from the caller ("previous" frame). This means 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't have the PC for the current method on the stack, which is 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pretty reasonable since it's in the "PC register" for the VM. Because 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exceptions need to show the correct line number we actually *do* have 1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an updated version in the fame's "xtra.currentPc", but it's unreliable. 1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note "framePtr" could be NULL in rare circumstances. 1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpFrames(const DebugOutputTarget* target, void* framePtr, 1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* thread) 1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea; 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method; 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int checkCount = 0; 1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u2* currentPc = NULL; 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool first = true; 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1197d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * We call functions that require us to be holding the thread list lock. 1198d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * It's probable that the caller has already done so, but it's not 1199d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * guaranteed. If it's not locked, lock it now. 1200d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden */ 1201d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden bool needThreadUnlock = dvmTryLockThreadList(); 1202d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden 1203d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden /* 1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "currentPc" is updated whenever we execute an instruction that 1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * might throw an exception. Show it here. 1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1207fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) { 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->xtra.currentPc != NULL) 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->xtra.currentPc; 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (framePtr != NULL) { 1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method = saveArea->method; 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1218fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)framePtr)) { 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmPrintDebugMessage(target, " (break frame)\n"); 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int relPc; 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (currentPc != NULL) 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = currentPc - saveArea->method->insns; 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = -1; 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12285719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes std::string methodName(dvmHumanReadableMethod(method, false)); 1229b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes if (dvmIsNativeMethod(method)) { 12305719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes dvmPrintDebugMessage(target, " at %s(Native Method)\n", 12315719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes methodName.c_str()); 1232b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes } else { 12335719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes dvmPrintDebugMessage(target, " at %s(%s:%s%d)\n", 12345719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes methodName.c_str(), dvmGetMethodSourceFile(method), 1235b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes (relPc >= 0 && first) ? "~" : "", 1236b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); 1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1239fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (first) { 1240fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1241fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Decorate WAIT and MONITOR threads with some detail on 1242fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the first frame. 1243fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1244fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * warning: wait status not stable, even in suspend 1245fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1246fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (thread->status == THREAD_WAIT || 1247fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden thread->status == THREAD_TIMED_WAIT) 1248fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 1249fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Monitor* mon = thread->waitMonitor; 1250fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = dvmGetMonitorObject(mon); 1251fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (obj != NULL) { 1252d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden Thread* joinThread = NULL; 1253708f143f318bb2167c810f9506102f4ad656545cElliott Hughes if (obj->clazz == gDvm.classJavaLangVMThread) { 1254d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden joinThread = dvmGetThreadFromThreadObject(obj); 1255d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } 1256708f143f318bb2167c810f9506102f4ad656545cElliott Hughes printWaitMessage(target, "on", obj, joinThread); 1257fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1258fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } else if (thread->status == THREAD_MONITOR) { 1259fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj; 1260fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread* owner; 1261fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (extractMonitorEnterObject(thread, &obj, &owner)) { 1262708f143f318bb2167c810f9506102f4ad656545cElliott Hughes printWaitMessage(target, "to lock", obj, owner); 1263fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get saved PC for previous frame. There's no savedPc in a "break" 1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame, because that represents native or interpreted code 1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoked by the VM. The saved PC is sitting in the "PC register", 1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a local variable on the native stack. 1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->savedPc; 1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12780083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) { 1279e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Warning: loop in stack trace at frame %d (%p -> %p)", 12800083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden checkCount, framePtr, saveArea->prevFrame); 12810083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 12820083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden } 1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project framePtr = saveArea->prevFrame; 1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount++; 12860083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (checkCount > 300) { 1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " ***** printed %d frames, not showing any more\n", 1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount); 1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1293d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden 1294d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden if (needThreadUnlock) { 1295d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden dvmUnlockThreadList(); 1296d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } 1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread. 1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) 1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 130530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dumpFrames(target, thread->interpSave.curFrame, thread); 1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread, which is still running. 1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very dangerous, because stack frames are being pushed on and 1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popped off, and if the thread exits we'll be looking at freed memory. 1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The plan here is to take a snapshot of the stack and then dump that 1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to try to minimize the chances of catching it mid-update. This should 1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work reasonably well on a single-CPU system. 1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is a small chance that calling here will crash the VM. 1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread) 1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* origStack; 1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackCopy = NULL; 1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int origSize, fpOffset; 1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* fp; 1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int depthLimit = 200; 1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 132830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (thread == NULL || thread->interpSave.curFrame == NULL) { 1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n", 1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thread, (thread != NULL) ? thread->threadId : 0); 1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* wait for a full quantum */ 1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sched_yield(); 1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* copy the info we need, then the stack itself */ 1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origSize = thread->interpStackSize; 1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origStack = (const u1*) thread->interpStackStart - origSize; 1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackCopy = (u1*) malloc(origSize); 134230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee fpOffset = (u1*) thread->interpSave.curFrame - origStack; 1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(stackCopy, origStack, origSize); 1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Run through the stack and rewrite the "prev" pointers. 1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 13484308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block //ALOGI("DR: fpOff=%d (from %p %p)",fpOffset, origStack, 134930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee // thread->interpSave.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 137230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveArea->prevFrame = (u4*)(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} 1382b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown 1383b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown/* 1384b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown * Dump the native stack for the specified thread. 1385b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown */ 1386b1212301d5cffc06907211d243a21d50c4419dc9Jeff Brownvoid dvmDumpNativeStack(const DebugOutputTarget* target, pid_t tid) 1387b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown{ 1388b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#ifdef HAVE_ANDROID_OS 1389b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown const size_t MAX_DEPTH = 32; 1390b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown backtrace_frame_t backtrace[MAX_DEPTH]; 1391b1212301d5cffc06907211d243a21d50c4419dc9Jeff Brown ssize_t frames = unwind_backtrace_thread(tid, backtrace, 0, MAX_DEPTH); 1392b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown if (frames > 0) { 1393b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown backtrace_symbol_t backtrace_symbols[MAX_DEPTH]; 1394b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown get_backtrace_symbols(backtrace, frames, backtrace_symbols); 1395b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown 1396b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown for (size_t i = 0; i < size_t(frames); i++) { 139769c475676546a97f872df9e19125c0154b40ae0bJeff Brown char line[MAX_BACKTRACE_LINE_LENGTH]; 139869c475676546a97f872df9e19125c0154b40ae0bJeff Brown format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i], 139969c475676546a97f872df9e19125c0154b40ae0bJeff Brown line, MAX_BACKTRACE_LINE_LENGTH); 140069c475676546a97f872df9e19125c0154b40ae0bJeff Brown dvmPrintDebugMessage(target, " %s\n", line); 1401b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown } 1402b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown 1403b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown free_backtrace_symbols(backtrace_symbols, frames); 1404b3667a19f5c573b7785876979af4781292d27327Andy McFadden } else { 1405b3667a19f5c573b7785876979af4781292d27327Andy McFadden dvmPrintDebugMessage(target, " (native backtrace unavailable)\n"); 1406b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown } 1407b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#endif 1408b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown} 1409